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

Explainer: Separate APIs for URL-scoped badge vs document badge #51

Merged
merged 14 commits into from
Oct 17, 2019

Conversation

mgiuca
Copy link
Collaborator

@mgiuca mgiuca commented Aug 30, 2019

@fallaciousreasoning could you have a look at this rewrite for the separation model?

explainer.md Outdated

```js
Badge.set(getUnreadCount());
Badge.setForDocument(getUnreadCount());
Copy link
Member

Choose a reason for hiding this comment

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

I wonder if we can can imply "document" if {scope} is missing?:

// document
Badge.set(5);
// some explicit scope
Badge.set(5, {scope: ""});

Copy link
Collaborator

Choose a reason for hiding this comment

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

What about browsers where setting a document Badge is not supported?

Would Badge.set(5); throw an error while Badge.set(5, { scope: '/' }); would not? This seems pretty weird to me. If not, how would we feature detect (to allow pages to fallback to some favicon/title polyfill)?

Copy link
Collaborator

Choose a reason for hiding this comment

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

On a separate note, I'm not convinced that document badges are the most natural default. Most of the time, a developer's intention is probably to badge all pages in an app (note: I don't mean a PWA here, I mean a conceptual group of pages that a user would consider an app. https://facebook.com, https://twitter.com, https://github.com, https://google.com/maps, https://outlook.com, https://mail.google.com ect). Except for weird edge cases (maps), the most useful default looks like the origin.

Maybe we should open an issue for this, we've bumped up against this a couple of times.

Copy link
Member

Choose a reason for hiding this comment

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

What about browsers where setting a document Badge is not supported?

That's something I hope we can avoid. At a minimum, document level badging should be supported, with scope level badging being optional...

On a separate note, I'm not convinced that document badges are the most natural default. Most of the time, a developer's intention is probably to badge all pages in an app .

Heh, I take the opposite view :) P-WAs are, after all, "Progressive" enhancements... "installed app" is never a default state of an application. In the rare case that an application is promoted to "installed", then that's great for the app - in that {scope: "path"} would work.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Heh, I take the opposite view :) P-WAs are, after all, "Progressive" enhancements... "installed app" is never a default state of an application. In the rare case that an application is promoted to "installed", then that's great for the app - in that {scope: "path"} would work.

I don't mean for an installed application ("app" is super overloaded term, I probably shouldn't've used it). I mean that conceptually, it is 'Facebook' that has an unread count, not each individual facebook.com tab. Even without installable PWAs there's a 'Facebook' thing that has a notification count (and I don't think that's a single open tab).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That's something I hope we can avoid. At a minimum, document level badging should be supported, with scope level badging being optional...

The point of this PR (and the direction we're trying to take the API with) is that, after a lot of discussion with many stakeholders (including the TAG review) we realised that these are just two separate APIs with very different properties (one is global, the other is document-local; one has a lifetime beyond that of the document, the other's lifetime is tied to the document; one works from service workers, the other is meaningless in that context).

Given that we have basically identified two different APIs, I don't think user agents need to support one of these APIs before they support the other. We don't initially intend to implement the document-level badging API because it doesn't fit with our priorities, as you don't initially intend to implement the scope-level API. I think these things can exist independently.

Copy link
Member

Choose a reason for hiding this comment

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

Apologies, I hadn't seen any updates to w3ctag/design-reviews#387 ? Was that discussion happening elsewhere (particularly around splitting the two APIs)?

I can definitely live with that (as it's good during this incubation phase!), but it does feel a bit odd/confusing that we will have two APIs that basically do very similar things.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sorry, maybe you were out of that loop.

It's something we discussed offline with @alice (from TAG) and then as a result of that, we added this section to the current explainer. (I somehow thought you were part of this discussion because I thought you were pushing for separate APIs from earlier on when I was trying to combine them.)

This PR is just me taking the "case for separation" part of that explainer and updating the rest of the document to do what it suggested.

The main motivation for this was a) the fact that a combined API had a complicated feature detection story (as discussed in the recent comments on the TAG review) and b) the complexity of dealing with nested scopes applied to pages --- we still have nested scopes in the new proposal, but they only apply to "handles" so you are much less likely to have a complex nesting of badge scopes since if you just want to badge individual pages you'll just use the document API.

I can definitely live with that (as it's good during this incubation phase!), but it does feel a bit odd/confusing that we will have two APIs that basically do very similar things.

It does a bit, but we'll spec them together in one document (they won't be "separate APIs" but just separate methods), and I think we have a good story for what the differences are. (If we let scopes apply to pages and the document API just overrides that, then it becomes murkier and harder to reason about, which is why I favour a clean separation where the scope API does not badge active documents at all, just inactive handles like app icons.)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@marcoscaceres Do you have any final thoughts (veto?) about this before I merge?

Copy link
Member

Choose a reason for hiding this comment

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

Just going through the document now. However, I'm still wondering if the TAG as a whole will take a position on this, as opposed to individual TAG members? for instance, I've also be talking to @dbaron about scope and concerns about complexity (but don't preclude David reaching a different position to mine) - hence asking for a TAG position that would close w3ctag/design-reviews#387.

Copy link
Collaborator

@fallaciousreasoning fallaciousreasoning left a comment

Choose a reason for hiding this comment

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

Mostly LGTM with some comments/nits.

explainer.md Outdated

```js
Badge.set(getUnreadCount());
Badge.setForDocument(getUnreadCount());
Copy link
Collaborator

Choose a reason for hiding this comment

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

What about browsers where setting a document Badge is not supported?

Would Badge.set(5); throw an error while Badge.set(5, { scope: '/' }); would not? This seems pretty weird to me. If not, how would we feature detect (to allow pages to fallback to some favicon/title polyfill)?

explainer.md Outdated

```js
Badge.set(getUnreadCount());
Badge.setForDocument(getUnreadCount());
Copy link
Collaborator

Choose a reason for hiding this comment

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

On a separate note, I'm not convinced that document badges are the most natural default. Most of the time, a developer's intention is probably to badge all pages in an app (note: I don't mean a PWA here, I mean a conceptual group of pages that a user would consider an app. https://facebook.com, https://twitter.com, https://github.com, https://google.com/maps, https://outlook.com, https://mail.google.com ect). Except for weird edge cases (maps), the most useful default looks like the origin.

Maybe we should open an issue for this, we've bumped up against this a couple of times.

explainer.md Outdated
specific set of URLs, and not the whole site, use the `scope` option (which
might be done if you have a different "unread count" on each page):
All of the above set the badge *only* on the current document (e.g., in the page
tab), and won't badge installed apps that have no window open. To set a badge
Copy link
Collaborator

Choose a reason for hiding this comment

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

This paragraph is a bit confusing.

  • unclear what "e.g. in the page tab" means? The favicon?
  • "won't badge installed apps that have no window open". I take it you mean we could badge the window icon if we wanted, but it took a while to parse.

All of the above set the badge only for the current document. They will not badge [link to os specific contexts document or handles or whatever]. To set a badge that applies to apps and other "handles":

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

  • unclear what "e.g. in the page tab" means? The favicon?

It's deliberately vague. It doesn't have to appear on the favicon, just somewhere in the page tab (or window border, etc).

  • "won't badge installed apps that have no window open". I take it you mean we could badge the window icon if we wanted, but it took a while to parse.

Yeah, OK, reworded as "won't affect any other documents, even those at the same URL".

explainer.md Outdated
More advanced examples are given in a [separate document](docs/examples.md).
As above, a value of 0 clears the badge and `Badge.clearForScope` can also
explicitly clear the badge for this origin. The effects of the scope API are
global and may outlast the document (it is intended to persist until the user
Copy link
Collaborator

Choose a reason for hiding this comment

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

Not sure about "It is intended to persist until the user agent closes". It's fine for it to persist longer, though this may only be an option on certain operating systems.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Added "at least".

explainer.md Outdated Show resolved Hide resolved
explainer.md Outdated Show resolved Hide resolved
explainer.md Outdated

```js
if (Badge.canBadgeDocument()) {
Badge.set(getUnreadCount(), {scopeDocument: true});
if (Badge && Badge.setForDocument) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

It just occurred to me but this will break if Badge is not defined. You need to check window.Badge or you'll get an Uncaught ReferenceError

(try !!some_variable_that_does_not_exist in your console)

Change to

if (window.Badge && Badge.setForDocument) {
...
}

or alternatively

if ('Badge' in window && Badge.setForDocument)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed to the former.

explainer.md Outdated

* Documents are badged with the most specific badge for their URL (i.e. prefer a badge for `/page/1` to a badge for `/page/` when on the url `/page/1?foo=7`).
* For [installed applications](https://www.w3.org/TR/appmanifest/#installable-web-applications), a user agent **MAY** display the badge with the most specific scope still encompassing the [navigation scope](https://www.w3.org/TR/appmanifest/#navigation-scope) of the application in an [OS specific context](#OS-Specific-Contexts).
* A document is only badged by a badge associated with that document (not by
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we need this restriction? I think it would be fine if the document badge overrode the scope badge. Or is this to make setting the badge via favicon hacks not get into weird situations?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Added a paragraph explaining why this restriction is required.

If we don't have this restriction, we may as well keep the two APIs combined into one. Yes, it brings back the feature detection problem for favicon hacks. It also takes control away from individual documents about when and how they want to be badged (there is no way to have certain documents have no badge, when the outer scope is badged).

explainer.md Outdated
* For [installed applications](https://www.w3.org/TR/appmanifest/#installable-web-applications), a user agent **MAY** display the badge with the most specific scope still encompassing the [navigation scope](https://www.w3.org/TR/appmanifest/#navigation-scope) of the application in an [OS specific context](#OS-Specific-Contexts).
* A document is only badged by a badge associated with that document (not by
scope-associated badges).
* For [installed applications](https://www.w3.org/TR/appmanifest/#installable-web-applications), a user agent **MAY** display the badge with the most specific scope encompassing the [navigation scope](https://www.w3.org/TR/appmanifest/#navigation-scope) of the application (e.g. prefer a badge for `/apps/x/` to a badge for `/apps/` for an app with scope `/apps/x/`) in an [OS specific context](#OS-Specific-Contexts).
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: I don't know how I feel about the flowing here. I think we should consistently break on 80 or consistently not (I lean towards not because my text editor wraps, and it makes the diffs easier to read but it's up to you).

Probably for a separate PR.

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 don't think it matters that much since it isn't visible to the reader.

My editor is set to auto-wrap and highlight long lines, for code editing:

image

So it depends on your workflow. I'm happy to just leave it ad-hoc; I don't think we need to have a "coding style" for a markdown file.

It doesn't affect the readability of the diff, since either way in the worst case you need to see a full - and + for a whole paragraph.

```

When displaying the badge for an app, the user agent should use the badge
matching the app's [scope URL](https://www.w3.org/TR/appmanifest/#scope-member).
More advanced examples are given in a [separate document](docs/examples.md).
Copy link
Collaborator

Choose a reason for hiding this comment

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

You probably need to update examples.md too

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'll do that later, depending on whether we commit to this.

@mgiuca mgiuca changed the title Separation Explainer: Separate APIs for URL-scoped badge vs document badge Sep 2, 2019
explainer.md Outdated
are deliberately agnostic about which contexts a badge can appear in, but have
two fairly different contexts in mind:
are deliberately agnostic about which contexts a badge can appear in, but there
are two major categories of context that will be supported:
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
are two major categories of context that will be supported:
are two major categories of context that we would like to support:

As this feature is UI heavy, I need the document to be framed in a manner that I can pitch internally to our Firefox Product Team as a proposal. I.e., it can't be read like "this is how it's going to be", as the Product team will actually decided what gets implemented in Firefox.

I know this is different than how Google/Chrome teams work... and Firefox may opt not to support the scoping stuff if we find it too complicated to implement/invest time in over other web features.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Note that "supported" here refers to the functionality that would be supported if everything in this document was implemented. It doesn't make any claims about implementations supporting it. And these two sides to the API are designed to be implementable independently (neither reqiures the other). So I don't see any conflict here with Firefox's plan to not (initially) support scoping side of the API.

I'm not sure if this is just about this sentence, or more general. In general, I don't see the point of rewriting "we will do X" sentences as "we would like to do X". By definition, every sentence in the proposal is conditional on the proposal being accepted.

To resolve this, I've rewritten it as "we are specifying methods to handle two major different categories of context".

Firefox may opt not to support the scoping stuff if we find it too complicated to implement/invest time in over other web features.

I think that would be fine, if you don't plan to support app badging (just document badging). That is the intention: if you are only badging documents while they are open, just implement the "ForDocument" methods. If you want to have persistent badges on shortcuts to websites while the site itself is not open (e.g., installed apps, but you could also apply the badge to other shortcuts such as links on the desktop, bookmarks, etc), then you implement the "ForScope" methods.

For that latter use case, we are all open to any proposal that lets us get away with not tying the badge to a URL scope. But nobody has suggested any. This is not a solution in search of a problem. We have a very clear problem: allow a site to set a semi-permanent badge on the icon of an installed web app, which persists even after the last window closes, and can be set by a service worker when no windows are open. Scoped URLs is our take on the solution.

explainer.md Outdated

```js
Badge.set(getUnreadCount());
Badge.setForDocument(getUnreadCount());
Copy link
Member

Choose a reason for hiding this comment

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

Just going through the document now. However, I'm still wondering if the TAG as a whole will take a position on this, as opposed to individual TAG members? for instance, I've also be talking to @dbaron about scope and concerns about complexity (but don't preclude David reaching a different position to mine) - hence asking for a TAG position that would close w3ctag/design-reviews#387.

This was referenced Sep 16, 2019
Copy link
Member

@marcoscaceres marcoscaceres left a comment

Choose a reason for hiding this comment

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

some suggestions....

explainer.md Outdated Show resolved Hide resolved
explainer.md Outdated Show resolved Hide resolved
explainer.md Outdated Show resolved Hide resolved
explainer.md Outdated Show resolved Hide resolved
explainer.md Outdated Show resolved Hide resolved
explainer.md Outdated Show resolved Hide resolved
explainer.md Outdated Show resolved Hide resolved
explainer.md Outdated Show resolved Hide resolved
* `Badge.clear([options])`: Clears the badge for the scope in *options*.
* `Badge.canBadgeDocument()`: Returns true if the user agent would display a
badge applying to a document scope on or near the page's favicon.
The Badge API methods are members of interface is a member object on
Copy link
Member

Choose a reason for hiding this comment

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

I think the API definition is redundant now (all of this has already been mentioned above)... plus it's starting to look like a spec. We should just add to the spec. Risk is that this explainer will quickly fall out of date.

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 think (at least for now) this serves a useful purpose of being in between the usage examples and the (non-existent) spec.

The usage examples show the basic usage but don't describe what the methods do and their arguments.

The spec will be very dense and state algorithms, not an informal description.

I like having an informal description of the methods (which is why I deleted the WebIDL and went back to this "conversational" documentation. Eventually this should be the role of MDN or similar, but for now, I'd like to keep it here.


## Security and Privacy Considerations
The API is set only, so data badged can't be used to track a user. Whether the API is present could possibly be used as a bit of entropy to fingerprint users, but this is the case for all new APIs.
The API is write-only, so data badged can't be used to track a user. Whether the API is present could possibly be used as a bit of entropy to fingerprint users, but this is the case for all new APIs.
Copy link
Member

Choose a reason for hiding this comment

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

We should probably mention that it's only exposed in secure contexts and not available to third-party iframe unless explicitly granted by feature policy.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Secure contexts: Done

Third-party iframe: We actually do allow this, but if you call the method from an iframe, you set the badge on the iframed contents' origin, not the containing page. This seems reasonable to me.

Copy link
Member

Choose a reason for hiding this comment

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

Third-party iframe: We actually do allow this, but if you call the method from an iframe, you set the badge on the iframed contents' origin, not the containing page. This seems reasonable to me.

heh... I kinda like that :) We might need to keep some kind of open issue around this as I have a feeling it's going to come up for discussion. I think the main pushback we will get from this API is that it risks high user annoyance, so we need to have a good story in place for third-party iframes.

@mgiuca
Copy link
Collaborator Author

mgiuca commented Oct 10, 2019

This is finally ready for review again! (Though I see @marcoscaceres has already taken the liberty.)

I'll get to those comments tomorrow. Also see the new comment on #55 where Jay and I hashed out in more detail the "link rel versus most specific scope" question, and came to the same conclusion as we did 2 weeks ago with Marcos, but with more confidence.

@mgiuca
Copy link
Collaborator Author

mgiuca commented Oct 11, 2019

Pushed a new version taking @marcoscaceres feedback into account.

Copy link
Member

@marcoscaceres marcoscaceres left a comment

Choose a reason for hiding this comment

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

This seems to capture nicely where we are at with the incubation process. Feel free to merge if you are happy with it.

@mgiuca mgiuca merged commit 8508df0 into w3c:master Oct 17, 2019
@marcoscaceres
Copy link
Member

Really excited about this. Thanks @mgiuca and @fallaciousreasoning for bring it all together. I'll keep pushing to get it on the roadmap on the Firefox side.

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

Successfully merging this pull request may close these issues.

3 participants