-
Notifications
You must be signed in to change notification settings - Fork 162
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
Web Manifest Overrides #1045
Comments
Thanks, @marcoscaceres, for doing the grunt work of summarizing all proposals so far. Boy, this space is complex. Regarding Purpose-built objects and members, it's not clear if your proposal would require CSS user preference media query parsing or not, since in your proposal you mention two ways: {
"color": "darkred",
"media": "(prefers-color-scheme: dark)"
} {
"other_icons": [{
"src": "/icons/play-later.svg",
"scheme": "dark"
}]
} Can you clarify? |
An extensible concept of manifest overriding sounds ideal to me if its syntax can accomodate all potential use cases. "conditional_overrides": [
{
"condition": <predicate>,
"path.to.manifest.field": <override value>,
...
},
...
] I'm somewhat skeptical an acceptable syntax can be found though. |
Thanks for putting this all together Marcos!
The main problem that I’m trying to solve with a dark theme_color is that currently when you open an app, you’ll see a flash of the manifest theme_color before the browser loads and the html theme_color takes over. If we have a media query for the theme_color we would still need to wait for the browser in order to evaluate the media query. So your point that media queries don't work for icons also applies here. Therefore I think we should use the |
Thanks Marcos! Seconding what @loubrett said: one of the main objections to using the MQ syntax is that it can't be processed without a browser engine. Given that we're open to using the simplified syntax for icons, I hope we can extend that to the other members too (not just because we need to process them without a browser, but also for consistency). @alancutter : my feeling is that we've spent a lot of energy trying to generalize this problem and have not come up with an acceptable syntax for quite some time. Sometimes, solving the specific problem you are trying to solve is better than finding a general solution to all conceivable problems (in particular, it means that we don't have to handle "ridiculous" cases that nobody will ever need, like making the name conditional on color scheme, or the theme_color conditional on language, and we can solve specific more complex problems, like icons that may need to be conditional on both, on a case-by-case basis). So I'm overall in favour of Marcos' purpose-built members. And excited that we appear to be headed towards consensus. If I may introduce a little bikeshedding: I think we can come up with a consistent naming scheme to avoid having So I would propose sticking with a consistent This isn't a hill to die on; I'm happy with any naming that lets us move forward, so treat this as a suggestion. |
+1 on not relying on property order. The JSON spec explicitly defines its objects as having unordered members and though most JS objects implement [[OwnPropertyKeys]] as OrdinaryOwnPropertyKeys and that usually would match source text order, even OOPK has an exceptional case that makes it poorly suited for stuff like this: |
This is a debate we've had many times on this spec :) I've carefully read the two (!) JSON specs and I think both of them are sufficiently vague as to whether we can actually rely on the order that objects define their members. Suffice to say, some JSON parsers preserve the order, many do not. I would very strongly prefer that when we write JSON-based formats like manifest, we do not rely on the order of dictionary keys (Marcos' final proposal here does not). Further, I would prefer that we treat objects in precisely one of two ways:
All of the objects in this proposal are "struct" type, so that's good with me. |
Oh, wild! I see what you mean about ECMA-402: it makes no semantic assertion about order and expressly permits other specs /implementations to overlay their own. I’m not sure what makes RFC 7159 vague since “An object is an unordered collection of...” is about as unambiguous as a semantic assertion can get — is that text not actually normative or something? In any case I hadn’t realized they conflicted on this and appreciate the info. |
@tomayac wrote:
You are spot on and this is exactly what we need to discuss. @alancutter wrote:
Same, why I proposed just skipping all that and just using "whatever_members" express the same semantics by hard-coding the solution. And 💯 to everything @mgiuca said on the matter. @loubrett wrote:
Got it. But hat will happen no matter what if there is a mismatch between the manifest and the HTML. Consider:
The solution is make sure the HTML theme is set via: <meta name="theme-color" media="(prefers-color-scheme: dark)" content="yellow">
<meta name="theme-color" media="(prefers-color-scheme: light)" content="blue"> (Or just leave it to the manifest to do its thing… only include the theme colors if not installed)
Sorry, let me try to be more clear. I’m proposing that the MQs are evaluated and (statically) transformed at install time, not evaluated at start/runtime. So:
Implementations already take “static snapshots” of things in the manifest and convert them to OS equivalent data: in particular The .2 above is the non-trivial part, and @mgiuca is raising valid concerns about. @mgiuca wrote:
Right. That's why I was proposing the browser convert the MQ to a static representation at install time, like we do with the color members. The valid question/concern is: how difficult is it going to be to do that? Putting on my WebKit hat for a second, and having chatted with @dcrousso, we think it could be doable… but we would need to check how insane MQs could get and how much trouble it is to translate them to OS equivalents… it’s on us (WebKit folks) to show that it would work and it’s not insanely complicated. On the other hand, if it does all get too crazy, falling back to a simple The motivating factors on the Webkit side are:
@mgiuca wrote:
Something like that would work... the other reason I chose |
About "other_", just want to be clear that was not a serious proposal... I was just coming up empty with what to call those 🫠 |
@bathos :
Yeah you're right I think: RFC 7159 does seem fairly opinionated that the objects' order should not matter (later on it says "JSON parsing libraries have been observed to differ as to whether or not they make the ordering of object members visible to calling software. Implementations whose behavior does not depend on member ordering will be interoperable in the sense that they will not be affected by these differences.". I don't know where I got the impression that it allowed the order to matter.
Yes, but the idea is that there should not be a mismatch between the manifest and HTML. If there is a mismatch, there will be a flash. All we are trying to do is make it possible for developers to write an app that has no mismatch. I think what you are suggesting here is that the manifest parser (at parse time, not at app load time) runs the MQ parser with both a dark and light context, and then stores the result in an OS-specific context. That is theoretically possible (though it still creates a non-trivial dependency between the manifest parser and CSS parser which did not exist before). But it still has a number of issues:
I can see the appeal of using MQs for this instead of "inventing a new wheel", but this really feels like using a sledgehammer when we need tweezers. We have a fairly simple feature request (be able to make manifest options conditional on theme colour and language), and while the CSS MQ can do the former, it can't (yet) do the latter, and it can do so many other things we don't want. |
Hi Marcos, As discussed today, we're looking forward to seeing a concrete proposal using media queries, and @loubrett will provide a concrete proposal using the lightweight per-purpose syntax. There are a few questions I'd like to see answered in the detailed MQ proposal:
Note that I'm focusing a lot on the implementation because my main concern here is that the MQ proposal adds significant complexity to the browser vendor. While I agree that when there is a trade-off between ease of use for the web developer vs ease of implementation for the browser vendor, the developer should win, there is a limit to this. IMO the benefit to the developer of MQ vs the per-purpose syntax would have to be shown to be extremely valuable to outweigh the large implementation overhead, or I would need to better understand how the implementation is not as complex as I think it is. (So before we go down the path of quantifying the benefits and costs, I'd like to have a clear picture of how you think a browser should implement this feature.) Thanks and looking forward to chatting further. |
In the non-CSS-parsing model, I’m curious whether there could be alignment with User Preference Media Features Client Hints Headers? They’re an existing spot where media query data is decoupled from media query syntax, anyway, and since I didn’t see em mentioned in the thread, figured it might be worth a link just in case there’s something useful there. |
CC: @beaufortfrancois who has implemented |
@bathos that's a cool idea to align on this. (To be clear: I don't think that we can use the UPMF Client Hints header for this use case, because we want it encoded in the manifest so it doesn't require a round-trip to the server at all to update the theme colour based on the user's mode preference. But I think what you're saying is that there's precedent for having a subset of MQ selectors without using the CSS MQ syntax.) I think what this precedent shows is that:
Both of those points apply to the manifest as well. What that suggests to me is that a proposal here that avoids using MQ syntax should still use the exact name |
Yep! Though I suspect it could also lead to a nice kinda symmetry story if implementing fallback/robustness behaviors alongside the overrides. One might choose to leverage the sec-ch-* & vary headers to select the default non-override values in a manifest response that also includes the new override fields. If the agent doesn’t yet understand the manifest overrides but does implement sec-ch-* (like current Chromium), the user would likely end up with sensible initial behavior even though the agent wouldn’t dynamically respond to subsequent changes to the media conditions (e.g. the user changing the system color scheme) like it would have if the overrides were supported too. I wouldn’t expect most folks to bother going that far I guess, but a common pattern shared between the two APIs might make that progressive enhancement strategy a little more discoverable / dev-friendly for those who do. |
Thanks for all this back and forth! It was a lot to catch up on post-vacation. One thing I’d like to see addressed with the proposal is this: The ability to handle intersections cleanly. If we go the purpose-built route, would a developer be able to provide alternate color mode icons (or screenshots) for each language if necessary? It doesn’t seem like they would. |
Marcos and I were talking a bit about the proposed approaches and some of the concerns around using Media Query syntax in the manifest. My sentiment on the topic is this:
|
I wanted to quickly chime in from the point of view of the WebExtensions Community Group (WECG). This discussion seems directly related to some conversations we're having with respect to WebExtensions. In particular, we're discussing how to handle light/dark icon declaration in the extension manifest, selecting an appropriate icon based on the browser's current theme, and how OS light/dark mode impact the default background color of a popup. I'm commenting as this issue is being discussed at TPAC, so I haven't had an opportunity to give the conversation a close read, but at the moment I suspect that we may want to align here. Relevant WECG discussions: |
Parses the 'theme_colors' and 'background_colors' fields as described in w3c/manifest#1045. The media query is parsed using the CSS parser. Bug: 1318305 Change-Id: I792275045a1adc2ace37e57458d60971fd638021 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3935769 Reviewed-by: Dominick Ng <[email protected]> Commit-Queue: Louise Brett <[email protected]> Cr-Commit-Position: refs/heads/main@{#1064150}
@loubrett Since the present Issue serves as the Explainer of the V2 origin trial and features several syntax ideas, could you add a comment with an example of the syntax developers need to use for the origin trial? Thank you! |
The syntax that I've implemented for the origin trial is: {
"theme_color": "#fff",
"background_color": "#fff",
"theme_colors": [
{ "color": "#000", "media": "(prefers-color-scheme: dark)" }
],
"background_colors": [
{ "color": "#000", "media": "(prefers-color-scheme: dark)" }
]
} Currently the only supported fields are |
how'd the origin trial go? |
Thread: https://groups.google.com/a/chromium.org/g/blink-dev/c/1uKxZUFUQsU/m/jeo18C5tAgAJ "The feedback from the trial showed there was very little interest so we are just going to let it expire." There is a discussion about this scheduled for TPAC in September IIRC. I think we should eventually pick this up again but the priorities didn't align for us this time. |
Shame. Thanks! |
@marcoscaceres sent I18N a pointer to this issue today and I'm going to spend a moment to comment on it in part because it is similar to comments we're engaged with with the verified credentials folks. There are two potential problems to organizing localization as proposed here. First, if a given manifest omits localizations, the core document has natural language strings that do not have language or direction metadata. In a number of examples, these consist of words that are both program internal values (which should be immutable and non-localized) and also the display name, e.g.:
Ideally the core manifest would have display names separate from enumerated program internal values. It may be useful to allow a manifest to declare a default language and direction that applies to any natural language string not overridden locally, e.g.:
The second problem I want to call out is the inconvenience of the localization structures found in JSON currently. Language maps don't allow direction metadata, but a list of objects makes it harder to implement selection because every one of the localization entries has to be parsed when matching. Using a "lookup" matcher generally works best when localized values are keyed by language:
Lacking a common structure for this in e.g. JSON-LD and other similar schemes means everyone will invent it over or try to adapt inconvenient solutions that omit direction or require additional processing. Look forward to chatting in Seville.
|
Potentially: "dir": "ltr",
"lang": "en-x-marcos",
"short_name": "I'm a short name",
"short_names": {
"en": { "value": "My App, hey!", "dir": "ltr", "lang": "fr"},
"en-GB": { "value": "My App, eh wut?", "dir": "ltr"},
"fr": "string",
"ar": { "value": "...", "dir": "rtl" }
} |
Not sure I fully follow what was happening in that last comment, but I am in favor of a simpler syntax where values that still hold from the root manifest are inherited unless explicitly reset (e.g., direction). Unless that's some major problem for parsers, I think it aligns more closely with other concepts developers are familiar with (e.g., language in HTML, inheritance, the CSS cascade). |
@aarongustafson Yes, that would be the plan. |
Quick update on the progress of the discussion in the WebExtensions Community Group (WECG). See w3c/webextensions#585 and w3c/webextensions#229. We concluded a new top level member needs to be introduced and I believe this is the moment we can align on a common syntax for both web app manifests and webExtensions. It seems in above discussion the purpose-built objects and members seems to be the way forward. A potential structure could be the following: [{
"any": "16.svg",
"type": "image/svg+xml"
}, {
"16": "mono16.png",
"32": "mono32.png",
"type": "image/png",
"purpose": "monochrome"
}, {
"16": "mono16fr.png",
"32": "mono32fr.png",
"type": "image/png",
"purpose": "monochrome",
"lang": "fr"
}, {
"16": "[email protected]",
"32": "[email protected]",
"type": "image/png",
"color_scheme": "dark",
"density": 2
}, {
"16": "light16.png",
"32": "light32.png",
"type": "image/png",
"color_scheme": "light"
}, {
"16": "default16.png",
"32": "default32.png",
"type": "image/png"
}] Some benefits are skipping repeated props (like type). Making the syntax less verbose. A similar tactic could be used for other properties like {
"names": [{
"full": "Some amazing app",
"short": "Amazing",
"lang": "en en-US"
}, {
"full": "Une application étonnante",
"lang": "fr"
}]
} We can then restrict the filters ( |
Current plans are triplets like so:
|
Just to clarify, Question: Could |
Related issue: #617 |
Related issue: #975 |
Browser extensions now solve dark mode icons via "icon_variants": [
{
"any": "any.svg"
},
{
"16": "16.png",
"32": "32.png"
},
{
"16": "dark16.png",
"32": "dark32.png",
"color_schemes": ["dark"],
},
{
"16": "light16.png",
"32": "light32.png",
"color_schemes": ["dark", "light"]
}
] |
Correct. Listed some of the benefits of using this syntax in this thread: |
We’ve known for a while that we need some way to override the value of manifest members based on some “environmental condition”, be it user’s preferred language, OS color scheme (i.e., light or dark mode), or something we haven’t thought of yet.
The working assumption is that the overrides may apply at install time and may persist after installation. For example, if an installed application is running, and the OS switches color scheme to “dark mode”, the user agent should apply a matching theme_color for the dark color scheme.
Thus, the solution needs to cater for both OS level changes independently of the browser engine running, and the browser engine should be able to re-apply a manifest to reflect the runtime environmental conditions at any moment in time.
Requirements
The solution needs to be:
Related issues
The following issues and pull request have driven this discussion:
translations
member #676color_scheme
member image-resource#26Points of contention
Throughout the discussion in the related issues, a few points of contention have arisen. There are valid arguments made for an against each of the following.
CSS media queries VS using manifest members
A primary point of contention is the use of CSS Media Queries VS using manifest members that represent the same thing. On the one hand, media queries define a lot of what we want (i.e., all the “prefers-“ media features and values). On the other hand, evaluation of those media features requires a CSS runtime.
As stated in #975:
Although the above holds true as a general statement, in the case of icons, the above currently has no bearing because operating systems don’t support switching application icons when the theme changes.
Further, some OSs restrain what iconography can be shown in shortcuts, again limiting the possibility of developers having to provide icons to the OS to deal with OS-level user preferences. Hence, if overrides only apply to members that are in control of the user agent, and which are applied at runtime: where interpreting a CSS media query is possible.
The point being: some members (e.g.,
theme_color
) are interpreted at runtime by the browser engine, while others might need to be handled specifically by the OS. We should handle those individually and on a case-by-case basis.Parsable property keys
Another point of contention has been using “parsable keys”, where by a key contains either a CSS media query or a language-tag. For example:
As opposed to using named keys with objects inside an array:
Using parsable keys is fairly common in JSON. However, where the order of keys is important, using parsable keys relies on JavaScript-based manifest parser in order to work: this is because JS treats JSON’s keys as an ordered map. As seen above, it also results in a flatter structure when compared to using arrays and objects.
However, a significant drawback is that a parsable-key structure is not extensible: The key needs to have all the information in it to support every type of matching. This works ok for matching user-preferences via media queries, but might not work for languages (because languages are not currently a media feature that can be matched).
On the other hand, using and array and a set of objects overcomes these issues at the cost of adding some verbosity. Nevertheless, using arrays + objects has several advantages:
Issue with translations proposal
Note that the “translations” proposal suffers from the same issues listed above, because it relies on a (parsable) language-tag as a key.
Language selection is generally done using Unicode’s “lookup” algorithm, meaning that it’s not a simple match. The solution may also be inadequate in that it doesn’t allow specifying per member direction and language override. If individual direction and language is a requirement, then the following object structure is more appropriate:
See "Purpose-built objects and members" below for how the above can be used to solve localization problems.
Media preference overrides
Another proposed solution was to have a grouping object with a special key (in this case
prefers_color_scheme
).The problem is that it’s overly broad in its applicability. For example, the following doesn’t make sense:
That is to say, changing the color scheme shouldn’t (and won’t) have any effect on the name of the application. The problem is that it’s not immediately obvious as to what
prefers_color_scheme
applies.The redefinitions proposal
Another proposal is to use specific members, which include an array of objects that provide a “context” and an “override”.
Although compact, this solution suffers from the same issues already mentioned above: in that a developer could end up adding members that are unaffected by the “context”. For example, adding “theme_color” under “translations“.
Thomas Steiner also showed that this separation between “translations” and “user_preferences” becomes unmanageable:
#975 (comment)
Purpose-built objects and members
Given that we need to override existing manifest members, another proposal is to just introduce new members and purpose-built objects. Then, each could contain an array of objects with a condition for the override it.
Thus, we could define a purpose-built “color object” and pluralize the name of “theme_color”. For example:
A potential problem with pluralization of member names is that we already have some members whose names are in plural form (icons, shortcuts), so this wouldn’t be backwards compatible. So, might need a new member for such cases (or we take the compat hit).
A possible solution might looks like:
It would be simple enough to apply the same principle to the “name“, ”short_name“ members, as well as the ”description“ member by defining a ”localizable object“ structure.
Despite having include new members, it does meet all the requirements:
Conclusions
Although we have a number of different solutions, none are without their own set of problems. However, of all the approaches, the “purpose-built objects and members” seems to be the least problematic and one that best meets the requirements.
The text was updated successfully, but these errors were encountered: