Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

core(installable-manifest): check for fetchable icon #10168

Merged
merged 31 commits into from
Jan 31, 2020

Conversation

connorjclark
Copy link
Collaborator

I think how Lighthouse deals with manifests could be improved, but that's a pretty big project for small gain. This PR does the minimal necessary to fix #789.

Copy link
Collaborator

@patrickhulce patrickhulce left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my biggest concern about this is that we could be fetching lots of files very slowing for not a ton of benefit... (especially in WPT-like environments that are throttled outside of our control)

what are thoughts on just fetching the largest icon to check and/or whatever one chrome is most likely to actually use?

// Add a warning for icons that aren't fetchable.
if (manifest.value && Array.isArray(manifest.value.icons.value)) {
const iconsToFetch = manifest.value.icons.value
.filter(icon => icon.value.src && icon.value.src.value);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

were empty string icons treated as acceptable before but now they won't be? or I suppose they will be valid because we won't try to fetch and put any warning on them?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

at this point empty strings were converted to undefined (see parser). later, the icons check will ignore icons whose src does not end in .png.

... however I've just noticed there's a bug if typeHint === 'image/png' and src is undefined. this is so dirty. Can fix by tweaking getFetchableIcons to also check for a nonempty string.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aight sgtm

${JSON.stringify(icon.value.src.value)}
)`;
if (!await passContext.driver.evaluateAsync(expression, {useIsolation: true})) {
icon.warning = 'Error fetching icon';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't love the Promise.all mutating an object, can we make this a map of the icon results?

const expression = `(${pageFunctions.fetchIsOkString})(
${JSON.stringify(icon.value.src.value)}
)`;
if (!await passContext.driver.evaluateAsync(expression, {useIsolation: true})) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels like we should make this timeout very short and .catch them to not be a fatal protocol timeout

@@ -36,6 +36,17 @@ describe('Icons helper', () => {
assert.equal(icons.doExist(manifest.value), false);
});

it('fails when a manifest contains no fetchable icons', () => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ooo ooo can we get an empty string test in here before we forget about it again :D

@connorjclark
Copy link
Collaborator Author

what are thoughts on just fetching the largest icon to check and/or whatever one chrome is most likely to actually use?

Only attempt the largest, or attempt all above 512px until one passes?

@patrickhulce
Copy link
Collaborator

Only attempt the largest, or attempt all above 512px until one passes?

Ideally, we'd do whatever browsers are most likely to do across all users. i.e. if Chrome will try the 512 icon first and use it if it works we do the same, try to fetch 512 and stop if it worked

@connorjclark
Copy link
Collaborator Author

connorjclark commented Jan 9, 2020

Here is the installation check. Just looks for any icon >= 144px (with a caveat for maskable icons that #10197 will no doubt need to consider). No fetch here.

More complicated logic is done to determine the best fitting icon. Rather than replicating that, we should just let Chrome do the fetching and sniff for the error it may create. Page.getAppManifest response's .errors should have that signal. (speaking of which .... why do we replicate all of these checks when this errors object exists?)

@connorjclark
Copy link
Collaborator Author

oh right, I forgot about this #8995

should be fine to use this protocol for just the signal for failure to fetch an icon.

@connorjclark
Copy link
Collaborator Author

image

unfortunately we just can't tie it back to a specific icon :(

@connorjclark connorjclark changed the title core(manifest-values): only consider icons that are fetchable core(installable-manifest): check for fetchable icon Jan 9, 2020
@paulirish
Copy link
Member

fyi: part 2 of the getInstallabilityErrors -- tweaks to frontend: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/2016235

Co-Authored-By: Patrick Hulce <patrick.hulce@gmail.com>
@brendankenny
Copy link
Member

I don't have anything fleshed out. I mostly mean that the manual checks we have are not great (we may be missing full coverage). The new protocol work on Page.getInstallabilityErrors will help us here in due time. Ideally we'll be able to lean on that 100% and replace the WebappManifest artifact with just the literal manifest, not all this parsing junk.

The parser code style is different because we forked it from an existing library, and at the time we didn't know what we'd actually need out of it, so the output is just the direct tree instead of linearized errors or whatever. If there are actual bugs to report we should fix them, we should rely on the protocol when we can do so, but in the meantime let's not unnecessarily antagonize those of us that had to do the library forking :)

@@ -115,15 +115,18 @@ describe('ReportRenderer', () => {
const container = renderer._dom._document.body;
const output = renderer.renderReport(sampleResultsCopy, container);

function isPWAGauge(el) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pwa category is failing for the sample report json now, which means the pwa__wrapper class isn't set. Changed the test to look at text content instead.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah well I had to update the sample artifacts anyways, but I'm gonna keep this test change.

@@ -2028,7 +2028,7 @@
"vulnCount": 2.0
}
],
"summary": {},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why have these changed?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because i forgot to edit them back

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i havent update proto ..

@patrickhulce
Copy link
Collaborator

@connorjclark the assignment was just to reflect our new policy right, you're not waiting on me? I don't see anything objectionable that's new so my approval still stands

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Ligthouse checks for an icon in the manifest but does not try to load it
6 participants