Skip to content

Commit 64db295

Browse files
lukewarlowsvgeesus
authored andcommitted
[mediaqueries-5] Migrate Web Preferences API proposal
1 parent c43eb2a commit 64db295

File tree

1 file changed

+309
-0
lines changed

1 file changed

+309
-0
lines changed

mediaqueries-5/Overview.bs

+309
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ spec:css-values-4;
3535
text:<number>
3636
text:<resolution>
3737
type:dfn; text:relative length
38+
spec:dom; type:dfn; text:origin
3839

3940
</pre>
4041

@@ -3217,6 +3218,306 @@ Automatic handling of User Preferences</h3>
32173218
allows for unlimited data or is on a metered plan.
32183219
</div>
32193220

3221+
<h2 id=auto-pref>
3222+
Script Control of User Preferences</h3>
3223+
3224+
It is common for website authors to want to respect the user's system preferences while also allowing
3225+
those preferences to be overridden. To help with this, this specification defines a way for authors to
3226+
override the [[#mf-user-preferences]] using the {{PreferenceManager}} interface.
3227+
3228+
This override allows the preference to integrate with various platform features that are affected by these preferences.
3229+
3230+
<h3 id=auto-pref>
3231+
Extensions to the {{Navigator}} interface</h3>
3232+
3233+
<script type=idl>
3234+
[Exposed=Window, SecureContext]
3235+
partial interface Navigator {
3236+
[SameObject] readonly attribute PreferenceManager preferences;
3237+
};
3238+
</script>
3239+
3240+
<h4 id=auto-pref>
3241+
{{preferences}} attribute</h4>
3242+
3243+
When getting the {{preferences}} attribute always return the same instance of the {{PreferenceManager}} object.
3244+
3245+
### {{PreferenceManager}} interface ### {#preference-manager}
3246+
3247+
<script type=idl>
3248+
[Exposed=Window, SecureContext]
3249+
interface PreferenceManager {
3250+
readonly attribute PreferenceObject colorScheme;
3251+
readonly attribute PreferenceObject contrast;
3252+
readonly attribute PreferenceObject reducedMotion;
3253+
readonly attribute PreferenceObject reducedTransparency;
3254+
readonly attribute PreferenceObject reducedData;
3255+
};
3256+
</script>
3257+
3258+
<h4 id=auto-pref>
3259+
{{colorScheme}} attribute</h4>
3260+
3261+
The {{colorScheme}} attribute is a {{PreferenceObject}} used to override the user's preference for the color scheme of the site.
3262+
This is modeled after the [[#prefers-color-scheme]].
3263+
3264+
<div algorithm='get valid values for colorScheme'>
3265+
The <dfn>get valid values for colorScheme</dfn> algorithm, when invoked, must run these steps:
3266+
3267+
1. Let |validValues| be a new empty [=sequence=].
3268+
1. Add ''light'' to |validValues|.
3269+
1. Add ''dark'' to |validValues|.
3270+
1. Return |validValues|.
3271+
</div>
3272+
3273+
If an override is set for this preference:
3274+
- The user agent MUST use this override for the [[#prefers-color-scheme]] in all stylesheets applied to an [=origin=] including the UA style sheet.
3275+
- The user agent MUST also use this override when queried via `matchMedia()` from [[cssom-view#extensions-to-the-window-interface]].
3276+
- The user agent MUST also use this override when calculating the [=used color scheme=].
3277+
- The user agent MUST also use this override when sending [[USER-PREFERENCE-MEDIA-FEATURES-HEADERS#sec-ch-prefers-color-scheme]].
3278+
- The user agent MUST also use this override for any UA features that are normally affected by [[#prefers-color-scheme]].
3279+
3280+
<h4 id=auto-pref>
3281+
{{contrast}} attribute</h4>
3282+
3283+
The {{contrast}} attribute is a {{PreferenceObject}} used to override the user's preference for the contrast of the site.
3284+
This is modeled after the [[#prefers-contrast]].
3285+
3286+
<div algorithm='get valid values for contrast'>
3287+
The <dfn>get valid values for contrast</dfn> algorithm, when invoked, must run these steps:
3288+
3289+
1. Let |validValues| be a new empty [=sequence=].
3290+
1. Add ''@media/prefers-contrast/more'' to |validValues|.
3291+
1. Add ''@media/prefers-contrast/less'' to |validValues|.
3292+
1. Add ''@media/prefers-contrast/no-preference'' to |validValues|.
3293+
1. Return |validValues|.
3294+
</div>
3295+
3296+
If an override is set for this preference:
3297+
- The user agent MUST use this override for the [[#prefers-contrast]] in all stylesheets applied to an [=origin=] including the UA style sheet.
3298+
- The user agent MUST also use this override when queried via `matchMedia()` from [[cssom-view#extensions-to-the-window-interface]].
3299+
- The user agent MUST also use this override when sending [[USER-PREFERENCE-MEDIA-FEATURES-HEADERS#sec-ch-prefers-contrast]].
3300+
- The user agent MUST also use this override for any UA features that are normally affected by [[#prefers-contrast]].
3301+
3302+
Note: Unlike the media feature this preference is NOT able to be set to ''@media/prefers-contrast/custom'' as this is tightly coupled to the [[#forced-colors]].
3303+
3304+
<h4 id=auto-pref>
3305+
{{reducedMotion}} attribute</h4>
3306+
3307+
The {{reducedMotion}} attribute is a {{PreferenceObject}} used to override the user's preference for reduced motion on the site.
3308+
This is modeled after the [[#prefers-reduced-motion]].
3309+
3310+
<div algorithm='get valid values for reducedMotion'>
3311+
The <dfn>get valid values for reducedMotion</dfn> algorithm, when invoked, must run these steps:
3312+
3313+
1. Let |validValues| be a new empty [=sequence=].
3314+
1. Add ''@media/prefers-reduced-motion/reduce'' to |validValues|.
3315+
1. Add ''@media/prefers-reduced-motion/no-preference'' to |validValues|.
3316+
1. Return |validValues|.
3317+
</div>
3318+
3319+
If an override is set for this preference:
3320+
- The user agent MUST use this override for the [[#prefers-reduced-motion]] in all stylesheets applied to an [=origin=] including the UA style sheet.
3321+
- The user agent MUST also use this override when queried via `matchMedia()` from [[cssom-view#extensions-to-the-window-interface]].
3322+
- The user agent MUST also use this override when sending [[USER-PREFERENCE-MEDIA-FEATURES-HEADERS#sec-ch-prefers-reduced-motion]].
3323+
- The user agent MUST also use this override for any UA features that are normally affected by [[#prefers-reduced-motion]].
3324+
3325+
Note: An example of a UA feature that is affected by this preference could be disabling smooth scrolling, or pausing marquee elements.
3326+
3327+
<h4 id=auto-pref>
3328+
{{reducedTransparency}} attribute</h4>
3329+
3330+
The {{reducedTransparency}} attribute is a {{PreferenceObject}} used to override the user's preference for reduced transparency on the site.
3331+
This is modeled after the [[#prefers-reduced-transparency]].
3332+
3333+
<div algorithm='get valid values for reducedTransparency'>
3334+
The <dfn>get valid values for reducedTransparency</dfn> algorithm, when invoked, must run these steps:
3335+
3336+
1. Let |validValues| be a new empty [=sequence=].
3337+
1. Add ''@media/prefers-reduced-transparency/reduce'' to |validValues|.
3338+
1. Add ''@media/prefers-reduced-transparency/no-preference'' to |validValues|.
3339+
1. Return |validValues|.
3340+
</div>
3341+
3342+
If an override is set for this preference:
3343+
- The user agent MUST use this override for the [[#prefers-reduced-transparency]] in all stylesheets applied to an [=origin=] including the UA style sheet.
3344+
- The user agent MUST also use this override when queried via `matchMedia()` from [[cssom-view#extensions-to-the-window-interface]].
3345+
- The user agent MUST also use this override when sending [[USER-PREFERENCE-MEDIA-FEATURES-HEADERS#sec-ch-prefers-reduced-transparency]].
3346+
- The user agent MUST also use this override for any UA features that are normally affected by [[#prefers-reduced-transparency]].
3347+
3348+
<h4 id=auto-pref>
3349+
{{reducedData}} attribute</h4>
3350+
3351+
The {{reducedData}} attribute is a {{PreferenceObject}} used to override the user's preference for reduced data usage on the site.
3352+
This is modeled after the [[#prefers-reduced-data]].
3353+
3354+
<div algorithm='get valid values for reducedData'>
3355+
The <dfn>get valid values for reducedData</dfn> algorithm, when invoked, must run these steps:
3356+
3357+
1. Let |validValues| be a new empty [=sequence=].
3358+
1. Add ''@media/prefers-reduced-data/reduce'' to |validValues|.
3359+
1. Add ''@media/prefers-reduced-data/no-preference'' to |validValues|.
3360+
1. Return |validValues|.
3361+
</div>
3362+
3363+
If an override is set for this preference:
3364+
- The user agent MUST use this override for the [[#prefers-reduced-data]] in all stylesheets applied to an [=origin=] including the UA style sheet.
3365+
- The user agent MUST also use this override when queried via `matchMedia()` from [[cssom-view#extensions-to-the-window-interface]].
3366+
- The user agent MUST also use this override when sending [[SAVEDATA#save-data-request-header-field]].
3367+
- The user agent MUST also use this override when calculating the [[SAVEDATA#savedata-attribute]].
3368+
- The user agent MUST also use this override for any UA features that are normally affected by [[#prefers-reduced-data]].
3369+
3370+
<h4 id=auto-pref>
3371+
{{PreferenceObject}} interface</h4>
3372+
3373+
<script type=idl>
3374+
[Exposed=Window, SecureContext]
3375+
interface PreferenceObject : EventTarget {
3376+
readonly attribute DOMString? override;
3377+
readonly attribute DOMString value;
3378+
readonly attribute FrozenArray<DOMString> validValues;
3379+
3380+
undefined clearOverride();
3381+
Promise<undefined> requestOverride(DOMString? value);
3382+
3383+
attribute EventHandler onchange;
3384+
};
3385+
</script>
3386+
3387+
<h5 id=auto-pref>
3388+
{{override}} attribute</h5>
3389+
3390+
<div algorithm='get preference override'>
3391+
The <dfn attribute for=PreferenceObject>override</dfn> attribute, when accessed, must run these steps:
3392+
3393+
1. Let |preference| be the preference object's name.
3394+
1. Let |override| be null.
3395+
1. If an override for |preference| exists, set |override| to the value of that override.
3396+
1. Return |override|.
3397+
</div>
3398+
3399+
<h5 id=auto-pref>
3400+
{{PreferenceObject/value}} attribute</h5>
3401+
3402+
<div algorithm='get preference value'>
3403+
The <dfn attribute for=PreferenceObject>value</dfn> attribute, when accessed, must run these steps:
3404+
3405+
1. Let |preference| be the preference object's name.
3406+
1. Let |value| be null.
3407+
1. If an override for |preference| exists, set |value| to the value of that override.
3408+
1. If |value| is null, set |value| to the UA value of the preference.
3409+
1. Return |value|.
3410+
</div>
3411+
3412+
<h5 id=auto-pref>
3413+
{{validValues}} attribute</h5>
3414+
3415+
<div algorithm>
3416+
The <dfn attribute for=PreferenceObject>validValues</dfn> attribute, when accessed, must run these steps:
3417+
3418+
<ol>
3419+
<li>Let |preference| be the preference object's name.
3420+
3421+
<li>Switch on |preference|:
3422+
<dl class="switch">
3423+
<dt>"{{colorScheme}}"</dt>
3424+
<dd>Return the result of [=get valid values for colorScheme=].</dd>
3425+
<dt>"{{contrast}}"</dt>
3426+
<dd>Return the result of [=get valid values for contrast=].</dd>
3427+
<dt>"{{reducedMotion}}"</dt>
3428+
<dd>Return the result of [=get valid values for reducedMotion=].</dd>
3429+
<dt>"{{reducedTransparency}}"</dt>
3430+
<dd>Return the result of [=get valid values for reducedTransparency=].</dd>
3431+
<dt>"{{reducedData}}"</dt>
3432+
<dd>Return the result of [=get valid values for reducedData=].</dd>
3433+
</dl>
3434+
</div>
3435+
3436+
<h5 id=auto-pref>
3437+
{{onchange}} event handler attribute</h5>
3438+
3439+
The <dfn attribute for=PreferenceObject>onchange</dfn> attribute is an [=event handler IDL attribute=] for
3440+
the {{onchange}} [=event handler=], whose [=event handler event type=]
3441+
is <dfn class="event" data-dfn-for="PreferenceObject">change</dfn>.
3442+
3443+
<div algorithm="update steps">
3444+
Whenever the [=user agent=] is aware that the state of a {{PreferenceObject}}
3445+
instance |value| has changed, it runs the <dfn algorithm for="PreferenceObject">{{PreferenceObject}}
3446+
update steps</dfn>:
3447+
3448+
1. Let |preference| be the {{PreferenceObject}} object that |value| is associated with.
3449+
1. If [=this=]'s [=relevant global object=] is a {{Window}} object, then:
3450+
1. Let |document| be |preference|'s [=relevant global object=]'s [=associated Document=].
3451+
1. If |document| is null or |document| is not [=Document/fully active=], terminate this algorithm.
3452+
1. <a>Fire an event</a> named <code>change</code> at |preference|.
3453+
3454+
<h5 id=auto-pref>
3455+
{{requestOverride()}} method</h5>
3456+
3457+
<div algorithm='request preference override'>
3458+
The <dfn method for=PreferenceObject>requestOverride(value)</dfn> method, when invoked, must run these steps:
3459+
3460+
1. Let |result| be [=a new promise=].
3461+
1. Let |allowed| be false.
3462+
1. Set |allowed| to the result of executing a UA defined algorithm for deciding whether the request is allowed.
3463+
1. If |allowed| is false, return [=a promise rejected with=] a "{{NotAllowedError}}" {{DOMException}}.
3464+
1. Let |value| be the method's argument.
3465+
1. Let |result| be [=a new promise=].
3466+
1. If |value| is null or the empty string:
3467+
1. Run {{clearOverride}}.
3468+
1. [=Resolve=] and return |result|.
3469+
1. Let |currentValue| be the preference object's |value|.
3470+
1. Let |validValues| be null.
3471+
1. Switch on |preference|:
3472+
<dl class="switch">
3473+
<dt>"{{colorScheme}}"</dt>
3474+
<dd>Set |validValues| to the result of [=get valid values for colorScheme=].</dd>
3475+
<dt>"{{contrast}}"</dt>
3476+
<dd>Set |validValues| to the result of [=get valid values for contrast=].</dd>
3477+
<dt>"{{reducedMotion}}"</dt>
3478+
<dd>Set |validValues| to the result of [=get valid values for reducedMotion=].</dd>
3479+
<dt>"{{reducedTransparency}}"</dt>
3480+
<dd>Set |validValues| to the result of [=get valid values for reducedTransparency=].</dd>
3481+
<dt>"{{reducedData}}"</dt>
3482+
<dd>Set |validValues| to the result of [=get valid values for reducedData=].</dd>
3483+
</dl>
3484+
1. If |value| is not in |validValues|:
3485+
1. [=Reject=] |result| with a "{{TypeError}}" {{DOMException}}.
3486+
1. Return |result|.
3487+
1. Let |previousOverride| be null.
3488+
1. If an override for |preference| exists, set |previousOverride| to the value of that override.
3489+
1. If |value| is different from |previousOverride|:
3490+
1. Set the preference override for |preference| to |value|.
3491+
1. If |previousOverride| is null, then:
3492+
1. If |value| is the same as |currentValue|, then:
3493+
1. <a>Fire an event</a> named <code>change</code> at [=this=].
3494+
1. [=Resolve=] and return |result|.
3495+
</div>
3496+
3497+
Issue: This algorithm needs more detail on what exactly setting the preference override does.
3498+
3499+
Issue: Is TypeError correct here?
3500+
3501+
Note: The `change` event is fired when the computed value changes, but when a new override is set it is also fired if the value hasn't changed.
3502+
3503+
<h5 id=auto-pref>
3504+
{{clearOverride()}} method</h5>
3505+
3506+
<div algorithm='clear preference override'>
3507+
The <dfn method for=PreferenceObject>clearOverride()</dfn> method, when invoked, must run these steps:
3508+
3509+
1. Let |preference| be the preference object's name.
3510+
1. Let |override| be null.
3511+
1. If an override for |preference| exists, set |override| to the value of that override.
3512+
1. If |override| is null, then return.
3513+
1. Clear the override for |preference|.
3514+
1. Let |newValue| be the preference object's |value|.
3515+
1. If |newValue| is equal to |override|, then:
3516+
1. <a>Fire an event</a> named <code>change</code> at [=this=].
3517+
</div>
3518+
3519+
Note: The `change` event is fired when the computed value changes, but when an override is cleared it is also fired if the value hasn't changed.
3520+
32203521
<!--
32213522
████ ██████ ██████ ██ ██ ████████ ██████
32223523
██ ██ ██ ██ ██ ██ ██ ██ ██ ██
@@ -3404,6 +3705,14 @@ Appendix B: Privacy and Security Considerations</h2>
34043705
may be an undesired source of fingerprinting,
34053706
with a bias towards low income with limited data.
34063707

3708+
The {{PreferenceManager}} object allows querying some user-preference [=media features=]. This
3709+
is not a privacy leak, as that information is already trivially
3710+
available by using [=media features=] themselves.
3711+
3712+
The {{PreferenceManager}} object also allows overriding these user-preference [=media features=]; this
3713+
is also neither a privacy nor accessibility regression, as the [=media features=] were already ignorable by simply
3714+
not querying them.
3715+
34073716
</div>
34083717

34093718
<h2 id="changes" class="no-num">

0 commit comments

Comments
 (0)