Skip to content

Commit 21b9f85

Browse files
committed
Update algorithm. Remove top-level-storage-access permissions content.
1 parent 205be9d commit 21b9f85

1 file changed

Lines changed: 58 additions & 111 deletions

File tree

index.bs

Lines changed: 58 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -100,115 +100,77 @@ When invoked on {{Document}} |doc| with {{USVString}} |requestedOrigin|, the <df
100100

101101
1. Let |p| be [=a new promise=].
102102
1. If |doc| is not [=Document/fully active=], then [=reject=] |p| with an "{{InvalidStateError}}" {{DOMException}} and return |p|.
103+
1. Let |global| be |doc|'s [=relevant global object=].
104+
1. Let |settings| be |doc|'s [=relevant settings object=].
105+
1. If |global| is not a [=secure context=], then [=/reject=] |p| with a "{{NotAllowedError}}" {{DOMException}} and return |p|.
106+
1. If |doc| is not [=allowed to use=] "`storage-access`", [=/reject=] |p| with a "{{NotAllowedError}}" {{DOMException}} and return |p|.
103107
1. If |doc|'s [=node navigable=] is not a [=traversable navigable=], [=reject=] |p| with an "{{NotAllowedError}}" {{DOMException}} and return |p|.
104108
1. If |doc|'s [=Document/origin=] is an [=opaque origin=], [=reject=] |p| with an "{{NotAllowedError}}" {{DOMException}} and return |p|.
105-
1. If |doc|'s [=relevant global object=] is not a [=secure context=], then [=reject=] |p| with a "{{NotAllowedError}}" {{DOMException}} and return |p|.
109+
1. If |doc|'s [=active sandboxing flag set=] has its [=sandbox storage access by user activation flag=] set, [=/reject=] |p| with a "{{NotAllowedError}}" {{DOMException}} and return |p|.
110+
1. Let |browsingContext| be |doc|'s [=Document/browsing context=].
111+
1. Let |topLevelOrigin| be the [=top-level origin=] of |doc|'s [=relevant settings object=].
112+
1. Let |topLevelSite| be the result of [=obtain a site|obtaining a site=] from |topLevelOrigin|.
106113
1. Let |parsedURL| be the the result of running the [=URL parser=] on |requestedOrigin|.
107114
1. If |parsedURL| is failure, [=reject=] |p| with a {{TypeError}} and return |p|.
108-
1. Let |origin| be |parsedURL|'s [=/origin=].
109-
1. If |origin| is an [=opaque origin=], [=reject=] |p| with an "{{NotAllowedError}}" {{DOMException}} and return |p|.
110-
1. If |doc|'s [=Document/origin=] is [=same origin=] with |origin|, [=resolve=] and return |p|.
111-
1. Let |descriptor| be a newly created {{TopLevelStorageAccessPermissionDescriptor}} with {{PermissionDescriptor/name}} set to "<a permission><code>top-level-storage-access</code></a>" and with {{TopLevelStorageAccessPermissionDescriptor/requestedOrigin}} set to |origin|.
115+
116+
1. Let |embeddedOrigin| be |parsedURL|'s [=/origin=].
117+
1. If |embeddedOrigin| is an [=opaque origin=], [=reject=] |p| with an "{{NotAllowedError}}" {{DOMException}} and return |p|.
118+
1. If |doc|'s [=Document/origin=] is [=same origin=] with |embeddedOrigin|, [=resolve=] and return |p|.
112119
1. Let |has activation| be true if |doc|'s {{Window}} object has [=transient activation=], and false otherwise.
113-
1. Run these steps [=in parallel=]:
114-
1. Let |settings| be |doc|'s [=relevant settings object=].
115-
1. Let |global| be |doc|'s [=relevant global object=].
116-
1. Let |existing state| be |descriptor|'s [=permission state=] with |settings|.
117-
1. If |existing state| is [=permission/granted=]:
118-
1. [=Queue a global task=] on the [=permissions task source=] given |global| to [=resolve=] |p|.
119-
1. Return.
120-
1. If |existing state| is [=permission/denied=]:
121-
1. If |doc|'s {{Window}} object has [=transient activation=], [=consume user activation=] with it.
122-
1. [=Queue a global task=] on the [=permissions task source=] given |global| to [=reject=] |p| with a "{{NotAllowedError}}" {{DOMException}}.
123-
1. Return.
124-
1. Assert that |doc|'s [=node navigable=] is a [=traversable navigable=].
125-
1. If |has activation| is false:
126-
1. [=Queue a global task=] on the [=permissions task source=] given |global| to [=reject=] |p| with a n "{{NotAllowedError}}" {{DOMException}}.
127-
1. Return.
128-
1. Let |permissionState| be the result of [=requesting permission to use=] "<a permission><code>top-level-storage-access</code></a>" with |descriptor|.
129-
130-
NOTE: Note that when requesting permissions and deciding whether to show a prompt, user agents apply implementation-defined behavior to shape the end user experience. Particularly for `top-level-storage-access`, user agents are known to apply custom rules that will grant or deny a permission without showing a prompt.
131-
132-
1. If |permissionState| is [=permission/granted=]:
133-
1. [=Queue a global task=] on the [=permissions task source=] given |global| to [=resolve=] |p|.
134-
1. Return.
135-
1. If |doc|'s {{Window}} object has [=transient activation=], [=consume user activation=] with it.
136-
1. [=Queue a global task=] on the [=permissions task source=] given |global| to [=reject=] |p| with a "{{NotAllowedError}}" {{DOMException}}.
120+
1. Run the following steps [=in parallel=]:
121+
1. Let |process permission state| be an algorithm that, given a [=permission state=] |state|, runs the following steps:
122+
1. [=Queue a global task=] on the [=networking task source=] given |global| to:
123+
1. If |state| is [=permission/granted=]:
124+
1. Set |global|'s [=environment/has storage access=] to true.
125+
1. [=/Resolve=] |p| with {{undefined}}.
126+
1. Else:
127+
1. [=Consume user activation=] given |global|.
128+
1. [=/Reject=] |p| with a "{{NotAllowedError}}" {{DOMException}}.
129+
1. Let |explicitSetting| be the result of [=determine whether the user agent explicitly allows unpartitioned cookie access|determining whether the user agent explicitly allows unpartitioned cookie access=] with (|topLevelSite|, |embeddedSite|).
130+
1. If |explicitSetting| is "`disallow`":
131+
1. Run |process permission state| with [=permission/denied=].
132+
1. Abort these steps.
133+
1. If |explicitSetting| is "`allow`":
134+
1. Run |process permission state| with [=permission/granted=].
135+
1. Abort these steps.
136+
1. [=Assert=]: |explicitSetting| is "`none`".
137+
1. If |browsingContext| is a [=top-level browsing context=]:
138+
1. Run |process permission state| with [=permission/granted=].
139+
1. Abort these steps.
140+
1. If |embeddedSite| is [=site/same site=] with |topLevelSite|:
141+
142+
NOTE: This check is [=site/same site=] on purpose, to allow embedded sites to use `requestStorageAccess()` to opt into storage access without involvement from the end user in scenarios where storage access is restricted for security and not privacy purposes.
143+
144+
1. Run |process permission state| with [=permission/granted=].
145+
1. Abort these steps.
146+
1. Let |previous permission state| be the result of [=getting the current permission state=] given "<a permission><code>storage-access</code></a>" and |global|.
147+
1. If |previous permission state| is not [=permission/prompt=]:
148+
1. Run |process permission state| with |previous permission state|.
149+
1. Abort these steps.
150+
1. Let |connected| be the result of [=Determine the effective FedCM connection status|determining the effective FedCM connection status=] given |topLevelOrigin|, |embeddedOrigin|, |doc|.
151+
1. If |connected|:
152+
153+
NOTE: User agents are encouraged to keep track of which (site, site) tuples have been allowed to access storage due to existing FedCM connections, and double-check that list when accessing cookies to catch malicious attackers that have tricked an [=environment=] into using an incorrect [=environment/has storage access=] bit.
154+
155+
1. Run |process permission state| with [=permission/granted=].
156+
1. Abort these steps.
157+
1. Let |permissionState| be the result of [=requesting permission to use=] "<a permission><code>storage-access</code></a>".
158+
159+
NOTE: Note that when requesting permissions and deciding whether to show a prompt, user agents apply implementation-defined behavior to shape the end user experience. Particularly for `storage-access`, user agents are known to apply custom rules that will grant or deny a permission without showing a prompt.
160+
161+
1. Run |process permission state| with |permissionState|.
137162
1. Return |p|.
138163

139-
ISSUE(privacycg/requestStorageAccessFor#15): The permissions task source shouldn't be used directly.
140-
141-
</div>
142-
143-
<h3 id="ua-policies">User Agent top-level storage access policies</h3>
144-
145-
<div algorithm>
146-
To <dfn>determine if a request has top-level storage access</dfn> with [=request=] |request|, run these steps:
164+
NOTE: The intent of this algorithm is to always require user activation before a storage-access permission will be set. Though it is within the means of user agents to set storage-access permissions based on custom heuristics without prior user activation, this specification strongly discourages such behavior, as it could lead to interoperability issues.
147165

148-
1. Let |settings| be |request|'s [=request/client=]'s [=relevant global object=]'s [=relevant settings object=].
149-
1. Let |embedded origin| be |request|'s [=request/url=]'s [=url/origin=].
150-
1. Let |descriptor| be a newly created {{TopLevelStorageAccessPermissionDescriptor}} with {{PermissionDescriptor/name}} set to "<a permission><code>top-level-storage-access</code></a>" and with {{TopLevelStorageAccessPermissionDescriptor/requestedOrigin}} set to |embedded origin|.
151-
1. Let |existing state| be |descriptor|'s [=permission state=] with |settings|.
152-
1. If |existing state| is [=permission/granted=], return true.
153-
1. Return false.
166+
ISSUE(privacycg/requestStorageAccessFor#15): The permissions task source shouldn't be used directly.
154167

155168
</div>
156169

157170
<h2 id="permissions-integration">Permissions Integration</h2>
158171

159-
The requestStorageAccessFor API defines a [=powerful feature=] identified by the [=powerful feature/name=] "<dfn export permission><code>top-level-storage-access</code></dfn>". It defines the following permission-related algorithms:
160-
161-
<dl>
162-
<dt>{{PermissionDescriptor}}</dt>
163-
<dd>
164-
The "<a permission><code>top-level-storage-access</code></a>" [=powerful feature=] defines a {{PermissionDescriptor}} as follows:
165-
<pre class="idl">
166-
dictionary TopLevelStorageAccessPermissionDescriptor : PermissionDescriptor {
167-
USVString requestedOrigin = "";
168-
};
169-
</pre>
170-
</dd>
171-
<dt>[=powerful feature/permission query algorithm=]</dt>
172-
<dd>
173-
<div algorithm='top-level-storage-access-query'>
174-
To query the "<a permission><code>top-level-storage-access</code></a>" permission, given a {{PermissionDescriptor}} |permissionDesc| and a {{PermissionStatus}} |status|, run the following steps:
175-
176-
1. Set |status|'s {{PermissionStatus/state}} to |permissionDesc|'s [=permission state=].
177-
1. If |status|'s {{PermissionStatus/state}} is [=permission/denied=], set |status|'s {{PermissionStatus/state}} to [=permission/prompt=].
178-
179-
Note: The [=permission/denied=] permission state is not revealed to avoid exposing the user's decision to developers. This is done to prevent retaliation against the user and repeated prompting to the detriment of the user experience.
180-
181-
</div>
182-
</dd>
183-
<dt>[=powerful feature/permission key type=]</dt>
184-
<dd>
185-
A [=permission key=] of the "<a permission><code>top-level-storage-access</code></a>" feature has the type [=site=].
186-
187-
Note: the {{TopLevelStorageAccessPermissionDescriptor/requestedOrigin}} field ensures that the [=permission store entry=] is double-keyed.
188-
</dd>
189-
<dt>[=powerful feature/permission key generation algorithm=]</dt>
190-
<dd>
191-
<div algorithm='top-level-storage-access-key-generation'>
192-
To generate a new [=permission key=] for the "<a permission><code>top-level-storage-access</code></a>" feature, given an [=environment settings object=] |settings|, run the following steps:
193-
1. Let |current origin| be |settings|' [=environment settings object/origin=].
194-
1. If |current origin| is not [=same site=] with |settings|' [=top-level origin=], return null.
195-
1. Return the result of [=obtain a site|obtaining a site=] from |settings|' [=top-level origin=].
196-
197-
Note: the check for whether |settings|' [=environment settings object/origin=] is [=same site=] with |settings|' [=top-level origin=] is intended to disallow permission queries from cross-site frames.
198-
This depends on the invariant that `top-level-storage-access` permission requests are only allowed in a [=top-level browsing context=]. As such, this check is only relevant in {{Permissions/query(permissionDesc)}}.
199-
200-
</div>
201-
</dd>
202-
<dt>[=powerful feature/permission key comparison algorithm=]</dt>
203-
<dd>
204-
<div algorithm='top-level-storage-access-key-comparison'>
205-
To compare [=permission keys=] |key1| and |key2| for the "<a permission><code>top-level-storage-access</code></a>" feature, run the following steps:
206-
1. If |key1| is null or |key2| is null, return false.
207-
1. Return |key1| is [=same site=] with |key2|.
208-
209-
</div>
210-
</dd>
211-
</dl>
172+
The requestStorageAccessFor API utilizes the existing [=powerful feature=] identified by the [=powerful feature/name=] "<dfn export permission><code>storage-access</code></dfn>" and the integration with permissions is defined in the spec where the permission was defined.
173+
212174

213175
<h2 id="fetch-integration">Fetch Integration</h2>
214176

@@ -226,21 +188,6 @@ In [=http network or cache fetch=], when determining whether to block cookies, r
226188

227189
</div>
228190

229-
<h2 id="storage-access-api-integration">Storage Access API Integration</h2>
230-
231-
Note: even after a successful {{Document/requestStorageAccessFor(requestedOrigin)}} call, frames have to explicitly invoke {{Document/requestStorageAccess()}} for cookie access.
232-
This modification allows {{Document/requestStorageAccessFor(requestedOrigin)}} to allow resolution of {{Document/requestStorageAccess()}} calls similarly to a prior successful {{Document/requestStorageAccess()}} grant.
233-
234-
<div algorithm='storage-access-policy-modification'>
235-
Modify {{Document/requestStorageAccess()}} to insert the following steps before step 13.4 (i.e. before checking transient activation):
236-
237-
1. Let |settings| be <var ignore>doc</var>'s [=relevant settings object=].
238-
1. Let |origin| be |settings|' [=environment settings object/origin=].
239-
1. Let |descriptor| be a newly created {{TopLevelStorageAccessPermissionDescriptor}} with {{PermissionDescriptor/name}} set to "<a permission><code>top-level-storage-access</code></a>" and with {{TopLevelStorageAccessPermissionDescriptor/requestedOrigin}} set to |origin|.
240-
1. If |descriptor|'s [=permission state=] is [=permission/granted=], [=queue a global task=] on the [=permissions task source=] given |global| to [=resolve=] |p|, and return.
241-
1. If |descriptor|'s [=permission state=] is [=permission/denied=], [=queue a global task=] on the [=permissions task source=] given |global| to [=reject=] |p| with a "{{NotAllowedError}}" {{DOMException}}, and return.
242-
243-
</div>
244191

245192
<h2 id="privacy">Privacy considerations</h2>
246193

0 commit comments

Comments
 (0)