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

Add draft of requestStorageAccessForSite spec #109

Closed
wants to merge 2 commits into from
Closed
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
58 changes: 55 additions & 3 deletions storage-access.bs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,12 @@ urlPrefix: https://w3c.github.io/webdriver/webdriver-spec.html#; spec: webdriver

User Agents sometimes prevent content inside certain <{iframe}>s from accessing data stored in client-side storage mechanisms like cookies. This can break embedded content which relies on having access to client-side storage.

The Storage Access API enables content inside <{iframe}>s to request and be granted access to their client-side storage, so that embedded content which relies on having access to client-side storage can work in such User Agents. [[STORAGE-ACCESS-INTRO]]
The Storage Access API enables developers to request access to client-side storage for embedded resources such as iframes, scripts, or images. It does this through two mechanisms:

1. {{Document/requestStorageAccess()}}, which can request access to unpartitioned data from within an iframe.
1. {{Document/requestStorageAccessForOrigin(origin)}}, which allows top-level browsing contexts to request access to unpartitioned data on behalf of another [=url/origin=].

[[STORAGE-ACCESS-INTRO]]

</section>

Expand All @@ -87,7 +92,7 @@ This specification depends on the Infra standard. [[!INFRA]]

<h2 id="the-storage-access-api">The Storage Access API</h2>

This specification defines a method to query whether or not a {{Document}} currently has access to its [=unpartitioned data=] ({{Document/hasStorageAccess()}}), and a method that can be used to request access to its [=unpartitioned data=] ({{Document/requestStorageAccess()}}).
This specification defines a method to query whether or not a {{Document}} currently has access to its [=unpartitioned data=] ({{Document/hasStorageAccess()}}), a method that can be used to request access to its [=unpartitioned data=] ({{Document/requestStorageAccess()}}), and a method that can be used to request access to [=unpartitioned data=] on behalf of another [=url/origin=] ({{Document/requestStorageAccessForOrigin(origin)}}).

<div class=example>

Expand All @@ -99,6 +104,18 @@ Script in the <{iframe}> can call |doc|`.`{{Document/hasStorageAccess()}} to det

</div>

<div class=example>

The API is not limited to iframes. An alternative scenario is:

Alex visits `https://social.example/`. The page sets a cookie. This cookie has been set in a [=first-party-site context=].

Later on, Alex visits `https://video.example/`, which has an <{img}> in it which loads `https://social.example/profile-image`. In this case, the `social.example` {{Document}} |doc| is in a [=third party context=], and the cookie set previously might or might not be visible from |doc|`.`{{Document/cookie}}, depending on User Agent storage access policies.

A script on `https://video.example/` could request access on behalf of `https://social.example` by calling |doc|`.`{{Document/requestStorageAccessForOrigin(origin)}} with {{USVString}} |origin| as `https://social.example`.

</div>

<dfn>Unpartitioned data</dfn> is client-side storage that would be available to a [=site=] were it loaded in a [=first-party-site context=].

A {{Document}} is in a <dfn>first-party-site context</dfn> if it is the [=active document=] of a [=top-level browsing context=]. Otherwise, it is in a [=first-party-site context=] if it is an [=active document=] and the [=environment settings object/origin=] and [=top-level origin=] of its [=relevant settings object=] are [=same site=] with one another.
Expand Down Expand Up @@ -139,6 +156,11 @@ To <dfn type="abstract-op">generate a partitioned storage key</dfn> for a {{Docu
1. Let |top-level site| be the result of [=obtain a site|obtaining a site=] from |settings|' [=top-level origin=].
1. Return the [=partitioned storage key=] (|top-level site|, |site|).

To <dfn type="abstract-op">generate a delegated partitioned storage key</dfn> for a {{Document}} |doc| and an [=url/origin=] |override|, run the following steps:
1. Let |settings| be |doc|'s [=relevant settings object=].
1. Let |top-level site| be the result of [=obtain a site|obtaining a site=] from |settings|' [=top-level origin=].
1. Return the [=partitioned storage key=] (|top-level site|, |override|).

A <dfn>storage access flag set</dfn> is a set of zero or more of the following flags, which are used to gate access to client-side storage for |embedded site| when loaded in a [=third party context=] on |top-level site|:

: The <dfn for="storage access flag set" id=has-storage-access-flag>has storage access flag</dfn>
Expand All @@ -163,6 +185,7 @@ To <dfn type="abstract-op">save the storage access flag set</dfn> for a [=partit
partial interface Document {
Promise&lt;boolean> hasStorageAccess();
Promise&lt;undefined> requestStorageAccess();
Promise&lt;undefined> requestStorageAccessForOrigin(USVString origin);
};
</pre>

Expand Down Expand Up @@ -224,9 +247,37 @@ When invoked on {{Document}} |doc|, the <dfn export method for=Document><code>re

ISSUE: Shouldn't step 3.7 be [=same site=]?

When invoked on {{Document}} |doc|, the <dfn export method for=Document><code>requestStorageAccessForOrigin(origin)</code></dfn> method must run these steps:

1. Let |p| be [=a new promise=].
mreichhoff marked this conversation as resolved.
Show resolved Hide resolved
1. If |doc| is not [=Document/fully active=], then [=reject=] |p| with an "{{InvalidStateError}}" {{DOMException}} and return |p|.
1. If this algorithm was invoked when |doc|'s {{Window}} object did not have [=transient activation=], [=reject=] and return |p|.
1. If |doc|'s [=Document/browsing context=] is not a [=top-level browsing context=], [=reject=] and return |p|.
1. If |doc|'s [=Document/origin=] is an [=opaque origin=], [=reject=] and return |p|.
1. Let |parsedURL| be the the result of running the [=URL parser=] on |site|.
1. If |parsedURL| is failure, [=reject=] |p| with a "{{TypeError}}" {{DOMException}} and return |p|.
1. Let |origin| be |parsedURL|'s [=url/origin=].
1. If |origin| is an [=opaque origin=], [=reject=] and return |p|.
1. If |doc|'s [=Document/origin=] is [=same origin=] with |origin|, [=/resolve=] and return |p|.
1. Let |key| be the result of [=generate a delegated partitioned storage key|generating a delegated partitioned storage key=] from |doc| and |origin|.
1. If |key| is failure, [=reject=] and return |p|.
1. Let |global| be |doc|'s [=relevant global object=].
1. Let |map| be the result of [=obtain the storage access map|obtaining the storage access map=] for |doc|.
1. Let |flag set| be the result of [=obtain a storage access flag set|obtaining the storage access flag set=] with |key| from |map|.
1. If |flag set|'s [=was expressly denied storage access flag=] is set, [=reject=] and return |p|.
1. If |flag set|'s [=has storage access flag=] is set, [=/resolve=] and return |p|.
1. Otherwise, run these steps [=in parallel=]:
1. Let |hasAccess| be [=a new promise=].
1. [=Determine the storage access policy=] with |key|, |doc| and |hasAccess|.
1. [=Queue a global task=] on the [=permission task source=] given |global| to
1. Set |flag set|'s [=has storage access flag=].
1. Resolve or reject |p| based on the result of |hasAccess|.
1. [=Save the storage access flag set=] for |key| in |map|.
1. Return |p|.

<h4 id="ua-policy">User Agent storage access policies</h4>

Different User Agents have different policies around whether or not [=sites=] may access their [=unpartitioned data=] when they're in a [=third party context=]. User Agents check and/or modify these policies when client-side storage is accessed (see [[#storage]]) as well as when {{Document/hasStorageAccess()}} and {{Document/requestStorageAccess()}} are called.
Different User Agents have different policies around whether or not [=sites=] may access their [=unpartitioned data=] when they're in a [=third party context=]. User Agents check and/or modify these policies when client-side storage is accessed (see [[#storage]]) as well as when {{Document/hasStorageAccess()}}, {{Document/requestStorageAccess()}}, and {{Document/requestStorageAccessForOrigin(origin)}} are called.

To <dfn type="abstract-op">determine if a site has storage access</dfn> with [=partitioned storage key=] |key| and {{Document}} |doc|, run these steps:

Expand Down Expand Up @@ -268,6 +319,7 @@ ISSUE: [since this is UA-defined, does it make sense to follow-up separately wit

Before changing the [=current entry=] of a [=session history=], run the following steps:

<!-- TODO: does rsaFor change this? We may need to modify it to 'unset all |has storage access flag| of sites requested from |doc|'...but is this really necessary? -->
1. Let |doc| be [=current entry=]'s {{Document}}.
1. Let |map| be the result of [=obtain the storage access map|obtaining the storage access map=] for |doc|'s [=Document/browsing context=]'s [=top-level browsing context=].
1. Let |key| be the result of [=generate a partitioned storage key|generating a partitioned storage key=] from |doc|.
Expand Down