diff --git a/storage-access.bs b/storage-access.bs index 79ceba8..a6c21aa 100644 --- a/storage-access.bs +++ b/storage-access.bs @@ -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]] @@ -87,7 +92,7 @@ This specification depends on the Infra standard. [[!INFRA]]

The Storage Access API

-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)}}).
@@ -99,6 +104,18 @@ Script in the <{iframe}> can call |doc|`.`{{Document/hasStorageAccess()}} to det
+
+ +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`. + +
+ Unpartitioned data 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 first-party-site context 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. @@ -139,6 +156,11 @@ To generate a partitioned storage key 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 generate a delegated partitioned storage key 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 storage access flag set 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 has storage access flag @@ -163,6 +185,7 @@ To save the storage access flag set for a [=partit partial interface Document { Promise<boolean> hasStorageAccess(); Promise<undefined> requestStorageAccess(); + Promise<undefined> requestStorageAccessForOrigin(USVString origin); }; @@ -224,9 +247,37 @@ When invoked on {{Document}} |doc|, the re ISSUE: Shouldn't step 3.7 be [=same site=]? +When invoked on {{Document}} |doc|, the requestStorageAccessForOrigin(origin) method must run these steps: + +1. Let |p| be [=a new promise=]. +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|. +

User Agent storage access policies

-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 determine if a site has storage access with [=partitioned storage key=] |key| and {{Document}} |doc|, run these steps: @@ -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: + 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|.