Introduce Storage Access API (document parts) as an experimental feature
authorwilander@apple.com <wilander@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 13 Sep 2017 17:47:52 +0000 (17:47 +0000)
committerwilander@apple.com <wilander@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 13 Sep 2017 17:47:52 +0000 (17:47 +0000)
https://bugs.webkit.org/show_bug.cgi?id=175759
<rdar://problem/33666847>

Reviewed by Alex Christensen.

Source/WebCore:

Storage Access API is an experimental feature which allows cross-origin,
sandboxed iframes to request access to their first-party storage (as
opposed to partitioned storage). This might be restricted to cookies or
might cover all stateful mechanisms.

It introduces the following three developer-facing things:
- A new readonly attribute, document.hasStorageAccess.
- A new function, document.requestStorageAccess().
- A new iframe sandbox token, allow-storage-access-by-user-activation.

Tests: http/tests/loading/resourceLoadStatistics/request-and-deny-storage-access-cross-origin-iframe.html
       http/tests/loading/resourceLoadStatistics/request-and-deny-storage-access-cross-origin-sandboxed-iframe.html
       http/tests/loading/resourceLoadStatistics/request-and-grant-storage-access-cross-origin-iframe.html
       http/tests/loading/resourceLoadStatistics/request-and-grant-storage-access-cross-origin-sandboxed-iframe.html
       http/tests/loading/resourceLoadStatistics/request-storage-access-cross-origin-sandboxed-iframe-with-unique-origin.html
       http/tests/loading/resourceLoadStatistics/request-storage-access-cross-origin-sandboxed-iframe-without-allow-token.html
       http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-iframe.html
       http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-sandboxed-iframe-without-allow-token.html
       http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-sandboxed-iframe.html
       http/tests/loading/resourceLoadStatistics/request-storage-access-top-frame.html

* dom/Document.cpp:
(WebCore::Document::requestStorageAccess):
* dom/Document.h:
(WebCore::Document::hasStorageAccess const):
(WebCore::Document::setUserGrantsStorageAccessOverride):
    See comments on WebCore::Internals below.
* dom/Document.idl:
* dom/SecurityContext.cpp:
(WebCore::SecurityContext::isSupportedSandboxPolicy):
(WebCore::SecurityContext::parseSandboxPolicy):
    Support for allow-storage-access-by-user-activation.
* dom/SecurityContext.h:
* loader/ResourceLoadObserver.cpp:
(WebCore::ResourceLoadObserver::registerStorageAccess):
    Newly granted storage access is reported to
    WebCore::ResourceLoadObserver.
* loader/ResourceLoadObserver.h:
* loader/ResourceLoadStatistics.cpp:
(WebCore::encodeHashSet):
(WebCore::ResourceLoadStatistics::encode const):
(WebCore::decodeHashSet):
(WebCore::ResourceLoadStatistics::decode):
(WebCore::appendHashSet):
(WebCore::ResourceLoadStatistics::toString const):
(WebCore::mergeHashSet):
(WebCore::ResourceLoadStatistics::merge):
    Storage of the new type of data.
* loader/ResourceLoadStatistics.h:
* page/Settings.in:
* testing/Internals.cpp:
(WebCore::Internals::resetToConsistentState):
(WebCore::Internals::setUserGrantsStorageAccess):
* testing/Internals.h:
* testing/Internals.idl:
    Added setUserGrantsStorageAccess(). It is used to
    override the eventSender's keyboard input which
    always results in a cancel action on the confirm()
    dialog.

Source/WebKit:

Storage Access API is an experimental feature which allows cross-origin,
sandboxed iframes to request access to their first-party storage (as
opposed to partitioned storage). This might be restricted to cookies or
might cover all stateful mechanisms.

It introduces the following three developer-facing things:
- A new readonly attribute, document.hasStorageAccess.
- A new function, document.requestStorageAccess().
- A new iframe sandbox token, allow-storage-access-by-user-activation.

* Shared/WebCoreArgumentCoders.cpp:
(IPC::ArgumentCoder<ResourceLoadStatistics>::encode):
(IPC::ArgumentCoder<ResourceLoadStatistics>::decode):
    Storage handling of the new type of data.
* Shared/WebPreferencesDefinitions.h:
* UIProcess/API/C/WKPreferences.cpp:
(WKPreferencesSetStorageAccessAPIEnabled):
(WKPreferencesGetStorageAccessAPIEnabled):
* UIProcess/API/C/WKPreferencesRefPrivate.h:
* UIProcess/WebResourceLoadStatisticsStore.cpp:
    Bumped the model version from 9 to 10.
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::updatePreferences):

Tools:

* WebKitTestRunner/TestController.cpp:
(WTR::TestController::resetPreferencesToConsistentValues):
    Turns the feature on for tests.

LayoutTests:

Storage Access API is an experimental feature which allows cross-origin,
sandboxed iframes to request access to their first-party storage (as
opposed to partitioned storage). This might be restricted to cookies or
might cover all stateful mechanisms.

It introduces the following three developer-facing things:
- A new readonly attribute, document.hasStorageAccess.
- A new function, document.requestStorageAccess().
- A new iframe sandbox token, allow-storage-access-by-user-activation.

* http/tests/loading/resourceLoadStatistics/request-and-deny-storage-access-cross-origin-iframe-expected.txt: Added.
* http/tests/loading/resourceLoadStatistics/request-and-deny-storage-access-cross-origin-iframe.html: Added.
* http/tests/loading/resourceLoadStatistics/request-and-deny-storage-access-cross-origin-sandboxed-iframe-expected.txt: Added.
* http/tests/loading/resourceLoadStatistics/request-and-deny-storage-access-cross-origin-sandboxed-iframe.html: Added.
* http/tests/loading/resourceLoadStatistics/request-and-grant-storage-access-cross-origin-iframe-expected.txt: Added.
* http/tests/loading/resourceLoadStatistics/request-and-grant-storage-access-cross-origin-iframe.html: Added.
* http/tests/loading/resourceLoadStatistics/request-and-grant-storage-access-cross-origin-sandboxed-iframe-expected.txt: Added.
* http/tests/loading/resourceLoadStatistics/request-and-grant-storage-access-cross-origin-sandboxed-iframe.html: Added.
* http/tests/loading/resourceLoadStatistics/request-storage-access-cross-origin-sandboxed-iframe-with-unique-origin-expected.txt: Added.
* http/tests/loading/resourceLoadStatistics/request-storage-access-cross-origin-sandboxed-iframe-with-unique-origin.html: Added.
* http/tests/loading/resourceLoadStatistics/request-storage-access-cross-origin-sandboxed-iframe-without-allow-token-expected.txt: Added.
* http/tests/loading/resourceLoadStatistics/request-storage-access-cross-origin-sandboxed-iframe-without-allow-token.html: Added.
* http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-iframe-expected.txt: Added.
* http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-iframe.html: Added.
* http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-sandboxed-iframe-expected.txt: Added.
* http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-sandboxed-iframe-without-allow-token-expected.txt: Added.
* http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-sandboxed-iframe-without-allow-token.html: Added.
* http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-sandboxed-iframe.html: Added.
* http/tests/loading/resourceLoadStatistics/request-storage-access-top-frame-expected.txt: Added.
* http/tests/loading/resourceLoadStatistics/request-storage-access-top-frame.html: Added.
* http/tests/loading/resourceLoadStatistics/resources/request-storage-access-iframe.html: Added.
* platform/mac-wk2/TestExpectations:
    New test cases that require a user gesture marked as [ Pass ].
    Also removed reference to (now closed) https://bugs.webkit.org/show_bug.cgi?id=175170.
* platform/wk2/TestExpectations:
    New test case request-storage-access-top-frame.html marked as [ Pass ].

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@221976 268f45cc-cd09-0410-ab3c-d52691b4dbfc

47 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/loading/resourceLoadStatistics/request-and-deny-storage-access-cross-origin-iframe-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/loading/resourceLoadStatistics/request-and-deny-storage-access-cross-origin-iframe.html [new file with mode: 0644]
LayoutTests/http/tests/loading/resourceLoadStatistics/request-and-deny-storage-access-cross-origin-sandboxed-iframe-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/loading/resourceLoadStatistics/request-and-deny-storage-access-cross-origin-sandboxed-iframe.html [new file with mode: 0644]
LayoutTests/http/tests/loading/resourceLoadStatistics/request-and-grant-storage-access-cross-origin-iframe-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/loading/resourceLoadStatistics/request-and-grant-storage-access-cross-origin-iframe.html [new file with mode: 0644]
LayoutTests/http/tests/loading/resourceLoadStatistics/request-and-grant-storage-access-cross-origin-sandboxed-iframe-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/loading/resourceLoadStatistics/request-and-grant-storage-access-cross-origin-sandboxed-iframe.html [new file with mode: 0644]
LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-cross-origin-sandboxed-iframe-with-unique-origin-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-cross-origin-sandboxed-iframe-with-unique-origin.html [new file with mode: 0644]
LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-cross-origin-sandboxed-iframe-without-allow-token-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-cross-origin-sandboxed-iframe-without-allow-token.html [new file with mode: 0644]
LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-iframe-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-iframe.html [new file with mode: 0644]
LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-sandboxed-iframe-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-sandboxed-iframe-without-allow-token-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-sandboxed-iframe-without-allow-token.html [new file with mode: 0644]
LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-sandboxed-iframe.html [new file with mode: 0644]
LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-top-frame-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-top-frame.html [new file with mode: 0644]
LayoutTests/http/tests/loading/resourceLoadStatistics/resources/request-storage-access-iframe.html [new file with mode: 0644]
LayoutTests/platform/mac-wk2/TestExpectations
LayoutTests/platform/wk2/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Document.h
Source/WebCore/dom/Document.idl
Source/WebCore/dom/SecurityContext.cpp
Source/WebCore/dom/SecurityContext.h
Source/WebCore/loader/ResourceLoadObserver.cpp
Source/WebCore/loader/ResourceLoadObserver.h
Source/WebCore/loader/ResourceLoadStatistics.cpp
Source/WebCore/loader/ResourceLoadStatistics.h
Source/WebCore/page/Settings.in
Source/WebCore/testing/Internals.cpp
Source/WebCore/testing/Internals.h
Source/WebCore/testing/Internals.idl
Source/WebKit/ChangeLog
Source/WebKit/Shared/WebCoreArgumentCoders.cpp
Source/WebKit/Shared/WebPreferencesDefinitions.h
Source/WebKit/UIProcess/API/C/WKPreferences.cpp
Source/WebKit/UIProcess/API/C/WKPreferencesRefPrivate.h
Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.cpp
Source/WebKit/WebProcess/WebPage/WebPage.cpp
Tools/ChangeLog
Tools/WebKitTestRunner/TestController.cpp

index 7c95d4e..f8383fb 100644 (file)
@@ -1,3 +1,48 @@
+2017-09-13  John Wilander  <wilander@apple.com>
+
+        Introduce Storage Access API (document parts) as an experimental feature
+        https://bugs.webkit.org/show_bug.cgi?id=175759
+        <rdar://problem/33666847>
+
+        Reviewed by Alex Christensen.
+
+        Storage Access API is an experimental feature which allows cross-origin,
+        sandboxed iframes to request access to their first-party storage (as
+        opposed to partitioned storage). This might be restricted to cookies or
+        might cover all stateful mechanisms.
+
+        It introduces the following three developer-facing things:
+        - A new readonly attribute, document.hasStorageAccess.
+        - A new function, document.requestStorageAccess().
+        - A new iframe sandbox token, allow-storage-access-by-user-activation.
+
+        * http/tests/loading/resourceLoadStatistics/request-and-deny-storage-access-cross-origin-iframe-expected.txt: Added.
+        * http/tests/loading/resourceLoadStatistics/request-and-deny-storage-access-cross-origin-iframe.html: Added.
+        * http/tests/loading/resourceLoadStatistics/request-and-deny-storage-access-cross-origin-sandboxed-iframe-expected.txt: Added.
+        * http/tests/loading/resourceLoadStatistics/request-and-deny-storage-access-cross-origin-sandboxed-iframe.html: Added.
+        * http/tests/loading/resourceLoadStatistics/request-and-grant-storage-access-cross-origin-iframe-expected.txt: Added.
+        * http/tests/loading/resourceLoadStatistics/request-and-grant-storage-access-cross-origin-iframe.html: Added.
+        * http/tests/loading/resourceLoadStatistics/request-and-grant-storage-access-cross-origin-sandboxed-iframe-expected.txt: Added.
+        * http/tests/loading/resourceLoadStatistics/request-and-grant-storage-access-cross-origin-sandboxed-iframe.html: Added.
+        * http/tests/loading/resourceLoadStatistics/request-storage-access-cross-origin-sandboxed-iframe-with-unique-origin-expected.txt: Added.
+        * http/tests/loading/resourceLoadStatistics/request-storage-access-cross-origin-sandboxed-iframe-with-unique-origin.html: Added.
+        * http/tests/loading/resourceLoadStatistics/request-storage-access-cross-origin-sandboxed-iframe-without-allow-token-expected.txt: Added.
+        * http/tests/loading/resourceLoadStatistics/request-storage-access-cross-origin-sandboxed-iframe-without-allow-token.html: Added.
+        * http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-iframe-expected.txt: Added.
+        * http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-iframe.html: Added.
+        * http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-sandboxed-iframe-expected.txt: Added.
+        * http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-sandboxed-iframe-without-allow-token-expected.txt: Added.
+        * http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-sandboxed-iframe-without-allow-token.html: Added.
+        * http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-sandboxed-iframe.html: Added.
+        * http/tests/loading/resourceLoadStatistics/request-storage-access-top-frame-expected.txt: Added.
+        * http/tests/loading/resourceLoadStatistics/request-storage-access-top-frame.html: Added.
+        * http/tests/loading/resourceLoadStatistics/resources/request-storage-access-iframe.html: Added.
+        * platform/mac-wk2/TestExpectations:
+            New test cases that require a user gesture marked as [ Pass ].
+            Also removed reference to (now closed) https://bugs.webkit.org/show_bug.cgi?id=175170.
+        * platform/wk2/TestExpectations:
+            New test case request-storage-access-top-frame.html marked as [ Pass ].
+
 2017-09-13  Carlos Garcia Campos  <cgarcia@igalia.com>
 
         [HarfBuzz] Wrong offset returned by HarfBuzzShaper::offsetForPosition in some cases
diff --git a/LayoutTests/http/tests/loading/resourceLoadStatistics/request-and-deny-storage-access-cross-origin-iframe-expected.txt b/LayoutTests/http/tests/loading/resourceLoadStatistics/request-and-deny-storage-access-cross-origin-iframe-expected.txt
new file mode 100644 (file)
index 0000000..2b150e7
--- /dev/null
@@ -0,0 +1,20 @@
+main frame - didStartProvisionalLoadForFrame
+main frame - didCommitLoadForFrame
+frame "theIframe" - didStartProvisionalLoadForFrame
+main frame - didFinishDocumentLoadForFrame
+frame "theIframe" - didCommitLoadForFrame
+frame "theIframe" - didFinishDocumentLoadForFrame
+CONSOLE MESSAGE: line 70: PASS document.hasStorageAccess was denied.
+frame "theIframe" - didHandleOnloadEventsForFrame
+main frame - didHandleOnloadEventsForFrame
+frame "theIframe" - didFinishLoadForFrame
+main frame - didFinishLoadForFrame
+Tests that cross-origin iframe storage access is denied if the iframe is not sandboxed.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/loading/resourceLoadStatistics/request-and-deny-storage-access-cross-origin-iframe.html b/LayoutTests/http/tests/loading/resourceLoadStatistics/request-and-deny-storage-access-cross-origin-iframe.html
new file mode 100644 (file)
index 0000000..3ee9b57
--- /dev/null
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script src="/js-test-resources/ui-helper.js"></script>
+    <script>
+        description("Tests that cross-origin iframe storage access is denied if the iframe is not sandboxed.");
+        jsTestIsAsync = true;
+
+        function activateElement(elementId) {
+            var element = document.getElementById(elementId);
+            var centerX = element.offsetLeft + element.offsetWidth / 2;
+            var centerY = element.offsetTop + element.offsetHeight / 2;
+            UIHelper.activateAt(centerX, centerY).then(
+                function () {
+                    if (window.eventSender)
+                        eventSender.keyDown("escape");
+                    finishJSTest();
+                },
+                function () {
+                    testFailed("Promise rejected.");
+                    finishJSTest();
+                }
+            );
+        }
+
+        function runTest() {
+            activateElement("theIframe");
+        }
+    </script>
+</head>
+<body>
+    <iframe onload="runTest()" id="theIframe" src="http://localhost:8000/loading/resourceLoadStatistics/resources/request-storage-access-iframe.html#userShouldDenyAccess,userShouldNotBeConsulted,policyShouldDenyAccess,isNotSameOriginIframe"></iframe>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/http/tests/loading/resourceLoadStatistics/request-and-deny-storage-access-cross-origin-sandboxed-iframe-expected.txt b/LayoutTests/http/tests/loading/resourceLoadStatistics/request-and-deny-storage-access-cross-origin-sandboxed-iframe-expected.txt
new file mode 100644 (file)
index 0000000..fa66a2d
--- /dev/null
@@ -0,0 +1,22 @@
+main frame - didStartProvisionalLoadForFrame
+main frame - didCommitLoadForFrame
+frame "theIframe" - didStartProvisionalLoadForFrame
+main frame - didFinishDocumentLoadForFrame
+frame "theIframe" - didCommitLoadForFrame
+frame "theIframe" - didFinishDocumentLoadForFrame
+CONFIRM: Do you want to use your  ID on ?
+CONFIRM: Do you want to use your  ID on ?
+CONSOLE MESSAGE: line 70: PASS document.hasStorageAccess was denied.
+frame "theIframe" - didHandleOnloadEventsForFrame
+main frame - didHandleOnloadEventsForFrame
+frame "theIframe" - didFinishLoadForFrame
+main frame - didFinishLoadForFrame
+Tests that cross-origin iframe storage access is denied if the iframe is sandboxed, has the allow token, but the user opts out.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/loading/resourceLoadStatistics/request-and-deny-storage-access-cross-origin-sandboxed-iframe.html b/LayoutTests/http/tests/loading/resourceLoadStatistics/request-and-deny-storage-access-cross-origin-sandboxed-iframe.html
new file mode 100644 (file)
index 0000000..73a0df6
--- /dev/null
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script src="/js-test-resources/ui-helper.js"></script>
+    <script>
+        description("Tests that cross-origin iframe storage access is denied if the iframe is sandboxed, has the allow token, but the user opts out.");
+        jsTestIsAsync = true;
+
+        function activateElement(elementId) {
+            var element = document.getElementById(elementId);
+            var centerX = element.offsetLeft + element.offsetWidth / 2;
+            var centerY = element.offsetTop + element.offsetHeight / 2;
+            UIHelper.activateAt(centerX, centerY).then(
+                function () {
+                    if (window.eventSender)
+                        eventSender.keyDown("escape");
+                    finishJSTest();
+                },
+                function () {
+                    testFailed("Promise rejected.");
+                    finishJSTest();
+                }
+            );
+        }
+
+        function runTest() {
+            activateElement("theIframe");
+        }
+    </script>
+</head>
+<body>
+    <iframe sandbox="allow-storage-access-by-user-activation allow-scripts allow-same-origin allow-modals" onload="runTest()" id="theIframe" src="http://localhost:8000/loading/resourceLoadStatistics/resources/request-storage-access-iframe.html#userShouldDenyAccess,userShouldBeConsulted,policyShouldGrantAccess,isNotSameOriginIframe"></iframe>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/http/tests/loading/resourceLoadStatistics/request-and-grant-storage-access-cross-origin-iframe-expected.txt b/LayoutTests/http/tests/loading/resourceLoadStatistics/request-and-grant-storage-access-cross-origin-iframe-expected.txt
new file mode 100644 (file)
index 0000000..2b150e7
--- /dev/null
@@ -0,0 +1,20 @@
+main frame - didStartProvisionalLoadForFrame
+main frame - didCommitLoadForFrame
+frame "theIframe" - didStartProvisionalLoadForFrame
+main frame - didFinishDocumentLoadForFrame
+frame "theIframe" - didCommitLoadForFrame
+frame "theIframe" - didFinishDocumentLoadForFrame
+CONSOLE MESSAGE: line 70: PASS document.hasStorageAccess was denied.
+frame "theIframe" - didHandleOnloadEventsForFrame
+main frame - didHandleOnloadEventsForFrame
+frame "theIframe" - didFinishLoadForFrame
+main frame - didFinishLoadForFrame
+Tests that cross-origin iframe storage access is denied if the iframe is not sandboxed.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/loading/resourceLoadStatistics/request-and-grant-storage-access-cross-origin-iframe.html b/LayoutTests/http/tests/loading/resourceLoadStatistics/request-and-grant-storage-access-cross-origin-iframe.html
new file mode 100644 (file)
index 0000000..a14a818
--- /dev/null
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script src="/js-test-resources/ui-helper.js"></script>
+    <script>
+        description("Tests that cross-origin iframe storage access is denied if the iframe is not sandboxed.");
+        jsTestIsAsync = true;
+
+        function activateElement(elementId) {
+            var element = document.getElementById(elementId);
+            var centerX = element.offsetLeft + element.offsetWidth / 2;
+            var centerY = element.offsetTop + element.offsetHeight / 2;
+            UIHelper.activateAt(centerX, centerY).then(
+                function () {
+                    if (window.eventSender)
+                        eventSender.keyDown("escape");
+                        finishJSTest();
+                    },
+                function () {
+                    testFailed("Promise rejected.");
+                    finishJSTest();
+                }
+            );
+        }
+
+        function runTest() {
+            activateElement("theIframe");
+        }
+    </script>
+</head>
+<body>
+    <iframe onload="runTest()" id="theIframe" src="http://localhost:8000/loading/resourceLoadStatistics/resources/request-storage-access-iframe.html#userShouldGrantAccess,userShouldNotBeConsulted,policyShouldDenyAccess,isNotSameOriginIframe"></iframe>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/http/tests/loading/resourceLoadStatistics/request-and-grant-storage-access-cross-origin-sandboxed-iframe-expected.txt b/LayoutTests/http/tests/loading/resourceLoadStatistics/request-and-grant-storage-access-cross-origin-sandboxed-iframe-expected.txt
new file mode 100644 (file)
index 0000000..8b2370c
--- /dev/null
@@ -0,0 +1,21 @@
+main frame - didStartProvisionalLoadForFrame
+main frame - didCommitLoadForFrame
+frame "theIframe" - didStartProvisionalLoadForFrame
+main frame - didFinishDocumentLoadForFrame
+frame "theIframe" - didCommitLoadForFrame
+frame "theIframe" - didFinishDocumentLoadForFrame
+CONFIRM: Do you want to use your  ID on ?
+CONSOLE MESSAGE: line 66: PASS document.hasStorageAccess was granted.
+frame "theIframe" - didHandleOnloadEventsForFrame
+main frame - didHandleOnloadEventsForFrame
+frame "theIframe" - didFinishLoadForFrame
+main frame - didFinishLoadForFrame
+Tests that cross-origin iframe storage access is granted if the iframe is sandboxed, has the allow token, and the user opts in.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/loading/resourceLoadStatistics/request-and-grant-storage-access-cross-origin-sandboxed-iframe.html b/LayoutTests/http/tests/loading/resourceLoadStatistics/request-and-grant-storage-access-cross-origin-sandboxed-iframe.html
new file mode 100644 (file)
index 0000000..a809eab
--- /dev/null
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script src="/js-test-resources/ui-helper.js"></script>
+    <script>
+        description("Tests that cross-origin iframe storage access is granted if the iframe is sandboxed, has the allow token, and the user opts in.");
+        jsTestIsAsync = true;
+
+        function activateElement(elementId) {
+            var element = document.getElementById(elementId);
+            var centerX = element.offsetLeft + element.offsetWidth / 2;
+            var centerY = element.offsetTop + element.offsetHeight / 2;
+            UIHelper.activateAt(centerX, centerY).then(
+                function () {
+                    if (window.eventSender)
+                        eventSender.keyDown("escape");
+                    finishJSTest();
+                },
+                function () {
+                    testFailed("Promise rejected.");
+                    finishJSTest();
+                }
+            );
+        }
+
+        function runTest() {
+            activateElement("theIframe");
+        }
+    </script>
+</head>
+<body>
+    <iframe sandbox="allow-storage-access-by-user-activation allow-scripts allow-same-origin allow-modals" onload="runTest()" id="theIframe" src="http://localhost:8000/loading/resourceLoadStatistics/resources/request-storage-access-iframe.html#userShouldGrantAccess,userShouldBeConsulted,policyShouldGrantAccess,isNotSameOriginIframe"></iframe>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-cross-origin-sandboxed-iframe-with-unique-origin-expected.txt b/LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-cross-origin-sandboxed-iframe-with-unique-origin-expected.txt
new file mode 100644 (file)
index 0000000..4bf94cb
--- /dev/null
@@ -0,0 +1,20 @@
+main frame - didStartProvisionalLoadForFrame
+main frame - didCommitLoadForFrame
+frame "theIframe" - didStartProvisionalLoadForFrame
+main frame - didFinishDocumentLoadForFrame
+frame "theIframe" - didCommitLoadForFrame
+frame "theIframe" - didFinishDocumentLoadForFrame
+CONSOLE MESSAGE: line 70: PASS document.hasStorageAccess was denied.
+frame "theIframe" - didHandleOnloadEventsForFrame
+main frame - didHandleOnloadEventsForFrame
+frame "theIframe" - didFinishLoadForFrame
+main frame - didFinishLoadForFrame
+Tests that cross-origin iframe storage access is denied if the iframe is sandboxed and has the unique origin because it lacks the allow-same-origin token.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-cross-origin-sandboxed-iframe-with-unique-origin.html b/LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-cross-origin-sandboxed-iframe-with-unique-origin.html
new file mode 100644 (file)
index 0000000..1c7b26e
--- /dev/null
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script src="/js-test-resources/ui-helper.js"></script>
+    <script>
+        description("Tests that cross-origin iframe storage access is denied if the iframe is sandboxed and has the unique origin because it lacks the allow-same-origin token.");
+        jsTestIsAsync = true;
+
+        function activateElement(elementId) {
+            var element = document.getElementById(elementId);
+            var centerX = element.offsetLeft + element.offsetWidth / 2;
+            var centerY = element.offsetTop + element.offsetHeight / 2;
+            UIHelper.activateAt(centerX, centerY).then(
+                function () {
+                    if (window.eventSender)
+                        eventSender.keyDown("escape");
+                    finishJSTest();
+                },
+                function () {
+                    testFailed("Promise rejected.");
+                    finishJSTest();
+                }
+            );
+        }
+
+        function runTest() {
+            activateElement("theIframe");
+        }
+    </script>
+</head>
+<body>
+    <iframe sandbox="allow-storage-access-by-user-activation allow-scripts allow-modals" onload="runTest()" id="theIframe" src="http://localhost:8000/loading/resourceLoadStatistics/resources/request-storage-access-iframe.html#userShouldGrantAccess,userShouldNotBeConsulted,policyShouldDenyAccess,isNotSameOriginIframe"></iframe>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-cross-origin-sandboxed-iframe-without-allow-token-expected.txt b/LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-cross-origin-sandboxed-iframe-without-allow-token-expected.txt
new file mode 100644 (file)
index 0000000..20d7846
--- /dev/null
@@ -0,0 +1,20 @@
+main frame - didStartProvisionalLoadForFrame
+main frame - didCommitLoadForFrame
+frame "theIframe" - didStartProvisionalLoadForFrame
+main frame - didFinishDocumentLoadForFrame
+frame "theIframe" - didCommitLoadForFrame
+frame "theIframe" - didFinishDocumentLoadForFrame
+CONSOLE MESSAGE: line 70: PASS document.hasStorageAccess was denied.
+frame "theIframe" - didHandleOnloadEventsForFrame
+main frame - didHandleOnloadEventsForFrame
+frame "theIframe" - didFinishLoadForFrame
+main frame - didFinishLoadForFrame
+Tests that cross-origin iframe storage access is denied if the iframe is sandboxed and doesn't have the allow token.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-cross-origin-sandboxed-iframe-without-allow-token.html b/LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-cross-origin-sandboxed-iframe-without-allow-token.html
new file mode 100644 (file)
index 0000000..9560bf3
--- /dev/null
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script src="/js-test-resources/ui-helper.js"></script>
+    <script>
+        description("Tests that cross-origin iframe storage access is denied if the iframe is sandboxed and doesn't have the allow token.");
+        jsTestIsAsync = true;
+
+        function activateElement(elementId) {
+            var element = document.getElementById(elementId);
+            var centerX = element.offsetLeft + element.offsetWidth / 2;
+            var centerY = element.offsetTop + element.offsetHeight / 2;
+            UIHelper.activateAt(centerX, centerY).then(
+                function () {
+                    if (window.eventSender)
+                        eventSender.keyDown("escape");
+                    finishJSTest();
+                },
+                function () {
+                    testFailed("Promise rejected.");
+                    finishJSTest();
+                }
+            );
+        }
+
+        function runTest() {
+            activateElement("theIframe");
+        }
+    </script>
+</head>
+<body>
+    <iframe sandbox="allow-scripts allow-same-origin allow-modals" onload="runTest()" id="theIframe" src="http://localhost:8000/loading/resourceLoadStatistics/resources/request-storage-access-iframe.html#userShouldGrantAccess,userShouldNotBeConsulted,policyShouldDenyAccess,isNotSameOriginIframe"></iframe>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-iframe-expected.txt b/LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-iframe-expected.txt
new file mode 100644 (file)
index 0000000..7eef986
--- /dev/null
@@ -0,0 +1,20 @@
+main frame - didStartProvisionalLoadForFrame
+main frame - didCommitLoadForFrame
+frame "theIframe" - didStartProvisionalLoadForFrame
+main frame - didFinishDocumentLoadForFrame
+frame "theIframe" - didCommitLoadForFrame
+frame "theIframe" - didFinishDocumentLoadForFrame
+CONSOLE MESSAGE: line 70: PASS document.hasStorageAccess was denied.
+frame "theIframe" - didHandleOnloadEventsForFrame
+main frame - didHandleOnloadEventsForFrame
+frame "theIframe" - didFinishLoadForFrame
+main frame - didFinishLoadForFrame
+Tests that same-origin iframe storage access is denied if the iframe is not sandboxed.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-iframe.html b/LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-iframe.html
new file mode 100644 (file)
index 0000000..4f9ce66
--- /dev/null
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script src="/js-test-resources/ui-helper.js"></script>
+    <script>
+        description("Tests that same-origin iframe storage access is denied if the iframe is not sandboxed.");
+        jsTestIsAsync = true;
+
+        function activateElement(elementId) {
+            var element = document.getElementById(elementId);
+            var centerX = element.offsetLeft + element.offsetWidth / 2;
+            var centerY = element.offsetTop + element.offsetHeight / 2;
+            UIHelper.activateAt(centerX, centerY).then(
+                function () {
+                    if (window.eventSender)
+                        eventSender.keyDown("escape");
+                    finishJSTest();
+                },
+                function () {
+                    testFailed("Promise rejected.");
+                    finishJSTest();
+                }
+            );
+        }
+
+        function runTest() {
+            activateElement("theIframe");
+        }
+    </script>
+</head>
+<body>
+    <iframe onload="runTest()" id="theIframe" src="http://127.0.0.1:8000/loading/resourceLoadStatistics/resources/request-storage-access-iframe.html#userShouldDenyAccess,userShouldNotBeConsulted,policyShouldDenyAccess,isSameOriginIframe"></iframe>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-sandboxed-iframe-expected.txt b/LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-sandboxed-iframe-expected.txt
new file mode 100644 (file)
index 0000000..5f042fb
--- /dev/null
@@ -0,0 +1,20 @@
+main frame - didStartProvisionalLoadForFrame
+main frame - didCommitLoadForFrame
+frame "theIframe" - didStartProvisionalLoadForFrame
+main frame - didFinishDocumentLoadForFrame
+frame "theIframe" - didCommitLoadForFrame
+frame "theIframe" - didFinishDocumentLoadForFrame
+CONSOLE MESSAGE: line 66: PASS document.hasStorageAccess was granted.
+frame "theIframe" - didHandleOnloadEventsForFrame
+main frame - didHandleOnloadEventsForFrame
+frame "theIframe" - didFinishLoadForFrame
+main frame - didFinishLoadForFrame
+Tests that same-origin iframe storage access is granted if the iframe is sandboxed and has the allow token.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-sandboxed-iframe-without-allow-token-expected.txt b/LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-sandboxed-iframe-without-allow-token-expected.txt
new file mode 100644 (file)
index 0000000..e780913
--- /dev/null
@@ -0,0 +1,20 @@
+main frame - didStartProvisionalLoadForFrame
+main frame - didCommitLoadForFrame
+frame "theIframe" - didStartProvisionalLoadForFrame
+main frame - didFinishDocumentLoadForFrame
+frame "theIframe" - didCommitLoadForFrame
+frame "theIframe" - didFinishDocumentLoadForFrame
+CONSOLE MESSAGE: line 70: PASS document.hasStorageAccess was denied.
+frame "theIframe" - didHandleOnloadEventsForFrame
+main frame - didHandleOnloadEventsForFrame
+frame "theIframe" - didFinishLoadForFrame
+main frame - didFinishLoadForFrame
+Tests that same-origin iframe storage access is denied if the iframe is sandboxed but doesn't have the allow token.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-sandboxed-iframe-without-allow-token.html b/LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-sandboxed-iframe-without-allow-token.html
new file mode 100644 (file)
index 0000000..ac0b090
--- /dev/null
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script src="/js-test-resources/ui-helper.js"></script>
+    <script>
+        description("Tests that same-origin iframe storage access is denied if the iframe is sandboxed but doesn't have the allow token.");
+        jsTestIsAsync = true;
+
+        function activateElement(elementId) {
+            var element = document.getElementById(elementId);
+            var centerX = element.offsetLeft + element.offsetWidth / 2;
+            var centerY = element.offsetTop + element.offsetHeight / 2;
+            UIHelper.activateAt(centerX, centerY).then(
+                function () {
+                    if (window.eventSender)
+                        eventSender.keyDown("escape");
+                    finishJSTest();
+                },
+                function () {
+                    testFailed("Promise rejected.");
+                    finishJSTest();
+                }
+            );
+        }
+
+        function runTest() {
+            activateElement("theIframe");
+        }
+    </script>
+</head>
+<body>
+    <iframe sandbox="allow-scripts allow-same-origin allow-modals" onload="runTest()" id="theIframe" src="http://127.0.0.1:8000/loading/resourceLoadStatistics/resources/request-storage-access-iframe.html#userShouldDenyAccess,userShouldNotBeConsulted,policyShouldDenyAccess,isSameOriginIframe"></iframe>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-sandboxed-iframe.html b/LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-sandboxed-iframe.html
new file mode 100644 (file)
index 0000000..2d2b0fc
--- /dev/null
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script src="/js-test-resources/ui-helper.js"></script>
+    <script>
+        description("Tests that same-origin iframe storage access is granted if the iframe is sandboxed and has the allow token.");
+        jsTestIsAsync = true;
+
+        function activateElement(elementId) {
+            var element = document.getElementById(elementId);
+            var centerX = element.offsetLeft + element.offsetWidth / 2;
+            var centerY = element.offsetTop + element.offsetHeight / 2;
+            UIHelper.activateAt(centerX, centerY).then(
+                function () {
+                    if (window.eventSender)
+                        eventSender.keyDown("escape");
+                    finishJSTest();
+                },
+                function () {
+                    testFailed("Promise rejected.");
+                    finishJSTest();
+                }
+            );
+        }
+
+        function runTest() {
+            activateElement("theIframe");
+        }
+    </script>
+</head>
+<body>
+    <iframe sandbox="allow-storage-access-by-user-activation allow-scripts allow-same-origin allow-modals" onload="runTest()" id="theIframe" src="http://127.0.0.1:8000/loading/resourceLoadStatistics/resources/request-storage-access-iframe.html#userShouldDenyAccess,userShouldNotBeConsulted,policyShouldGrantAccess,isSameOriginIframe"></iframe>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-top-frame-expected.txt b/LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-top-frame-expected.txt
new file mode 100644 (file)
index 0000000..fe61819
--- /dev/null
@@ -0,0 +1,18 @@
+main frame - didStartProvisionalLoadForFrame
+main frame - didCommitLoadForFrame
+main frame - didFinishDocumentLoadForFrame
+main frame - didHandleOnloadEventsForFrame
+main frame - didFinishLoadForFrame
+Tests that top frame storage access is always granted in case the page requests it.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS requestStorageAccessReturnValue is true
+PASS document.hasStorageAccess is true
+PASS requestStorageAccessReturnValue is true
+PASS document.hasStorageAccess is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+Request Access
diff --git a/LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-top-frame.html b/LayoutTests/http/tests/loading/resourceLoadStatistics/request-storage-access-top-frame.html
new file mode 100644 (file)
index 0000000..f05e2d7
--- /dev/null
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+<body onload="runTest()">
+<script src="/js-test-resources/js-test.js"></script>
+<script src="/js-test-resources/ui-helper.js"></script>
+<script>
+    description("Tests that top frame storage access is always granted in case the page requests it.");
+    jsTestIsAsync = true;
+
+    function activateElement(elementId) {
+        var element = document.getElementById(elementId);
+        var centerX = element.offsetLeft + element.offsetWidth / 2;
+        var centerY = element.offsetTop + element.offsetHeight / 2;
+        UIHelper.activateAt(centerX, centerY).then(
+            function() { },
+            function() {
+                testFailed("Promise rejected.");
+                finishJSTest();
+            }
+        );
+    }
+
+    var requestStorageAccessReturnValue;
+
+    function makeRequestWithoutUserGesture() {
+        document.requestStorageAccess();
+        var promise = document.requestStorageAccess();
+        promise.then(function (hasAccess) {
+            requestStorageAccessReturnValue = hasAccess;
+            shouldBe("requestStorageAccessReturnValue", "true");
+            shouldBe("document.hasStorageAccess", "true");
+            activateElement("theButton");
+        });
+    }
+
+    function makeRequestWithUserGesture() {
+        document.requestStorageAccess();
+        var promise = document.requestStorageAccess();
+        promise.then(function (hasAccess) {
+            requestStorageAccessReturnValue = hasAccess;
+            shouldBe("requestStorageAccessReturnValue", "true");
+            shouldBe("document.hasStorageAccess", "true");
+            finishJSTest();
+        });
+    }
+
+    function runTest() {
+        makeRequestWithoutUserGesture();
+    }
+</script>
+<button id="theButton" onclick="makeRequestWithUserGesture()">Request Access</button>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/http/tests/loading/resourceLoadStatistics/resources/request-storage-access-iframe.html b/LayoutTests/http/tests/loading/resourceLoadStatistics/resources/request-storage-access-iframe.html
new file mode 100644 (file)
index 0000000..b3ce8fe
--- /dev/null
@@ -0,0 +1,84 @@
+<html>
+<head>
+    <script>
+        const hashArguments = document.location.hash.substring(1).split(",");
+        const userShouldGrantAccess = hashArguments[0] === "userShouldGrantAccess";
+        const userShouldBeConsulted = hashArguments[1] === "userShouldBeConsulted";
+        const policyShouldGrantAccess = hashArguments[2] === "policyShouldGrantAccess";
+        const isSameOriginIframe = hashArguments[3] === "isSameOriginIframe";
+
+        if (internals && userShouldGrantAccess)
+                internals.setUserGrantsStorageAccess(true);
+
+        function storageAccessShouldBeFalse() {
+            if (document.hasStorageAccess)
+                console.log("FAIL document.hasStorageAccess was true when it was not supposed to.");
+            if (requestStorageAccessReturnValue)
+                console.log("FAIL requestStorageAccessReturnValue was true when it was not supposed to.");
+        }
+
+        function storageAccessShouldBeTrue() {
+            if (!document.hasStorageAccess)
+                console.log("FAIL document.hasStorageAccess was false when it was not supposed to.");
+            if (!requestStorageAccessReturnValue)
+                console.log("FAIL requestStorageAccessReturnValue was false when it was not supposed to.");
+        }
+
+        var requestStorageAccessReturnValue;
+
+        function makeRequestWithoutUserGesture() {
+            storageAccessShouldBeFalse();
+
+            document.requestStorageAccess();
+            var promise = document.requestStorageAccess();
+            promise.then(function (hasAccess) {
+                requestStorageAccessReturnValue = hasAccess;
+                continueAfterRequestWithoutUserGesture();
+            });
+        }
+
+        function continueAfterRequestWithoutUserGesture() {
+            if (isSameOriginIframe && policyShouldGrantAccess)
+                storageAccessShouldBeTrue();
+            else
+                storageAccessShouldBeFalse();
+        }
+
+        function makeRequestWithUserGesture() {
+            if (isSameOriginIframe && policyShouldGrantAccess)
+                storageAccessShouldBeTrue();
+            else
+                storageAccessShouldBeFalse();
+
+            document.requestStorageAccess();
+            var promise = document.requestStorageAccess();
+            promise.then(function (hasAccess) {
+                requestStorageAccessReturnValue = hasAccess;
+                continueAfterRequestWithUserGesture();
+            });
+        }
+
+        function continueAfterRequestWithUserGesture() {
+            if (requestStorageAccessReturnValue
+                && document.hasStorageAccess
+                && (userShouldGrantAccess || !userShouldBeConsulted)
+                && policyShouldGrantAccess)
+                console.log("PASS document.hasStorageAccess was granted.");
+            else if (!document.hasStorageAccess
+                    && !requestStorageAccessReturnValue
+                    && ((!userShouldGrantAccess && userShouldBeConsulted) || !policyShouldGrantAccess))
+                console.log("PASS document.hasStorageAccess was denied.");
+            else
+                console.log("FAIL document.hasStorageAccess was " +
+                    (document.hasStorageAccess ? "" : "not ") +
+                    "granted and requestStorageAccessReturnValue was " +
+                    (requestStorageAccessReturnValue ? "" : "not ") +
+                    "granted but should " +
+                    (userShouldGrantAccess && policyShouldGrantAccess ? "" : "not ") +
+                    "have been granted.");
+        }
+    </script>
+</head>
+<body onload="makeRequestWithoutUserGesture()" onclick="makeRequestWithUserGesture()">
+</body>
+</html>
\ No newline at end of file
index 9a5b909..4a88d4e 100644 (file)
@@ -742,10 +742,19 @@ webkit.org/b/167757 workers/bomb.html [ Pass Timeout ]
 
 webkit.org/b/172397 [ Sierra Debug ] animations/needs-layout.html [ Pass ImageOnlyFailure ]
 
-# Move to general wk2 expectations once webkit.org/b/175170 is resolved.
+# Touch events are not available on open source bots, thus only tested on Mac.
 http/tests/loading/resourceLoadStatistics/user-interaction-in-cross-origin-sub-frame.html [ Pass ]
 http/tests/loading/resourceLoadStatistics/user-interaction-only-reported-once-within-short-period-of-time.html [ Pass ]
 http/tests/loading/resourceLoadStatistics/user-interaction-reported-after-website-data-removal.html [ Pass ]
+http/tests/loading/resourceLoadStatistics/request-and-deny-storage-access-cross-origin-iframe.html [ Pass ]
+http/tests/loading/resourceLoadStatistics/request-and-deny-storage-access-cross-origin-sandboxed-iframe.html [ Pass ]
+http/tests/loading/resourceLoadStatistics/request-and-grant-storage-access-cross-origin-iframe.html [ Pass ]
+http/tests/loading/resourceLoadStatistics/request-and-grant-storage-access-cross-origin-sandboxed-iframe.html [ Pass ]
+http/tests/loading/resourceLoadStatistics/request-storage-access-cross-origin-sandboxed-iframe-with-unique-origin.html [ Pass ]
+http/tests/loading/resourceLoadStatistics/request-storage-access-cross-origin-sandboxed-iframe-without-allow-token.html [ Pass ]
+http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-iframe.html [ Pass ]
+http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-sandboxed-iframe-without-allow-token.html [ Pass ]
+http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-sandboxed-iframe.html [ Pass ]
 
 webkit.org/b/173861 [ Release ] http/tests/webrtc/filtering-ice-candidate-same-origin-frame.html [ Pass Timeout ]
 webkit.org/b/173861 [ Release ] http/tests/webrtc/filtering-ice-candidate-cross-origin-frame.html [ Pass Timeout ]
index 7aa5806..843dbd5 100644 (file)
@@ -688,6 +688,7 @@ webkit.org/b/175263 http/tests/loading/resourceLoadStatistics/clear-in-memory-an
 webkit.org/b/172452 http/tests/loading/resourceLoadStatistics/grandfathering.html [ Pass Failure Timeout ]
 webkit.org/b/173499 http/tests/loading/resourceLoadStatistics/telemetry-generation.html [ Pass Failure ]
 http/tests/loading/resourceLoadStatistics/prune-statistics.html [ Pass ]
+http/tests/loading/resourceLoadStatistics/request-storage-access-top-frame.html [ Pass ]
 
 ### END OF (5) Progressions, expected successes that are expected failures in WebKit1.
 ########################################
index 71374f1..c82bb9e 100644 (file)
@@ -1,3 +1,71 @@
+2017-09-13  John Wilander  <wilander@apple.com>
+
+        Introduce Storage Access API (document parts) as an experimental feature
+        https://bugs.webkit.org/show_bug.cgi?id=175759
+        <rdar://problem/33666847>
+
+        Reviewed by Alex Christensen.
+
+        Storage Access API is an experimental feature which allows cross-origin,
+        sandboxed iframes to request access to their first-party storage (as
+        opposed to partitioned storage). This might be restricted to cookies or
+        might cover all stateful mechanisms.
+
+        It introduces the following three developer-facing things:
+        - A new readonly attribute, document.hasStorageAccess.
+        - A new function, document.requestStorageAccess().
+        - A new iframe sandbox token, allow-storage-access-by-user-activation.
+
+        Tests: http/tests/loading/resourceLoadStatistics/request-and-deny-storage-access-cross-origin-iframe.html
+               http/tests/loading/resourceLoadStatistics/request-and-deny-storage-access-cross-origin-sandboxed-iframe.html
+               http/tests/loading/resourceLoadStatistics/request-and-grant-storage-access-cross-origin-iframe.html
+               http/tests/loading/resourceLoadStatistics/request-and-grant-storage-access-cross-origin-sandboxed-iframe.html
+               http/tests/loading/resourceLoadStatistics/request-storage-access-cross-origin-sandboxed-iframe-with-unique-origin.html
+               http/tests/loading/resourceLoadStatistics/request-storage-access-cross-origin-sandboxed-iframe-without-allow-token.html
+               http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-iframe.html
+               http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-sandboxed-iframe-without-allow-token.html
+               http/tests/loading/resourceLoadStatistics/request-storage-access-same-origin-sandboxed-iframe.html
+               http/tests/loading/resourceLoadStatistics/request-storage-access-top-frame.html
+
+        * dom/Document.cpp:
+        (WebCore::Document::requestStorageAccess):
+        * dom/Document.h:
+        (WebCore::Document::hasStorageAccess const):
+        (WebCore::Document::setUserGrantsStorageAccessOverride):
+            See comments on WebCore::Internals below.
+        * dom/Document.idl:
+        * dom/SecurityContext.cpp:
+        (WebCore::SecurityContext::isSupportedSandboxPolicy):
+        (WebCore::SecurityContext::parseSandboxPolicy):
+            Support for allow-storage-access-by-user-activation.
+        * dom/SecurityContext.h:
+        * loader/ResourceLoadObserver.cpp:
+        (WebCore::ResourceLoadObserver::registerStorageAccess):
+            Newly granted storage access is reported to 
+            WebCore::ResourceLoadObserver.
+        * loader/ResourceLoadObserver.h:
+        * loader/ResourceLoadStatistics.cpp:
+        (WebCore::encodeHashSet):
+        (WebCore::ResourceLoadStatistics::encode const):
+        (WebCore::decodeHashSet):
+        (WebCore::ResourceLoadStatistics::decode):
+        (WebCore::appendHashSet):
+        (WebCore::ResourceLoadStatistics::toString const):
+        (WebCore::mergeHashSet):
+        (WebCore::ResourceLoadStatistics::merge):
+            Storage of the new type of data.
+        * loader/ResourceLoadStatistics.h:
+        * page/Settings.in:
+        * testing/Internals.cpp:
+        (WebCore::Internals::resetToConsistentState):
+        (WebCore::Internals::setUserGrantsStorageAccess):
+        * testing/Internals.h:
+        * testing/Internals.idl:
+            Added setUserGrantsStorageAccess(). It is used to
+            override the eventSender's keyboard input which
+            always results in a cancel action on the confirm()
+            dialog.
+
 2017-09-13  Carlos Garcia Campos  <cgarcia@igalia.com>
 
         [HarfBuzz] Wrong offset returned by HarfBuzzShaper::offsetForPosition in some cases
index a5eae05..f991a89 100644 (file)
 #include "ImageLoader.h"
 #include "InspectorInstrumentation.h"
 #include "JSCustomElementInterface.h"
+#include "JSDOMPromiseDeferred.h"
 #include "JSLazyEventListener.h"
 #include "KeyboardEvent.h"
 #include "LayoutDisallowedScope.h"
 #include "RenderView.h"
 #include "RenderWidget.h"
 #include "RequestAnimationFrameCallback.h"
+#include "ResourceLoadObserver.h"
 #include "RuntimeEnabledFeatures.h"
 #include "SVGDocumentExtensions.h"
 #include "SVGElement.h"
@@ -7285,4 +7287,65 @@ Logger& Document::logger() const
     return *m_logger;
 }
 
+void Document::requestStorageAccess(Ref<DeferredPromise>&& passedPromise)
+{
+    ASSERT(settings().storageAccessAPIEnabled());
+    
+    RefPtr<DeferredPromise> promise(WTFMove(passedPromise));
+    
+    if (m_hasStorageAccess) {
+        promise->resolve<IDLBoolean>(true);
+        return;
+    }
+    
+    if (!m_frame || securityOrigin().isUnique()) {
+        promise->resolve<IDLBoolean>(false);
+        return;
+    }
+    
+    if (m_frame->isMainFrame()) {
+        m_hasStorageAccess = true;
+        promise->resolve<IDLBoolean>(true);
+        return;
+    }
+    
+    // There has to be a sandbox and it has to allow the storage access API to be called.
+    if (sandboxFlags() == SandboxNone || isSandboxed(SandboxStorageAccessByUserActivation)) {
+        promise->resolve<IDLBoolean>(false);
+        return;
+    }
+    
+    auto& securityOrigin = this->securityOrigin();
+    auto& topSecurityOrigin = topDocument().securityOrigin();
+    if (securityOrigin.equal(&topSecurityOrigin)) {
+        m_hasStorageAccess = true;
+        promise->resolve<IDLBoolean>(true);
+        return;
+    }
+    
+    if (!UserGestureIndicator::processingUserGesture()) {
+        promise->resolve<IDLBoolean>(false);
+        return;
+    }
+    
+    auto partitionDomain = securityOrigin.domainForCachePartition();
+    auto topPartitionDomain = topSecurityOrigin.domainForCachePartition();
+    StringBuilder builder;
+    builder.appendLiteral("Do you want to use your ");
+    builder.append(partitionDomain);
+    builder.appendLiteral(" ID on ");
+    builder.append(topPartitionDomain);
+    builder.appendLiteral("?");
+    Page* page = this->page();
+    // FIXME: Don't use runJavaScriptConfirm because it responds synchronously.
+    if ((page && page->chrome().runJavaScriptConfirm(*m_frame, builder.toString())) || m_grantStorageAccessOverride) {
+        m_hasStorageAccess = true;
+        ResourceLoadObserver::shared().registerStorageAccess(partitionDomain, topPartitionDomain);
+        promise->resolve<IDLBoolean>(true);
+        return;
+    }
+    
+    promise->resolve<IDLBoolean>(false);
+}
+
 } // namespace WebCore
index 6baf3db..9ccd63a 100644 (file)
@@ -103,6 +103,7 @@ class DOMWindow;
 class DOMWrapperWorld;
 class Database;
 class DatabaseThread;
+class DeferredPromise;
 class DocumentFragment;
 class DocumentLoader;
 class DocumentMarkerController;
@@ -1361,6 +1362,10 @@ public:
 
     PAL::Logger& logger() const;
 
+    bool hasStorageAccess() const { return m_hasStorageAccess; };
+    void requestStorageAccess(Ref<DeferredPromise>&& passedPromise);
+    void setUserGrantsStorageAccessOverride(bool value) { m_grantStorageAccessOverride = value; }
+
 protected:
     enum ConstructionFlags { Synthesized = 1, NonRenderedPlaceholder = 1 << 1 };
     Document(Frame*, const URL&, unsigned = DefaultDocumentClass, unsigned constructionFlags = 0);
@@ -1814,6 +1819,9 @@ private:
     mutable RefPtr<PAL::Logger> m_logger;
 
     static bool hasEverCreatedAnAXObjectCache;
+
+    bool m_hasStorageAccess { false };
+    bool m_grantStorageAccessOverride { false };
 };
 
 Element* eventTargetElementForDocument(Document*);
index cc053c4..456da2f 100644 (file)
@@ -192,6 +192,9 @@ typedef (
     // Non standard (https://developer.apple.com/reference/webkitjs/document/1633863-webkitgetnamedflows).
     [Conditional=CSS_REGIONS] DOMNamedFlowCollection webkitGetNamedFlows();
 
+    // Non standard, to bring up with standards working group.
+    [EnabledBySetting=StorageAccessAPI] readonly attribute boolean hasStorageAccess;
+    [EnabledBySetting=StorageAccessAPI] Promise<boolean> requestStorageAccess();
 
     // Obsolete features from https://html.spec.whatwg.org/multipage/obsolete.html
 
index 9be14b8..7c4c7cd 100644 (file)
@@ -85,7 +85,7 @@ void SecurityContext::enforceSandboxFlags(SandboxFlags mask)
 bool SecurityContext::isSupportedSandboxPolicy(StringView policy)
 {
     static const char* const supportedPolicies[] = {
-        "allow-forms", "allow-same-origin", "allow-scripts", "allow-top-navigation", "allow-pointer-lock", "allow-popups", "allow-popups-to-escape-sandbox", "allow-top-navigation-by-user-activation", "allow-modals"
+        "allow-forms", "allow-same-origin", "allow-scripts", "allow-top-navigation", "allow-pointer-lock", "allow-popups", "allow-popups-to-escape-sandbox", "allow-top-navigation-by-user-activation", "allow-modals", "allow-storage-access-by-user-activation"
     };
 
     for (auto* supportedPolicy : supportedPolicies) {
@@ -136,6 +136,8 @@ SandboxFlags SecurityContext::parseSandboxPolicy(const String& policy, String& i
             flags &= ~SandboxTopNavigationByUserActivation;
         else if (equalLettersIgnoringASCIICase(sandboxToken, "allow-modals"))
             flags &= ~SandboxModals;
+        else if (equalLettersIgnoringASCIICase(sandboxToken, "allow-storage-access-by-user-activation"))
+            flags &= ~SandboxStorageAccessByUserActivation;
         else {
             if (numberOfTokenErrors)
                 tokenErrors.appendLiteral(", '");
index b32009f..0734860 100644 (file)
@@ -54,6 +54,7 @@ enum SandboxFlag {
     SandboxTopNavigationByUserActivation = 1 << 10,
     SandboxDocumentDomain       = 1 << 11,
     SandboxModals               = 1 << 12,
+    SandboxStorageAccessByUserActivation = 1 << 13,
     SandboxAll                  = -1 // Mask with all bits set to 1.
 };
 
index 5c228eb..c320f03 100644 (file)
@@ -284,6 +284,23 @@ void ResourceLoadObserver::logUserInteractionWithReducedTimeResolution(const Doc
     notifyObserver();
 }
 
+void ResourceLoadObserver::registerStorageAccess(const String& subFrameTopPrivatelyControlledDomain, const String& topFrameTopPrivatelyControlledDomain)
+{
+    auto addResult = m_storageAccessMap.add(subFrameTopPrivatelyControlledDomain, HashSet<String> { });
+    if (!addResult.isNewEntry && addResult.iterator->value.contains(topFrameTopPrivatelyControlledDomain))
+        return;
+
+    if (addResult.isNewEntry)
+        addResult.iterator->value = HashSet<String> { topFrameTopPrivatelyControlledDomain };
+    else
+        m_storageAccessMap.get(subFrameTopPrivatelyControlledDomain).add(topFrameTopPrivatelyControlledDomain);
+
+    auto& statistics = ensureResourceStatisticsForPrimaryDomain(subFrameTopPrivatelyControlledDomain);
+    statistics.storageAccessUnderTopFrameOrigins.add(topFrameTopPrivatelyControlledDomain);
+    m_notificationTimer.stop();
+    notifyObserver();
+}
+
 ResourceLoadStatistics& ResourceLoadObserver::ensureResourceStatisticsForPrimaryDomain(const String& primaryDomain)
 {
     auto addResult = m_resourceStatisticsMap.ensure(primaryDomain, [&primaryDomain] {
index dcc2946..5e2cab0 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "Timer.h"
 #include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
 #include <wtf/NeverDestroyed.h>
 #include <wtf/text/WTFString.h>
 
@@ -59,6 +60,7 @@ public:
     void logWebSocketLoading(const Frame*, const URL&);
     void logUserInteractionWithReducedTimeResolution(const Document&);
 
+    void registerStorageAccess(const String& subFrameTopPrivatelyControlledDomain, const String& topFrameTopPrivatelyControlledDomain);
     WEBCORE_EXPORT String statisticsForOrigin(const String&);
 
     WEBCORE_EXPORT void setNotificationCallback(WTF::Function<void (Vector<ResourceLoadStatistics>&&)>&&);
@@ -75,6 +77,7 @@ private:
     Vector<ResourceLoadStatistics> takeStatistics();
 
     HashMap<String, ResourceLoadStatistics> m_resourceStatisticsMap;
+    HashMap<String, HashSet<String>> m_storageAccessMap;
     HashMap<String, WTF::WallTime> m_lastReportedUserInteractionMap;
     WTF::Function<void (Vector<ResourceLoadStatistics>&&)> m_notificationCallback;
     Timer m_notificationTimer;
index 49b4d24..a83e139 100644 (file)
@@ -46,6 +46,16 @@ static void encodeHashCountedSet(KeyedEncoder& encoder, const String& label, con
     });
 }
 
+static void encodeHashSet(KeyedEncoder& encoder, const String& label, const HashSet<String>& hashSet)
+{
+    if (hashSet.isEmpty())
+        return;
+    
+    encoder.encodeObjects(label, hashSet.begin(), hashSet.end(), [](KeyedEncoder& encoderInner, const String& origin) {
+        encoderInner.encodeString("origin", origin);
+    });
+}
+
 void ResourceLoadStatistics::encode(KeyedEncoder& encoder) const
 {
     encoder.encodeString("PrevalentResourceOrigin", highLevelDomain);
@@ -56,7 +66,10 @@ void ResourceLoadStatistics::encode(KeyedEncoder& encoder) const
     encoder.encodeBool("hadUserInteraction", hadUserInteraction);
     encoder.encodeDouble("mostRecentUserInteraction", mostRecentUserInteractionTime.secondsSinceEpoch().value());
     encoder.encodeBool("grandfathered", grandfathered);
-    
+
+    // Storage access
+    encodeHashSet(encoder, "storageAccessUnderTopFrameOrigins", storageAccessUnderTopFrameOrigins);
+
     // Subframe stats
     encodeHashCountedSet(encoder, "subframeUnderTopFrameOrigins", subframeUnderTopFrameOrigins);
     
@@ -85,6 +98,18 @@ static void decodeHashCountedSet(KeyedDecoder& decoder, const String& label, Has
     });
 }
 
+static void decodeHashSet(KeyedDecoder& decoder, const String& label, HashSet<String>& hashSet)
+{
+    Vector<String> ignore;
+    decoder.decodeObjects(label, ignore, [&hashSet](KeyedDecoder& decoderInner, String& origin) {
+        if (!decoderInner.decodeString("origin", origin))
+            return false;
+        
+        hashSet.add(origin);
+        return true;
+    });
+}
+
 bool ResourceLoadStatistics::decode(KeyedDecoder& decoder)
 {
     if (!decoder.decodeString("PrevalentResourceOrigin", highLevelDomain))
@@ -93,7 +118,10 @@ bool ResourceLoadStatistics::decode(KeyedDecoder& decoder)
     // User interaction
     if (!decoder.decodeBool("hadUserInteraction", hadUserInteraction))
         return false;
-    
+
+    // Storage access
+    decodeHashSet(decoder, "storageAccessUnderTopFrameOrigins", storageAccessUnderTopFrameOrigins);
+
     // Subframe stats
     decodeHashCountedSet(decoder, "subframeUnderTopFrameOrigins", subframeUnderTopFrameOrigins);
     
@@ -150,6 +178,22 @@ static void appendHashCountedSet(StringBuilder& builder, const String& label, co
     }
 }
 
+static void appendHashSet(StringBuilder& builder, const String& label, const HashSet<String>& hashSet)
+{
+    if (hashSet.isEmpty())
+        return;
+    
+    builder.appendLiteral("    ");
+    builder.append(label);
+    builder.appendLiteral(":\n");
+    
+    for (auto& entry : hashSet) {
+        builder.appendLiteral("        ");
+        builder.append(entry);
+        builder.append('\n');
+    }
+}
+
 String ResourceLoadStatistics::toString() const
 {
     StringBuilder builder;
@@ -166,7 +210,10 @@ String ResourceLoadStatistics::toString() const
     builder.append('\n');
     appendBoolean(builder, "    grandfathered", grandfathered);
     builder.append('\n');
-    
+
+    // Storage access
+    appendHashSet(builder, "storageAccessUnderTopFrameOrigins", storageAccessUnderTopFrameOrigins);
+
     // Subframe stats
     appendHashCountedSet(builder, "subframeUnderTopFrameOrigins", subframeUnderTopFrameOrigins);
     
@@ -196,6 +243,13 @@ static void mergeHashCountedSet(HashCountedSet<T>& to, const HashCountedSet<T>&
         to.add(entry.key, entry.value);
 }
 
+template <typename T>
+static void mergeHashSet(HashSet<T>& to, const HashSet<T>& from)
+{
+    for (auto& entry : from)
+        to.add(entry);
+}
+
 void ResourceLoadStatistics::merge(const ResourceLoadStatistics& other)
 {
     ASSERT(other.highLevelDomain == highLevelDomain);
@@ -216,7 +270,10 @@ void ResourceLoadStatistics::merge(const ResourceLoadStatistics& other)
             mostRecentUserInteractionTime = other.mostRecentUserInteractionTime;
     }
     grandfathered |= other.grandfathered;
-    
+
+    // Storage access
+    mergeHashSet(storageAccessUnderTopFrameOrigins, other.storageAccessUnderTopFrameOrigins);
+
     // Subframe stats
     mergeHashCountedSet(subframeUnderTopFrameOrigins, other.subframeUnderTopFrameOrigins);
     
index bd9f1f5..2f58d10 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "URL.h"
 #include <wtf/HashCountedSet.h>
+#include <wtf/HashSet.h>
 #include <wtf/WallTime.h>
 #include <wtf/text/StringHash.h>
 #include <wtf/text/WTFString.h>
@@ -68,7 +69,10 @@ struct ResourceLoadStatistics {
     // Timestamp. Default value is negative, 0 means it was reset.
     WallTime mostRecentUserInteractionTime { WallTime::fromRawSeconds(-1) };
     bool grandfathered { false };
-    
+
+    // Storage access
+    HashSet<String> storageAccessUnderTopFrameOrigins;
+
     // Subframe stats
     HashCountedSet<String> subframeUnderTopFrameOrigins;
     
index efe88ed..9277c0a 100644 (file)
@@ -300,3 +300,5 @@ viewportFitEnabled initial=false
 allowMediaContentTypesRequiringHardwareSupportAsFallback initial=false
 
 paymentRequestEnabled initial=false, conditional=PAYMENT_REQUEST
+
+storageAccessAPIEnabled initial=false
index 9e29f9a..ea68815 100644 (file)
@@ -466,6 +466,8 @@ void Internals::resetToConsistentState(Page& page)
 #if USE(LIBWEBRTC)
     WebCore::useRealRTCPeerConnectionFactory();
 #endif
+
+    page.settings().setStorageAccessAPIEnabled(false);
 }
 
 Internals::Internals(Document& document)
@@ -3836,6 +3838,15 @@ void Internals::setResourceLoadStatisticsEnabled(bool enable)
     Settings::setResourceLoadStatisticsEnabled(enable);
 }
 
+void Internals::setUserGrantsStorageAccess(bool value)
+{
+    Document* document = contextDocument();
+    if (!document)
+        return;
+
+    document->setUserGrantsStorageAccessOverride(value);
+}
+
 String Internals::composedTreeAsText(Node& node)
 {
     if (!is<ContainerNode>(node))
index dad1f4a..9a5472c 100644 (file)
@@ -538,6 +538,7 @@ public:
 
     String resourceLoadStatisticsForOrigin(const String& origin);
     void setResourceLoadStatisticsEnabled(bool);
+    void setUserGrantsStorageAccess(bool);
 
 #if ENABLE(STREAMS_API)
     bool isReadableStreamDisturbed(JSC::ExecState&, JSC::JSValue);
index 3bf02b7..22e3d5c 100644 (file)
@@ -496,6 +496,7 @@ enum EventThrottlingBehavior {
 
     DOMString resourceLoadStatisticsForOrigin(DOMString domain);
     void setResourceLoadStatisticsEnabled(boolean enable);
+    [EnabledBySetting=StorageAccessAPI] void setUserGrantsStorageAccess(boolean value);
 
     [MayThrowException] void setCanShowModalDialogOverride(boolean allow);
 
index 523d564..a68077d 100644 (file)
@@ -1,3 +1,35 @@
+2017-09-13  John Wilander  <wilander@apple.com>
+
+        Introduce Storage Access API (document parts) as an experimental feature
+        https://bugs.webkit.org/show_bug.cgi?id=175759
+        <rdar://problem/33666847>
+
+        Reviewed by Alex Christensen.
+
+        Storage Access API is an experimental feature which allows cross-origin,
+        sandboxed iframes to request access to their first-party storage (as
+        opposed to partitioned storage). This might be restricted to cookies or
+        might cover all stateful mechanisms.
+
+        It introduces the following three developer-facing things:
+        - A new readonly attribute, document.hasStorageAccess.
+        - A new function, document.requestStorageAccess().
+        - A new iframe sandbox token, allow-storage-access-by-user-activation.
+
+        * Shared/WebCoreArgumentCoders.cpp:
+        (IPC::ArgumentCoder<ResourceLoadStatistics>::encode):
+        (IPC::ArgumentCoder<ResourceLoadStatistics>::decode):
+            Storage handling of the new type of data.
+        * Shared/WebPreferencesDefinitions.h:
+        * UIProcess/API/C/WKPreferences.cpp:
+        (WKPreferencesSetStorageAccessAPIEnabled):
+        (WKPreferencesGetStorageAccessAPIEnabled):
+        * UIProcess/API/C/WKPreferencesRefPrivate.h:
+        * UIProcess/WebResourceLoadStatisticsStore.cpp:
+            Bumped the model version from 9 to 10.
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::updatePreferences):
+
 2017-09-13  Sergio Villar Senin  <svillar@igalia.com>
 
         [WebVR] Add IDLs and stubs
index 2d9fcc6..5e7ef0e 100644 (file)
@@ -2398,7 +2398,10 @@ void ArgumentCoder<ResourceLoadStatistics>::encode(Encoder& encoder, const WebCo
     encoder << statistics.hadUserInteraction;
     encoder << statistics.mostRecentUserInteractionTime.secondsSinceEpoch().value();
     encoder << statistics.grandfathered;
-    
+
+    // Storage access
+    encoder << statistics.storageAccessUnderTopFrameOrigins;
+
     // Subframe stats
     encoder << statistics.subframeUnderTopFrameOrigins;
     
@@ -2432,7 +2435,11 @@ bool ArgumentCoder<ResourceLoadStatistics>::decode(Decoder& decoder, WebCore::Re
 
     if (!decoder.decode(statistics.grandfathered))
         return false;
-    
+
+    // Storage access
+    if (!decoder.decode(statistics.storageAccessUnderTopFrameOrigins))
+        return false;
+
     // Subframe stats
     if (!decoder.decode(statistics.subframeUnderTopFrameOrigins))
         return false;
index f2e31ee..b3c1cae 100644 (file)
     macro(IsSecureContextAttributeEnabled, isSecureContextAttributeEnabled, Bool, bool, DEFAULT_EXPERIMENTAL_FEATURES_ENABLED, "Secure Contexts API", "Enable Secure Contexts API") \
     macro(ServiceWorkersEnabled, serviceWorkersEnabled, Bool, bool, false, "ServiceWorkers", "Enable ServiceWorkers") \
     macro(CacheAPIEnabled, cacheAPIEnabled, Bool, bool, false, "Cache API", "Enable Cache API") \
+    macro(StorageAccessAPIEnabled, storageAccessAPIEnabled, Bool, bool, false, "Storage Access API", "Enable Storage Access API") \
     macro(SubresourceIntegrityEnabled, subresourceIntegrityEnabled, Bool, bool, DEFAULT_EXPERIMENTAL_FEATURES_ENABLED, "SubresourceIntegrity", "Enable SubresourceIntegrity") \
     macro(ViewportFitEnabled, viewportFitEnabled, Bool, bool, true, "Viewport Fit", "Enable viewport-fit viewport parameter") \
     macro(WebAnimationsEnabled, webAnimationsEnabled, Bool, bool, false, "Web Animations", "Web Animations prototype") \
index 22d13e8..f4d450f 100644 (file)
@@ -1879,3 +1879,13 @@ bool WKPreferencesGetPaymentRequestEnabled(WKPreferencesRef preferencesRef)
 {
     return toImpl(preferencesRef)->paymentRequestEnabled();
 }
+
+void WKPreferencesSetStorageAccessAPIEnabled(WKPreferencesRef preferencesRef, bool flag)
+{
+    toImpl(preferencesRef)->setStorageAccessAPIEnabled(flag);
+}
+
+bool WKPreferencesGetStorageAccessAPIEnabled(WKPreferencesRef preferencesRef)
+{
+    return toImpl(preferencesRef)->storageAccessAPIEnabled();
+}
index 4746ad3..db8c51a 100644 (file)
@@ -529,6 +529,10 @@ WK_EXPORT bool WKPreferencesGetInspectorAdditionsEnabled(WKPreferencesRef);
 WK_EXPORT void WKPreferencesSetPaymentRequestEnabled(WKPreferencesRef, bool flag);
 WK_EXPORT bool WKPreferencesGetPaymentRequestEnabled(WKPreferencesRef);
 
+// Defaults to false.
+WK_EXPORT void WKPreferencesSetStorageAccessAPIEnabled(WKPreferencesRef, bool flag);
+WK_EXPORT bool WKPreferencesGetStorageAccessAPIEnabled(WKPreferencesRef);
+    
 #ifdef __cplusplus
 }
 #endif
index 134a70c..439b469 100644 (file)
@@ -45,7 +45,7 @@ using namespace WebCore;
 namespace WebKit {
 
 constexpr unsigned operatingDatesWindow { 30 };
-constexpr unsigned statisticsModelVersion { 9 };
+constexpr unsigned statisticsModelVersion { 10 };
 constexpr unsigned maxImportance { 3 };
 
 template<typename T> static inline String isolatedPrimaryDomain(const T& value)
index 673550d..bc24ba2 100644 (file)
@@ -3386,6 +3386,8 @@ void WebPage::updatePreferences(const WebPreferencesStore& store)
     settings.setPaymentRequestEnabled(store.getBoolValueForKey(WebPreferencesKey::paymentRequestEnabledKey()));
 #endif
 
+    settings.setStorageAccessAPIEnabled(store.getBoolValueForKey(WebPreferencesKey::storageAccessAPIEnabledKey()));
+    
     platformPreferencesDidChange(store);
 
     if (m_drawingArea)
index 03ddf3f..302b74c 100644 (file)
@@ -1,3 +1,15 @@
+2017-09-13  John Wilander  <wilander@apple.com>
+
+        Introduce Storage Access API (document parts) as an experimental feature
+        https://bugs.webkit.org/show_bug.cgi?id=175759
+        <rdar://problem/33666847>
+
+        Reviewed by Alex Christensen.
+
+        * WebKitTestRunner/TestController.cpp:
+        (WTR::TestController::resetPreferencesToConsistentValues):
+            Turns the feature on for tests.
+
 2017-09-13  Per Arne Vollan  <pvollan@apple.com>
 
         [Win] DRT option --gc-between-tests is not implemented.
index 8739939..2f0f922 100644 (file)
@@ -741,6 +741,8 @@ void TestController::resetPreferencesToConsistentValues(const TestOptions& optio
     WKPreferencesSetPaymentRequestEnabled(preferences, true);
 #endif
 
+    WKPreferencesSetStorageAccessAPIEnabled(preferences, true);
+
     platformResetPreferencesToConsistentValues();
 }