Skip to content

Commit

Permalink
Finish up hasStorageAccess() and requestStorageAccess().
Browse files Browse the repository at this point in the history
  • Loading branch information
hober committed Apr 14, 2020
1 parent a764b94 commit 8c9b716
Showing 1 changed file with 66 additions and 31 deletions.
97 changes: 66 additions & 31 deletions storage-access.bs
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ spec:html; type:dfn; text:current entry; url:https://html.spec.whatwg.org/multip

<em>This section is non-normative.</em>

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]]

</section>

Expand All @@ -62,7 +62,7 @@ This specification defines several additions to the HTML standard, and depends o

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

Each {{Document}} has an associated <dfn export for=Document id=storage-access-flag>has storage access flag</dfn>, initially unset.
<h3 id="the-document-object">Changes to {{Document}}</h3>

<pre class="idl">
partial interface Document {
Expand All @@ -71,52 +71,87 @@ partial interface Document {
};
</pre>

When invoked, |document|.<dfn export method for=Document><code>hasStorageAccess()</code></dfn> 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 <dfn export for=Document id=has-storage-access-flag>has storage access flag</dfn>, initially unset.

Each {{Document}} has an associated <dfn export for=Document id=was-expressly-denied-storage-access-flag>was expressly denied storage access flag</dfn>, initially unset.

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

<!-- https://developer.mozilla.org/en-US/docs/Web/API/Document/hasStorageAccess -->
<!-- https://trac.webkit.org/browser/webkit/trunk/Source/WebCore/dom/DocumentStorageAccess.cpp#L80 -->
<!-- https://hg.mozilla.org/mozilla-central/file/tip/dom/base/Document.cpp#l15512 -->

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 <a for=Document>browsing context</a> is a [=top-level browsing context=], [=resolve=] |p| with true and abort these steps.
1. If |document|'s <a for=Document>browsing context</a> is [=same origin=] with its [=top-level browsing context=], [=resolve=] |p| with true and abort these steps.
1. <span class=XXX>Finish this algorithm.</span>
1. If |doc|'s [=was expressly denied storage access flag=] is set, [=resolve=] |p| with false and abort these steps. <!-- WebKit's DocumentStorageAccess.cpp#L85 -->
1. If |doc|'s [=active sandboxing flag set=] has its [=sandboxed origin browsing context flag=] set, [=resolve=] |p| with false and abort these steps. <!-- WebKit's DocumentStorageAccess.cpp#L90 --> <!-- Gecko's Document.cpp#l15526 -->
1. If |doc|'s <a for=Document>browsing context</a> is a [=top-level browsing context=], [=resolve=] |p| with true and abort these steps. <!-- WebKit's DocumentStorageAccess.cpp#L95 --> <!-- Gecko's Document.cpp#l15531 -->
1. Let |topDoc| be the [=active document=] of |doc|'s <a for=Document>browsing context</a>'s [=top-level browsing context=].
1. If |doc| is [=same origin=] with |topDoc|, [=resolve=] |p| with true and abort these steps. <!-- WebKit's DocumentStorageAccess.cpp#L102 --> <!-- Gecko's Document.cpp#l15541 -->
1. Resolve |p| with the result of running [=determine if a document has storage access=] with |doc| and |topDoc| and abort these steps. <!-- WebKit's DocumentStorageAccess.cpp#L115 --> <!-- Gecko's Document.cpp#l15548 -->
1. [=If aborted=], return |p|.

<div class=issue>
<p>Complete this algorithm.
<p>See its <a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/hasStorageAccess">MDN page</a>, <a href="https://trac.webkit.org/browser/webkit/trunk/Source/WebCore/dom/DocumentStorageAccess.cpp#L80">WebKit implementation</a>, and <a href="https://hg.mozilla.org/mozilla-central/file/tip/dom/base/Document.cpp#l15558">Gecko implementation</a>.
</ul>
</div>
When invoked on {{Document}} |doc|, the <dfn export method for=Document><code>requestStorageAccess()</code></dfn> method must run these steps:

When invoked, |document|.<dfn export method for=Document><code>requestStorageAccess()</code></dfn> must run these steps:
<!-- https://developer.mozilla.org/en-US/docs/Web/API/Document/requestStorageAccess -->
<!-- https://trac.webkit.org/browser/webkit/trunk/Source/WebCore/dom/DocumentStorageAccess.cpp#L123 -->
<!-- https://hg.mozilla.org/mozilla-central/file/tip/dom/base/Document.cpp#l15629 -->

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 <a for=Document>browsing context</a> is a [=top-level browsing context=], [=resolve=] |p| and abort these steps.
1. If |document|'s <a for=Document>browsing context</a> 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. <span class=XXX>Remove this step when [privacycg/storage-access#10](https://github.com/privacycg/storage-access/issues/10) is resolved.</span> If |document|'s <a for=Document>browsing context</a>'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. <span class=XXX>Finish this algorithm.</span>
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. <!-- WebKit's DocumentStorageAccess.cpp#L128 --> <!-- Gecko's Document.cpp#l15604 -->
1. If the |doc|'s [=active sandboxing flag set=] has its [=sandboxed origin browsing context flag=] set, [=reject=] |p| and abort these steps. <!-- WebKit's DocumentStorageAccess.cpp#L133 --> <!-- Gecko's Document.cpp#l15618 -->
1. If |doc|'s <a for=Document>browsing context</a> is a [=top-level browsing context=], [=resolve=] |p| and abort these steps. <!-- WebKit's DocumentStorageAccess.cpp#L138 --> <!-- Gecko's Document.cpp#l15632 -->
1. Let |topDoc| be the [=active document=] of |doc|'s <a for=Document>browsing context</a>'s [=top-level browsing context=].
1. If |doc| is [=same origin=] with |topDoc|, [=resolve=] |p| and abort these steps. <!-- WebKit's DocumentStorageAccess.cpp#L146 --> <!-- Gecko's Document.cpp#l15604 --> <!-- Gecko's Document.cpp#l15657 -->
1. If |doc|'s [=active sandboxing flag set=] has its [=sandbox storage access by user activation flag=] set, [=reject=] |p| and abort these steps. <!-- WebKit's DocumentStorageAccess.cpp#L152 --> <!-- Gecko's Document.cpp#l15667 -->
1. If |doc|'s <a for=Document>browsing context</a>'s [=opener browsing context=] is not its [=top-level browsing context=], [=reject=] |p| and abort these steps. <!-- WebKit's DocumentStorageAccess.cpp#L158 --> <!-- Gecko's Document.cpp#l15673 -->
1. If the algorithm is invoked when |doc|'s {{Window}} object does not have [=transient activation=], [=reject=] |p| and abort these steps. <!-- WebKit's DocumentStorageAccess.cpp#L163 --> <!-- Gecko's Document.cpp#l15680 -->
1. [=Determine the storage access policy=] with |doc|, |topDoc|, and |p| and abort these steps. <!-- WebKit's DocumentStorageAccess.cpp#L177 --> <!-- Gecko's Document.cpp#l15685 -->
1. Set |doc|'s [=has storage access flag=], [=resolve=] |p|, and abort these steps. <!-- Gecko's Document.cpp#l15805 -->
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.

<div class=issue>
<p>Complete this algorithm.
<p>See its <a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/requestStorageAccess">MDN page</a>, <a href="https://trac.webkit.org/browser/webkit/trunk/Source/WebCore/dom/DocumentStorageAccess.cpp#L123">WebKit implementation</a>, and <a href="https://hg.mozilla.org/mozilla-central/file/tip/dom/base/Document.cpp#l15629">Gecko implementation</a>.
</ul>
</div>
<h4 id="ua-policy">User Agent storage access policies</h4>

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 <a for=Document>origin</a> 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 <dfn type="abstract-op">determine if a document has storage access</dfn> with {{Document|Documents}} |doc| and |topDoc|, run these steps:

1. Assert: |topDoc| is the [=active document=] of |doc|'s <a for=Document>browsing context</a>'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 <dfn type="abstract-op">determine the storage access policy</dfn> for {{Document|Documents}} |doc| and |topDoc| with {{Promise}} |p|, run these steps:

1. Assert: |topDoc| is the [=active document=] of |doc|'s <a for=Document>browsing context</a>'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|. <!-- WebKit's DocumentStorageAccess.cpp#L191 -->
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|. <!-- WebKit's DocumentStorageAccess.cpp#L181 -->
1. Unset |doc|'s [=has storage access flag=].
1. Set |doc|'s [=was expressly denied storage access flag=].
1. [=Reject=] |p|. <!-- WebKit's DocumentStorageAccess.cpp#L194 --> <!-- Gecko's Document.cpp#l15805 -->

<h3 id="navigation">Changes to navigation</h3>

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.

<h3 id="storage">Changes to various client-side storage mechanisms</h3>

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?

<h4 id="cookies">Cookies</h4>
Expand Down

0 comments on commit 8c9b716

Please sign in to comment.