Skip to content

Commit

Permalink
document.requestStorageAccess should consider user explicit settings …
Browse files Browse the repository at this point in the history
…for unpartitioned data access (#186)
  • Loading branch information
shuranhuang authored Feb 19, 2024
1 parent 7d8e6b7 commit c957718
Showing 1 changed file with 39 additions and 25 deletions.
64 changes: 39 additions & 25 deletions storage-access.bs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,15 @@ A {{Document}} is in a <dfn>first-party-site context</dfn> if it is the [=active

A {{Document}} is in a <dfn>third party context</dfn> if it is not in a [=first-party-site context=].

To <dfn>determine whether the user agent explicitly allows unpartitioned cookie access</dfn>, given a [=tuple=] |tuple| consisting of two [=sites=], run the following steps. This algorithm returns "`none`", "`allow`" or "`disallow`".

Note: A user agent's settings might explicitly allow or disallow unpartitioned cookie access through per-site allow-lists, the user changing global browser settings, or similar custom overrides.

1. If the user agent does not have explicit settings for unpartitioned cookie access for |tuple|, return "`none`".
1. If the user agent's settings explicitly allow unpartitioned cookie access for |tuple|, return "`allow`".
1. [=Assert=]: the user agent's settings explicitly disallow unpartitioned cookie access for |tuple|.
1. Return "`disallow`".

<h3 id="ua-state">Changes to user agent state related to storage access</h3>

Modify the definition of [=environment=] in the following manner:
Expand Down Expand Up @@ -158,27 +167,20 @@ When invoked on {{Document}} |doc|, the <dfn export method for=Document><code>ha
1. Let |topLevelSite| be the result of [=obtain a site|obtaining a site=] from the [=top-level origin=] of |doc|'s [=relevant settings object=].
1. Let |embeddedSite| be the result of [=obtain a site|obtaining a site=] from |doc|'s [=Document/origin=].
1. Run the following steps [=in parallel=]:
1. Let |whether the user agent explicitly allows unpartitioned cookie access| be an algorithm that, given a [=tuple=] |tuple| consisting of two [=sites=], runs the following steps. This algorithm returns "`none`", "`allow`" or "`disallow`".

Note: A user agent's settings might explicitly allow or disallow unpartitioned cookie access through per-site allow-lists, the user changing global browser settings, or similar custom overrides.

1. If the user agent does not have explicit settings for unpartitioned cookie access for |tuple|, return "`none`".
1. If the user agent's settings explicitly allow unpartitioned cookie access for |tuple|, return "`allow`".
1. If the user agent's settings explicitly disallow unpartitioned cookie access for |tuple|, return "`disallow`".
1. Let |explicitSetting| be the result of determining |whether the user agent explicitly allows unpartitioned cookie access| with (|topLevelSite|, |embeddedSite|).
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|).
1. Let |permissionState| be the result of [=getting the current permission state=] given "<a permission><code>storage-access</code></a>" and |global|.
1. [=Queue a global task=] on the [=networking task source=] given |global| to:
1. If |explicitSetting| is "`disallow`", [=/resolve=] |p| with false.
1. If |explicitSetting| is "`allow`", [=/resolve=] |p| with true.
1. If |explicitSetting| is "`none`":
1. If |browsingContext| is a [=top-level browsing context=], [=/resolve=] |p| with true.
1. If |browsingContext| is same authority with |browsingContext|'s [=top-level browsing context=]'s [=active document=], [=/resolve=] |p| with true.

ISSUE: "same authority" here is a placeholder for a future concept that allows user agents to perform [=same site=] checks while adhering to additional security aspects such as the presence of a cross-site parent document, see [whatwg/storage#142](https://github.com/whatwg/storage/issues/142#issuecomment-1122147159). In practice, this might involve comparing the [=site for cookies=] or performing a [=same site=] check with the top-level document.

1. If |permissionState| is [=permission/granted=], [=/resolve=] |p| with |global|'s [=environment/has storage access=].
1. [=Assert=]: |explicitSetting| is "`none`".
1. If |browsingContext| is a [=top-level browsing context=], [=/resolve=] |p| with true.
1. If |browsingContext| is same authority with |browsingContext|'s [=top-level browsing context=]'s [=active document=], [=/resolve=] |p| with true.

Note: The global storage access permission state takes precedence over the local [=environment/has storage access=] flag here, in order to immediately reflect a possible user choice to revoke the permission in their settings.
ISSUE: "same authority" here is a placeholder for a future concept that allows user agents to perform [=same site=] checks while adhering to additional security aspects such as the presence of a cross-site parent document, see [whatwg/storage#142](https://github.com/whatwg/storage/issues/142#issuecomment-1122147159). In practice, this might involve comparing the [=site for cookies=] or performing a [=same site=] check with the top-level document.

1. If |permissionState| is [=permission/granted=], [=/resolve=] |p| with |global|'s [=environment/has storage access=].

Note: The global storage access permission state takes precedence over the local [=environment/has storage access=] flag here, in order to immediately reflect a possible user choice to revoke the permission in their settings.

1. [=/Resolve=] |p| with false.
1. Return |p|.
Expand All @@ -192,18 +194,13 @@ When invoked on {{Document}} |doc|, the <dfn export method for=Document><code>re
1. Let |global| be |doc|'s [=relevant global object=].
1. Let |settings| be |doc|'s [=relevant settings object=].
1. If |global| is not a [=secure context=], then [=/reject=] |p| with a "{{NotAllowedError}}" {{DOMException}} and return |p|.
1. If |doc|'s [=Document/browsing context=] is a [=top-level browsing context=], [=/resolve=] and return |p|.
1. If |doc| is not [=allowed to use=] "`storage-access`", [=/reject=] |p| with a "{{NotAllowedError}}" {{DOMException}} and return |p|.
1. If |doc|'s [=Document/origin=] is an [=opaque origin=], [=/reject=] |p| with a "{{NotAllowedError}}" {{DOMException}} and return |p|.
1. If |settings|'s [=top-level origin=] is an [=opaque origin=], [=/reject=] |p| with a "{{NotAllowedError}}" {{DOMException}} and return |p|.
1. If |settings|'s [=top-level origin=] is [=same site=] with |settings|'s [=environment settings object/origin=]:
1. Set |global|'s [=environment/has storage access=] to true.
1. [=/Resolve=] and return |p|.

NOTE: This check is [=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.

1. If |settings|'s [=top-level origin=] is an [=opaque origin=], [=/reject=] |p| with a "{{NotAllowedError}}" {{DOMException}} and return |p|.
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|.
1. If |global|'s [=environment/has storage access=] is true, [=/resolve=] |p| with {{undefined}} and return.
1. Let |browsingContext| be |doc|'s [=Document/browsing context=].
1. Let |topLevelSite| be the result of [=obtain a site|obtaining a site=] from the [=top-level origin=] of |doc|'s [=relevant settings object=].
1. Let |embeddedSite| be the result of [=obtain a site|obtaining a site=] from |doc|'s [=Document/origin=].
1. Let |has transient activation| be whether |doc|'s {{Window}} object has [=transient activation=].
1. Run the following steps [=in parallel=]:
1. Let |process permission state| be an algorithm that, given a [=permission state=] |state|, runs the following steps:
Expand All @@ -214,6 +211,23 @@ When invoked on {{Document}} |doc|, the <dfn export method for=Document><code>re
1. Else:
1. [=Consume user activation=] given |global|.
1. [=/Reject=] |p| with a "{{NotAllowedError}}" {{DOMException}}.
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|).
1. If |explicitSetting| is "`disallow`":
1. Run |process permission state| with [=permission/denied=].
1. Abort these steps.
1. If |explicitSetting| is "`allow`":
1. Run |process permission state| with [=permission/granted=].
1. Abort these steps.
1. [=Assert=]: |explicitSetting| is "`none`".
1. If |browsingContext| is a [=top-level browsing context=]:
1. Run |process permission state| with [=permission/granted=].
1. Abort these steps.
1. If |embeddedSite| is [=same site=] with |topLevelSite|:

NOTE: This check is [=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.

1. Run |process permission state| with [=permission/granted=].
1. Abort these steps.
1. Let |previous permission state| be the result of [=getting the current permission state=] given "<a permission><code>storage-access</code></a>" and |global|.
1. If |previous permission state| is not [=permission/prompt=]:
1. Run |process permission state| with |previous permission state|.
Expand Down

0 comments on commit c957718

Please sign in to comment.