Skip to content

Should <meta name=accept-ch content> be parsed like HTTP Permissions-Policy or HTML allow? #108

Description

@eeeps
  • The spec (step 11) points to Permissions Policy's Parse a policy directive algorithm, which parses the HTML allow attribute.
  • allow has a different syntax than the HTTP Permissions-Policy header, which relies on Structured Field parsing.
  • Chrome is shipping with <meta name="accept-ch"> syntax that resembles Permissions-Policy/Structured Fields, with at least one subtle difference: origins can't be quoted, as sf-strings are.

Here's what I got to work in shipping Chrome:

<meta name="accept-ch" content="sec-ch-dpr=(self https://o.img.rodeo https://res.cloudinary.com), sec-ch-width=(self https://o.img.rodeo https://res.cloudinary.com)">

Here's what I would expect, based on the spec:

<meta name="accept-ch" content="sec-ch-dpr 'self' https://o.img.rodeo https://res.cloudinary.com; sec-ch-width 'self' https://o.img.rodeo https://res.cloudinary.com">

(although I'm not 100% on what quotes go where, honestly. luv 2 interpret ABNF...)

I see three ways forward:

  1. Chrome changes its implementation to match the spec, using theallow parsing rules (too late?)
  2. The spec changes, so that the content attribute is parsed using the Permissions-Policy sf-header rules, and Chrome updates its implementation to eliminate any subtle differences (e.g. sf-string quoting... perhaps others?)
  3. The spec changes to document the <meta name="accept-ch"> parsing rules that are shipping in Chrome, which match neither allow nor Permissions-Policy.

I'd prefer 1 over 2 over 3, but if there's any usage, we may be stuck with 3.

Activity

  1. arichiv commented on Apr 20, 2022

    @arichiv
    Collaborator

    I think 3 is most likely, I'll take a stab at that Friday.

  2. arichiv commented on Apr 20, 2022

    @arichiv
    Collaborator

    I think 3 is most likely, I'll take a stab at that Friday.

    To elaborate on reasoning:
    (1) We not only ignore * in the meta tag, but don't override a default/http-header policy of * no matter how the meta tag is defined.

    Permissions-Policy: ch-dpr=*
    +
    <meta name="accept-ch" content="sec-ch-dpr=(https://foo.bar)">
    =
    ch-dpr=*
    

    (2) We not only ignore self in the meta tag, but don't remove self as a valid target if it's in the default/http-header policy no matter how the meta tag is defined.

    Permissions-Policy: ch-dpr=(self)
    +
    <meta name="accept-ch" content="sec-ch-dpr=(https://foo.bar)">
    =
    ch-dpr=(self "https://foo.bar")
    

    (3) We only read the new list of hosts for each policy, and append it to the list that already exists.

    Permissions-Policy: ch-dpr=(self "https://foo.bar")
    +
    <meta name="accept-ch" content="sec-ch-dpr=(https://baz.qux)">
    +
    <meta name="accept-ch" content="sec-ch-dpr=(https://dead.beef)">
    =
    ch-dpr=(self "https://foo.bar" "https://baz.qux" "https://dead.beef")
    

    We are very deliberately providing something short of a true permissions policy and really need to document it.

  3. self-assigned this
    on Apr 20, 2022
  4. eeeps commented on Apr 21, 2022

    @eeeps
    CollaboratorAuthor

    Is there any precedent for serializing:

    [key1: [value1, value2,...], key2: [value1, value2...]]

    ...into an HTML attribute? allow is the only one I can think of. I get the argument that we don't want it to look like allow because it doesn't work like allow, but inventing something new that looks almost like Permissions-Policy but doesn't work like Permissions-Policy doesn't feel great either. But again, shipping/usage may make that moot.

  5. eeeps commented on Apr 21, 2022

    @eeeps
    CollaboratorAuthor

    I suppose srcset with multiple descriptors is shaped like this, and just like allow, relies on white-space + comma separation, and order.

    srcset="a.jpg 300w 200h, b.jpg 600w 400h, c.jpg 1200w 800h"

    So is style, which is just CSS, which is its own little universe of DSLs and not really relevant, other than to say, putting other serializations (like Permissions-Policy's) into HTML has precedent.

    style="font-family: system-ui, sans-serif; margin: 2em 1em;"

  6. eeeps commented on May 6, 2022

    @eeeps
    CollaboratorAuthor

    @arichiv Is there any usage of the new <meta> yet?

    Cloudinary, for one, is still well-situated to update our recommendations to customers, if the syntax changes. We haven't published docs or a blog post and have yet to reach out to many customers. But that door is closing.

    For the (hopefully many) developers who try to implement HTML hint delegation in the future, I'd rather we end up with a less confusing syntax. Here are things I find tripping people up about it:

    • The <meta> has a name of accept-ch but doesn't interact with the accept-ch cache or use the accept-ch HTTP header syntax. Also, authors aren't expressing what hints they'll accept, but rather asking the user-agent to send hints to trusted third parties. This "who is accepting what?" ambiguity seems to have caused some of the confusion present in the TAG review. Would a name like delegate-ch make more sense?
    • The content looks a lot like the Permissions Policy Structured Headers syntax, but it isn't. As you point out, it's doing something very different; perhaps it should look even more different. As it stands I've already seen people try to copy and paste Permissions-Policy header values into this <meta content>, and fail.
    • There's no precedent for a Structured Headers syntax in HTML.
    • This isn't even valid Structured Headers syntax, due to the quoting of strings.

    @arichiv do you agree with any of that? Is the door to changing Chrome's implementation already closed? Again, I'm most of all excited that this functionality exists. Existing >>> it being perfect, or even all that easy to learn/teach (most of our customers will be copy/pasting from our docs). And sincere apologies for swooping in with criticism late, after having ample opportunity to review earlier, after Chrome already shipped!

  7. arichiv commented on May 10, 2022

    @arichiv
    Collaborator
    1. We wanted to use accept-ch because it's not just delegating (changing permissions policies) but requesting the hint be shared the same way the HTTP header does.
    2. I still need to update the spec to reflect the actual syntax, sorry for the delay on that.
    3. I still think the right choice is unifying the Permissions-Policy and Accept-CH headers into the meta tag's syntax. Long term, we probably want a meta tag for Permissions-Policy generally, but I don't think that's in the cards in the near future.
    4. I could add support for quoted strings, that would unify the syntax to a greater extent, but of course the naming (sec-ch-* vs ch-*) and the tokens allowed (no * or self) still prevent copying.

    @yoavweiss wanted to get your take on the above ideas as well, it's true the place we ended up is kinda weird.

  8. eeeps commented on May 26, 2022

    @eeeps
    CollaboratorAuthor

    Any progress? M104 is getting closer and Cloudinary has paused our customer outreach efforts until this is settled.

  9. arichiv commented on May 27, 2022

    @arichiv
    Collaborator

    Sorry for the delay, Yoav and I are slated to discuss next week. As long as the change is parsing only, there will not be an issue making M104. Additionally, if there is a parsing change we will support the current format for at least a milestone and add counters to detect when it's safe to remove.

  10. arichiv commented on May 31, 2022

    @arichiv
    Collaborator

    Okay @yoavweiss and I talked, we have four options:

    1. Keep current format
    • <meta name="accept-ch" content="sec-ch-dpr=(https://foo.bar/), sec-ch-width=(https://foo.bar/)">
    1. Support quotes (like PermissionsPolicy HTTP Header)
    • <meta name="accept-ch" content="sec-ch-dpr=("https://foo.bar/"), sec-ch-width=("https://foo.bar/")">
    1. Support allow like format
    • <meta name="accept-ch" content="sec-ch-dpr https://foo.bar/; sec-ch-width https://foo.bar/">
    1. Require http-equiv accept-ch and add delegate-ch
    • <meta http-equiv="accept-ch" content="sec-ch-dpr, sec-ch-width">
    • <meta name="delegate-ch" content="ch-dpr https://foo.bar/; ch-width https://foo.bar/">

    We're leaning toward moving back the CH-Legacy-Mode change to M105 to have longer to discuss, and will be considering disabling the name="accept-ch" (not the http-equiv="accept-ch") in M104 while we consider. Options 1 and 4 are likely the best ones, but we'll be running this by TAG as well.

    https://bugs.chromium.org/p/chromium/issues/detail?id=1330554

  11. miketaylr commented on May 31, 2022

    @miketaylr
    Collaborator

    @eeeps would be interested in your thoughts to the options above. 🙇

  12. eeeps commented on Jun 1, 2022

    @eeeps
    CollaboratorAuthor

    @arichiv Thanks for working on this and @miketaylr thanks for the ping!

    Thanks also for the updates re: timelines!

    Seeing them laid out like this, option 2 seems by far the worst, because you'd have to single quote the HTML attribute or I guess use &quot;s; which seems, at best, weird, and at worst, incompatible with anything (?) that assumes HTML attributes don't contain quotes. I totally get why you removed quotes from the shipping implementation...

    I will also feel bad if this issue results in option 4, if only because, while I get that they're currently separate mechanisms, I don't see why an author would ever delegate without enabling (see: #23), and was excited that the initial proposal here rolled the two actions into one.

    Between 1 and 3 I'd go with option 3, purely because it has the HTML-iest feel to it. I don't see the benefit of adopting a structured-headers-ish syntax in an HTML attribute.

    I hesitate to do this but perhaps I could present... option 5?:

    <meta name="send-ch" content="sec-ch-dpr https://foo.bar https://baz.qux; sec-ch-width https://foo.bar" />

    • send-ch name:
      1. Does what it says. We're asking the browser to send certain hints to certain origins within this document, not advertising that we (or anyone else) accepts hints.
      2. Doesn't look like <meta http-equiv=accept-ch>, clarifying that this works differently (no Accept-CH-Cache interactions, performing enablement + delegation in one...).
    • Allow-esque format, with hint names (not feature names) as keys:
      1. Parses in an HTML-y way (splitting on U+003B and then whitespace), yay no new microsyntaxes.
      2. Doesn't look like a Permissions-Policy, clarifying that it works differently (can only append origins, can't do anything with self or *).
  13. arichiv commented on Jun 1, 2022

    @arichiv
    Collaborator

    5 is the same as 3 but with a different name right? The one point of confusion we foresee is that it looks like allow syntax but rather than use policy names (ch-dpr) it uses the actual hint names (sec-ch-dpr). This makes sense as we aren't just delegating hints, but requesting hints as well. However, it's still a point of difference from the allow syntax.

  14. eeeps commented on Jun 1, 2022

    @eeeps
    CollaboratorAuthor

    @arichiv Yeah. And that's valid; I'm worried about folks mistaking it for Permissions-Policy; I should also worry about it looking like allow. I'm less worried because I think allow looks more like other things in HTML, I think.

    A rough survey of a few people and a quick tour through the HTML spec indicates that while spaces are the most common way to delimit lists in HTML, commas come in a close second. Maybe we could further differentiate by changing that second-level delimiter?

    And @zcorpan pointed me to whatwg/html#2335, which, while unresolved, seems relevant.

    [noises from the bikeshed intensify]:

    <meta crossoriginclienthints="sec-ch-dpr https://foo.bar https://baz.qux, sec-ch-width https://foo.bar">
    
  15. 7 remaining items

  16. added a commit that references this issue on Jun 14, 2022
    5c39d3a
  17. arichiv commented on Jul 7, 2022

    @arichiv
    Collaborator

    Heads up that in M105 not only will the new http-equiv="delegate-ch" syntax be added, but the older name="accept-ch" syntax will be removed. The even older http-equiv="accept-ch" that does not support delegation will not be touched as usage is too high.

  18. zcorpan commented on Jul 7, 2022

    @zcorpan

    Heads up that in M105 not only will the new http-equiv="delegate-ch" syntax be removed

    Did you mean supported?

  19. arichiv commented on Jul 8, 2022

    @arichiv
    Collaborator

    Heads up that in M105 not only will the new http-equiv="delegate-ch" syntax be removed

    Did you mean supported?

    Very sorry yes, meant to say 'added'. The comment has been updated

  20. jonarnes commented on Sep 13, 2022

    @jonarnes

    Just to recap, a new syntax like the following will be introduced

    <meta http-equiv="delegate-ch" value="sec-ch-dpr https://foo.bar https://baz.qux; sec-ch-width https://foo.bar">
    

    in M105. No changes to the M104 launch schedule will occur.

    Just a note on the actual implementation vs. the syntax described in this thread and and elsewhere :

    It's the content attribute that holds the client hints, not value. A working opt in would be:

    <meta http-equiv="delegate-ch" content="sec-ch-dpr https://foo.bar https://baz.qux; sec-ch-width https://foo.bar">
    

    Hopefully this saves some time/frustration...

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions