w3ctag / design-reviews

W3C specs and API reviews
Creative Commons Zero v1.0 Universal
327 stars 55 forks source link

Badging API #387

Closed fallaciousreasoning closed 4 years ago

fallaciousreasoning commented 5 years ago

こんにちはTAG!

I'm requesting a TAG review of:

Further details:

We'd prefer the TAG provide feedback as (please select one):

torgo commented 5 years ago

What is the current implementation status outside of Chromium? The spec only links to a Chromium implementation...

torgo commented 5 years ago

@hober brought up a good point in last week's TAG call that there is a kind of badging that happens in tabs in the background in some webapps that accumulate notification. Is this reflected in any current discussion?

fallaciousreasoning commented 5 years ago

What is the current implementation status outside of Chromium? The spec only links to a Chromium implementation...

There is not currently any implementation outside of Chromium. Is this a requirement for a TAG review? FWIW: Firefox: Worth prototyping Edge: Positive (they also have a similar proprietary API). Safari: No signals Chromium: Origin trial

@hober brought up a good point in last week's TAG call that there is a kind of badging that happens in tabs in the background in some webapps that accumulate notification. Is this reflected in any current discussion?

Do you mean the favicon/<title> tricks to show some kind of status in the tabstrip? This is discussed a bit in Issue #1.

Or do you mean something more like Android Badging, where a badge is shown if the app has any unread notifications? This is discussed a bit here. There are other arguments for keeping the two separate in the Overview section of the explainer.

alice commented 5 years ago

I had a chat with @hober and we agreed on several points about this design:

fallaciousreasoning commented 5 years ago

We're working on integrating this into the explainer, but in the meantime to address some of your specific concerns:

In particular, was a declarative solution considered?

Yes. However, as badges may be shared across multiple documents, it was decided that this could be kind of confusing (e.g. there is a <link rel="shortcut icon badge" href="/favicon.ico" badge="99"> in the head of a document, but it is being badged with 7 because another page was loaded afterwards). There is some discussion of this here and here.

We weren't clear on why this proposal only addressed OS-level application badges and not the common pattern of decorating the favicon and/or title to display the same information in a browser tab label.

@mgiuca, @marcoscaceres and I came up with the following direction forward for having an integrated solution for tabs/app badging.

  1. All badges have a scope.
  2. Pages are badged with the most specific badge matching their scope.
  3. By default Badge.set(...) will be scoped to the current origin.
  4. The scope for a badge can be explicitly specified Badge.set(..., { scope: '/scope/to/badge/' }).
  5. For installed apps, the badge with the most specific scope which encompasses the app's navigation scope is applied to the the app's OS specific context.

This idea is being discussed (in more detail, and with examples) here. Does this seem like a good approach to you?

In a mobile app scenario, code may not be guaranteed to run unless the user is actively using the app. How does this API fit in to a mobile PWA use case?

In future, we intend the API to be available from the service worker (e.g. when a push notification occurs). However, there are still some details around privacy and security that need to be fleshed out. There is an (admittedly brief) section in the FAQ.

Given that this is ostensibly "per-app", it seems like having the Badge object hanging off Window might be misleading - it might be better suited to Navigator or Notifications.

As above, the API is now more general and not specific to apps. Also, there was a poll and developers seem to prefer APIs being accessible off window.

hober commented 5 years ago

@fallaciousreasoning could you expand on the privacy and security implications of making this API available in service workers?

fallaciousreasoning commented 5 years ago

Sure :) Our main concern at the moment is how to indicate to the user that the service worker is running. With push notifications (and presumably we would want this to be triggerable via some kind of push) we can enforce that a notification is shown, to let the user know the app is doing something in the background.

This is harder with Badging. We can enforce that the notification calls Badge.set(...) or Badge.clear(...) but this isn't enough to ensure that there is some user-visible change (and if there is, the change might be subtle enough that the user doesn't notice). For example, the service worker could continually set the badge to 5 (or clear) and it would not be obvious to the user that it was doing anything at all.

We've got a few approaches we're considering here, including a special type of push for setting the badge which specifies the badge but doesn't let you run javascript (this is what iOS does) but we're not sure how we want to jump here.

mgiuca commented 5 years ago

@fallaciousreasoning and I looked into the spec on this and it seems that the "user-visible change" requirement is underspecified and potentially specific to Chrome. Do other browsers require this too?

Service Workers §7.2 defines this as:

The userVisibleOnly member, when set to true, indicates that the push subscription will only be used for push messages whose effect is made visible to the user, for example by displaying a Web Notification. [NOTIFICATIONS]

That's all it says. It doesn't give any normative requirements about how the UA should behave when userVisibleOnly is true (Chrome apparently forcibly displays a notification if you don't). And Chrome fails the subscription if you don't set userVisibleOnly to true (which isn't mentioned in the spec). This is explained here and here.

Do other UAs a) force userVisibleOnly, and/or b) take some (unspecified) action when userVisibleOnly is true?

We can try to work around the problem of push messages requiring a "user-visible action" but it's hard to justify it from a spec perspective if this is a Chrome-only provision.

hober commented 5 years ago

Hi @fallaciousreasoning @raymeskhoury, I have a question about progressive enhancement & feature detection.

Suppose I'm a Twitter engineer. Twitter currently munges document.title to badge an unread count. I'd like to adopt Badge.set() when it's available, and I'd prefer to only fall back to my legacy document.title munging when Badge.set() won't work for me. How would such an author know when to fall back to the legacy code path?

My read of the proposal is that this isn't currently possible. That is, feature-detecting the presence of window.Badge or the Badge.set() method doesn't tell me, the website author, if calling Badge.set() will result in some kind of user-visible UI change.

marcoscaceres commented 5 years ago

As I’ve been working closely on this spec I hope it’s ok that I jump in.

@hober, not sure I follow. Setting document.title is also not observable nor guaranteed to result in a user-visible UI change. Same with setting a favicon (see Safari, for instance). I’m wondering how this is different?

I guess the fallback path would be as you suggested: 1. check for the API. 2. If not there, fallback to using title.

The above assumes that the developer can badge a browser tab, not just an installed web app. For an installed web app, a developer could check if they are “installed” by querying the CSS display-mode media feature, which is applied by the web app manifest... it’s not a perfect solution, but could do the trick.

In any case, if the Badge API is present, it implies a badge will be shown either in the dock (if app is installed) or in a browser tab (regular browser instance).

alice commented 5 years ago

In any case, if the Badge API is present, it implies a badge will be shown either in the dock (if app is installed) or in a browser tab (regular browser instance).

Ah - I think I must have misunderstood in this case. I was under the impression that implementors needn't implement support for all badging surfaces at once.

marcoscaceres commented 5 years ago

@alice, you definitely are not wrong: consider the case that @hober brought up regarding document title. Every browser supports title, but not all browsers display it. For instance, Safari in iOS on the iPhone only displays a page’s title when the user views open “tabs” in a stack view. On desktop browsers, sometimes users have so many tabs open that the browser can only show one or two letters, making the title useless as a badge fallback.

With Badge, each browser vendor will need to figure out how to best present the badge (and perhaps in constrained visual environments, or because of user preference, it may make sense to not show it at all).

fallaciousreasoning commented 5 years ago

I think @marcoscaceres has expressed this better than I could've :)

I'd just like to add that if the UA has decided not to display the badge somewhere it's probably good not to let sites know that, so they can't hack around it.

alice commented 5 years ago

I feel there has been some miscommunication here:

https://github.com/w3ctag/design-reviews/issues/387#issuecomment-519634016

if the Badge API is present, it implies a badge will be shown either in the dock (if app is installed) or in a browser tab (regular browser instance).

If implementors needn't implement support for all badging surfaces at once, then it the presence of the API necessarily does not imply a badge will be shown in a browser tab.

consider the case that @hober brought up regarding document title.

@hober was suggesting that if the tab is not successfully badged via the badging API, the author might wish to fall back to existing hacks including document title (usually as well as directly setting an alternative favicon), which are known to work under certain circumstances where the badging API may be used as an alternative if it is implemented there.

fallaciousreasoning commented 5 years ago

Whoops yes, should've been a can't. Edited.

alice commented 5 years ago

if the UA has decided not to display the badge somewhere it's probably good not to let sites know that, so they can't hack around it.

So this implies that UAs should implement support simultaneously for badging all the UI surfaces they intend to support, then?

And if, say, Chrome doesn't implement support for badging tabs, then authors should ... do what exactly?

marcoscaceres commented 5 years ago

So this implies that UAs should implement support simultaneously for badging all the UI surfaces they intend to support, then?

Not necessarily, and you raised a good point: The API (not the UI) could ship everywhere, but calling set() is a no-op.

Alternatively, and perhaps more helpfully, when .set() is called it could throw a “NotSupportedError”.

That would satisfy the fallback case, while obscuring if the badge was visually presented.

And if, say, Chrome doesn't implement support for badging tabs, then authors should ... do what exactly?

As above. Badge is a progressive enhancement after all. That’s not to say that developers (ab)using title and favicons for unsanctioned badging is a bad thing, but it’s definitely not ideal for them, users, or the browser.

mgiuca commented 5 years ago

Hi @fallaciousreasoning @raymeskhoury, I have a question about progressive enhancement & feature detection.

Suppose I'm a Twitter engineer. Twitter currently munges document.title to badge an unread count. I'd like to adopt Badge.set() when it's available, and I'd prefer to only fall back to my legacy document.title munging when Badge.set() won't work for me. How would such an author know when to fall back to the legacy code path?

My read of the proposal is that this isn't currently possible. That is, feature-detecting the presence of window.Badge or the Badge.set() method doesn't tell me, the website author, if calling Badge.set() will result in some kind of user-visible UI change.

This is a pretty important point. We probably need not only feature detection but some way to know whether the badge will be applied to the current tab or not (for example, Chrome might only badge the app icon but not apply it to the tab, so the feature would be present but not show anything in the tab strip.

Web-spec-theoretically we shouldn't expose the details of the UI to the developer (like we could say "it's none of their business whether it shows in the tab strip or not; you just give us the data and the UA will display it as they see fit"). But practically, because there are already ways to do this, the developer needs to know whether the Badge API will be seen in the tab, so they can turn off the fallback mechanisms. They're not going to want to use the Badge API if there's a chance of showing a duplicate badge with the title or favicon.

So we could do Badge.canSet() but I think we need a more advanced "will this be shown alongside the favicon and/or title?" feature detector.

hober commented 5 years ago

Note to TAG colleagues: the explainer’s been extensively updated since we last looked at this—everyone interested should take another look at it.

marcoscaceres commented 5 years ago

Just noting that I personally have concerns about the complexity of {"scope"}. I think it makes (browser) implementation quite complicated, and feel authors could use many of the existing Web APIs to achieve the same thing (e.g., broadcast channel)... however, I'd accept and support the recommendations of the TAG with respect to "scope".

mgiuca commented 5 years ago

@marcoscaceres perhaps best discussed on a new issue, but could you give detail about how broadcast channel would be applicable to the use case that we've now narrowed down "scope" to provide? ("scope" is no longer about specifying which documents show a badge, it is specifically to badge URL handles, such as apps, bookmarks and shortcuts, that may be displayed by the UA or OS when there is no document active).

mgiuca commented 5 years ago

We are discussing this on WICG/badging#51. Is there a TAG consensus on this (roughly, on the changes outlined in A Case For Separation which are expanded on with the new new explainer rewrite in that PR?

Also, which work mode would TAG prefer:

marcoscaceres commented 4 years ago

Post TPAC, I think we should update the spec as we've reached consensus on how to proceed - then update the Explainer based on that. We've gotten really excellent feedback from the TAG (with a huge thanks to @alice, who chime into various bugs, and to @hober, who helped us reshape the API into something really nice during TPAC itself!) - so I wonder if we can consider this design review as complete? @mgiuca wdyt?

mgiuca commented 4 years ago

Yes. I'm working on rewriting the explainer (again) and spec. We can close this for now and perhaps I'll re-open when both are updated.

mgiuca commented 4 years ago

Hello, I forgot to update this thread awhile back.

I rewrote much of the explainer to describe the split API, with scope removed, as proposed at TPAC (WICG/badging#55): https://github.com/WICG/badging/blob/master/explainer.md

chrishtr commented 4 years ago

@hober @mgiuca Should we re-open this TAG review then?

alice commented 4 years ago

Reopening this in light of new explainer.

alice commented 4 years ago

Oof, so sorry I put this off so long, although I did chat with Matt about my comments in person before now, at least.

In short, using Navigator to set a badge which is scoped to a single document seems odd to me.

I am happy with Navigator.setAppBadge(), and it seems like Navigator.setClientBadge() was intended to keep the document-based API as close as possible to the app-based API, short of having them be the same API which I believe was @hober and @marcoscaceres' preference.

However, I still believe the use cases for these two situations look different enough that separate APIs are warranted: in particular, that an installed application or a bookmark may have zero, one or multiple tabs/windows, whereas, a document by definition has one tab/window, and multiple instances of documents with the same URL may have different transient local state which authors may wish to expose as a badge.

That being the case, I think the two APIs being so similar will create confusion - I'd be hard placed to remember which of setAppBadge() and setClientBadge() was going to do the thing I want.

Could we have setClientBadge() as an API on Document instead, perhaps?

mgiuca commented 4 years ago

@alice Thanks for summarizing. That mostly accords with what we discussed in person. (gazes wistfully out the window ... ahhh. Back in the before times. sigh)

It's a pretty nice insight I think: we previously discussed whether the two APIs should go on Navigator or Document, but I don't think anyone (before Alice) suggested that setAppBadge should go on Navigator, while setClientBadge should go on Document, to better convey the semantics that setAppBadge is setting something external to the document, while setClientBadge is specific to the current document. I like this and would be supportive of moving setClientBadge to Document, whilst keeping setAppBadge on Navigator. (Happily, this means we won't have to change Chrome's implementation which only has setAppBadge.)

That being the case, I think the two APIs being so similar will create confusion - I'd be hard placed to remember which of setAppBadge() and setClientBadge() was going to do the thing I want.

Beyond putting them on different parent objects, I don't want to just make the two APIs different for the sake of being different. Even though they have different scope, lifetime and badge location, they both represent essentially the same data model and semantics for the badge:

I don't want to arbitrarily make the APIs different just so that users can better distinguish between the two.

But, I am supportive of moving setClientBadge and clearClientBadge to Document (or an object within).

Also @cmumford who is taking over ownership of the Badging API on the Chrome side.

marcoscaceres commented 4 years ago

Personally, I'd be inclined to leave them both on Navigator tbh... if only to keep them consistent as to where to find them. I also feel like methods on Document should affect the document tree or have a strong relationship the document itself. Although what @alice says about the relationship between .setClientBadge() and the document holds, it still feels like it's affecting something outside the document... a browser tab, a home screen icon... now I'm thinking it would more accurately be on Window, but let's not go there 🤭😂.

My 2c.

alice commented 4 years ago

Window makes sense to me, why not go there?

fallaciousreasoning commented 4 years ago

+1 to Window, conceptually that is what's being badged. Does putting it there increase the implementation complexity (or does it make getting the spec approved harder?)?

dbaron commented 4 years ago

The downside to Window is that adding things to window pollutes the global namespace, and thus has the potential (at least in some edge cases) for breaking scripts that use the name you're adding as a variable name.

alice commented 4 years ago

The other reason not to have them both on Navigator is that it's a source of confusion - I predict needing to look up every single time whether I want setAppBadge() or setClientBadge().

I think Document is defensible, if we don't want to go with Window - the title and favicon are in the document, after all.

marcoscaceres commented 4 years ago

@hober, want to cast a tie breaker or add some thoughts?

mgiuca commented 4 years ago

Yeah, I don't want to use Window just because it pollutes the global namespace.

I think it's important to consider sometimes that the mechanics of these things can be more important than the names. Even if "window" is the right name for this, it's mechanically problematic. These things go way way back to the history of the web, so the best thing to do is shrug and say "they have the wrong names, for historical reasons". Modern web design should consider Window to mean "the global top-level namespace" and Document to mean "the object that represents the current document and its window". New APIs should only go in Window if they're fundamental things that should be available automatically, like a new array type, not a new API that will be called in one very special place across the entire site.

hober commented 4 years ago

I don't have a strong preference between document and navigator.

hober commented 4 years ago

I think this review has run its course, so I'm going to close it. Please let us know if anything changes and you'd like to re-open it. Thanks!