diff --git a/storage-access.bs b/storage-access.bs index 1182429..94fac66 100644 --- a/storage-access.bs +++ b/storage-access.bs @@ -50,9 +50,9 @@ spec:html; type:dfn; text:current entry; url:https://html.spec.whatwg.org/multip This section is non-normative. -Browsers sometimes block access to client-side storage mechanisms in third-party contexts. This can break authenticated embeds such as commenting widgets, which often rely on cookies for authentication. +User Agents sometimes block access to client-side storage mechanisms in third-party contexts. This can break authenticated embeds such as commenting widgets, which often rely on cookies for authentication. -The Storage Access API enables cross-origin iframes to request and be granted access to their client-side storage, so that authenticated embeds can work in such browsers. [[STORAGE-ACCESS-INTRO]] +The Storage Access API enables cross-origin <{iframe}>s to request and be granted access to their client-side storage, so that authenticated embeds can work in such User Agents. [[STORAGE-ACCESS-INTRO]] @@ -62,7 +62,7 @@ This specification defines several additions to the HTML standard, and depends o

The Storage Access API

-Each {{Document}} has an associated has storage access flag, initially unset. +

Changes to {{Document}}

 partial interface Document {
@@ -71,52 +71,87 @@ partial interface Document {
 };
 
-When invoked, |document|.hasStorageAccess() must run these steps: +This specification defines two methods on {{Document}}: {{Document/hasStorageAccess()}} and {{Document/requestStorageAccess()}}. The {{Document/hasStorageAccess()}} method returns a {{Promise}} that resolves with a {{boolean}} indicating whether the document has access to its first-party storage. The {{Document/requestStorageAccess()}} method returns a {{Promise}} that resolves when the document has been granted access to its first-party storage, and rejects otherwise. + +Each {{Document}} has an associated has storage access flag, initially unset. + +Each {{Document}} has an associated was expressly denied storage access flag, initially unset. + +When invoked on {{Document}} |doc|, the hasStorageAccess() method must run these steps: + + + + 1. Let |p| be [=a new promise=]. -1. If |document|'s [=has storage access flag=] is set, [=resolve=] |p| with true and abort these steps. -1. If the |document|'s [=active sandboxing flag set=] has its [=sandboxed origin browsing context flag=] set, [=resolve=] |p| with false and abort these steps. -1. If |document|'s browsing context is a [=top-level browsing context=], [=resolve=] |p| with true and abort these steps. -1. If |document|'s browsing context is [=same origin=] with its [=top-level browsing context=], [=resolve=] |p| with true and abort these steps. -1. Finish this algorithm. +1. If |doc|'s [=was expressly denied storage access flag=] is set, [=resolve=] |p| with false and abort these steps. +1. If |doc|'s [=active sandboxing flag set=] has its [=sandboxed origin browsing context flag=] set, [=resolve=] |p| with false and abort these steps. +1. If |doc|'s browsing context is a [=top-level browsing context=], [=resolve=] |p| with true and abort these steps. +1. Let |topDoc| be the [=active document=] of |doc|'s browsing context's [=top-level browsing context=]. +1. If |doc| is [=same origin=] with |topDoc|, [=resolve=] |p| with true and abort these steps. +1. Resolve |p| with the result of running [=determine if a document has storage access=] with |doc| and |topDoc| and abort these steps. 1. [=If aborted=], return |p|. -
-

Complete this algorithm. -

See its MDN page, WebKit implementation, and Gecko implementation. - -

+When invoked on {{Document}} |doc|, the requestStorageAccess() method must run these steps: -When invoked, |document|.requestStorageAccess() must run these steps: + + + 1. Let |p| be [=a new promise=]. -1. If |document|'s [=has storage access flag=] is set, [=resolve=] |p| and abort these steps. -1. If the |document|'s [=active sandboxing flag set=] has its [=sandboxed origin browsing context flag=] set, [=reject=] |p| and abort these steps. -1. If |document|'s [=has storage access flag=] is unset, [=reject=] |p| and abort these steps. -1. If |document|'s browsing context is a [=top-level browsing context=], [=resolve=] |p| and abort these steps. -1. If |document|'s browsing context is [=same origin=] with its [=top-level browsing context=], [=resolve=] |p| and abort these steps. -1. If the |document|'s {{Window}} object has [=transient activation=] and the |document|'s [=active sandboxing flag set=] has its [=sandbox storage access by user activation flag=] set, [=reject=] |p| and abort these steps. -1. Remove this step when [privacycg/storage-access#10](https://github.com/privacycg/storage-access/issues/10) is resolved. If |document|'s browsing context's [=opener browsing context=] is not its [=top-level browsing context=], [=reject=] |p| and abort these steps. -1. If the algorithm is invoked when the |document|'s {{Window}} object does not have [=transient activation=], [=reject=] |p| and abort these steps. -1. Finish this algorithm. +1. If |doc|'s [=was expressly denied storage access flag=] is set, [=reject=] |p| and abort these steps. +1. If |doc|'s [=has storage access flag=] is set, [=resolve=] |p| and abort these steps. +1. If the |doc|'s [=active sandboxing flag set=] has its [=sandboxed origin browsing context flag=] set, [=reject=] |p| and abort these steps. +1. If |doc|'s browsing context is a [=top-level browsing context=], [=resolve=] |p| and abort these steps. +1. Let |topDoc| be the [=active document=] of |doc|'s browsing context's [=top-level browsing context=]. +1. If |doc| is [=same origin=] with |topDoc|, [=resolve=] |p| and abort these steps. +1. If |doc|'s [=active sandboxing flag set=] has its [=sandbox storage access by user activation flag=] set, [=reject=] |p| and abort these steps. +1. If |doc|'s browsing context's [=opener browsing context=] is not its [=top-level browsing context=], [=reject=] |p| and abort these steps. +1. If the algorithm is invoked when |doc|'s {{Window}} object does not have [=transient activation=], [=reject=] |p| and abort these steps. +1. [=Determine the storage access policy=] with |doc|, |topDoc|, and |p| and abort these steps. +1. Set |doc|'s [=has storage access flag=], [=resolve=] |p|, and abort these steps. 1. [=If aborted=], return |p|. -ISSUE(10): Provide mechanism for nested iframes to request storage access +ISSUE(10): Remove step 9 if we determine that nested <{iframe}>s should be able to request storage access. -
-

Complete this algorithm. -

See its MDN page, WebKit implementation, and Gecko implementation. - -

+

User Agent storage access policies

+ +Different User Agents have different policies around whether or not third-party <{iframe}>'s may access data placed into client-side storage mechanisms when the <{iframe}>'s {{Document}}'s origin was loaded in a first-party context. User Agents check these policies when client-side storage is accessed (see [[#storage]]) as well as by {{Document/hasStorageAccess()}} and {{Document/requestStorageAccess()}}. + +When required to determine if a document has storage access with {{Document|Documents}} |doc| and |topDoc|, run these steps: + +1. Assert: |topDoc| is the [=active document=] of |doc|'s browsing context's [=top-level browsing context=]. +1. If |doc|'s [=has storage access flag=] is set, return true. +1. Let |has storage access| (a {{boolean}}) be the result of running a UA-defined set of steps to determine if |doc| has storage access when it is loaded in a third-party context on |topDoc|. +1. If |has storage access| is true, set |doc|'s [=has storage access flag=]. +1. Return |has storage access|. + +When required to determine the storage access policy for {{Document|Documents}} |doc| and |topDoc| with {{Promise}} |p|, run these steps: + +1. Assert: |topDoc| is the [=active document=] of |doc|'s browsing context's [=top-level browsing context=]. +1. Let |should implicitly grant| and |should implicitly deny| (both {{boolean|booleans}}) be the result of running a UA-defined set of steps to determine if |doc|'s request for storage access on |topDoc| should be granted or denied without prompting the user. +1. If |should implicitly grant| is true, [=resolve=] |p| and abort these steps. +1. If |should implicitly deny| is true, [=reject=] |p| and abort these steps. +1. Ask the user if they would like to grant |doc| access to its storage when it is loaded in a third-party context on |topDoc|, and wait for an answer. Let |user expression of permission| (a {{boolean}}) be the result. + + Note: if |user expression of permission| is false, the user **expressly chose** to deny |doc| access to its storage. +1. If |user expression of permission| is true, [=resolve=] |p|. +1. If |user expression of permission| is false, let |w| be |doc|'s {{Window}} object and run these steps: + 1. If |w| has [=transient activation=] and |user expression of permission| is false, [=consume user activation=] with |w|. + 1. Unset |doc|'s [=has storage access flag=]. + 1. Set |doc|'s [=was expressly denied storage access flag=]. + 1. [=Reject=] |p|. -When the [=current entry=] of a [=browsing context=]'s [=session history=] changes, the [=has storage access flag=] of the {{Document}} of the old [=current entry=] is unset. +Before changing the [=current entry=] of a [=session history=], unset the [=has storage access flag=] of the old [=current entry=]'s {{Document}}, if it has one. ISSUE: Finish this section.

Changes to various client-side storage mechanisms

+ISSUE: Write this section. For each kind of client-side storage affected, modify them to invoke [=determine if a document has storage access=] & modify their behavior based on the result. + ISSUE(4): Should this API affect client-side storage other than cookies?

Cookies