Closed Bug 962630 Opened 11 years ago Closed 10 years ago

Browser API: Access URLs of multiple favicons provided for the same page

Categories

(Core :: DOM: Core & HTML, defect)

defect
Not set
normal

Tracking

()

RESOLVED FIXED
2.1 S2 (15aug)

People

(Reporter: benfrancis, Unassigned)

References

Details

(Keywords: dev-doc-complete, feature)

The browser API has a mozbrowsericonchange event which can be used to get the favicon URL for a given web page, as specified in a <link rel=icon> element. Some web pages provide multiple icon URLs including larger, higher quality options to the usual 16 or 32 pixel square option. The W3C specification recommends that the user agent should "select the most appropriate icon based on type, media and sizes attributes". http://www.w3.org/TR/html5/links.html#rel-icon In Gaia we would like to be able to access higher quality icons to use when adding a bookmark to the homescreen. To do this, we either need to get the platform to detect that multiple icons are available and somehow select a higher quality option, or we need to provide all the URLs and other attributes to Gaia so that it can select its own icon.
Keywords: feature
Again, this also interacts with the manifest spec: <http://w3c.github.io/manifest/#icons-member>
This is a platform issue. In Gecko, the selection algorithm does the minimum the HTML spec requires (i.e., just picks the last icon). It does not discriminate on the @sizes or @media, as far as I can tell from testing. It's also important not to confuse the link rel=icon icons with the favicon. The favicon is a fallback that behaves as it was a link rel=icon - but it's always at the same location "/favicon.ico". Favicons are also badly broken (in that only the smallest is ever chosen and scaled to 16x16)... but that's a different bug ^_^. With regards to the manifest, yes... when manifest icons are missing, the ones in HTML should be used instead.
> In Gaia we would like to be able to access higher quality icons to use when > adding a bookmark to the homescreen. mozbrowsericonchange event is triggered for any <link rel='icon'> tag. The event contains the 'href' and the sizes. Is this enough?
Oh, so in the example below, would multiple events be fired on the same page, one for each link tag? What properties are included in the event object exactly? <head> <link rel=icon href=favicon.png sizes="16x16" type="image/png"> <link rel=icon href=windows.ico sizes="32x32 48x48" type="image/vnd.microsoft.icon"> <link rel=icon href=mac.icns sizes="128x128 512x512 8192x8192 32768x32768"> <link rel=icon href=iphone.png sizes="57x57" type="image/png"> <link rel=icon href=gnome.svg sizes="any" type="image/svg+xml"> </head> The documentation on MDN says that an event is fired "whenever a favicon changes" which probably isn't accurate given comment 2, but it also says that the detail property of the event is just a string containing the URL. Where do you get the size and type?
Yep, the documentation must be updated. I tested your example with these code: iframe1.addEventListener('mozbrowsericonchange', function(e) { console.log(e.detail.toSource()); }); and here the console log: "({href:"favicon.png", sizes:"16x16", msg_name:"iconchange"})" "({href:"windows.ico", sizes:"32x32 48x48", msg_name:"iconchange"})" "({href:"mac.icns", sizes:"128x128 512x512 8192x8192 32768x32768", msg_name:"iconchange"})" "({href:"iphone.png", sizes:"57x57", msg_name:"iconchange"})" "({href:"gnome.svg", sizes:"any", msg_name:"iconchange"})" The 'detail' property is an object with 3 properties (2 useful): 'href' containing the URL of the icon. String. 'sizes' a string with the value of the 'sizes' attribute if any. 'msg_name': for internal use.. it's the name of the event.
Keywords: dev-doc-needed
Oh, cool! It seems I should already know about the href property as I r+'d a patch to start using it a few months ago https://github.com/mozilla-b2g/gaia/pull/12275 So I guess right now in Gaia we're handling all the events fired then using the last one, so the SVG file in the example above. I didn't realise that. I guess one downside of these events is that we can't access the type or media attributes of the link tag, so we could end up trying to use an audio file (for auditory icons), or unsupported image format, and can only choose between icons based on size. But it's cool that we get the sizes attribute, we could try and parse that as a starting point.
(In reply to Ben Francis [:benfrancis] from comment #7) > we get the sizes attribute, we could try and parse that > as a starting point. I have filed bug 963047 for this. (In reply to :Ehsan Akhgari (needinfo? me!) from comment #1) > Again, this also interacts with the manifest spec: > <http://w3c.github.io/manifest/#icons-member> If we add support for the W3C manifest spec, we should definitely use an icon provided in the manifest spec, then fallback to a link tag if a manifest does not exist. Do we have any bugs tracking that implementation? See my comments in bug https://bugzilla.mozilla.org/show_bug.cgi?id=962626#c4 regarding how we might access the manifest data.
I'm currently in the process of spec'ing how fallback is going to work for icons and other elements. Manifest that exclude the icons member will cause the UA to search the HTML for icons (or use the favicon)... I've still not decided if manifest + icons in the HTML document should be used together - probably not.
(In reply to Andrea Marchesini (:baku) from comment #6) > Yep, the documentation must be updated. > > I tested your example with these code: > > iframe1.addEventListener('mozbrowsericonchange', function(e) { > console.log(e.detail.toSource()); > }); > > and here the console log: > > "({href:"favicon.png", sizes:"16x16", msg_name:"iconchange"})" > "({href:"windows.ico", sizes:"32x32 48x48", msg_name:"iconchange"})" > "({href:"mac.icns", sizes:"128x128 512x512 8192x8192 32768x32768", > msg_name:"iconchange"})" > "({href:"iphone.png", sizes:"57x57", msg_name:"iconchange"})" > "({href:"gnome.svg", sizes:"any", msg_name:"iconchange"})" > > The 'detail' property is an object with 3 properties (2 useful): > > 'href' containing the URL of the icon. String. > 'sizes' a string with the value of the 'sizes' attribute if any. > 'msg_name': for internal use.. it's the name of the event. So unless I'm missing something, this doesn't let us implement what the spec requires here. The spec requires us to use the last appropriate icon in tree order.
(In reply to :Ehsan Akhgari (needinfo? me!) from comment #10) > So unless I'm missing something, this doesn't let us implement what the spec > requires here. The spec requires us to use the last appropriate icon in > tree order. It doesn't really matter what the spec says - as it's quite contextual where/which icon is shown (e.g., adding to the homescreen would require a different icon to showing it in the URL bar). So, pick the most appropriate icon, and not the last one. It would be nice to at least start discriminating on sizes and content type ... and eventually even (CSS) media.
(In reply to :Ehsan Akhgari (needinfo? me!) from comment #10) > So unless I'm missing something, this doesn't let us implement what the spec > requires here. The spec requires us to use the last appropriate icon in > tree order. I think the relevant part of the spec is: "If multiple icons are provided, the user agent must select the most appropriate icon according to the type, media, and sizes attributes. If there are multiple equally appropriate icons, user agents must use the last one declared in tree order at the time that the user agent collected the list of icons. If the user agent tries to use an icon but that icon is determined, upon closer examination, to in fact be inappropriate (e.g. because it uses an unsupported format), then the user agent must try the next-most-appropriate icon as determined by the attributes." As a first step we can try to pick an icon based on the sizes of available icons, but the challenge may be that we don't know whether any given iconchange event is the last, so we may start to download what we think is the most appropriate icon, but then another event arrives informing us of a more appropriate one.
(In reply to comment #11) > (In reply to :Ehsan Akhgari (needinfo? me!) from comment #10) > > So unless I'm missing something, this doesn't let us implement what the spec > > requires here. The spec requires us to use the last appropriate icon in > > tree order. > > It doesn't really matter what the spec says - as it's quite contextual > where/which icon is shown (e.g., adding to the homescreen would require a > different icon to showing it in the URL bar). So, pick the most appropriate > icon, and not the last one. Well, the spec addresses the case where multiple images match the contextual criteria based on the size, etc. I was not suggesting that we should pick the last icon no matter what. :-) > It would be nice to at least start discriminating on sizes and content type ... > and eventually even (CSS) media. Sure.
(In reply to comment #12) > (In reply to :Ehsan Akhgari (needinfo? me!) from comment #10) > > So unless I'm missing something, this doesn't let us implement what the spec > > requires here. The spec requires us to use the last appropriate icon in > > tree order. > > I think the relevant part of the spec is: > > "If multiple icons are provided, the user agent must select the most > appropriate icon according to the type, media, and sizes attributes. If there > are multiple equally appropriate icons, user agents must use the last one > declared in tree order at the time that the user agent collected the list of > icons. If the user agent tries to use an icon but that icon is determined, upon > closer examination, to in fact be inappropriate (e.g. because it uses an > unsupported format), then the user agent must try the next-most-appropriate > icon as determined by the attributes." > > As a first step we can try to pick an icon based on the sizes of available > icons, but the challenge may be that we don't know whether any given iconchange > event is the last, so we may start to download what we think is the most > appropriate icon, but then another event arrives informing us of a more > appropriate one. Yeah exactly. This is also the same issue I brought up in my review on bug 962626, and as mentioned there, it's definitely an edge case.
(In reply to :Ehsan Akhgari (needinfo? me!) from comment #14) > Yeah exactly. This is also the same issue I brought up in my review on bug > 962626, and as mentioned there, it's definitely an edge case. I'm not sure it's that much of an edge case. When do you select and start downloading an icon? After the first iconchange event? On loadend? After a fixed timeout? Would it make sense to have a single iconchange event which enumerates all the icons present in the initial parse of the DOM, then fires again on any further elements which are added/removed into the DOM? (I have no idea how this is parsed so that might not be possible). We could start downloading based on the first iconChange event then try to abort the XHR request if a better option comes along, but that doesn't seem very efficient.
It seems like it would be nice to end up with document.icons or something like that? Then we could abstract away all the manifest, <link rel="icons"> and favicon.ico stuff out of the front-end where its getting increasingly complicated to do what seems like it should be a simple thing.
(Sorry for the late reply, please use needinfo?, thanks! :-) (In reply to Ben Francis [:benfrancis] from comment #15) > (In reply to :Ehsan Akhgari (needinfo? me!) from comment #14) > > Yeah exactly. This is also the same issue I brought up in my review on bug > > 962626, and as mentioned there, it's definitely an edge case. > > I'm not sure it's that much of an edge case. When do you select and start > downloading an icon? After the first iconchange event? On loadend? After a > fixed timeout? By edge case I meant that I think most pages don't set multiple icons (but of course I have no data.) Not sure if I have a good answer to any of these questions. > Would it make sense to have a single iconchange event which enumerates all > the icons present in the initial parse of the DOM, then fires again on any > further elements which are added/removed into the DOM? (I have no idea how > this is parsed so that might not be possible). > > We could start downloading based on the first iconChange event then try to > abort the XHR request if a better option comes along, but that doesn't seem > very efficient. If we want to do anything sensible with multiple icons, we should do that inside Gecko before emitting the event I think, since it's at that point where we have the DOM tree of the original document. It would be too late to do anything in response to the iconchange event.
(In reply to Sam Foster [:sfoster] from comment #16) > It seems like it would be nice to end up with document.icons or something > like that? Then we could abstract away all the manifest, <link rel="icons"> > and favicon.ico stuff out of the front-end where its getting increasingly > complicated to do what seems like it should be a simple thing. document.icons won't capture the relationships of the link elements inside the DOM tree. I think if we want to handle the case of multiple icons, we should either follow what the spec says today or come up with an alternative and get the spec changed based on that.
(In reply to :Ehsan Akhgari (lagging on bugmail, needinfo? me!) from comment #17) > If we want to do anything sensible with multiple icons, we should do that > inside Gecko before emitting the event I think, since it's at that point > where we have the DOM tree of the original document. It would be too late > to do anything in response to the iconchange event. What might that look like in practice? And how would Gecko know what size the consumer needs? We have a possible use case in Gaia where we might want a large icon for the homescreen, but a smaller icon for awesomebar style results. I like the idea of Gecko doing the hard work and just exposing one icon via the iconchange event, but that does lose us flexibility in requesting different size or multiple icons.
Flags: needinfo?(ehsan)
> I'm not sure it's that much of an edge case. When do you select and start > downloading an icon? After the first iconchange event? On loadend? After a > fixed timeout? What about if we emit an event when the <head> is fully loaded? You can collect the iconchange events and wait for the head-loaded event. When you will have all the icons and you can decide what you want to load. Of course if a new icon is added via JS, you will receive a new iconchange, but this is another edge case.
(In reply to Ben Francis [:benfrancis] from comment #19) > (In reply to :Ehsan Akhgari (lagging on bugmail, needinfo? me!) from comment > #17) > > If we want to do anything sensible with multiple icons, we should do that > > inside Gecko before emitting the event I think, since it's at that point > > where we have the DOM tree of the original document. It would be too late > > to do anything in response to the iconchange event. > > What might that look like in practice? This is the relevant piece of the spec <http://www.whatwg.org/specs/web-apps/current-work/#rel-icon>: "If multiple icons are provided, the user agent must select the most appropriate icon according to the type, media, and sizes attributes. If there are multiple equally appropriate icons, user agents must use the last one declared in tree order at the time that the user agent collected the list of icons. If the user agent tries to use an icon but that icon is determined, upon closer examination, to in fact be inappropriate (e.g. because it uses an unsupported format), then the user agent must try the next-most-appropriate icon as determined by the attributes." Right now we don't respect any of the above, IOW, for every single <link rel="icon"> that gets added to the DOM tree, we raise one mozbrowsericonchange event. So for example, if a document has two icons with the same size, we report them both, violating the "in tree order" part of the spec above. > And how would Gecko know what size > the consumer needs? If we were to respect the spec here, we would emit an event with the *right* <link> for a given size. This doesn't really have anything to do with picking a size. That can still be handled by the consumer of this API. > We have a possible use case in Gaia where we might want a large icon for the > homescreen, but a smaller icon for awesomebar style results. That's fine, we don't violate the spec for multiple icons each with a different size (of course, I mean, we don't violate the spec in Gecko, not sure about Gaia. ;-) > I like the idea of Gecko doing the hard work and just exposing one icon via > the iconchange event, but that does lose us flexibility in requesting > different size or multiple icons. Not necessarily, what I had in mind was that Gecko would still give you multiple mozbrowsericonchange events for different sizes, but it would give you the right icon for a given size.
Flags: needinfo?(ehsan)
(In reply to Andrea Marchesini (:baku) from comment #20) > > I'm not sure it's that much of an edge case. When do you select and start > > downloading an icon? After the first iconchange event? On loadend? After a > > fixed timeout? > > What about if we emit an event when the <head> is fully loaded? > You can collect the iconchange events and wait for the head-loaded event. > When you will have all the icons and you can decide what you want to load. > > Of course if a new icon is added via JS, you will receive a new iconchange, > but this is another edge case. There's nothing special about <head>, <link> elements can go anywhere in the document and they can also be dynamically injected. See the previous comment for a solution, but I'm still not sure if we care about this enough.
That spec is pretty ambiguous - "the user agent must select the most appropriate icon according to the type, media, and sizes attributeshow" - I have no idea what most appropriate would mean or how we would communicate that. The existing one event per <link rel=icon> gives us enough info to work with, its the not knowing when we're finished that is an immediate problem. I think a </head> event is sufficient for the gaia uses cases at least - and most web apps. That gives us a sensible time to stop listening for iconchange events, and get a head start on loading the icon while the rest of the document loads. Its inline with existing best practices. Also, there's nothing stopping you from listening for further iconchange events if you want. The other issue here is the conflation of icons (.ico) with images. A favicon might have multiple images in it and right now we have no way to know ahead of time which sizes are in there; we can only hope for the best with .ico#-moz-resolution=n,n,. It would still be nice to resolve the various ways icons are provided into a neat API, but the blocker
oops, trailed off at the end there. Nothing of consequence clipped.
We still need to be able to handle dynamically inserted <link> elements, right? Why do we need to know when we're finished here? Can't we just have the icon change dynamically according to what the page does at runtime?
When we receive the icon event we start to download the icon over XHR and save it into the places database. We do this for every new icon you come across while browsing the web, to be used when displaying frecency based awesomebar results from your browsing history. We also use icons when bookmarking to the homescreen. So it isn't just about displaying the icon, there's a lot of I/O involved. We really need a definitive way to express a preference for a size, media and type of icon and to get one icon back that matches those requirements as closely as possible. And sometimes we might want to use a different icon for search results (a smaller icon) than for adding to the homescreen (a larger icon). I'm not sure how much of this should happen in Gecko and how much should happen in Gaia though.
(In reply to Sam Foster [:sfoster] from comment #23) > That spec is pretty ambiguous - "the user agent must select the most > appropriate icon according to the type, media, and sizes attributeshow" - I > have no idea what most appropriate would mean or how we would communicate > that. I don't think it's ambiguous (the appropriate needs to be evaluated against the attributes): type: supported? yes/no, media: matches media when the media query is evaluted? yes/no, sizes: does the sizes fit the render context for the icon? yes/no. If any is no, then you move onto the next one. If you have more than one, you use the last one in tree order.
Is this still needed or do we have everything we need in bug 1041482?
Flags: needinfo?(kgrandon)
This bug seems specific to the <link rel=icon> usage. I'm not sure if we have support for this or need it off the top of my head. Francisco/Dale - do we still need to do work here?
Flags: needinfo?(kgrandon)
Flags: needinfo?(francisco)
Flags: needinfo?(dale)
Nope I think we are good here, there are follow ups to do with the icons, but support is in there
Status: NEW → RESOLVED
Closed: 10 years ago
Flags: needinfo?(dale)
Resolution: --- → FIXED
Flags: needinfo?(francisco)
Target Milestone: --- → 2.1 S2 (15aug)
Component: DOM → DOM: Core & HTML
You need to log in before you can comment on or make changes to this bug.