WebResourceLoadStatisticsStore::requestStorageAccessUnderOpener() should call its...
authorwilander@apple.com <wilander@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 19 Mar 2020 01:26:16 +0000 (01:26 +0000)
committerwilander@apple.com <wilander@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 19 Mar 2020 01:26:16 +0000 (01:26 +0000)
https://bugs.webkit.org/show_bug.cgi?id=209245
<rdar://problem/60511121>

Reviewed by Chris Dumez.

Source/WebKit:

This change makes sure that WebResourceLoadStatisticsStore::requestStorageAccessUnderOpener()
calls WebResourceLoadStatisticsStore::requestStorageAccessUnderOpenerEphemeral() for ephemeral
sessions.

Tests: http/tests/storageAccess/deny-storage-access-under-opener-ephemeral.html
       http/tests/storageAccess/deny-storage-access-under-opener-if-auto-dismiss-ephemeral.html
       http/tests/storageAccess/grant-storage-access-under-opener-at-popup-user-gesture-ephemeral.html

* NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::requestStorageAccessUnderOpener):

Tools:

These changes to the TestRunner makes sure that
- statisticsClearInMemoryAndPersistentStore()
- statisticsClearInMemoryAndPersistentStoreModifiedSinceHours()
... use their own StatisticsDidClearInMemoryAndPersistentStoreCallbackID
and adds the infrastructure for that.

* WebKitTestRunner/InjectedBundle/InjectedBundle.cpp:
(WTR::InjectedBundle::didReceiveMessageToPage):
* WebKitTestRunner/InjectedBundle/TestRunner.cpp:
(WTR::TestRunner::statisticsClearInMemoryAndPersistentStore):
(WTR::TestRunner::statisticsClearInMemoryAndPersistentStoreModifiedSinceHours):
(WTR::TestRunner::statisticsCallClearInMemoryAndPersistentStoreCallback):
* WebKitTestRunner/InjectedBundle/TestRunner.h:
* WebKitTestRunner/TestController.cpp:
(WTR::TestController::statisticsClearInMemoryAndPersistentStore):
(WTR::TestController::statisticsClearInMemoryAndPersistentStoreModifiedSinceHours):
* WebKitTestRunner/TestInvocation.cpp:
(WTR::TestInvocation::didClearStatisticsInMemoryAndPersistentStore):
* WebKitTestRunner/TestInvocation.h:

LayoutTests:

There are new tests added for the code change. The rest of these change are to better
align test cases with asynchronous TestRunner functions that landed in
https://trac.webkit.org/changeset/258566 and https://trac.webkit.org/changeset/258598.

While working on the new tests, I found a crasher which Chris Dumez fixed in
https://trac.webkit.org/changeset/258562, so there's a dependency on that change.

* http/tests/resourceLoadStatistics/cookies-with-and-without-user-interaction-database.html:
* http/tests/resourceLoadStatistics/cookies-with-and-without-user-interaction.html:
* http/tests/resourceLoadStatistics/count-third-party-script-import-in-worker-database.html:
* http/tests/resourceLoadStatistics/count-third-party-script-import-in-worker.html:
* http/tests/resourceLoadStatistics/count-third-party-script-loads-database.html:
* http/tests/resourceLoadStatistics/count-third-party-script-loads.html:
* http/tests/resourceLoadStatistics/do-not-switch-session-on-navigation-to-prevalent-without-interaction-database.php:
* http/tests/resourceLoadStatistics/do-not-switch-session-on-navigation-to-prevalent-without-interaction.php:
* http/tests/resourceLoadStatistics/dont-count-third-party-image-as-third-party-script-database.html:
* http/tests/resourceLoadStatistics/dont-count-third-party-image-as-third-party-script.html:
* http/tests/resourceLoadStatistics/grandfathering-database.html:
* http/tests/resourceLoadStatistics/grandfathering.html:
* http/tests/resourceLoadStatistics/switch-session-on-navigation-to-prevalent-with-interaction-database.php:
* http/tests/resourceLoadStatistics/switch-session-on-navigation-to-prevalent-with-interaction.php:
* http/tests/storageAccess/deny-storage-access-under-opener-ephemeral-expected.txt: Added.
* http/tests/storageAccess/deny-storage-access-under-opener-ephemeral.html: Added.
* http/tests/storageAccess/deny-storage-access-under-opener-if-auto-dismiss-ephemeral-expected.txt: Added.
* http/tests/storageAccess/deny-storage-access-under-opener-if-auto-dismiss-ephemeral.html: Added.
* http/tests/storageAccess/grant-storage-access-under-opener-at-popup-user-gesture-ephemeral-expected.txt: Added.
* http/tests/storageAccess/grant-storage-access-under-opener-at-popup-user-gesture-ephemeral.html: Added.

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

30 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/resourceLoadStatistics/cookies-with-and-without-user-interaction-database.html
LayoutTests/http/tests/resourceLoadStatistics/cookies-with-and-without-user-interaction.html
LayoutTests/http/tests/resourceLoadStatistics/count-third-party-script-import-in-worker-database.html
LayoutTests/http/tests/resourceLoadStatistics/count-third-party-script-import-in-worker.html
LayoutTests/http/tests/resourceLoadStatistics/count-third-party-script-loads-database.html
LayoutTests/http/tests/resourceLoadStatistics/count-third-party-script-loads.html
LayoutTests/http/tests/resourceLoadStatistics/do-not-switch-session-on-navigation-to-prevalent-without-interaction-database.php
LayoutTests/http/tests/resourceLoadStatistics/do-not-switch-session-on-navigation-to-prevalent-without-interaction.php
LayoutTests/http/tests/resourceLoadStatistics/dont-count-third-party-image-as-third-party-script-database.html
LayoutTests/http/tests/resourceLoadStatistics/dont-count-third-party-image-as-third-party-script.html
LayoutTests/http/tests/resourceLoadStatistics/grandfathering-database.html
LayoutTests/http/tests/resourceLoadStatistics/grandfathering.html
LayoutTests/http/tests/resourceLoadStatistics/switch-session-on-navigation-to-prevalent-with-interaction-database.php
LayoutTests/http/tests/resourceLoadStatistics/switch-session-on-navigation-to-prevalent-with-interaction.php
LayoutTests/http/tests/storageAccess/deny-storage-access-under-opener-ephemeral-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/storageAccess/deny-storage-access-under-opener-ephemeral.html [new file with mode: 0644]
LayoutTests/http/tests/storageAccess/deny-storage-access-under-opener-if-auto-dismiss-ephemeral-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/storageAccess/deny-storage-access-under-opener-if-auto-dismiss-ephemeral.html [new file with mode: 0644]
LayoutTests/http/tests/storageAccess/grant-storage-access-under-opener-at-popup-user-gesture-ephemeral-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/storageAccess/grant-storage-access-under-opener-at-popup-user-gesture-ephemeral.html [new file with mode: 0644]
Source/WebKit/ChangeLog
Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp
Tools/ChangeLog
Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp
Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp
Tools/WebKitTestRunner/InjectedBundle/TestRunner.h
Tools/WebKitTestRunner/TestController.cpp
Tools/WebKitTestRunner/TestInvocation.cpp
Tools/WebKitTestRunner/TestInvocation.h

index b78ee31..e93153d 100644 (file)
@@ -1,3 +1,39 @@
+2020-03-18  John Wilander  <wilander@apple.com>
+
+        WebResourceLoadStatisticsStore::requestStorageAccessUnderOpener() should call its ephemeral counterpart when appropriate
+        https://bugs.webkit.org/show_bug.cgi?id=209245
+        <rdar://problem/60511121>
+
+        Reviewed by Chris Dumez.
+
+        There are new tests added for the code change. The rest of these change are to better
+        align test cases with asynchronous TestRunner functions that landed in
+        https://trac.webkit.org/changeset/258566 and https://trac.webkit.org/changeset/258598.
+
+        While working on the new tests, I found a crasher which Chris Dumez fixed in
+        https://trac.webkit.org/changeset/258562, so there's a dependency on that change.
+
+        * http/tests/resourceLoadStatistics/cookies-with-and-without-user-interaction-database.html:
+        * http/tests/resourceLoadStatistics/cookies-with-and-without-user-interaction.html:
+        * http/tests/resourceLoadStatistics/count-third-party-script-import-in-worker-database.html:
+        * http/tests/resourceLoadStatistics/count-third-party-script-import-in-worker.html:
+        * http/tests/resourceLoadStatistics/count-third-party-script-loads-database.html:
+        * http/tests/resourceLoadStatistics/count-third-party-script-loads.html:
+        * http/tests/resourceLoadStatistics/do-not-switch-session-on-navigation-to-prevalent-without-interaction-database.php:
+        * http/tests/resourceLoadStatistics/do-not-switch-session-on-navigation-to-prevalent-without-interaction.php:
+        * http/tests/resourceLoadStatistics/dont-count-third-party-image-as-third-party-script-database.html:
+        * http/tests/resourceLoadStatistics/dont-count-third-party-image-as-third-party-script.html:
+        * http/tests/resourceLoadStatistics/grandfathering-database.html:
+        * http/tests/resourceLoadStatistics/grandfathering.html:
+        * http/tests/resourceLoadStatistics/switch-session-on-navigation-to-prevalent-with-interaction-database.php:
+        * http/tests/resourceLoadStatistics/switch-session-on-navigation-to-prevalent-with-interaction.php:
+        * http/tests/storageAccess/deny-storage-access-under-opener-ephemeral-expected.txt: Added.
+        * http/tests/storageAccess/deny-storage-access-under-opener-ephemeral.html: Added.
+        * http/tests/storageAccess/deny-storage-access-under-opener-if-auto-dismiss-ephemeral-expected.txt: Added.
+        * http/tests/storageAccess/deny-storage-access-under-opener-if-auto-dismiss-ephemeral.html: Added.
+        * http/tests/storageAccess/grant-storage-access-under-opener-at-popup-user-gesture-ephemeral-expected.txt: Added.
+        * http/tests/storageAccess/grant-storage-access-under-opener-at-popup-user-gesture-ephemeral.html: Added.
+
 2020-03-18  Ryan Haddad  <ryanhaddad@apple.com>
 
         svg/as-object/object-box-sizing-no-width-height.html is a flaky failure
index b26bf02..5badfa4 100644 (file)
@@ -68,8 +68,8 @@
 
     if (document.location.host === partitionHost && document.location.hash == "" && window.testRunner && window.internals) {
         testRunner.setUseITPDatabase(true);
+        testRunner.waitUntilDone();
         setEnableFeature(true, function() {
-            testRunner.waitUntilDone();
             testRunner.dumpChildFramesAsText();
             document.location.hash = "step1";
             if (testRunner.isStatisticsPrevalentResource(thirdPartyOrigin))
index 8267739..d1a96f4 100644 (file)
@@ -67,8 +67,8 @@
     }
 
     if (document.location.host === partitionHost && document.location.hash == "" && window.testRunner && window.internals) {
+        testRunner.waitUntilDone();
         setEnableFeature(true, function() {
-            testRunner.waitUntilDone();
             testRunner.dumpChildFramesAsText();
             document.location.hash = "step1";
             if (testRunner.isStatisticsPrevalentResource(thirdPartyOrigin))
index c175701..b18d9c1 100644 (file)
@@ -26,9 +26,9 @@
         switch (document.location.hash) {
             case "":
                 if (window.testRunner && window.internals) {
+                    testRunner.waitUntilDone();
                     setEnableFeature(true, function() {
                         testRunner.setUseITPDatabase(true);
-                        testRunner.waitUntilDone();
                         testRunner.setStatisticsNotifyPagesWhenDataRecordsWereScanned(true);
                         testRunner.installStatisticsDidScanDataRecordsCallback(finishTest);
                         document.location.hash = "LoadWorker";
index 1668cca..02fd6be 100644 (file)
@@ -26,8 +26,8 @@
         switch (document.location.hash) {
             case "":
                 if (window.testRunner && window.internals) {
+                    testRunner.waitUntilDone();
                     setEnableFeature(true, function() {
-                        testRunner.waitUntilDone();
                         testRunner.setStatisticsNotifyPagesWhenDataRecordsWereScanned(true);
                         testRunner.installStatisticsDidScanDataRecordsCallback(finishTest);
                         document.location.hash = "LoadWorker";
index 439ec49..3418d0c 100644 (file)
@@ -22,9 +22,9 @@
         switch (document.location.hash) {
             case "":
                 if (window.testRunner && window.internals) {
+                    testRunner.waitUntilDone();
                     setEnableFeature(true, function() {
                         testRunner.setUseITPDatabase(true);
-                        testRunner.waitUntilDone();
                         testRunner.setStatisticsNotifyPagesWhenDataRecordsWereScanned(true);
                         testRunner.installStatisticsDidScanDataRecordsCallback(finishTest);
                         document.location.hash = "step1";
index e305073..9a459cc 100644 (file)
@@ -22,8 +22,8 @@
         switch (document.location.hash) {
             case "":
                 if (window.testRunner && window.internals) {
+                    testRunner.waitUntilDone();
                     setEnableFeature(true, function() {
-                        testRunner.waitUntilDone();
                         testRunner.setStatisticsNotifyPagesWhenDataRecordsWereScanned(true);
                         testRunner.installStatisticsDidScanDataRecordsCallback(finishTest);
                         document.location.hash = "step1";
index 409a35d..a2a0f8c 100644 (file)
 
     function runTest() {
         switch (document.location.hash) {
+            case "":
+                if (document.location.origin !== prevalentOrigin)
+                    testFailed("Test is not starting out on " + prevalentOrigin + ".");
+
+                testRunner.setUseITPDatabase(true);
+                setEnableFeature(true, function () {
+                    if (testRunner.isStatisticsPrevalentResource(prevalentOrigin))
+                        testFailed(prevalentOrigin + " was classified as prevalent resource before the test starts.");
+                    document.location.hash = "step1";
+                    runTest();
+                });
             case "#step1":
                 setSessionCookie();
                 setPersistentCookie();
                 setEnableFeature(false, finishJSTest);
         }
     }
-
-    if (document.location.hash === "") {
-        if (document.location.origin !== prevalentOrigin)
-            testFailed("Test is not starting out on " + prevalentOrigin + ".");
-            
-            testRunner.setUseITPDatabase(true);
-        setEnableFeature(true, function () {
-            if (testRunner.isStatisticsPrevalentResource(prevalentOrigin))
-                testFailed(prevalentOrigin + " was classified as prevalent resource before the test starts.");
-            document.location.hash = "step1";
-        });
-    }
 </script>
 </body>
 </html>
index 079562a..8b1be9e 100644 (file)
 
     function runTest() {
         switch (document.location.hash) {
+            case "":
+                if (document.location.origin !== prevalentOrigin)
+                    testFailed("Test is not starting out on " + prevalentOrigin + ".");
+
+                setEnableFeature(true, function () {
+                    if (testRunner.isStatisticsPrevalentResource(prevalentOrigin))
+                        testFailed(prevalentOrigin + " was classified as prevalent resource before the test starts.");
+                    document.location.hash = "step1";
+                    runTest();
+                });
             case "#step1":
                 setSessionCookie();
                 setPersistentCookie();
                 setEnableFeature(false, finishJSTest);
         }
     }
-
-    if (document.location.hash === "") {
-        if (document.location.origin !== prevalentOrigin)
-            testFailed("Test is not starting out on " + prevalentOrigin + ".");
-        setEnableFeature(true, function () {
-            if (testRunner.isStatisticsPrevalentResource(prevalentOrigin))
-                testFailed(prevalentOrigin + " was classified as prevalent resource before the test starts.");
-            document.location.hash = "step1";
-        });
-    }
 </script>
 </body>
 </html>
index 5216090..cf1a135 100644 (file)
@@ -22,9 +22,9 @@
         switch (document.location.hash) {
             case "":
                 if (window.testRunner && window.internals) {
+                    testRunner.waitUntilDone();
                     setEnableFeature(true, function() {
                         testRunner.setUseITPDatabase(true);
-                        testRunner.waitUntilDone();
                         testRunner.setStatisticsNotifyPagesWhenDataRecordsWereScanned(true);
                         testRunner.installStatisticsDidScanDataRecordsCallback(finishTest);
                         document.location.hash = "step1";
index a51e64c..8172c1a 100644 (file)
@@ -22,8 +22,8 @@
         switch (document.location.hash) {
             case "":
                 if (window.testRunner && window.internals) {
+                    testRunner.waitUntilDone();
                     setEnableFeature(true, function() {
-                        testRunner.waitUntilDone();
                         testRunner.setStatisticsNotifyPagesWhenDataRecordsWereScanned(true);
                         testRunner.installStatisticsDidScanDataRecordsCallback(finishTest);
                         document.location.hash = "step1";
index 816d911..266fcfb 100644 (file)
 
     if (document.location.hash === "" && window.testRunner && window.internals) {
         testRunner.setUseITPDatabase(true);
+        testRunner.waitUntilDone();
         setEnableFeature(true, function() {
             testRunner.setStatisticsShouldClassifyResourcesBeforeDataRecordsRemoval(false);
             testRunner.setStatisticsMinimumTimeBetweenDataRecordsRemoval(0);
 
-            testRunner.waitUntilDone();
             testRunner.dumpChildFramesAsText();
             document.location.hash = "step1";
             runTest();
index b1ba5e7..d7ba638 100644 (file)
     }
 
     if (document.location.hash === "" && window.testRunner && window.internals) {
+        testRunner.waitUntilDone();
         setEnableFeature(true, function() {
             testRunner.setStatisticsShouldClassifyResourcesBeforeDataRecordsRemoval(false);
             testRunner.setStatisticsMinimumTimeBetweenDataRecordsRemoval(0);
 
-            testRunner.waitUntilDone();
             testRunner.dumpChildFramesAsText();
             document.location.hash = "step1";
             runTest();
index 97efeb7..9d6587f 100644 (file)
 
     function runTest() {
         switch (document.location.hash) {
+            case "":
+                if (document.location.origin !== prevalentOrigin)
+                    testFailed("Test is not starting out on " + prevalentOrigin + ".");
+                testRunner.setUseITPDatabase(true);
+                setEnableFeature(true, function () {
+                    if (testRunner.isStatisticsPrevalentResource(prevalentOrigin))
+                        testFailed(prevalentOrigin + " was classified as prevalent resource before the test starts.");
+                    document.location.hash = "step1";
+                    runTest();
+                });
+                break;
             case "#step1":
                 testRunner.setStatisticsHasHadUserInteraction(prevalentOrigin, true, function() {
                     setSessionCookie();
                 setEnableFeature(false, finishJSTest);
         }
     }
-
-    if (document.location.hash === "") {
-        if (document.location.origin !== prevalentOrigin)
-            testFailed("Test is not starting out on " + prevalentOrigin + ".");
-        testRunner.setUseITPDatabase(true);
-        setEnableFeature(true, function () {
-            if (testRunner.isStatisticsPrevalentResource(prevalentOrigin))
-                testFailed(prevalentOrigin + " was classified as prevalent resource before the test starts.");
-            document.location.hash = "step1";
-        });
-    }
 </script>
 </body>
 </html>
index ab03083..4cc4115 100644 (file)
 
     function runTest() {
         switch (document.location.hash) {
+            case "":
+                if (document.location.origin !== prevalentOrigin)
+                    testFailed("Test is not starting out on " + prevalentOrigin + ".");
+                setEnableFeature(true, function () {
+                    if (testRunner.isStatisticsPrevalentResource(prevalentOrigin))
+                        testFailed(prevalentOrigin + " was classified as prevalent resource before the test starts.");
+                    document.location.hash = "step1";
+                    runTest();
+                });
+                break;
             case "#step1":
                 testRunner.setStatisticsHasHadUserInteraction(prevalentOrigin, true, function() {
                     setSessionCookie();
                 setEnableFeature(false, finishJSTest);
         }
     }
-
-    if (document.location.hash === "") {
-        if (document.location.origin !== prevalentOrigin)
-            testFailed("Test is not starting out on " + prevalentOrigin + ".");
-        setEnableFeature(true, function () {
-            if (testRunner.isStatisticsPrevalentResource(prevalentOrigin))
-                testFailed(prevalentOrigin + " was classified as prevalent resource before the test starts.");
-            document.location.hash = "step1";
-        });
-    }
 </script>
 </body>
 </html>
diff --git a/LayoutTests/http/tests/storageAccess/deny-storage-access-under-opener-ephemeral-expected.txt b/LayoutTests/http/tests/storageAccess/deny-storage-access-under-opener-ephemeral-expected.txt
new file mode 100644 (file)
index 0000000..e55ebaa
--- /dev/null
@@ -0,0 +1,17 @@
+Tests that a cross-origin window without user interaction is denied storage access under its opener (ephemeral).
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Cookie created.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+
+--------
+Frame: '<!--frame1-->'
+--------
+Should not receive first-party cookie.
+Did not receive cookie named 'firstPartyCookie'.
+Client-side document.cookie:
diff --git a/LayoutTests/http/tests/storageAccess/deny-storage-access-under-opener-ephemeral.html b/LayoutTests/http/tests/storageAccess/deny-storage-access-under-opener-ephemeral.html
new file mode 100644 (file)
index 0000000..dcf4208
--- /dev/null
@@ -0,0 +1,66 @@
+<!-- webkit-test-runner [ useEphemeralSession=true ] -->
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script src="/resourceLoadStatistics/resources/util.js"></script>
+</head>
+<body onload="run()">
+<script>
+    description("Tests that a cross-origin window without user interaction is denied storage access under its opener (ephemeral).");
+    jsTestIsAsync = true;
+
+    window.addEventListener("message", receiveMessage, false);
+
+    function finishTest() {
+        testRunner.setStatisticsShouldBlockThirdPartyCookies(false, function() {
+            setEnableFeature(false, finishJSTest);
+        });
+    }
+
+    function openIframe(url, onLoadHandler) {
+        const element = document.createElement("iframe");
+        element.src = url;
+        if (onLoadHandler) {
+            element.onload = onLoadHandler;
+        }
+        document.body.appendChild(element);
+    }
+
+    function receiveMessage(event) {
+        if (event.origin === "http://localhost:8000") {
+            if (event.data.indexOf("PASS") !== -1)
+                testPassed(event.data.replace("PASS ", ""));
+            else
+                testFailed(event.data);
+        } else
+            testFailed("Received a message from an unexpected origin: " + event.origin);
+
+        newWin.close();
+        openIframe(thirdPartyBaseUrl + subPathToGetCookies + "&message=Should not receive first-party cookie.", finishTest);
+    }
+
+    const thirdPartyOrigin = "http://localhost:8000";
+    const resourcePath = "/storageAccess/resources";
+    const thirdPartyBaseUrl = thirdPartyOrigin + resourcePath;
+    const firstPartyCookieName = "firstPartyCookie";
+    const subPathToGetCookies = "/get-cookies.php?name1=" + firstPartyCookieName;
+    let newWin;
+
+    function run() {
+        setEnableFeature(true, function () {
+            testRunner.setCanOpenWindows();
+
+            if (testRunner.isStatisticsHasHadUserInteraction(thirdPartyOrigin))
+                testFailed("Host logged for user interaction.");
+            testRunner.dumpChildFramesAsText();
+            testRunner.setCloseRemainingWindowsWhenComplete(true);
+
+            testRunner.setStatisticsShouldBlockThirdPartyCookies(true, function() {
+                newWin = window.open(thirdPartyOrigin + "/storageAccess/resources/set-cookie-and-report-back.html", "testWindow");
+            });
+        });
+    }
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/http/tests/storageAccess/deny-storage-access-under-opener-if-auto-dismiss-ephemeral-expected.txt b/LayoutTests/http/tests/storageAccess/deny-storage-access-under-opener-if-auto-dismiss-ephemeral-expected.txt
new file mode 100644 (file)
index 0000000..d6a1f36
--- /dev/null
@@ -0,0 +1,17 @@
+Tests that a cross-origin window with non-recent user interaction doesn't get storage access under its opener if it just loads and auto-dismisses (ephemeral).
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Cookie created.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+
+--------
+Frame: '<!--frame1-->'
+--------
+Should not receive first-party cookie.
+Did not receive cookie named 'firstPartyCookie'.
+Client-side document.cookie:
diff --git a/LayoutTests/http/tests/storageAccess/deny-storage-access-under-opener-if-auto-dismiss-ephemeral.html b/LayoutTests/http/tests/storageAccess/deny-storage-access-under-opener-if-auto-dismiss-ephemeral.html
new file mode 100644 (file)
index 0000000..0a27b6d
--- /dev/null
@@ -0,0 +1,68 @@
+<!-- webkit-test-runner [ useEphemeralSession=true ] -->
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script src="/resourceLoadStatistics/resources/util.js"></script>
+</head>
+<body onload="run()">
+<script>
+    description("Tests that a cross-origin window with non-recent user interaction doesn't get storage access under its opener if it just loads and auto-dismisses (ephemeral).");
+    jsTestIsAsync = true;
+
+    function finishTest() {
+        testRunner.setStatisticsShouldBlockThirdPartyCookies(false, function() {
+            setEnableFeature(false, finishJSTest);
+        });
+    }
+
+    function openIframe(url, onLoadHandler) {
+        const element = document.createElement("iframe");
+        element.src = url;
+        if (onLoadHandler) {
+            element.onload = onLoadHandler;
+        }
+        document.body.appendChild(element);
+    }
+
+    function receiveMessage(event) {
+        if (event.origin === "http://localhost:8000") {
+            if (event.data.indexOf("PASS") !== -1)
+                testPassed(event.data.replace("PASS ", ""));
+            else
+                testFailed(event.data);
+        } else
+            testFailed("Received a message from an unexpected origin: " + event.origin);
+
+        newWin.close();
+        openIframe(thirdPartyBaseUrl + subPathToGetCookies + "&message=Should not receive first-party cookie.", finishTest);
+    }
+
+    const thirdPartyOrigin = "http://localhost:8000";
+    const resourcePath = "/storageAccess/resources";
+    const thirdPartyBaseUrl = thirdPartyOrigin + resourcePath;
+    const firstPartyCookieName = "firstPartyCookie";
+    const subPathToGetCookies = "/get-cookies.php?name1=" + firstPartyCookieName;
+    let newWin;
+
+    function run() {
+        setEnableFeature(true, function() {
+            window.addEventListener("message", receiveMessage, false);
+
+            testRunner.setCanOpenWindows();
+
+            testRunner.setStatisticsHasHadUserInteraction(thirdPartyOrigin, true, function() {
+                if (!testRunner.isStatisticsHasHadUserInteraction(thirdPartyOrigin))
+                    testFailed("Host did not get logged for user interaction.");
+                testRunner.dumpChildFramesAsText();
+                testRunner.setCloseRemainingWindowsWhenComplete(true);
+
+                testRunner.setStatisticsShouldBlockThirdPartyCookies(true, function () {
+                    newWin = window.open(thirdPartyOrigin + "/storageAccess/resources/set-cookie-and-report-back.html", "testWindow");
+                });
+            });
+        });
+    }
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/http/tests/storageAccess/grant-storage-access-under-opener-at-popup-user-gesture-ephemeral-expected.txt b/LayoutTests/http/tests/storageAccess/grant-storage-access-under-opener-at-popup-user-gesture-ephemeral-expected.txt
new file mode 100644 (file)
index 0000000..e80f572
--- /dev/null
@@ -0,0 +1,17 @@
+Tests that a cross-origin window from a prevalent domain with previous user interaction gets storage access under its opener if it gets user interaction (ephemeral).
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Cookie created.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+
+--------
+Frame: '<!--frame1-->'
+--------
+Should receive first-party cookie.
+Received cookie named 'firstPartyCookie'.
+Client-side document.cookie: firstPartyCookie=value
diff --git a/LayoutTests/http/tests/storageAccess/grant-storage-access-under-opener-at-popup-user-gesture-ephemeral.html b/LayoutTests/http/tests/storageAccess/grant-storage-access-under-opener-at-popup-user-gesture-ephemeral.html
new file mode 100644 (file)
index 0000000..ac4450c
--- /dev/null
@@ -0,0 +1,67 @@
+<!-- webkit-test-runner [ useEphemeralSession=true ] -->
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script src="/resourceLoadStatistics/resources/util.js"></script>
+</head>
+<body onload="run()">
+<script>
+    description("Tests that a cross-origin window from a prevalent domain with previous user interaction gets storage access under its opener if it gets user interaction (ephemeral).");
+    jsTestIsAsync = true;
+
+    function finishTest() {
+        testRunner.setStatisticsShouldBlockThirdPartyCookies(false, function () {
+            setEnableFeature(false, finishJSTest);
+        });
+    }
+
+    function openIframe(url, onLoadHandler) {
+        const element = document.createElement("iframe");
+        element.src = url;
+        if (onLoadHandler) {
+            element.onload = onLoadHandler;
+        }
+        document.body.appendChild(element);
+    }
+
+    function receiveMessage(event) {
+        if (event.origin === "http://localhost:8000") {
+            if (event.data.indexOf("PASS") !== -1)
+                testPassed(event.data.replace("PASS ", ""));
+            else
+                testFailed(event.data);
+        } else
+            testFailed("Received a message from an unexpected origin: " + event.origin);
+
+        newWin.close();
+        openIframe(thirdPartyBaseUrl + subPathToGetCookies + "&message=Should receive first-party cookie.", finishTest);
+    }
+
+    const thirdPartyOrigin = "http://localhost:8000";
+    const resourcePath = "/storageAccess/resources";
+    const thirdPartyBaseUrl = thirdPartyOrigin + resourcePath;
+    const firstPartyCookieName = "firstPartyCookie";
+    const subPathToGetCookies = "/get-cookies.php?name1=" + firstPartyCookieName;
+    let newWin;
+
+    function run() {
+        setEnableFeature(true, function () {
+            window.addEventListener("message", receiveMessage, false);
+
+            testRunner.setCanOpenWindows();
+            testRunner.setStatisticsHasHadUserInteraction(thirdPartyOrigin, true, function() {
+                if (!testRunner.isStatisticsHasHadUserInteraction(thirdPartyOrigin))
+                    testFailed("Host did not get logged for user interaction.");
+                testRunner.dumpChildFramesAsText();
+                testRunner.setCloseRemainingWindowsWhenComplete(true);
+
+                testRunner.setStatisticsShouldBlockThirdPartyCookies(true, function () {
+                    newWin = window.open(thirdPartyOrigin + "/storageAccess/resources/produce-user-gesture-set-cookie-and-report-back.html", "testWindow");
+                });
+            });
+        });
+    }
+</script>
+</body>
+</html>
\ No newline at end of file
index dcc258b..9acc9d2 100644 (file)
@@ -1,3 +1,22 @@
+2020-03-18  John Wilander  <wilander@apple.com>
+
+        WebResourceLoadStatisticsStore::requestStorageAccessUnderOpener() should call its ephemeral counterpart when appropriate
+        https://bugs.webkit.org/show_bug.cgi?id=209245
+        <rdar://problem/60511121>
+
+        Reviewed by Chris Dumez.
+
+        This change makes sure that WebResourceLoadStatisticsStore::requestStorageAccessUnderOpener()
+        calls WebResourceLoadStatisticsStore::requestStorageAccessUnderOpenerEphemeral() for ephemeral
+        sessions.
+
+        Tests: http/tests/storageAccess/deny-storage-access-under-opener-ephemeral.html
+               http/tests/storageAccess/deny-storage-access-under-opener-if-auto-dismiss-ephemeral.html
+               http/tests/storageAccess/grant-storage-access-under-opener-at-popup-user-gesture-ephemeral.html
+
+        * NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp:
+        (WebKit::WebResourceLoadStatisticsStore::requestStorageAccessUnderOpener):
+
 2020-03-18  Brent Fulgham  <bfulgham@apple.com>
 
         Avoid calling 'notifyThisWebProcessPoolWasCreated' inside the constructor
index 2ab6c0e..7d9459a 100644 (file)
@@ -484,6 +484,9 @@ void WebResourceLoadStatisticsStore::requestStorageAccessUnderOpener(Registrable
 {
     ASSERT(RunLoop::isMain());
 
+    if (isEphemeral())
+        return requestStorageAccessUnderOpenerEphemeral(WTFMove(domainInNeedOfStorageAccess), openerPageID, WTFMove(openerDomain));
+
     // It is safe to move the strings to the background queue without isolated copy here because they are r-value references
     // coming from IPC. Strings which are safe to move to other threads as long as nobody on this thread holds a reference
     // to those strings.
index fb44654..a915910 100644 (file)
@@ -1,3 +1,31 @@
+2020-03-18  John Wilander  <wilander@apple.com>
+
+        WebResourceLoadStatisticsStore::requestStorageAccessUnderOpener() should call its ephemeral counterpart when appropriate
+        https://bugs.webkit.org/show_bug.cgi?id=209245
+        <rdar://problem/60511121>
+
+        Reviewed by Chris Dumez.
+
+        These changes to the TestRunner makes sure that
+        - statisticsClearInMemoryAndPersistentStore()
+        - statisticsClearInMemoryAndPersistentStoreModifiedSinceHours()
+        ... use their own StatisticsDidClearInMemoryAndPersistentStoreCallbackID
+        and adds the infrastructure for that.
+
+        * WebKitTestRunner/InjectedBundle/InjectedBundle.cpp:
+        (WTR::InjectedBundle::didReceiveMessageToPage):
+        * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+        (WTR::TestRunner::statisticsClearInMemoryAndPersistentStore):
+        (WTR::TestRunner::statisticsClearInMemoryAndPersistentStoreModifiedSinceHours):
+        (WTR::TestRunner::statisticsCallClearInMemoryAndPersistentStoreCallback):
+        * WebKitTestRunner/InjectedBundle/TestRunner.h:
+        * WebKitTestRunner/TestController.cpp:
+        (WTR::TestController::statisticsClearInMemoryAndPersistentStore):
+        (WTR::TestController::statisticsClearInMemoryAndPersistentStoreModifiedSinceHours):
+        * WebKitTestRunner/TestInvocation.cpp:
+        (WTR::TestInvocation::didClearStatisticsInMemoryAndPersistentStore):
+        * WebKitTestRunner/TestInvocation.h:
+
 2020-03-18  Wenson Hsieh  <wenson_hsieh@apple.com>
 
         REGRESSION (r257214): Targeted preview animates to the wrong place when dropping in editable content
index a2b8f7a..52f1689 100644 (file)
@@ -327,6 +327,11 @@ void InjectedBundle::didReceiveMessageToPage(WKBundlePageRef page, WKStringRef m
         return;
     }
 
+    if (WKStringIsEqualToUTF8CString(messageName, "CallDidClearStatisticsInMemoryAndPersistentStore")) {
+        m_testRunner->statisticsCallClearInMemoryAndPersistentStoreCallback();
+        return;
+    }
+
     if (WKStringIsEqualToUTF8CString(messageName, "CallDidClearStatisticsThroughWebsiteDataRemoval")) {
         m_testRunner->statisticsCallClearThroughWebsiteDataRemovalCallback();
         return;
index 5bcde30..e0c7ebf 100644 (file)
@@ -748,6 +748,7 @@ enum {
     StatisticsDidScanDataRecordsCallbackID,
     StatisticsDidRunTelemetryCallbackID,
     StatisticsDidClearThroughWebsiteDataRemovalCallbackID,
+    StatisticsDidClearInMemoryAndPersistentStoreCallbackID,
     StatisticsDidResetToConsistentStateCallbackID,
     StatisticsDidSetBlockCookiesForHostCallbackID,
     StatisticsDidSetShouldDowngradeReferrerCallbackID,
@@ -2143,7 +2144,7 @@ void TestRunner::setStatisticsPruneEntriesDownTo(unsigned entries)
     
 void TestRunner::statisticsClearInMemoryAndPersistentStore(JSValueRef callback)
 {
-    cacheTestRunnerCallback(StatisticsDidClearThroughWebsiteDataRemovalCallbackID, callback);
+    cacheTestRunnerCallback(StatisticsDidClearInMemoryAndPersistentStoreCallbackID, callback);
 
     WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("StatisticsClearInMemoryAndPersistentStore"));
     WKBundlePostMessage(InjectedBundle::singleton().bundle(), messageName.get(), nullptr);
@@ -2151,7 +2152,7 @@ void TestRunner::statisticsClearInMemoryAndPersistentStore(JSValueRef callback)
 
 void TestRunner::statisticsClearInMemoryAndPersistentStoreModifiedSinceHours(unsigned hours, JSValueRef callback)
 {
-    cacheTestRunnerCallback(StatisticsDidClearThroughWebsiteDataRemovalCallbackID, callback);
+    cacheTestRunnerCallback(StatisticsDidClearInMemoryAndPersistentStoreCallbackID, callback);
 
     WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("StatisticsClearInMemoryAndPersistentStoreModifiedSinceHours"));
     WKRetainPtr<WKTypeRef> messageBody = adoptWK(WKUInt64Create(hours));
@@ -2275,6 +2276,11 @@ void TestRunner::statisticsCallDidSetFirstPartyWebsiteDataRemovalModeCallback()
     m_hasSetFirstPartyWebsiteDataRemovalModeCallback = false;
 }
 
+void TestRunner::statisticsCallClearInMemoryAndPersistentStoreCallback()
+{
+    callTestRunnerCallback(StatisticsDidClearInMemoryAndPersistentStoreCallbackID);
+}
+
 void TestRunner::statisticsCallClearThroughWebsiteDataRemovalCallback()
 {
     callTestRunnerCallback(StatisticsDidClearThroughWebsiteDataRemovalCallbackID);
index 61db93f..5f2475c 100644 (file)
@@ -437,6 +437,7 @@ public:
     void statisticsClearInMemoryAndPersistentStoreModifiedSinceHours(unsigned hours, JSValueRef callback);
     void statisticsClearThroughWebsiteDataRemoval(JSValueRef callback);
     void statisticsDeleteCookiesForHost(JSStringRef hostName, bool includeHttpOnlyCookies);
+    void statisticsCallClearInMemoryAndPersistentStoreCallback();
     void statisticsCallClearThroughWebsiteDataRemovalCallback();
     bool isStatisticsHasLocalStorage(JSStringRef hostName);
     void setStatisticsCacheMaxAgeCap(double seconds);
index 5e06f36..3cbcd62 100644 (file)
@@ -3631,7 +3631,7 @@ void TestController::statisticsClearInMemoryAndPersistentStore()
     ResourceStatisticsCallbackContext context(*this);
     WKWebsiteDataStoreStatisticsClearInMemoryAndPersistentStore(websiteDataStore(), &context, resourceStatisticsVoidResultCallback);
     runUntil(context.done, noTimeout);
-    m_currentInvocation->didClearStatisticsThroughWebsiteDataRemoval();
+    m_currentInvocation->didClearStatisticsInMemoryAndPersistentStore();
 }
 
 void TestController::statisticsClearInMemoryAndPersistentStoreModifiedSinceHours(unsigned hours)
@@ -3639,7 +3639,7 @@ void TestController::statisticsClearInMemoryAndPersistentStoreModifiedSinceHours
     ResourceStatisticsCallbackContext context(*this);
     WKWebsiteDataStoreStatisticsClearInMemoryAndPersistentStoreModifiedSinceHours(websiteDataStore(), hours, &context, resourceStatisticsVoidResultCallback);
     runUntil(context.done, noTimeout);
-    m_currentInvocation->didClearStatisticsThroughWebsiteDataRemoval();
+    m_currentInvocation->didClearStatisticsInMemoryAndPersistentStore();
 }
 
 void TestController::statisticsClearThroughWebsiteDataRemoval()
index ef221be..e4749d2 100644 (file)
@@ -1880,6 +1880,12 @@ void TestInvocation::notifyDownloadDone()
     WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0);
 }
 
+void TestInvocation::didClearStatisticsInMemoryAndPersistentStore()
+{
+    WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallDidClearStatisticsInMemoryAndPersistentStore"));
+    WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0);
+}
+
 void TestInvocation::didClearStatisticsThroughWebsiteDataRemoval()
 {
     WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallDidClearStatisticsThroughWebsiteDataRemoval"));
index a4ad391..dc1f953 100644 (file)
@@ -72,6 +72,7 @@ public:
 
     void notifyDownloadDone();
 
+    void didClearStatisticsInMemoryAndPersistentStore();
     void didClearStatisticsThroughWebsiteDataRemoval();
     void didSetShouldDowngradeReferrer();
     void didSetShouldBlockThirdPartyCookies();