Skip to content
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

document.requestStorageAccess should consider user explicit settings for unpartitioned data access #186

Merged
merged 5 commits into from
Feb 19, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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