Resource Load Statistics: Allow multiple third-party cookie blocking settings
authorwilander@apple.com <wilander@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 24 Nov 2019 03:05:49 +0000 (03:05 +0000)
committerwilander@apple.com <wilander@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 24 Nov 2019 03:05:49 +0000 (03:05 +0000)
https://bugs.webkit.org/show_bug.cgi?id=204389
<rdar://problem/57344054>

Reviewed by Brent Fulgham.

Source/WebCore:

This change introduces an enum ThirdPartyCookieBlockingMode for how third-party
cookie blocking should be carried out. It then uses the set mode in
NetworkStorageSession::shouldBlockCookies().

The reason for supporting three different modes is that what is now named
OnlyAccordingToPerDomainPolicy is shipping, AllOnSitesWithoutUserInteraction is
in beta, and All is behind an experimental flag.

Tests: http/tests/resourceLoadStatistics/third-party-cookie-blocking-on-sites-without-user-interaction-database.html
       http/tests/resourceLoadStatistics/third-party-cookie-blocking-on-sites-without-user-interaction.html

* page/Settings.yaml:
    Flipped the isThirdPartyCookieBlockingEnabled flag to on by default.
* platform/network/NetworkStorageSession.cpp:
(WebCore::NetworkStorageSession::shouldBlockCookies const):
(WebCore::NetworkStorageSession::setThirdPartyCookieBlockingMode):
* platform/network/NetworkStorageSession.h:
(WebCore::NetworkStorageSession::setIsThirdPartyCookieBlockingEnabled): Deleted.

Source/WebKit:

This change make the third-party cookie blocking setting go from a boolean to
the new enum WebCore::ThirdPartyCookieBlockingMode with three different settings.
Functions and member variables are renamed accordingly.

The reason for supporting three different modes is that what is now named
OnlyAccordingToPerDomainPolicy is shipping, AllOnSitesWithoutUserInteraction is
in beta, and All is behind an experimental flag.

The change also updates the test API to map the TestRunner call to the enum.

* NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp:
(WebKit::ResourceLoadStatisticsDatabaseStore::hasStorageAccess):
(WebKit::ResourceLoadStatisticsDatabaseStore::requestStorageAccess):
(WebKit::ResourceLoadStatisticsDatabaseStore::clearUserInteraction):
    Now makes use of a completion handler and updates the cookie blocking state.
(WebKit::ResourceLoadStatisticsDatabaseStore::hasHadUserInteraction):
(WebKit::ResourceLoadStatisticsDatabaseStore::areAllThirdPartyCookiesBlockedUnder):
    New convenience function to check the cookie blocking status per first-party domain.
(WebKit::ResourceLoadStatisticsDatabaseStore::cookieAccess):
    Restructured the code to make it very clear that the logic is the same as the
    corresponding function in ResourceLoadStatisticsMemoryStore.
    Can no longer be const since it calls areAllThirdPartyCookiesBlockedUnder() which
    in turn calls hasHadUserInteraction() and that function may clear user interaction data.
(WebKit::ResourceLoadStatisticsDatabaseStore::hasHadUnexpiredRecentUserInteraction):
(WebKit::ResourceLoadStatisticsDatabaseStore::cookieAccess const): Deleted.
    See comment above on the non-const version of this function.
* NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h:
* NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.cpp:
(WebKit::ResourceLoadStatisticsMemoryStore::areAllThirdPartyCookiesBlockedUnder):
    New convenience function to check the cookie blocking status per first-party domain.
(WebKit::ResourceLoadStatisticsMemoryStore::cookieAccess):
    Restructured the code to make it very clear that the logic is the same as the
    corresponding function in ResourceLoadStatisticsDatabaseStore.
    Can no longer be const since it calls areAllThirdPartyCookiesBlockedUnder() which
    in turn calls hasHadUserInteraction() and that function may clear user interaction data.
(WebKit::ResourceLoadStatisticsMemoryStore::hasStorageAccess):
(WebKit::ResourceLoadStatisticsMemoryStore::requestStorageAccess):
(WebKit::ResourceLoadStatisticsMemoryStore::clearUserInteraction):
    Now makes use of a completion handler and updates the cookie blocking state.
(WebKit::ResourceLoadStatisticsMemoryStore::cookieAccess const): Deleted.
    See comment above on the non-const version of this function.
* NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.h:
* NetworkProcess/Classifier/ResourceLoadStatisticsStore.h:
(WebKit::ResourceLoadStatisticsStore::setThirdPartyCookieBlockingMode):
(WebKit::ResourceLoadStatisticsStore::thirdPartyCookieBlockingMode const):
(WebKit::ResourceLoadStatisticsStore::setIsThirdPartyCookieBlockingEnabled): Deleted.
(WebKit::ResourceLoadStatisticsStore::isThirdPartyCookieBlockingEnabled const): Deleted.
* NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::setThirdPartyCookieBlockingMode):
(WebKit::WebResourceLoadStatisticsStore::clearUserInteraction):
    Now forwards the completion handler.
(WebKit::WebResourceLoadStatisticsStore::setIsThirdPartyCookieBlockingEnabled): Deleted.
* NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h:
* NetworkProcess/NetworkProcess.cpp:
(WebKit::NetworkProcess::setShouldBlockThirdPartyCookiesForTesting):
* NetworkProcess/NetworkProcess.h:
* NetworkProcess/NetworkProcess.messages.in:
    The SetShouldBlockThirdPartyCookiesForTesting message now uses an enum instead of a
    boolean.
* NetworkProcess/NetworkSession.cpp:
(WebKit::NetworkSession::setResourceLoadStatisticsEnabled):
    Now forwards the enum value instead of a boolean.
(WebKit::NetworkSession::recreateResourceLoadStatisticStore):
    Now makes sure the cookie blocking setting is forwarded to the recreated store.
(WebKit::NetworkSession::setThirdPartyCookieBlockingMode):
(WebKit::NetworkSession::setIsThirdPartyCookieBlockingEnabled): Deleted.
* NetworkProcess/NetworkSession.h:
* NetworkProcess/NetworkSessionCreationParameters.cpp:
(WebKit::NetworkSessionCreationParameters::encode const):
(WebKit::NetworkSessionCreationParameters::decode):
    Support for the new enum.
* NetworkProcess/NetworkSessionCreationParameters.h:
* NetworkProcess/cocoa/NetworkSessionCocoa.mm:
(WebKit::NetworkSessionCocoa::NetworkSessionCocoa):
* Scripts/webkit/messages.py:
    Tells the IPC code generator where to find WebCore::ThirdPartyCookieBlockingMode.
* Shared/WebPreferences.yaml:
    Flipped the IsThirdPartyCookieBlockingEnabled flag to on by default.
* UIProcess/API/C/WKWebsiteDataStoreRef.cpp:
(WKWebsiteDataStoreSetResourceLoadStatisticsShouldBlockThirdPartyCookiesForTesting):
(WKWebsiteDataStoreStatisticsResetToConsistentState):
* UIProcess/API/C/WKWebsiteDataStoreRef.h:
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::setShouldBlockThirdPartyCookiesForTesting):
* UIProcess/Network/NetworkProcessProxy.h:
* UIProcess/WebProcessPool.cpp:
(WebKit::WebProcessPool::ensureNetworkProcess):
    Makes use of the enum in the NetworkSessionCreationParameters.
* UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm:
(WebKit::WebsiteDataStore::parameters):
* UIProcess/WebsiteData/WebsiteDataStore.cpp:
(WebKit::WebsiteDataStore::setResourceLoadStatisticsShouldBlockThirdPartyCookiesForTesting):
* UIProcess/WebsiteData/WebsiteDataStore.h:

Tools:

This change allows the existing TestRunner function
setStatisticsShouldBlockThirdPartyCookies() to set an optional boolean
parameter onlyOnSitesWithoutUserInteraction to opt in to that behavior.

* WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
* WebKitTestRunner/InjectedBundle/TestRunner.cpp:
(WTR::TestRunner::setStatisticsShouldBlockThirdPartyCookies):
* WebKitTestRunner/InjectedBundle/TestRunner.h:
* WebKitTestRunner/TestController.cpp:
(WTR::TestController::setStatisticsShouldBlockThirdPartyCookies):
* WebKitTestRunner/TestController.h:
* WebKitTestRunner/TestInvocation.cpp:
(WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):

LayoutTests:

The added tests existed before and are not re-introduced to test their dedicated setting.

The changed tests have been expanded to cover the new code paths.

* http/tests/resourceLoadStatistics/third-party-cookie-blocking-on-sites-without-user-interaction-database-expected.txt: Added.
* http/tests/resourceLoadStatistics/third-party-cookie-blocking-on-sites-without-user-interaction-database.html: Added.
* http/tests/resourceLoadStatistics/third-party-cookie-blocking-on-sites-without-user-interaction-expected.txt: Added.
* http/tests/resourceLoadStatistics/third-party-cookie-blocking-on-sites-without-user-interaction.html: Added.
* http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking-database-expected.txt:
* http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking-database.html:
* http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking-expected.txt:
* http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking.html:
* http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie-database-expected.txt:
* http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie-database.html:
* http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie-expected.txt:
* http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie.html:

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

50 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/resourceLoadStatistics/third-party-cookie-blocking-on-sites-without-user-interaction-database-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/resourceLoadStatistics/third-party-cookie-blocking-on-sites-without-user-interaction-database.html [new file with mode: 0644]
LayoutTests/http/tests/resourceLoadStatistics/third-party-cookie-blocking-on-sites-without-user-interaction-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/resourceLoadStatistics/third-party-cookie-blocking-on-sites-without-user-interaction.html [new file with mode: 0644]
LayoutTests/http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking-database-expected.txt
LayoutTests/http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking-database.html
LayoutTests/http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking-expected.txt
LayoutTests/http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking.html
LayoutTests/http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie-database-expected.txt
LayoutTests/http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie-database.html
LayoutTests/http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie-expected.txt
LayoutTests/http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie.html
Source/WebCore/ChangeLog
Source/WebCore/page/Settings.yaml
Source/WebCore/platform/network/NetworkStorageSession.cpp
Source/WebCore/platform/network/NetworkStorageSession.h
Source/WebKit/ChangeLog
Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp
Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h
Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.cpp
Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.h
Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsStore.h
Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp
Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h
Source/WebKit/NetworkProcess/NetworkProcess.cpp
Source/WebKit/NetworkProcess/NetworkProcess.h
Source/WebKit/NetworkProcess/NetworkProcess.messages.in
Source/WebKit/NetworkProcess/NetworkSession.cpp
Source/WebKit/NetworkProcess/NetworkSession.h
Source/WebKit/NetworkProcess/NetworkSessionCreationParameters.cpp
Source/WebKit/NetworkProcess/NetworkSessionCreationParameters.h
Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm
Source/WebKit/Scripts/webkit/messages.py
Source/WebKit/Shared/WebPreferences.yaml
Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp
Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.h
Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp
Source/WebKit/UIProcess/Network/NetworkProcessProxy.h
Source/WebKit/UIProcess/WebProcessPool.cpp
Source/WebKit/UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm
Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp
Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h
Tools/ChangeLog
Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl
Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp
Tools/WebKitTestRunner/InjectedBundle/TestRunner.h
Tools/WebKitTestRunner/TestController.cpp
Tools/WebKitTestRunner/TestController.h
Tools/WebKitTestRunner/TestInvocation.cpp

index f81a013..db923ce 100644 (file)
@@ -1,3 +1,28 @@
+2019-11-23  John Wilander  <wilander@apple.com>
+
+        Resource Load Statistics: Allow multiple third-party cookie blocking settings
+        https://bugs.webkit.org/show_bug.cgi?id=204389
+        <rdar://problem/57344054>
+
+        Reviewed by Brent Fulgham.
+
+        The added tests existed before and are not re-introduced to test their dedicated setting.
+
+        The changed tests have been expanded to cover the new code paths.
+
+        * http/tests/resourceLoadStatistics/third-party-cookie-blocking-on-sites-without-user-interaction-database-expected.txt: Added.
+        * http/tests/resourceLoadStatistics/third-party-cookie-blocking-on-sites-without-user-interaction-database.html: Added.
+        * http/tests/resourceLoadStatistics/third-party-cookie-blocking-on-sites-without-user-interaction-expected.txt: Added.
+        * http/tests/resourceLoadStatistics/third-party-cookie-blocking-on-sites-without-user-interaction.html: Added.
+        * http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking-database-expected.txt:
+        * http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking-database.html:
+        * http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking-expected.txt:
+        * http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking.html:
+        * http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie-database-expected.txt:
+        * http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie-database.html:
+        * http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie-expected.txt:
+        * http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie.html:
+
 2019-11-23  Jonathan Bedard  <jbedard@apple.com>
 
         [WebGL] Garden dedicated queue (Part 2)
diff --git a/LayoutTests/http/tests/resourceLoadStatistics/third-party-cookie-blocking-on-sites-without-user-interaction-database-expected.txt b/LayoutTests/http/tests/resourceLoadStatistics/third-party-cookie-blocking-on-sites-without-user-interaction-database-expected.txt
new file mode 100644 (file)
index 0000000..a908c8e
--- /dev/null
@@ -0,0 +1,23 @@
+Tests that all third-party cookies are blocked under websites that have not received user interaction.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+  
+
+--------
+Frame: '<!--frame1-->'
+--------
+Before user interaction, should receive no cookies.
+Did not receive cookie named 'firstPartyCookie'.
+Client-side document.cookie:
+
+--------
+Frame: '<!--frame2-->'
+--------
+After user interaction, should receive first-party cookie.
+Received cookie named 'firstPartyCookie'.
+Client-side document.cookie: firstPartyCookie=value
diff --git a/LayoutTests/http/tests/resourceLoadStatistics/third-party-cookie-blocking-on-sites-without-user-interaction-database.html b/LayoutTests/http/tests/resourceLoadStatistics/third-party-cookie-blocking-on-sites-without-user-interaction-database.html
new file mode 100644 (file)
index 0000000..27ae073
--- /dev/null
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <script src="/js-test-resources/js-test.js"></script>
+    <script src="resources/util.js"></script>
+</head>
+<body>
+<script>
+    description("Tests that all third-party cookies are blocked under websites that have not received user interaction.");
+    jsTestIsAsync = true;
+
+    const partitionHost = "127.0.0.1:8000";
+    const partitionOrigin = "http://" + partitionHost;
+    const thirdPartyOrigin = "http://localhost:8000";
+    const resourcePath = "/resourceLoadStatistics/resources";
+    const thirdPartyBaseUrl = thirdPartyOrigin + resourcePath;
+    const firstPartyCookieName = "firstPartyCookie";
+    const subPathToSetFirstPartyCookie = "/set-cookie.php?name=" + firstPartyCookieName + "&value=value";
+    const returnUrl = partitionOrigin + "/resourceLoadStatistics/third-party-cookie-blocking-on-sites-without-user-interaction-database.html";
+    const subPathToGetCookies = "/get-cookies.php?name1=" + firstPartyCookieName;
+
+    function openIframe(url, onLoadHandler) {
+        const element = document.createElement("iframe");
+        element.src = url;
+        if (onLoadHandler) {
+            element.onload = onLoadHandler;
+        }
+        document.body.appendChild(element);
+    }
+
+    function runTest() {
+        switch (document.location.hash) {
+            case "#step1":
+                // Set first-party cookie for localhost.
+                document.location.href = thirdPartyBaseUrl + subPathToSetFirstPartyCookie + "#" + returnUrl + "#step2";
+                break;
+            case "#step2":
+                document.location.hash = "step3";
+                // Check that the cookie is blocked for localhost under 127.0.0.1 even though localhost is not prevalent.
+                openIframe(thirdPartyBaseUrl + subPathToGetCookies + "&message=Before user interaction, should receive no cookies.", runTest);
+                break;
+            case "#step3":
+                document.location.hash = "step4";
+                // Produce user interaction for the first-party to allow third-party cookie access.
+                testRunner.setStatisticsHasHadUserInteraction(partitionOrigin, true, function() {
+                    testRunner.statisticsUpdateCookieBlocking(function() {
+                        // Check that the cookie is no longer blocked for localhost under 127.0.0.1.
+                        openIframe(thirdPartyBaseUrl + subPathToGetCookies +  "&message=After user interaction, should receive first-party cookie.", runTest);
+                    });
+                });
+                break;
+            case "#step4":
+                testRunner.setStatisticsShouldBlockThirdPartyCookies(false, function() {
+                    setEnableFeature(false, finishJSTest);
+                });
+                break;
+        }
+    }
+
+    if (document.location.hash === "") {
+        testRunner.setUseITPDatabase(true);
+        setEnableFeature(true, function () {
+            if (testRunner.isStatisticsPrevalentResource(thirdPartyOrigin))
+                testFailed("Localhost was classified as prevalent resource before the test starts.");
+            testRunner.dumpChildFramesAsText();
+            document.location.hash = "step1";
+            testRunner.setStatisticsShouldBlockThirdPartyCookies(true, runTest, true);
+        });
+    } else {
+        runTest();
+    }
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/http/tests/resourceLoadStatistics/third-party-cookie-blocking-on-sites-without-user-interaction-expected.txt b/LayoutTests/http/tests/resourceLoadStatistics/third-party-cookie-blocking-on-sites-without-user-interaction-expected.txt
new file mode 100644 (file)
index 0000000..a908c8e
--- /dev/null
@@ -0,0 +1,23 @@
+Tests that all third-party cookies are blocked under websites that have not received user interaction.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+  
+
+--------
+Frame: '<!--frame1-->'
+--------
+Before user interaction, should receive no cookies.
+Did not receive cookie named 'firstPartyCookie'.
+Client-side document.cookie:
+
+--------
+Frame: '<!--frame2-->'
+--------
+After user interaction, should receive first-party cookie.
+Received cookie named 'firstPartyCookie'.
+Client-side document.cookie: firstPartyCookie=value
diff --git a/LayoutTests/http/tests/resourceLoadStatistics/third-party-cookie-blocking-on-sites-without-user-interaction.html b/LayoutTests/http/tests/resourceLoadStatistics/third-party-cookie-blocking-on-sites-without-user-interaction.html
new file mode 100644 (file)
index 0000000..4a2114a
--- /dev/null
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <script src="/js-test-resources/js-test.js"></script>
+    <script src="resources/util.js"></script>
+</head>
+<body>
+<script>
+    description("Tests that all third-party cookies are blocked under websites that have not received user interaction.");
+    jsTestIsAsync = true;
+
+    const partitionHost = "127.0.0.1:8000";
+    const partitionOrigin = "http://" + partitionHost;
+    const thirdPartyOrigin = "http://localhost:8000";
+    const resourcePath = "/resourceLoadStatistics/resources";
+    const thirdPartyBaseUrl = thirdPartyOrigin + resourcePath;
+    const firstPartyCookieName = "firstPartyCookie";
+    const subPathToSetFirstPartyCookie = "/set-cookie.php?name=" + firstPartyCookieName + "&value=value";
+    const returnUrl = partitionOrigin + "/resourceLoadStatistics/third-party-cookie-blocking-on-sites-without-user-interaction.html";
+    const subPathToGetCookies = "/get-cookies.php?name1=" + firstPartyCookieName;
+
+    function openIframe(url, onLoadHandler) {
+        const element = document.createElement("iframe");
+        element.src = url;
+        if (onLoadHandler) {
+            element.onload = onLoadHandler;
+        }
+        document.body.appendChild(element);
+    }
+
+    function runTest() {
+        switch (document.location.hash) {
+            case "#step1":
+                // Set first-party cookie for localhost.
+                document.location.href = thirdPartyBaseUrl + subPathToSetFirstPartyCookie + "#" + returnUrl + "#step2";
+                break;
+            case "#step2":
+                document.location.hash = "step3";
+                // Check that the cookie is blocked for localhost under 127.0.0.1 even though localhost is not prevalent.
+                openIframe(thirdPartyBaseUrl + subPathToGetCookies + "&message=Before user interaction, should receive no cookies.", runTest);
+                break;
+            case "#step3":
+                document.location.hash = "step4";
+                // Produce user interaction for the first-party to allow third-party cookie access.
+                testRunner.setStatisticsHasHadUserInteraction(partitionOrigin, true, function() {
+                    testRunner.statisticsUpdateCookieBlocking(function() {
+                        // Check that the cookie is no longer blocked for localhost under 127.0.0.1.
+                        openIframe(thirdPartyBaseUrl + subPathToGetCookies +  "&message=After user interaction, should receive first-party cookie.", runTest);
+                    });
+                });
+                break;
+            case "#step4":
+                testRunner.setStatisticsShouldBlockThirdPartyCookies(false, function() {
+                    setEnableFeature(false, finishJSTest);
+                });
+                break;
+        }
+    }
+
+    if (document.location.hash === "") {
+        setEnableFeature(true, function () {
+            if (testRunner.isStatisticsPrevalentResource(thirdPartyOrigin))
+                testFailed("Localhost was classified as prevalent resource before the test starts.");
+            testRunner.dumpChildFramesAsText();
+            document.location.hash = "step1";
+            testRunner.setStatisticsShouldBlockThirdPartyCookies(true, runTest, true);
+        });
+    } else {
+        runTest();
+    }
+</script>
+</body>
+</html>
\ No newline at end of file
index 56f0f03..313e879 100644 (file)
@@ -4,6 +4,7 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 
 
 PASS Storage access was granted. document.cookie == firstPartyCookie=value, cookies seen server-side == {"firstPartyCookie":"value"}
+PASS Storage access was granted. document.cookie == firstPartyCookie=value, cookies seen server-side == {"firstPartyCookie":"value"}
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 1ab0e2e..c0cbdc8 100644 (file)
                     testFailed(event.data.replace("FAIL ", ""));
             } else
                 testFailed("Received a message from an unexpected origin: " + event.origin);
-            testRunner.setStatisticsShouldBlockThirdPartyCookies(false, function() {
-                setEnableFeature(false, finishJSTest);
-            });
+
+            switch (document.location.hash) {
+                case "#firstTest":
+                    document.location.hash = "secondTest";
+                    // Clear all data so that the previous grant doesn't count toward the next test.
+                    testRunner.statisticsClearInMemoryAndPersistentStore(runTest);
+                    break;
+                case "#secondTest":
+                    testRunner.setStatisticsShouldBlockThirdPartyCookies(false, function() {
+                        setEnableFeature(false, finishJSTest);
+                    });
+                    break;
+                default:
+                    testFailed("Message handler called under unknown circumstances.");
+                    testRunner.setStatisticsShouldBlockThirdPartyCookies(false, function() {
+                        setEnableFeature(false, finishJSTest);
+                    });
+            }
         }
 
         window.addEventListener("message", receiveMessage, false);
         }
 
         function runTest() {
-            if (document.location.hash !== "#cookieSet") {
-                setEnableFeature(true, function() {
-                    document.location.href = thirdPartyUrl + "/storageAccess/resources/set-cookie.php?name=firstPartyCookie&value=value#" + firstPartyUrl + "/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking-database.html#cookieSet";
-                });
-            } else {
-                testRunner.setStatisticsShouldBlockThirdPartyCookies(true, function() {
-                    if (testRunner.isStatisticsPrevalentResource(thirdPartyUrl))
-                        testFailed("Third-party set as prevalent resource.");
-                    testRunner.setStatisticsHasHadUserInteraction(firstPartyUrl, true, function() {
-                        if (!testRunner.isStatisticsHasHadUserInteraction(firstPartyUrl))
-                            testFailed("First-party did not get logged for user interaction.");
+            switch (document.location.hash) {
+                case "":
+                    setEnableFeature(true, function() {
+                        document.location.href = thirdPartyUrl + "/storageAccess/resources/set-cookie.php?dummy=" + Math.random() + "&name=firstPartyCookie&value=value#" + firstPartyUrl + "/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking-database.html#firstTest";
+                    });
+                    break;
+                case "#firstTest":
+                    // Test that the request is granted if third-party cookies are blocked under first-parties without
+                    // user interaction.
+                    testRunner.setStatisticsShouldBlockThirdPartyCookies(true, function() {
+                        if (testRunner.isStatisticsPrevalentResource(thirdPartyUrl))
+                            testFailed("Third-party set as prevalent resource.");
+                        if (testRunner.isStatisticsHasHadUserInteraction(firstPartyUrl))
+                            testFailed("First-party was logged for user interaction.");
                         testRunner.setStatisticsHasHadUserInteraction(thirdPartyUrl, true, function() {
                             if (!testRunner.isStatisticsHasHadUserInteraction(thirdPartyUrl))
                                 testFailed("Third-party did not get logged for user interaction.");
                             let iframeElement = document.createElement("iframe");
                             iframeElement.onload = function() {
-                                activateElement("TheIframeThatRequestsStorageAccess");
+                                activateElement("TheFirstIframeThatRequestsStorageAccess");
                             };
-                            iframeElement.id = "TheIframeThatRequestsStorageAccess";
-                            iframeElement.src = "http://localhost:8000/storageAccess/resources/request-storage-access-iframe.html#userShouldGrantAccess,userShouldBeConsulted,policyShouldGrantAccess,isNotSameOriginIframe";
+                            iframeElement.id = "TheFirstIframeThatRequestsStorageAccess";
+                            iframeElement.src = "http://localhost:8000/storageAccess/resources/request-storage-access-iframe.html?dummy=" + Math.random() + "#userShouldGrantAccess,userShouldBeConsulted,policyShouldGrantAccess,isNotSameOriginIframe";
                             document.body.appendChild(iframeElement);
                         });
-                    });
-                });
+                    }, true);
+                    break;
+                case "#secondTest":
+                    // Test that the request is granted if third-party cookies are blocked unconditionally.
+                    testRunner.setStatisticsShouldBlockThirdPartyCookies(true, function() {
+                        if (testRunner.isStatisticsPrevalentResource(thirdPartyUrl))
+                            testFailed("Third-party set as prevalent resource.");
+                        testRunner.setStatisticsHasHadUserInteraction(thirdPartyUrl, true, function() {
+                            if (!testRunner.isStatisticsHasHadUserInteraction(thirdPartyUrl))
+                                testFailed("Third-party did not get logged for user interaction.");
+                            let iframeElement = document.createElement("iframe");
+                            iframeElement.onload = function() {
+                                activateElement("TheSecondIframeThatRequestsStorageAccess");
+                            };
+                            iframeElement.id = "TheSecondIframeThatRequestsStorageAccess";
+                            iframeElement.src = "http://localhost:8000/storageAccess/resources/request-storage-access-iframe.html?dummy=" + Math.random() + "#userShouldGrantAccess,userShouldBeConsulted,policyShouldGrantAccess,isNotSameOriginIframe";
+                            document.body.appendChild(iframeElement);
+                        });
+                    }, false);
+                    break;
             }
         }
     </script>
index 56f0f03..313e879 100644 (file)
@@ -4,6 +4,7 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 
 
 PASS Storage access was granted. document.cookie == firstPartyCookie=value, cookies seen server-side == {"firstPartyCookie":"value"}
+PASS Storage access was granted. document.cookie == firstPartyCookie=value, cookies seen server-side == {"firstPartyCookie":"value"}
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 2f1fb43..b4eeab6 100644 (file)
                     testFailed(event.data.replace("FAIL ", ""));
             } else
                 testFailed("Received a message from an unexpected origin: " + event.origin);
-            testRunner.setStatisticsShouldBlockThirdPartyCookies(false, function() {
-                setEnableFeature(false, finishJSTest);
-            });
+
+            switch (document.location.hash) {
+                case "#firstTest":
+                    document.location.hash = "secondTest";
+                    // Clear all data so that the previous grant doesn't count toward the next test.
+                    testRunner.statisticsClearInMemoryAndPersistentStore(runTest);
+                    break;
+                case "#secondTest":
+                    testRunner.setStatisticsShouldBlockThirdPartyCookies(false, function() {
+                        setEnableFeature(false, finishJSTest);
+                    });
+                    break;
+                default:
+                    testFailed("Message handler called under unknown circumstances.");
+                    testRunner.setStatisticsShouldBlockThirdPartyCookies(false, function() {
+                        setEnableFeature(false, finishJSTest);
+                    });
+            }
         }
 
         window.addEventListener("message", receiveMessage, false);
         }
 
         function runTest() {
-            if (document.location.hash !== "#cookieSet") {
-                setEnableFeature(true, function() {
-                    document.location.href = thirdPartyUrl + "/storageAccess/resources/set-cookie.php?name=firstPartyCookie&value=value#" + firstPartyUrl + "/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking.html#cookieSet";
-                });
-            } else {
-                testRunner.setStatisticsShouldBlockThirdPartyCookies(true, function() {
-                    if (testRunner.isStatisticsPrevalentResource(thirdPartyUrl))
-                        testFailed("Third-party set as prevalent resource.");
-                    testRunner.setStatisticsHasHadUserInteraction(firstPartyUrl, true, function() {
-                        if (!testRunner.isStatisticsHasHadUserInteraction(firstPartyUrl))
-                            testFailed("First-party did not get logged for user interaction.");
+            switch (document.location.hash) {
+                case "":
+                    setEnableFeature(true, function() {
+                        document.location.href = thirdPartyUrl + "/storageAccess/resources/set-cookie.php?dummy=" + Math.random() + "&name=firstPartyCookie&value=value#" + firstPartyUrl + "/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking.html#firstTest";
+                    });
+                    break;
+                case "#firstTest":
+                    // Test that the request is granted if third-party cookies are blocked under first-parties without
+                    // user interaction.
+                    testRunner.setStatisticsShouldBlockThirdPartyCookies(true, function() {
+                        if (testRunner.isStatisticsPrevalentResource(thirdPartyUrl))
+                            testFailed("Third-party set as prevalent resource.");
+                            if (testRunner.isStatisticsHasHadUserInteraction(firstPartyUrl))
+                                testFailed("First-party was logged for user interaction.");
+                            testRunner.setStatisticsHasHadUserInteraction(thirdPartyUrl, true, function() {
+                                if (!testRunner.isStatisticsHasHadUserInteraction(thirdPartyUrl))
+                                    testFailed("Third-party did not get logged for user interaction.");
+                                let iframeElement = document.createElement("iframe");
+                                iframeElement.onload = function() {
+                                    activateElement("TheFirstIframeThatRequestsStorageAccess");
+                                };
+                                iframeElement.id = "TheFirstIframeThatRequestsStorageAccess";
+                                iframeElement.src = "http://localhost:8000/storageAccess/resources/request-storage-access-iframe.html?dummy=" + Math.random() + "#userShouldGrantAccess,userShouldBeConsulted,policyShouldGrantAccess,isNotSameOriginIframe";
+                                document.body.appendChild(iframeElement);
+                            });
+                    }, true);
+                    break;
+                case "#secondTest":
+                    // Test that the request is granted if third-party cookies are blocked unconditionally.
+                    testRunner.setStatisticsShouldBlockThirdPartyCookies(true, function() {
+                        if (testRunner.isStatisticsPrevalentResource(thirdPartyUrl))
+                            testFailed("Third-party set as prevalent resource.");
                         testRunner.setStatisticsHasHadUserInteraction(thirdPartyUrl, true, function() {
                             if (!testRunner.isStatisticsHasHadUserInteraction(thirdPartyUrl))
                                 testFailed("Third-party did not get logged for user interaction.");
                             let iframeElement = document.createElement("iframe");
                             iframeElement.onload = function() {
-                                activateElement("TheIframeThatRequestsStorageAccess");
+                                activateElement("TheSecondIframeThatRequestsStorageAccess");
                             };
-                            iframeElement.id = "TheIframeThatRequestsStorageAccess";
-                            iframeElement.src = "http://localhost:8000/storageAccess/resources/request-storage-access-iframe.html#userShouldGrantAccess,userShouldBeConsulted,policyShouldGrantAccess,isNotSameOriginIframe";
+                            iframeElement.id = "TheSecondIframeThatRequestsStorageAccess";
+                            iframeElement.src = "http://localhost:8000/storageAccess/resources/request-storage-access-iframe.html?dummy=" + Math.random() + "#userShouldGrantAccess,userShouldBeConsulted,policyShouldGrantAccess,isNotSameOriginIframe";
                             document.body.appendChild(iframeElement);
                         });
-                    });
-                });
+                    }, false);
+                    break;
             }
         }
     </script>
index ec8e3db..cb17103 100644 (file)
@@ -8,6 +8,7 @@ PASS Has storage access. document.cookie == firstPartyCookie=value, cookies seen
 PASS Has storage access. document.cookie == firstPartyCookie=value, cookies seen server-side == {"firstPartyCookie":"value"}
 PASS No storage access. document.cookie == , cookies seen server-side == "No cookies"
 PASS No storage access. document.cookie == , cookies seen server-side == "No cookies"
+PASS No storage access. document.cookie == , cookies seen server-side == "No cookies"
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 0be6f3a..acf5df3 100644 (file)
@@ -21,6 +21,7 @@
                     testFailed(event.data.replace("FAIL ", ""));
             } else
                 testFailed("Received a message from an unexpected origin: " + event.origin);
+
             if (document.location.hash === "#lastStep") {
                 testRunner.setStatisticsShouldBlockThirdPartyCookies(false, function() {
                     setEnableFeature(false, finishJSTest);
@@ -50,7 +51,7 @@
                     document.location.hash = "step2";
                     // No general third-party cookie blocking, no user interaction, not prevalent.
                     let iframeElement = document.createElement("iframe");
-                    iframeElement.src = thirdPartyUrl + "/storageAccess/resources/has-storage-access-iframe.html#policyShouldGrantAccess";
+                    iframeElement.src = thirdPartyUrl + "/storageAccess/resources/has-storage-access-iframe.html?dummy=" + Math.random() + "#policyShouldGrantAccess";
                     document.body.appendChild(iframeElement);
                     break;
                 case "#step2":
@@ -60,7 +61,7 @@
                         if (!testRunner.isStatisticsHasHadUserInteraction(thirdPartyUrl))
                             testFailed("Third-party did not get logged for user interaction.");
                         let iframeElement = document.createElement("iframe");
-                        iframeElement.src = thirdPartyUrl + "/storageAccess/resources/has-storage-access-iframe.html#policyShouldGrantAccess";
+                        iframeElement.src = thirdPartyUrl + "/storageAccess/resources/has-storage-access-iframe.html?dummy=" + Math.random() + "#policyShouldGrantAccess";
                         document.body.appendChild(iframeElement);
                     });
                     break;
                         if (!testRunner.isStatisticsHasHadUserInteraction(firstPartyUrl))
                             testFailed("First-party did not get logged for user interaction.");
                         let iframeElement = document.createElement("iframe");
-                        iframeElement.src = thirdPartyUrl + "/storageAccess/resources/has-storage-access-iframe.html#policyShouldGrantAccess";
+                        iframeElement.src = thirdPartyUrl + "/storageAccess/resources/has-storage-access-iframe.html?dummy=" + Math.random() + "#policyShouldGrantAccess";
                         document.body.appendChild(iframeElement);
                     });
                     break;
                 case "#step4":
                     document.location.hash = "step5";
-                    // General third-party cookie blocking, first- and third-party user interaction, not prevalent.
+                    // Third-party cookie blocking under first-parties without user interaction, only third-party user interaction, not prevalent.
                     testRunner.setStatisticsShouldBlockThirdPartyCookies(true, function() {
-                        let iframeElement = document.createElement("iframe");
-                        iframeElement.src = thirdPartyUrl + "/storageAccess/resources/has-storage-access-iframe.html#policyShouldNotGrantAccess";
-                        document.body.appendChild(iframeElement);
-                    });
+                        testRunner.setStatisticsHasHadUserInteraction(firstPartyUrl, false, function() {
+                            if (testRunner.isStatisticsHasHadUserInteraction(firstPartyUrl))
+                                testFailed("First-party got logged for user interaction.");
+                            let iframeElement = document.createElement("iframe");
+                            iframeElement.src = thirdPartyUrl + "/storageAccess/resources/has-storage-access-iframe.html?dummy=" + Math.random() + "#policyShouldNotGrantAccess";
+                            document.body.appendChild(iframeElement);
+                        });
+                    }, true);
                     break;
                 case "#step5":
+                    document.location.hash = "step6";
+                    // General third-party cookie blocking, first- and third-party user interaction, not prevalent.
+                    testRunner.setStatisticsShouldBlockThirdPartyCookies(true, function() {
+                        testRunner.setStatisticsHasHadUserInteraction(firstPartyUrl, true, function() {
+                            if (!testRunner.isStatisticsHasHadUserInteraction(firstPartyUrl))
+                                testFailed("First-party did not get logged for user interaction.");
+                            let iframeElement = document.createElement("iframe");
+                            iframeElement.src = thirdPartyUrl + "/storageAccess/resources/has-storage-access-iframe.html?dummy=" + Math.random() + "#policyShouldNotGrantAccess";
+                            document.body.appendChild(iframeElement);
+                        });
+                    }, false);
+                    break;
+                case "#step6":
                     document.location.hash = "lastStep";
                     // General third-party cookie blocking, first- and third-party user interaction, prevalent.
                     testRunner.setStatisticsPrevalentResource(thirdPartyUrl, true, function() {
                             testFailed("Third-party not set as prevalent resource.");
                         testRunner.statisticsUpdateCookieBlocking(function() {
                             let iframeElement = document.createElement("iframe");
-                            iframeElement.src = thirdPartyUrl + "/storageAccess/resources/has-storage-access-iframe.html#policyShouldNotGrantAccess";
+                            iframeElement.src = thirdPartyUrl + "/storageAccess/resources/has-storage-access-iframe.html?dummy=" + Math.random() + "#policyShouldNotGrantAccess";
                             document.body.appendChild(iframeElement);
                         });
                     });
index ec8e3db..cb17103 100644 (file)
@@ -8,6 +8,7 @@ PASS Has storage access. document.cookie == firstPartyCookie=value, cookies seen
 PASS Has storage access. document.cookie == firstPartyCookie=value, cookies seen server-side == {"firstPartyCookie":"value"}
 PASS No storage access. document.cookie == , cookies seen server-side == "No cookies"
 PASS No storage access. document.cookie == , cookies seen server-side == "No cookies"
+PASS No storage access. document.cookie == , cookies seen server-side == "No cookies"
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 60395cc..0732529 100644 (file)
@@ -20,6 +20,7 @@
                     testFailed(event.data.replace("FAIL ", ""));
             } else
                 testFailed("Received a message from an unexpected origin: " + event.origin);
+
             if (document.location.hash === "#lastStep") {
                 testRunner.setStatisticsShouldBlockThirdPartyCookies(false, function() {
                     setEnableFeature(false, finishJSTest);
@@ -49,7 +50,7 @@
                     document.location.hash = "step2";
                     // No general third-party cookie blocking, no user interaction, not prevalent.
                     let iframeElement = document.createElement("iframe");
-                    iframeElement.src = thirdPartyUrl + "/storageAccess/resources/has-storage-access-iframe.html#policyShouldGrantAccess";
+                    iframeElement.src = thirdPartyUrl + "/storageAccess/resources/has-storage-access-iframe.html?dummy=" + Math.random() + "#policyShouldGrantAccess";
                     document.body.appendChild(iframeElement);
                     break;
                 case "#step2":
@@ -59,7 +60,7 @@
                         if (!testRunner.isStatisticsHasHadUserInteraction(thirdPartyUrl))
                             testFailed("Third-party did not get logged for user interaction.");
                         let iframeElement = document.createElement("iframe");
-                        iframeElement.src = thirdPartyUrl + "/storageAccess/resources/has-storage-access-iframe.html#policyShouldGrantAccess";
+                        iframeElement.src = thirdPartyUrl + "/storageAccess/resources/has-storage-access-iframe.html?dummy=" + Math.random() + "#policyShouldGrantAccess";
                         document.body.appendChild(iframeElement);
                     });
                     break;
                         if (!testRunner.isStatisticsHasHadUserInteraction(firstPartyUrl))
                             testFailed("First-party did not get logged for user interaction.");
                         let iframeElement = document.createElement("iframe");
-                        iframeElement.src = thirdPartyUrl + "/storageAccess/resources/has-storage-access-iframe.html#policyShouldGrantAccess";
+                        iframeElement.src = thirdPartyUrl + "/storageAccess/resources/has-storage-access-iframe.html?dummy=" + Math.random() + "#policyShouldGrantAccess";
                         document.body.appendChild(iframeElement);
                     });
                     break;
                 case "#step4":
                     document.location.hash = "step5";
+                    // Third-party cookie blocking under first-parties without user interaction, only third-party user interaction, not prevalent.
+                    testRunner.setStatisticsShouldBlockThirdPartyCookies(true, function() {
+                        testRunner.setStatisticsHasHadUserInteraction(firstPartyUrl, false, function() {
+                            if (testRunner.isStatisticsHasHadUserInteraction(firstPartyUrl))
+                                testFailed("First-party got logged for user interaction.");
+                            let iframeElement = document.createElement("iframe");
+                            iframeElement.src = thirdPartyUrl + "/storageAccess/resources/has-storage-access-iframe.html?dummy=" + Math.random() + "#policyShouldNotGrantAccess";
+                            document.body.appendChild(iframeElement);
+                        });
+                    }, true);
+                    break;
+                case "#step5":
+                    document.location.hash = "step6";
                     // General third-party cookie blocking, first- and third-party user interaction, not prevalent.
                     testRunner.setStatisticsShouldBlockThirdPartyCookies(true, function() {
+                        testRunner.setStatisticsHasHadUserInteraction(firstPartyUrl, true, function() {
+                            if (!testRunner.isStatisticsHasHadUserInteraction(firstPartyUrl))
+                                testFailed("First-party did not get logged for user interaction.");
                         let iframeElement = document.createElement("iframe");
-                        iframeElement.src = thirdPartyUrl + "/storageAccess/resources/has-storage-access-iframe.html#policyShouldNotGrantAccess";
+                        iframeElement.src = thirdPartyUrl + "/storageAccess/resources/has-storage-access-iframe.html?dummy=" + Math.random() + "#policyShouldNotGrantAccess";
                         document.body.appendChild(iframeElement);
-                    });
+                        });
+                    }, false);
                     break;
-                case "#step5":
+                case "#step6":
                     document.location.hash = "lastStep";
                     // General third-party cookie blocking, first- and third-party user interaction, prevalent.
                     testRunner.setStatisticsPrevalentResource(thirdPartyUrl, true, function() {
                             testFailed("Third-party not set as prevalent resource.");
                         testRunner.statisticsUpdateCookieBlocking(function() {
                             let iframeElement = document.createElement("iframe");
-                            iframeElement.src = thirdPartyUrl + "/storageAccess/resources/has-storage-access-iframe.html#policyShouldNotGrantAccess";
+                            iframeElement.src = thirdPartyUrl + "/storageAccess/resources/has-storage-access-iframe.html?dummy=" + Math.random() + "#policyShouldNotGrantAccess";
                             document.body.appendChild(iframeElement);
                         });
                     });
index 79691c1..4229fd0 100644 (file)
@@ -1,3 +1,30 @@
+2019-11-23  John Wilander  <wilander@apple.com>
+
+        Resource Load Statistics: Allow multiple third-party cookie blocking settings
+        https://bugs.webkit.org/show_bug.cgi?id=204389
+        <rdar://problem/57344054>
+
+        Reviewed by Brent Fulgham.
+
+        This change introduces an enum ThirdPartyCookieBlockingMode for how third-party
+        cookie blocking should be carried out. It then uses the set mode in 
+        NetworkStorageSession::shouldBlockCookies().
+
+        The reason for supporting three different modes is that what is now named
+        OnlyAccordingToPerDomainPolicy is shipping, AllOnSitesWithoutUserInteraction is
+        in beta, and All is behind an experimental flag.
+
+        Tests: http/tests/resourceLoadStatistics/third-party-cookie-blocking-on-sites-without-user-interaction-database.html
+               http/tests/resourceLoadStatistics/third-party-cookie-blocking-on-sites-without-user-interaction.html
+
+        * page/Settings.yaml:
+            Flipped the isThirdPartyCookieBlockingEnabled flag to on by default.
+        * platform/network/NetworkStorageSession.cpp:
+        (WebCore::NetworkStorageSession::shouldBlockCookies const):
+        (WebCore::NetworkStorageSession::setThirdPartyCookieBlockingMode):
+        * platform/network/NetworkStorageSession.h:
+        (WebCore::NetworkStorageSession::setIsThirdPartyCookieBlockingEnabled): Deleted.
+
 2019-11-23  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r252805.
index d669c4a..566acc1 100644 (file)
@@ -881,7 +881,7 @@ webRTCEncryptionEnabled:
   inspectorOverride: true
 
 isThirdPartyCookieBlockingEnabled:
-  initial: false
+  initial: true
 
 isLoggedInAPIEnabled:
   initial: false
index 369d119..93f254e 100644 (file)
@@ -113,10 +113,16 @@ bool NetworkStorageSession::shouldBlockCookies(const URL& firstPartyForCookies,
     if (pageID && hasStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID.value()))
         return false;
 
-    if (m_isThirdPartyCookieBlockingEnabled)
+    switch (m_thirdPartyCookieBlockingMode) {
+    case ThirdPartyCookieBlockingMode::All:
         return true;
-
-    return shouldBlockThirdPartyCookies(resourceDomain);
+    case ThirdPartyCookieBlockingMode::AllOnSitesWithoutUserInteraction:
+        if (!hasHadUserInteractionAsFirstParty(firstPartyDomain))
+            return true;
+        FALLTHROUGH;
+    case ThirdPartyCookieBlockingMode::OnlyAccordingToPerDomainPolicy:
+        return shouldBlockThirdPartyCookies(resourceDomain);
+    }
 }
 
 Optional<Seconds> NetworkStorageSession::maxAgeCacheCap(const ResourceRequest& request)
@@ -269,6 +275,11 @@ void NetworkStorageSession::resetCrossSiteLoadsWithLinkDecorationForTesting()
     m_navigationWithLinkDecorationTestMode = true;
 }
 
+void NetworkStorageSession::setThirdPartyCookieBlockingMode(ThirdPartyCookieBlockingMode blockingMode)
+{
+    m_thirdPartyCookieBlockingMode = blockingMode;
+}
+
 Optional<Seconds> NetworkStorageSession::clientSideCookieCap(const RegistrableDomain& firstParty, Optional<PageIdentifier> pageID) const
 {
     if (!m_ageCapForClientSideCookies || !pageID || m_navigatedToWithLinkDecorationByPrevalentResource.isEmpty())
index 17410ba..aa77c3a 100644 (file)
@@ -74,6 +74,7 @@ struct SameSiteInfo;
 
 enum class IncludeSecureCookies : bool;
 enum class IncludeHttpOnlyCookies : bool;
+enum class ThirdPartyCookieBlockingMode : uint8_t { All, AllOnSitesWithoutUserInteraction, OnlyAccordingToPerDomainPolicy };
 
 class NetworkStorageSession {
     WTF_MAKE_NONCOPYABLE(NetworkStorageSession); WTF_MAKE_FAST_ALLOCATED;
@@ -165,7 +166,7 @@ public:
     WEBCORE_EXPORT Optional<Seconds> maxAgeCacheCap(const ResourceRequest&);
     WEBCORE_EXPORT void didCommitCrossSiteLoadWithDataTransferFromPrevalentResource(const RegistrableDomain& toDomain, PageIdentifier);
     WEBCORE_EXPORT void resetCrossSiteLoadsWithLinkDecorationForTesting();
-    void setIsThirdPartyCookieBlockingEnabled(bool enabled) { m_isThirdPartyCookieBlockingEnabled = enabled; }
+    WEBCORE_EXPORT void setThirdPartyCookieBlockingMode(ThirdPartyCookieBlockingMode);
 #endif
 
 private:
@@ -201,7 +202,7 @@ private:
     Optional<Seconds> m_ageCapForClientSideCookiesShort { };
     HashMap<WebCore::PageIdentifier, RegistrableDomain> m_navigatedToWithLinkDecorationByPrevalentResource;
     bool m_navigationWithLinkDecorationTestMode = false;
-    bool m_isThirdPartyCookieBlockingEnabled = false;
+    ThirdPartyCookieBlockingMode m_thirdPartyCookieBlockingMode { ThirdPartyCookieBlockingMode::AllOnSitesWithoutUserInteraction };
 #endif
 
 #if PLATFORM(COCOA)
@@ -219,3 +220,16 @@ WEBCORE_EXPORT CFURLStorageSessionRef createPrivateStorageSession(CFStringRef id
 #endif
 
 }
+
+namespace WTF {
+
+template<> struct EnumTraits<WebCore::ThirdPartyCookieBlockingMode> {
+    using values = EnumValues<
+        WebCore::ThirdPartyCookieBlockingMode,
+        WebCore::ThirdPartyCookieBlockingMode::All,
+        WebCore::ThirdPartyCookieBlockingMode::AllOnSitesWithoutUserInteraction,
+        WebCore::ThirdPartyCookieBlockingMode::OnlyAccordingToPerDomainPolicy
+    >;
+};
+
+}
index fcabb92..dfefc13 100644 (file)
@@ -1,3 +1,105 @@
+2019-11-23  John Wilander  <wilander@apple.com>
+
+        Resource Load Statistics: Allow multiple third-party cookie blocking settings
+        https://bugs.webkit.org/show_bug.cgi?id=204389
+        <rdar://problem/57344054>
+
+        Reviewed by Brent Fulgham.
+
+        This change make the third-party cookie blocking setting go from a boolean to
+        the new enum WebCore::ThirdPartyCookieBlockingMode with three different settings.
+        Functions and member variables are renamed accordingly.
+
+        The reason for supporting three different modes is that what is now named
+        OnlyAccordingToPerDomainPolicy is shipping, AllOnSitesWithoutUserInteraction is
+        in beta, and All is behind an experimental flag.
+
+        The change also updates the test API to map the TestRunner call to the enum.
+
+        * NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp:
+        (WebKit::ResourceLoadStatisticsDatabaseStore::hasStorageAccess):
+        (WebKit::ResourceLoadStatisticsDatabaseStore::requestStorageAccess):
+        (WebKit::ResourceLoadStatisticsDatabaseStore::clearUserInteraction):
+            Now makes use of a completion handler and updates the cookie blocking state.
+        (WebKit::ResourceLoadStatisticsDatabaseStore::hasHadUserInteraction):
+        (WebKit::ResourceLoadStatisticsDatabaseStore::areAllThirdPartyCookiesBlockedUnder):
+            New convenience function to check the cookie blocking status per first-party domain.
+        (WebKit::ResourceLoadStatisticsDatabaseStore::cookieAccess):
+            Restructured the code to make it very clear that the logic is the same as the
+            corresponding function in ResourceLoadStatisticsMemoryStore.
+            Can no longer be const since it calls areAllThirdPartyCookiesBlockedUnder() which
+            in turn calls hasHadUserInteraction() and that function may clear user interaction data.
+        (WebKit::ResourceLoadStatisticsDatabaseStore::hasHadUnexpiredRecentUserInteraction):
+        (WebKit::ResourceLoadStatisticsDatabaseStore::cookieAccess const): Deleted.
+            See comment above on the non-const version of this function.
+        * NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h:
+        * NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.cpp:
+        (WebKit::ResourceLoadStatisticsMemoryStore::areAllThirdPartyCookiesBlockedUnder):
+            New convenience function to check the cookie blocking status per first-party domain.
+        (WebKit::ResourceLoadStatisticsMemoryStore::cookieAccess):
+            Restructured the code to make it very clear that the logic is the same as the
+            corresponding function in ResourceLoadStatisticsDatabaseStore.
+            Can no longer be const since it calls areAllThirdPartyCookiesBlockedUnder() which
+            in turn calls hasHadUserInteraction() and that function may clear user interaction data.
+        (WebKit::ResourceLoadStatisticsMemoryStore::hasStorageAccess):
+        (WebKit::ResourceLoadStatisticsMemoryStore::requestStorageAccess):
+        (WebKit::ResourceLoadStatisticsMemoryStore::clearUserInteraction):
+            Now makes use of a completion handler and updates the cookie blocking state.
+        (WebKit::ResourceLoadStatisticsMemoryStore::cookieAccess const): Deleted.
+            See comment above on the non-const version of this function.
+        * NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.h:
+        * NetworkProcess/Classifier/ResourceLoadStatisticsStore.h:
+        (WebKit::ResourceLoadStatisticsStore::setThirdPartyCookieBlockingMode):
+        (WebKit::ResourceLoadStatisticsStore::thirdPartyCookieBlockingMode const):
+        (WebKit::ResourceLoadStatisticsStore::setIsThirdPartyCookieBlockingEnabled): Deleted.
+        (WebKit::ResourceLoadStatisticsStore::isThirdPartyCookieBlockingEnabled const): Deleted.
+        * NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp:
+        (WebKit::WebResourceLoadStatisticsStore::setThirdPartyCookieBlockingMode):
+        (WebKit::WebResourceLoadStatisticsStore::clearUserInteraction):
+            Now forwards the completion handler.
+        (WebKit::WebResourceLoadStatisticsStore::setIsThirdPartyCookieBlockingEnabled): Deleted.
+        * NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h:
+        * NetworkProcess/NetworkProcess.cpp:
+        (WebKit::NetworkProcess::setShouldBlockThirdPartyCookiesForTesting):
+        * NetworkProcess/NetworkProcess.h:
+        * NetworkProcess/NetworkProcess.messages.in:
+            The SetShouldBlockThirdPartyCookiesForTesting message now uses an enum instead of a
+            boolean.
+        * NetworkProcess/NetworkSession.cpp:
+        (WebKit::NetworkSession::setResourceLoadStatisticsEnabled):
+            Now forwards the enum value instead of a boolean.
+        (WebKit::NetworkSession::recreateResourceLoadStatisticStore):
+            Now makes sure the cookie blocking setting is forwarded to the recreated store.
+        (WebKit::NetworkSession::setThirdPartyCookieBlockingMode):
+        (WebKit::NetworkSession::setIsThirdPartyCookieBlockingEnabled): Deleted.
+        * NetworkProcess/NetworkSession.h:
+        * NetworkProcess/NetworkSessionCreationParameters.cpp:
+        (WebKit::NetworkSessionCreationParameters::encode const):
+        (WebKit::NetworkSessionCreationParameters::decode):
+            Support for the new enum.
+        * NetworkProcess/NetworkSessionCreationParameters.h:
+        * NetworkProcess/cocoa/NetworkSessionCocoa.mm:
+        (WebKit::NetworkSessionCocoa::NetworkSessionCocoa):
+        * Scripts/webkit/messages.py:
+            Tells the IPC code generator where to find WebCore::ThirdPartyCookieBlockingMode.
+        * Shared/WebPreferences.yaml:
+            Flipped the IsThirdPartyCookieBlockingEnabled flag to on by default.
+        * UIProcess/API/C/WKWebsiteDataStoreRef.cpp:
+        (WKWebsiteDataStoreSetResourceLoadStatisticsShouldBlockThirdPartyCookiesForTesting):
+        (WKWebsiteDataStoreStatisticsResetToConsistentState):
+        * UIProcess/API/C/WKWebsiteDataStoreRef.h:
+        * UIProcess/Network/NetworkProcessProxy.cpp:
+        (WebKit::NetworkProcessProxy::setShouldBlockThirdPartyCookiesForTesting):
+        * UIProcess/Network/NetworkProcessProxy.h:
+        * UIProcess/WebProcessPool.cpp:
+        (WebKit::WebProcessPool::ensureNetworkProcess):
+            Makes use of the enum in the NetworkSessionCreationParameters.
+        * UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm:
+        (WebKit::WebsiteDataStore::parameters):
+        * UIProcess/WebsiteData/WebsiteDataStore.cpp:
+        (WebKit::WebsiteDataStore::setResourceLoadStatisticsShouldBlockThirdPartyCookiesForTesting):
+        * UIProcess/WebsiteData/WebsiteDataStore.h:
+
 2019-11-23  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r252805.
index 1d4e409..cc20da7 100644 (file)
@@ -1257,7 +1257,7 @@ void ResourceLoadStatisticsDatabaseStore::hasStorageAccess(const SubFrameDomain&
 
     ensureResourceStatisticsForRegistrableDomain(subFrameDomain);
 
-    switch (cookieAccess(subFrameDomain)) {
+    switch (cookieAccess(subFrameDomain, topFrameDomain)) {
     case CookieAccess::CannotRequest:
         completionHandler(false);
         return;
@@ -1290,7 +1290,7 @@ void ResourceLoadStatisticsDatabaseStore::requestStorageAccess(SubFrameDomain&&
 
     auto subFrameStatus = ensureResourceStatisticsForRegistrableDomain(subFrameDomain);
     
-    switch (cookieAccess(subFrameDomain)) {
+    switch (cookieAccess(subFrameDomain, topFrameDomain)) {
     case CookieAccess::CannotRequest:
         RELEASE_LOG_INFO_IF(debugLoggingEnabled(), ITPDebug, "Cannot grant storage access to %{private}s since its cookies are blocked in third-party contexts and it has not received user interaction as first-party.", subFrameDomain.string().utf8().data());
         completionHandler(StorageAccessStatus::CannotRequestAccess);
@@ -1499,7 +1499,7 @@ void ResourceLoadStatisticsDatabaseStore::logUserInteraction(const TopFrameDomai
     updateCookieBlocking(WTFMove(completionHandler));
 }
 
-void ResourceLoadStatisticsDatabaseStore::clearUserInteraction(const RegistrableDomain& domain)
+void ResourceLoadStatisticsDatabaseStore::clearUserInteraction(const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
 {
     ASSERT(!RunLoop::isMain());
 
@@ -1513,6 +1513,11 @@ void ResourceLoadStatisticsDatabaseStore::clearUserInteraction(const Registrable
         RELEASE_LOG_ERROR_IF_ALLOWED(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::logUserInteraction failed to bind, error message: %{private}s", this, m_database.lastErrorMsg());
         ASSERT_NOT_REACHED();
     }
+
+    // Update cookie blocking unconditionally since a call to hasHadUserInteraction()
+    // to check the previous user interaction status could call clearUserInteraction(),
+    // blowing the call stack.
+    updateCookieBlocking(WTFMove(completionHandler));
 }
 
 bool ResourceLoadStatisticsDatabaseStore::hasHadUserInteraction(const RegistrableDomain& domain, OperatingDatesWindow operatingDatesWindow)
@@ -1541,7 +1546,7 @@ bool ResourceLoadStatisticsDatabaseStore::hasHadUserInteraction(const Registrabl
         // Drop privacy sensitive data because we no longer need it.
         // Set timestamp to 0 so that statistics merge will know
         // it has been reset as opposed to its default -1.
-        clearUserInteraction(domain);
+        clearUserInteraction(domain, [] { });
         hadUserInteraction = false;
     }
     
@@ -1852,29 +1857,35 @@ void ResourceLoadStatisticsDatabaseStore::clear(CompletionHandler<void()>&& comp
     updateCookieBlockingForDomains(domainsToBlock, [callbackAggregator = callbackAggregator.copyRef()] { });
 }
 
-CookieAccess ResourceLoadStatisticsDatabaseStore::cookieAccess(const RegistrableDomain& domain) const
+bool ResourceLoadStatisticsDatabaseStore::areAllThirdPartyCookiesBlockedUnder(const TopFrameDomain& topFrameDomain)
+{
+    if (thirdPartyCookieBlockingMode() == ThirdPartyCookieBlockingMode::All)
+        return true;
+
+    if (thirdPartyCookieBlockingMode() == ThirdPartyCookieBlockingMode::AllOnSitesWithoutUserInteraction && !hasHadUserInteraction(topFrameDomain, OperatingDatesWindow::Long))
+        return true;
+
+    return false;
+}
+
+CookieAccess ResourceLoadStatisticsDatabaseStore::cookieAccess(const SubResourceDomain& subresourceDomain, const TopFrameDomain& topFrameDomain)
 {
     ASSERT(!RunLoop::isMain());
 
     SQLiteStatement statement(m_database, "SELECT isPrevalent, hadUserInteraction FROM ObservedDomains WHERE registrableDomain = ?");
     if (statement.prepare() != SQLITE_OK
-        || statement.bindText(1, domain.string()) != SQLITE_OK) {
+        || statement.bindText(1, subresourceDomain.string()) != SQLITE_OK) {
         RELEASE_LOG_ERROR_IF_ALLOWED(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::cookieAccess failed to bind, error message: %{private}s", this, m_database.lastErrorMsg());
         ASSERT_NOT_REACHED();
     }
-    
+
     bool hasNoEntry = statement.step() != SQLITE_ROW;
-    if (hasNoEntry) {
-        if (isThirdPartyCookieBlockingEnabled())
-            return CookieAccess::OnlyIfGranted;
-        return CookieAccess::BasedOnCookiePolicy;
-    }
+    bool isPrevalent = !hasNoEntry && !!statement.getColumnInt(0);
+    bool hadUserInteraction = !hasNoEntry && statement.getColumnInt(1) ? true : false;
 
-    bool isPrevalent = !!statement.getColumnInt(0);
-    if (!isPrevalent && !isThirdPartyCookieBlockingEnabled())
+    if (!areAllThirdPartyCookiesBlockedUnder(topFrameDomain) && !isPrevalent)
         return CookieAccess::BasedOnCookiePolicy;
 
-    bool hadUserInteraction = statement.getColumnInt(1) ? true : false;
     if (!hadUserInteraction)
         return CookieAccess::CannotRequest;
 
@@ -2062,7 +2073,7 @@ void ResourceLoadStatisticsDatabaseStore::clearGrandfathering(Vector<unsigned>&&
 bool ResourceLoadStatisticsDatabaseStore::hasHadUnexpiredRecentUserInteraction(const DomainData& resourceStatistic, OperatingDatesWindow operatingDatesWindow)
 {
     if (resourceStatistic.hadUserInteraction && hasStatisticsExpired(resourceStatistic.mostRecentUserInteractionTime, operatingDatesWindow)) {
-        clearUserInteraction(resourceStatistic.registrableDomain);
+        clearUserInteraction(resourceStatistic.registrableDomain, [] { });
         return false;
     }
 
index e7bd595..93969a9 100644 (file)
@@ -127,7 +127,7 @@ public:
     void logUserInteraction(const TopFrameDomain&, CompletionHandler<void()>&&) override;
     void logCrossSiteLoadWithLinkDecoration(const NavigatedFromDomain&, const NavigatedToDomain&) override;
 
-    void clearUserInteraction(const RegistrableDomain&) override;
+    void clearUserInteraction(const RegistrableDomain&, CompletionHandler<void()>&&) override;
     bool hasHadUserInteraction(const RegistrableDomain&, OperatingDatesWindow) override;
 
     void setLastSeen(const RegistrableDomain&, Seconds) override;
@@ -194,8 +194,9 @@ private:
 
     bool predicateValueForDomain(WebCore::SQLiteStatement&, const RegistrableDomain&) const;
 
-    CookieAccess cookieAccess(const RegistrableDomain&) const;
-    
+    bool areAllThirdPartyCookiesBlockedUnder(const TopFrameDomain&) override;
+    CookieAccess cookieAccess(const SubResourceDomain&, const TopFrameDomain&);
+
     void setPrevalentResource(const RegistrableDomain&, ResourceLoadPrevalence);
     unsigned recursivelyFindNonPrevalentDomainsThatRedirectedToThisDomain(unsigned primaryDomainID, StdSet<unsigned>& nonPrevalentRedirectionSources, unsigned numberOfRecursiveCalls);
     void setDomainsAsPrevalent(StdSet<unsigned>&&);
index 030b1f1..c4e7d4a 100644 (file)
@@ -212,12 +212,26 @@ void ResourceLoadStatisticsMemoryStore::syncStorageImmediately()
         m_persistentStorage->scheduleOrWriteMemoryStore(ResourceLoadStatisticsPersistentStorage::ForceImmediateWrite::Yes);
 }
 
-CookieAccess ResourceLoadStatisticsMemoryStore::cookieAccess(const ResourceLoadStatistics& resourceStatistic) const
+bool ResourceLoadStatisticsMemoryStore::areAllThirdPartyCookiesBlockedUnder(const TopFrameDomain& topFrameDomain)
 {
-    if (!isThirdPartyCookieBlockingEnabled() && !resourceStatistic.isPrevalentResource)
+    if (thirdPartyCookieBlockingMode() == ThirdPartyCookieBlockingMode::All)
+        return true;
+
+    if (thirdPartyCookieBlockingMode() == ThirdPartyCookieBlockingMode::AllOnSitesWithoutUserInteraction && !hasHadUserInteraction(topFrameDomain, OperatingDatesWindow::Long))
+        return true;
+
+    return false;
+}
+
+CookieAccess ResourceLoadStatisticsMemoryStore::cookieAccess(const ResourceLoadStatistics& resourceStatistic, const TopFrameDomain& topFrameDomain)
+{
+    bool isPrevalent = resourceStatistic.isPrevalentResource;
+    bool hadUserInteraction = resourceStatistic.hadUserInteraction;
+
+    if (!areAllThirdPartyCookiesBlockedUnder(topFrameDomain) && !isPrevalent)
         return CookieAccess::BasedOnCookiePolicy;
 
-    if (!resourceStatistic.hadUserInteraction)
+    if (!hadUserInteraction)
         return CookieAccess::CannotRequest;
     
     return CookieAccess::OnlyIfGranted;
@@ -228,7 +242,7 @@ void ResourceLoadStatisticsMemoryStore::hasStorageAccess(const SubFrameDomain& s
     ASSERT(!RunLoop::isMain());
 
     auto& subFrameStatistic = ensureResourceStatisticsForRegistrableDomain(subFrameDomain);
-    switch (cookieAccess(subFrameStatistic)) {
+    switch (cookieAccess(subFrameStatistic, topFrameDomain)) {
     case CookieAccess::CannotRequest:
         completionHandler(false);
         return;
@@ -260,7 +274,7 @@ void ResourceLoadStatisticsMemoryStore::requestStorageAccess(SubFrameDomain&& su
     ASSERT(!RunLoop::isMain());
 
     auto& subFrameStatistic = ensureResourceStatisticsForRegistrableDomain(subFrameDomain);
-    switch (cookieAccess(subFrameStatistic)) {
+    switch (cookieAccess(subFrameStatistic, topFrameDomain)) {
     case CookieAccess::CannotRequest:
         RELEASE_LOG_INFO_IF(debugLoggingEnabled(), ITPDebug, "Cannot grant storage access to %{public}s since its cookies are blocked in third-party contexts and it has not received user interaction as first-party.", subFrameDomain.string().utf8().data());
         completionHandler(StorageAccessStatus::CannotRequestAccess);
@@ -439,13 +453,19 @@ void ResourceLoadStatisticsMemoryStore::logCrossSiteLoadWithLinkDecoration(const
         toStatistics.gotLinkDecorationFromPrevalentResource = true;
 }
 
-void ResourceLoadStatisticsMemoryStore::clearUserInteraction(const RegistrableDomain& domain)
+void ResourceLoadStatisticsMemoryStore::clearUserInteraction(const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
 {
     ASSERT(!RunLoop::isMain());
 
     auto& statistics = ensureResourceStatisticsForRegistrableDomain(domain);
+    bool didHavePreviousUserInteraction = statistics.hadUserInteraction;
     statistics.hadUserInteraction = false;
     statistics.mostRecentUserInteractionTime = { };
+    if (!didHavePreviousUserInteraction) {
+        completionHandler();
+        return;
+    }
+    updateCookieBlocking(WTFMove(completionHandler));
 }
 
 bool ResourceLoadStatisticsMemoryStore::hasHadUserInteraction(const RegistrableDomain& domain, OperatingDatesWindow operatingDatesWindow)
index c18c51d..c8fc685 100644 (file)
@@ -97,7 +97,8 @@ public:
 
     void calculateAndSubmitTelemetry() const override;
 
-    CookieAccess cookieAccess(const ResourceLoadStatistics&) const;
+    bool areAllThirdPartyCookiesBlockedUnder(const TopFrameDomain&) override;
+    CookieAccess cookieAccess(const ResourceLoadStatistics&, const TopFrameDomain&);
     void hasStorageAccess(const SubFrameDomain&, const TopFrameDomain&, Optional<WebCore::FrameIdentifier>, WebCore::PageIdentifier, CompletionHandler<void(bool)>&&) override;
     void requestStorageAccess(SubFrameDomain&&, TopFrameDomain&&, WebCore::FrameIdentifier, WebCore::PageIdentifier, CompletionHandler<void(StorageAccessStatus)>&&) override;
     void grantStorageAccess(SubFrameDomain&&, TopFrameDomain&&, WebCore::FrameIdentifier, WebCore::PageIdentifier, WebCore::StorageAccessPromptWasShown, CompletionHandler<void(WebCore::StorageAccessWasGranted)>&&) override;
@@ -106,7 +107,7 @@ public:
     void logUserInteraction(const TopFrameDomain&, CompletionHandler<void()>&&) override;
     void logCrossSiteLoadWithLinkDecoration(const NavigatedFromDomain&, const NavigatedToDomain&) override;
 
-    void clearUserInteraction(const RegistrableDomain&) override;
+    void clearUserInteraction(const RegistrableDomain&, CompletionHandler<void()>&&) override;
     bool hasHadUserInteraction(const RegistrableDomain&, OperatingDatesWindow) override;
 
     void setLastSeen(const RegistrableDomain&, Seconds) override;
index 64bee5b..bfa4d70 100644 (file)
@@ -30,6 +30,7 @@
 #include "ResourceLoadStatisticsClassifier.h"
 #include "WebResourceLoadStatisticsStore.h"
 #include <WebCore/FrameIdentifier.h>
+#include <WebCore/NetworkStorageSession.h>
 #include <wtf/CompletionHandler.h>
 #include <wtf/Vector.h>
 #include <wtf/WeakPtr.h>
@@ -161,9 +162,10 @@ public:
     void setResourceLoadStatisticsDebugMode(bool);
     bool isDebugModeEnabled() const { return m_debugModeEnabled; };
     void setPrevalentResourceForDebugMode(const RegistrableDomain&);
-    void setIsThirdPartyCookieBlockingEnabled(bool enabled) { m_thirdPartyCookieBlockingEnabled = enabled; };
-    bool isThirdPartyCookieBlockingEnabled() const { return m_thirdPartyCookieBlockingEnabled; };
+    void setThirdPartyCookieBlockingMode(WebCore::ThirdPartyCookieBlockingMode mode) { m_thirdPartyCookieBlockingMode = mode; };
+    WebCore::ThirdPartyCookieBlockingMode thirdPartyCookieBlockingMode() const { return m_thirdPartyCookieBlockingMode; };
 
+    virtual bool areAllThirdPartyCookiesBlockedUnder(const TopFrameDomain&) = 0;
     virtual void hasStorageAccess(const SubFrameDomain&, const TopFrameDomain&, Optional<WebCore::FrameIdentifier>, WebCore::PageIdentifier, CompletionHandler<void(bool)>&&) = 0;
     virtual void requestStorageAccess(SubFrameDomain&&, TopFrameDomain&&, WebCore::FrameIdentifier, WebCore::PageIdentifier, CompletionHandler<void(StorageAccessStatus)>&&) = 0;
     virtual void grantStorageAccess(SubFrameDomain&&, TopFrameDomain&&, WebCore::FrameIdentifier, WebCore::PageIdentifier, WebCore::StorageAccessPromptWasShown, CompletionHandler<void(WebCore::StorageAccessWasGranted)>&&) = 0;
@@ -172,7 +174,7 @@ public:
     virtual void logUserInteraction(const TopFrameDomain&, CompletionHandler<void()>&&) = 0;
     virtual void logCrossSiteLoadWithLinkDecoration(const NavigatedFromDomain&, const NavigatedToDomain&) = 0;
 
-    virtual void clearUserInteraction(const RegistrableDomain&) = 0;
+    virtual void clearUserInteraction(const RegistrableDomain&, CompletionHandler<void()>&&) = 0;
     virtual bool hasHadUserInteraction(const RegistrableDomain&, OperatingDatesWindow) = 0;
 
     virtual void setLastSeen(const RegistrableDomain& primaryDomain, Seconds) = 0;
@@ -270,7 +272,7 @@ private:
     const RegistrableDomain m_debugStaticPrevalentResource { URL { URL(), "https://3rdpartytestwebkit.org"_s } };
     bool m_debugLoggingEnabled { false };
     bool m_debugModeEnabled { false };
-    bool m_thirdPartyCookieBlockingEnabled { false };
+    WebCore::ThirdPartyCookieBlockingMode m_thirdPartyCookieBlockingMode { WebCore::ThirdPartyCookieBlockingMode::AllOnSitesWithoutUserInteraction };
     bool m_dataRecordsBeingRemoved { false };
     ShouldIncludeLocalhost m_shouldIncludeLocalhost { ShouldIncludeLocalhost::Yes };
 };
index 88a47f6..4d66997 100644 (file)
@@ -462,22 +462,22 @@ void WebResourceLoadStatisticsStore::hasCookies(const RegistrableDomain& domain,
     completionHandler(false);
 }
 
-void WebResourceLoadStatisticsStore::setIsThirdPartyCookieBlockingEnabled(bool enabled)
+void WebResourceLoadStatisticsStore::setThirdPartyCookieBlockingMode(ThirdPartyCookieBlockingMode blockingMode)
 {
     ASSERT(RunLoop::isMain());
 
     if (m_networkSession) {
         if (auto* storageSession = m_networkSession->networkStorageSession())
-            storageSession->setIsThirdPartyCookieBlockingEnabled(enabled);
+            storageSession->setThirdPartyCookieBlockingMode(blockingMode);
         else
             ASSERT_NOT_REACHED();
     }
 
-    postTask([this, enabled]() {
+    postTask([this, blockingMode]() {
         if (!m_statisticsStore)
             return;
 
-        m_statisticsStore->setIsThirdPartyCookieBlockingEnabled(enabled);
+        m_statisticsStore->setThirdPartyCookieBlockingMode(blockingMode);
     });
 }
 
@@ -611,9 +611,14 @@ void WebResourceLoadStatisticsStore::clearUserInteraction(const RegistrableDomai
     ASSERT(RunLoop::isMain());
     
     postTask([this, domain = domain.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
-        if (m_statisticsStore)
-            m_statisticsStore->clearUserInteraction(domain);
-        postTaskReply(WTFMove(completionHandler));
+        auto innerCompletionHandler = [completionHandler = WTFMove(completionHandler)]() mutable {
+            postTaskReply(WTFMove(completionHandler));
+        };
+        if (m_statisticsStore) {
+            m_statisticsStore->clearUserInteraction(domain, WTFMove(innerCompletionHandler));
+            return;
+        }
+        innerCompletionHandler();
     });
 }
 
index cb331e1..0ca426a 100644 (file)
@@ -52,6 +52,7 @@ enum class ShouldSample : bool;
 enum class IncludeHttpOnlyCookies : bool;
 enum class StorageAccessPromptWasShown : bool;
 enum class StorageAccessWasGranted : bool;
+enum class ThirdPartyCookieBlockingMode : uint8_t;
 }
 
 namespace WebKit {
@@ -179,7 +180,7 @@ public:
     void callHasStorageAccessForFrameHandler(const SubFrameDomain&, const TopFrameDomain&, WebCore::FrameIdentifier, WebCore::PageIdentifier, CompletionHandler<void(bool)>&&);
 
     void hasCookies(const RegistrableDomain&, CompletionHandler<void(bool)>&&);
-    void setIsThirdPartyCookieBlockingEnabled(bool);
+    void setThirdPartyCookieBlockingMode(WebCore::ThirdPartyCookieBlockingMode);
     void didCreateNetworkProcess();
 
     void notifyResourceLoadStatisticsProcessed();
index 5f23cc6..13fce2e 100644 (file)
@@ -1253,10 +1253,10 @@ void NetworkProcess::setShouldDowngradeReferrerForTesting(bool enabled, Completi
     completionHandler();
 }
 
-void NetworkProcess::setShouldBlockThirdPartyCookiesForTesting(PAL::SessionID sessionID, bool enabled, CompletionHandler<void()>&& completionHandler)
+void NetworkProcess::setShouldBlockThirdPartyCookiesForTesting(PAL::SessionID sessionID, WebCore::ThirdPartyCookieBlockingMode blockingMode, CompletionHandler<void()>&& completionHandler)
 {
     if (auto* networkSession = this->networkSession(sessionID))
-        networkSession->setIsThirdPartyCookieBlockingEnabled(enabled);
+        networkSession->setThirdPartyCookieBlockingMode(blockingMode);
     else
         ASSERT_NOT_REACHED();
     completionHandler();
index f62f01d..f0806b2 100644 (file)
@@ -260,7 +260,7 @@ public:
     void hasIsolatedSession(PAL::SessionID, const WebCore::RegistrableDomain&, CompletionHandler<void(bool)>&&) const;
     bool isITPDatabaseEnabled() const { return m_isITPDatabaseEnabled; }
     void setShouldDowngradeReferrerForTesting(bool, CompletionHandler<void()>&&);
-    void setShouldBlockThirdPartyCookiesForTesting(PAL::SessionID, bool, CompletionHandler<void()>&&);
+    void setShouldBlockThirdPartyCookiesForTesting(PAL::SessionID, WebCore::ThirdPartyCookieBlockingMode, CompletionHandler<void()>&&);
 #endif
 
     using CacheStorageRootPathCallback = CompletionHandler<void(String&&)>;
index 3677677..ae03619 100644 (file)
@@ -136,7 +136,7 @@ messages -> NetworkProcess LegacyReceiver {
     DeleteCookiesForTesting(PAL::SessionID sessionID, WebCore::RegistrableDomain domain, bool includeHttpOnlyCookies) -> () Async
     HasIsolatedSession(PAL::SessionID sessionID, WebCore::RegistrableDomain domain) -> (bool hasIsolatedSession) Async
     SetShouldDowngradeReferrerForTesting(bool enabled) -> () Async
-    SetShouldBlockThirdPartyCookiesForTesting(PAL::SessionID sessionID, bool enabled) -> () Async
+    SetShouldBlockThirdPartyCookiesForTesting(PAL::SessionID sessionID, enum:uint8_t WebCore::ThirdPartyCookieBlockingMode blockingMode) -> () Async
 #endif
 
     SetSessionIsControlledByAutomation(PAL::SessionID sessionID, bool controlled);
index bd21a3c..bff9ba7 100644 (file)
@@ -39,7 +39,6 @@
 #include "WebSocketTask.h"
 #include <WebCore/AdClickAttribution.h>
 #include <WebCore/CookieJar.h>
-#include <WebCore/NetworkStorageSession.h>
 #include <WebCore/ResourceRequest.h>
 
 #if PLATFORM(COCOA)
@@ -175,7 +174,7 @@ void NetworkSession::setResourceLoadStatisticsEnabled(bool enable)
     // This should always be forwarded since debug mode may be enabled at runtime.
     if (!m_resourceLoadStatisticsManualPrevalentResource.isEmpty())
         m_resourceLoadStatistics->setPrevalentResourceForDebugMode(m_resourceLoadStatisticsManualPrevalentResource, [] { });
-    m_resourceLoadStatistics->setIsThirdPartyCookieBlockingEnabled(m_thirdPartyCookieBlockingEnabled);
+    m_resourceLoadStatistics->setThirdPartyCookieBlockingMode(m_thirdPartyCookieBlockingMode);
 }
 
 void NetworkSession::recreateResourceLoadStatisticStore(CompletionHandler<void()>&& completionHandler)
@@ -183,6 +182,7 @@ void NetworkSession::recreateResourceLoadStatisticStore(CompletionHandler<void()
     destroyResourceLoadStatistics();
     m_resourceLoadStatistics = WebResourceLoadStatisticsStore::create(*this, m_resourceLoadStatisticsDirectory, m_shouldIncludeLocalhostInResourceLoadStatistics);
     m_resourceLoadStatistics->populateMemoryStoreFromDisk(WTFMove(completionHandler));
+    m_resourceLoadStatistics->setThirdPartyCookieBlockingMode(m_thirdPartyCookieBlockingMode);
 }
 
 bool NetworkSession::isResourceLoadStatisticsEnabled() const
@@ -225,12 +225,12 @@ bool NetworkSession::shouldDowngradeReferrer() const
     return m_downgradeReferrer;
 }
 
-void NetworkSession::setIsThirdPartyCookieBlockingEnabled(bool enabled)
+void NetworkSession::setThirdPartyCookieBlockingMode(ThirdPartyCookieBlockingMode blockingMode)
 {
     ASSERT(m_resourceLoadStatistics);
-    m_thirdPartyCookieBlockingEnabled = enabled;
+    m_thirdPartyCookieBlockingMode = blockingMode;
     if (m_resourceLoadStatistics)
-        m_resourceLoadStatistics->setIsThirdPartyCookieBlockingEnabled(m_thirdPartyCookieBlockingEnabled);
+        m_resourceLoadStatistics->setThirdPartyCookieBlockingMode(blockingMode);
 }
 #endif // ENABLE(RESOURCE_LOAD_STATISTICS)
 
index f25dd65..698ce0d 100644 (file)
@@ -30,6 +30,7 @@
 #include "WebResourceLoadStatisticsStore.h"
 #include <WebCore/AdClickAttribution.h>
 #include <WebCore/BlobRegistryImpl.h>
+#include <WebCore/NetworkStorageSession.h>
 #include <WebCore/RegistrableDomain.h>
 #include <pal/SessionID.h>
 #include <wtf/HashSet.h>
@@ -97,7 +98,7 @@ public:
     virtual void clearIsolatedSessions() { }
     void setShouldDowngradeReferrerForTesting(bool);
     bool shouldDowngradeReferrer() const;
-    void setIsThirdPartyCookieBlockingEnabled(bool);
+    void setThirdPartyCookieBlockingMode(WebCore::ThirdPartyCookieBlockingMode);
 #endif
     void storeAdClickAttribution(WebCore::AdClickAttribution&&);
     void handleAdClickAttributionConversion(WebCore::AdClickAttribution::Conversion&&, const URL& requestURL, const WebCore::ResourceRequest& redirectRequest);
@@ -144,7 +145,7 @@ protected:
     WebCore::RegistrableDomain m_resourceLoadStatisticsManualPrevalentResource;
     bool m_enableResourceLoadStatisticsLogTestingEvent;
     bool m_downgradeReferrer { true };
-    bool m_thirdPartyCookieBlockingEnabled { false };
+    WebCore::ThirdPartyCookieBlockingMode m_thirdPartyCookieBlockingMode { WebCore::ThirdPartyCookieBlockingMode::AllOnSitesWithoutUserInteraction };
 #endif
     bool m_isStaleWhileRevalidateEnabled { false };
     UniqueRef<AdClickAttributionManager> m_adClickAttribution;
index 3e85bea..122a1a8 100644 (file)
@@ -68,7 +68,7 @@ void NetworkSessionCreationParameters::encode(IPC::Encoder& encoder) const
     encoder << shouldIncludeLocalhostInResourceLoadStatistics;
     encoder << enableResourceLoadStatisticsDebugMode;
     encoder << resourceLoadStatisticsManualPrevalentResource;
-    encoder << enableThirdPartyCookieBlocking;
+    encoder << thirdPartyCookieBlockingMode;
 
     encoder << networkCacheDirectory << networkCacheDirectoryExtensionHandle;
 
@@ -200,9 +200,9 @@ Optional<NetworkSessionCreationParameters> NetworkSessionCreationParameters::dec
     if (!resourceLoadStatisticsManualPrevalentResource)
         return WTF::nullopt;
 
-    Optional<bool> enableThirdPartyCookieBlocking;
-    decoder >> enableThirdPartyCookieBlocking;
-    if (!enableThirdPartyCookieBlocking)
+    Optional<WebCore::ThirdPartyCookieBlockingMode> thirdPartyCookieBlockingMode;
+    decoder >> thirdPartyCookieBlockingMode;
+    if (!thirdPartyCookieBlockingMode)
         return WTF::nullopt;
 
     Optional<String> networkCacheDirectory;
@@ -288,7 +288,7 @@ Optional<NetworkSessionCreationParameters> NetworkSessionCreationParameters::dec
         , WTFMove(*enableResourceLoadStatisticsLogTestingEvent)
         , WTFMove(*shouldIncludeLocalhostInResourceLoadStatistics)
         , WTFMove(*enableResourceLoadStatisticsDebugMode)
-        , WTFMove(*enableThirdPartyCookieBlocking)
+        , WTFMove(*thirdPartyCookieBlockingMode)
         , WTFMove(*deviceManagementRestrictionsEnabled)
         , WTFMove(*allLoadsBlockedByDeviceManagementRestrictionsForTesting)
         , WTFMove(*resourceLoadStatisticsManualPrevalentResource)
index ac436a3..f7e05f8 100644 (file)
@@ -26,6 +26,7 @@
 #pragma once
 
 #include "SandboxExtension.h"
+#include <WebCore/NetworkStorageSession.h>
 #include <WebCore/RegistrableDomain.h>
 #include <pal/SessionID.h>
 #include <wtf/Seconds.h>
@@ -85,7 +86,7 @@ struct NetworkSessionCreationParameters {
     bool enableResourceLoadStatisticsLogTestingEvent { false };
     bool shouldIncludeLocalhostInResourceLoadStatistics { true };
     bool enableResourceLoadStatisticsDebugMode { false };
-    bool enableThirdPartyCookieBlocking { false };
+    WebCore::ThirdPartyCookieBlockingMode thirdPartyCookieBlockingMode { WebCore::ThirdPartyCookieBlockingMode::AllOnSitesWithoutUserInteraction };
     bool deviceManagementRestrictionsEnabled { false };
     bool allLoadsBlockedByDeviceManagementRestrictionsForTesting { false };
     WebCore::RegistrableDomain resourceLoadStatisticsManualPrevalentResource { };
index c2765f1..6dc580d 100644 (file)
@@ -1135,7 +1135,7 @@ NetworkSessionCocoa::NetworkSessionCocoa(NetworkProcess& networkProcess, Network
     m_shouldIncludeLocalhostInResourceLoadStatistics = parameters.shouldIncludeLocalhostInResourceLoadStatistics ? ShouldIncludeLocalhost::Yes : ShouldIncludeLocalhost::No;
     m_enableResourceLoadStatisticsDebugMode = parameters.enableResourceLoadStatisticsDebugMode ? EnableResourceLoadStatisticsDebugMode::Yes : EnableResourceLoadStatisticsDebugMode::No;
     m_resourceLoadStatisticsManualPrevalentResource = parameters.resourceLoadStatisticsManualPrevalentResource;
-    m_thirdPartyCookieBlockingEnabled = parameters.enableThirdPartyCookieBlocking;
+    m_thirdPartyCookieBlockingMode = parameters.thirdPartyCookieBlockingMode;
     setResourceLoadStatisticsEnabled(parameters.enableResourceLoadStatistics);
 #endif
 
index 06013a5..a2c5a6a 100644 (file)
@@ -588,6 +588,7 @@ def headers_for_type(type):
         'WebCore::TextCheckingResult': ['<WebCore/TextCheckerClient.h>'],
         'WebCore::TextCheckingType': ['<WebCore/TextChecking.h>'],
         'WebCore::TextIndicatorData': ['<WebCore/TextIndicator.h>'],
+        'WebCore::ThirdPartyCookieBlockingMode': ['<WebCore/NetworkStorageSession.h>'],
         'WebCore::ViewportAttributes': ['<WebCore/ViewportArguments.h>'],
         'WebCore::WillContinueLoading': ['<WebCore/FrameLoaderTypes.h>'],
         'WebCore::SelectionRect': ['"EditorState.h"'],
index dcea8a3..18db8cf 100644 (file)
@@ -1795,7 +1795,7 @@ LazyImageLoadingEnabled:
 
 IsThirdPartyCookieBlockingEnabled:
   type: bool
-  defaultValue: false
+  defaultValue: true
   humanReadableName: "Block All 3rd-Party Cookies (ITP)"
   humanReadableDescription: "Block all third-party cookies when Intelligent Tracking Prevention is enabled"
   category: experimental
index 7eb7577..24cc1af 100644 (file)
@@ -538,10 +538,10 @@ void WKWebsiteDataStoreSetResourceLoadStatisticsShouldDowngradeReferrerForTestin
 #endif
 }
 
-void WKWebsiteDataStoreSetResourceLoadStatisticsShouldBlockThirdPartyCookiesForTesting(WKWebsiteDataStoreRef dataStoreRef, bool enabled, void* context, WKWebsiteDataStoreSetResourceLoadStatisticsShouldBlockThirdPartyCookiesForTestingFunction completionHandler)
+void WKWebsiteDataStoreSetResourceLoadStatisticsShouldBlockThirdPartyCookiesForTesting(WKWebsiteDataStoreRef dataStoreRef, bool enabled, bool onlyOnSitesWithoutUserInteraction, void* context, WKWebsiteDataStoreSetResourceLoadStatisticsShouldBlockThirdPartyCookiesForTestingFunction completionHandler)
 {
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
-    WebKit::toImpl(dataStoreRef)->setResourceLoadStatisticsShouldBlockThirdPartyCookiesForTesting(enabled, [context, completionHandler] {
+    WebKit::toImpl(dataStoreRef)->setResourceLoadStatisticsShouldBlockThirdPartyCookiesForTesting(enabled, onlyOnSitesWithoutUserInteraction, [context, completionHandler] {
         completionHandler(context);
     });
 #else
@@ -561,7 +561,7 @@ void WKWebsiteDataStoreStatisticsResetToConsistentState(WKWebsiteDataStoreRef da
     store.resetCacheMaxAgeCapForPrevalentResources([callbackAggregator = callbackAggregator.copyRef()] { });
     store.resetCrossSiteLoadsWithLinkDecorationForTesting([callbackAggregator = callbackAggregator.copyRef()] { });
     store.setResourceLoadStatisticsShouldDowngradeReferrerForTesting(true, [callbackAggregator = callbackAggregator.copyRef()] { });
-    store.setResourceLoadStatisticsShouldBlockThirdPartyCookiesForTesting(false, [callbackAggregator = callbackAggregator.copyRef()] { });
+    store.setResourceLoadStatisticsShouldBlockThirdPartyCookiesForTesting(false, false, [callbackAggregator = callbackAggregator.copyRef()] { });
     store.resetParametersToDefaultValues([callbackAggregator = callbackAggregator.copyRef()] { });
     store.scheduleClearInMemoryAndPersistent(WebKit::ShouldGrandfatherStatistics::No, [callbackAggregator = callbackAggregator.copyRef()] { });
     store.setUseITPDatabase(false, [callbackAggregator = callbackAggregator.copyRef()] { });
index 95239a3..10baf7e 100644 (file)
@@ -120,7 +120,7 @@ WK_EXPORT void WKWebsiteDataStoreStatisticsHasIsolatedSession(WKWebsiteDataStore
 typedef void (*WKWebsiteDataStoreSetResourceLoadStatisticsShouldDowngradeReferrerForTestingFunction)(void* functionContext);
 WK_EXPORT void WKWebsiteDataStoreSetResourceLoadStatisticsShouldDowngradeReferrerForTesting(WKWebsiteDataStoreRef dataStoreRef, bool enabled, void* context, WKWebsiteDataStoreSetResourceLoadStatisticsShouldDowngradeReferrerForTestingFunction completionHandler);
 typedef void (*WKWebsiteDataStoreSetResourceLoadStatisticsShouldBlockThirdPartyCookiesForTestingFunction)(void* functionContext);
-WK_EXPORT void WKWebsiteDataStoreSetResourceLoadStatisticsShouldBlockThirdPartyCookiesForTesting(WKWebsiteDataStoreRef dataStoreRef, bool enabled, void* context, WKWebsiteDataStoreSetResourceLoadStatisticsShouldBlockThirdPartyCookiesForTestingFunction completionHandler);
+WK_EXPORT void WKWebsiteDataStoreSetResourceLoadStatisticsShouldBlockThirdPartyCookiesForTesting(WKWebsiteDataStoreRef dataStoreRef, bool enabled, bool onlyOnSitesWithoutUserInteraction, void* context, WKWebsiteDataStoreSetResourceLoadStatisticsShouldBlockThirdPartyCookiesForTestingFunction completionHandler);
 typedef void (*WKWebsiteDataStoreStatisticsResetToConsistentStateFunction)(void* functionContext);
 WK_EXPORT void WKWebsiteDataStoreStatisticsResetToConsistentState(WKWebsiteDataStoreRef dataStoreRef, void* context, WKWebsiteDataStoreStatisticsResetToConsistentStateFunction completionHandler);
 
index ad57991..172bb33 100644 (file)
@@ -1057,14 +1057,14 @@ void NetworkProcessProxy::setShouldDowngradeReferrerForTesting(bool enabled, Com
     sendWithAsyncReply(Messages::NetworkProcess::SetShouldDowngradeReferrerForTesting(enabled), WTFMove(completionHandler));
 }
 
-void NetworkProcessProxy::setShouldBlockThirdPartyCookiesForTesting(PAL::SessionID sessionID, bool enabled, CompletionHandler<void()>&& completionHandler)
+void NetworkProcessProxy::setShouldBlockThirdPartyCookiesForTesting(PAL::SessionID sessionID, ThirdPartyCookieBlockingMode blockingMode, CompletionHandler<void()>&& completionHandler)
 {
     if (!canSendMessage()) {
         completionHandler();
         return;
     }
     
-    sendWithAsyncReply(Messages::NetworkProcess::SetShouldBlockThirdPartyCookiesForTesting(sessionID, enabled), WTFMove(completionHandler));
+    sendWithAsyncReply(Messages::NetworkProcess::SetShouldBlockThirdPartyCookiesForTesting(sessionID, blockingMode), WTFMove(completionHandler));
 }
 #endif // ENABLE(RESOURCE_LOAD_STATISTICS)
 
index 72ce425..b1322bb 100644 (file)
@@ -157,7 +157,7 @@ public:
     void deleteWebsiteDataInUIProcessForRegistrableDomains(PAL::SessionID, OptionSet<WebsiteDataType>, OptionSet<WebsiteDataFetchOption>, Vector<RegistrableDomain>, CompletionHandler<void(HashSet<WebCore::RegistrableDomain>&&)>&&);
     void hasIsolatedSession(PAL::SessionID, const RegistrableDomain&, CompletionHandler<void(bool)>&&);
     void setShouldDowngradeReferrerForTesting(bool, CompletionHandler<void()>&&);
-    void setShouldBlockThirdPartyCookiesForTesting(PAL::SessionID, bool, CompletionHandler<void()>&&);
+    void setShouldBlockThirdPartyCookiesForTesting(PAL::SessionID, WebCore::ThirdPartyCookieBlockingMode, CompletionHandler<void()>&&);
 #endif
     
     void synthesizeAppIsBackground(bool background);
index 4068ee4..4025556 100644 (file)
@@ -562,7 +562,7 @@ NetworkProcessProxy& WebProcessPool::ensureNetworkProcess(WebsiteDataStore* with
     bool enableResourceLoadStatisticsLogTestingEvent = false;
     bool shouldIncludeLocalhost = true;
     bool enableResourceLoadStatisticsDebugMode = false;
-    bool enableThirdPartyCookieBlocking = false;
+    WebCore::ThirdPartyCookieBlockingMode thirdPartyCookieBlockingMode = WebCore::ThirdPartyCookieBlockingMode::AllOnSitesWithoutUserInteraction;
     WebCore::RegistrableDomain manualPrevalentResource { };
     if (withWebsiteDataStore) {
         enableResourceLoadStatistics = withWebsiteDataStore->resourceLoadStatisticsEnabled();
@@ -573,7 +573,7 @@ NetworkProcessProxy& WebProcessPool::ensureNetworkProcess(WebsiteDataStore* with
             auto networkSessionParameters = withWebsiteDataStore->parameters().networkSessionParameters;
             shouldIncludeLocalhost = networkSessionParameters.shouldIncludeLocalhostInResourceLoadStatistics;
             enableResourceLoadStatisticsDebugMode = networkSessionParameters.enableResourceLoadStatisticsDebugMode;
-            enableThirdPartyCookieBlocking = networkSessionParameters.enableThirdPartyCookieBlocking;
+            thirdPartyCookieBlockingMode = networkSessionParameters.thirdPartyCookieBlockingMode;
             manualPrevalentResource = networkSessionParameters.resourceLoadStatisticsManualPrevalentResource;
         }
 
@@ -594,7 +594,7 @@ NetworkProcessProxy& WebProcessPool::ensureNetworkProcess(WebsiteDataStore* with
             auto networkSessionParameters = m_websiteDataStore->parameters().networkSessionParameters;
             shouldIncludeLocalhost = networkSessionParameters.shouldIncludeLocalhostInResourceLoadStatistics;
             enableResourceLoadStatisticsDebugMode = networkSessionParameters.enableResourceLoadStatisticsDebugMode;
-            enableThirdPartyCookieBlocking = networkSessionParameters.enableThirdPartyCookieBlocking;
+            thirdPartyCookieBlockingMode = networkSessionParameters.thirdPartyCookieBlockingMode;
             manualPrevalentResource = networkSessionParameters.resourceLoadStatisticsManualPrevalentResource;
         }
 
@@ -618,7 +618,7 @@ NetworkProcessProxy& WebProcessPool::ensureNetworkProcess(WebsiteDataStore* with
     parameters.defaultDataStoreParameters.networkSessionParameters.enableResourceLoadStatisticsLogTestingEvent = enableResourceLoadStatisticsLogTestingEvent;
     parameters.defaultDataStoreParameters.networkSessionParameters.shouldIncludeLocalhostInResourceLoadStatistics = shouldIncludeLocalhost;
     parameters.defaultDataStoreParameters.networkSessionParameters.enableResourceLoadStatisticsDebugMode = enableResourceLoadStatisticsDebugMode;
-    parameters.defaultDataStoreParameters.networkSessionParameters.enableThirdPartyCookieBlocking = enableThirdPartyCookieBlocking;
+    parameters.defaultDataStoreParameters.networkSessionParameters.thirdPartyCookieBlockingMode = thirdPartyCookieBlockingMode;
     parameters.defaultDataStoreParameters.networkSessionParameters.resourceLoadStatisticsManualPrevalentResource = manualPrevalentResource;
 
     // Add any platform specific parameters
index 0ff3ea0..b1f5401 100644 (file)
@@ -32,6 +32,7 @@
 #import "WebPreferencesKeys.h"
 #import "WebResourceLoadStatisticsStore.h"
 #import "WebsiteDataStoreParameters.h"
+#import <WebCore/NetworkStorageSession.h>
 #import <WebCore/RegistrableDomain.h>
 #import <WebCore/RuntimeApplicationChecks.h>
 #import <WebCore/RuntimeEnabledFeatures.h>
@@ -69,14 +70,17 @@ WebsiteDataStoreParameters WebsiteDataStore::parameters()
     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
     bool shouldLogCookieInformation = false;
     bool enableResourceLoadStatisticsDebugMode = false;
-    bool enableThirdPartyCookieBlocking = false;
+    auto thirdPartyCookieBlockingMode = WebCore::ThirdPartyCookieBlockingMode::OnlyAccordingToPerDomainPolicy;
     bool enableLegacyTLS = true;
     if (id value = [defaults objectForKey:@"WebKitEnableLegacyTLS"])
         enableLegacyTLS = [value boolValue];
     WebCore::RegistrableDomain resourceLoadStatisticsManualPrevalentResource { };
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
     enableResourceLoadStatisticsDebugMode = [defaults boolForKey:@"ITPDebugMode"];
-    enableThirdPartyCookieBlocking = [defaults boolForKey:[NSString stringWithFormat:@"Experimental%@", WebPreferencesKey::isThirdPartyCookieBlockingEnabledKey().createCFString().get()]];
+    if ([defaults boolForKey:[NSString stringWithFormat:@"Experimental%@", WebPreferencesKey::isThirdPartyCookieBlockingEnabledKey().createCFString().get()]])
+        thirdPartyCookieBlockingMode = WebCore::ThirdPartyCookieBlockingMode::All;
+    else
+        thirdPartyCookieBlockingMode = WebCore::ThirdPartyCookieBlockingMode::AllOnSitesWithoutUserInteraction;
     auto* manualPrevalentResource = [defaults stringForKey:@"ITPManualPrevalentResource"];
     if (manualPrevalentResource) {
         URL url { URL(), manualPrevalentResource };
@@ -140,7 +144,7 @@ WebsiteDataStoreParameters WebsiteDataStore::parameters()
         hasStatisticsTestingCallback(),
         shouldIncludeLocalhostInResourceLoadStatistics,
         enableResourceLoadStatisticsDebugMode,
-        enableThirdPartyCookieBlocking,
+        thirdPartyCookieBlockingMode,
         m_configuration->deviceManagementRestrictionsEnabled(),
         m_configuration->allLoadsBlockedByDeviceManagementRestrictionsForTesting(),
         WTFMove(resourceLoadStatisticsManualPrevalentResource),
index bb98416..6b4b02c 100644 (file)
@@ -49,6 +49,7 @@
 #include <WebCore/CredentialStorage.h>
 #include <WebCore/DatabaseTracker.h>
 #include <WebCore/HTMLMediaElement.h>
+#include <WebCore/NetworkStorageSession.h>
 #include <WebCore/OriginLock.h>
 #include <WebCore/RegistrableDomain.h>
 #include <WebCore/SecurityOrigin.h>
@@ -1787,13 +1788,16 @@ void WebsiteDataStore::setResourceLoadStatisticsShouldDowngradeReferrerForTestin
     ASSERT(!completionHandler);
 }
 
-void WebsiteDataStore::setResourceLoadStatisticsShouldBlockThirdPartyCookiesForTesting(bool enabled, CompletionHandler<void()>&& completionHandler)
+void WebsiteDataStore::setResourceLoadStatisticsShouldBlockThirdPartyCookiesForTesting(bool enabled, bool onlyOnSitesWithoutUserInteraction, CompletionHandler<void()>&& completionHandler)
 {
     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
-    
+    WebCore::ThirdPartyCookieBlockingMode blockingMode = WebCore::ThirdPartyCookieBlockingMode::OnlyAccordingToPerDomainPolicy;
+    if (enabled)
+        blockingMode = onlyOnSitesWithoutUserInteraction ? WebCore::ThirdPartyCookieBlockingMode::AllOnSitesWithoutUserInteraction : WebCore::ThirdPartyCookieBlockingMode::All;
+
     for (auto& processPool : processPools()) {
         if (auto* networkProcess = processPool->networkProcess()) {
-            networkProcess->setShouldBlockThirdPartyCookiesForTesting(m_sessionID, enabled, [callbackAggregator = callbackAggregator.copyRef()] { });
+            networkProcess->setShouldBlockThirdPartyCookiesForTesting(m_sessionID, blockingMode, [callbackAggregator = callbackAggregator.copyRef()] { });
             ASSERT(processPools().size() == 1);
             break;
         }
index 2784fe3..eb9604e 100644 (file)
@@ -194,7 +194,7 @@ public:
     void hasLocalStorageForTesting(const URL&, CompletionHandler<void(bool)>&&) const;
     void hasIsolatedSessionForTesting(const URL&, CompletionHandler<void(bool)>&&) const;
     void setResourceLoadStatisticsShouldDowngradeReferrerForTesting(bool, CompletionHandler<void()>&&);
-    void setResourceLoadStatisticsShouldBlockThirdPartyCookiesForTesting(bool, CompletionHandler<void()>&&);
+    void setResourceLoadStatisticsShouldBlockThirdPartyCookiesForTesting(bool enabled, bool onlyOnSitesWithoutUserInteraction, CompletionHandler<void()>&&);
 #endif
     void setCacheMaxAgeCapForPrevalentResources(Seconds, CompletionHandler<void()>&&);
     void resetCacheMaxAgeCapForPrevalentResources(CompletionHandler<void()>&&);
index a905b2a..2c74355 100644 (file)
@@ -1,3 +1,25 @@
+2019-11-23  John Wilander  <wilander@apple.com>
+
+        Resource Load Statistics: Allow multiple third-party cookie blocking settings
+        https://bugs.webkit.org/show_bug.cgi?id=204389
+        <rdar://problem/57344054>
+
+        Reviewed by Brent Fulgham.
+
+        This change allows the existing TestRunner function
+        setStatisticsShouldBlockThirdPartyCookies() to set an optional boolean
+        parameter onlyOnSitesWithoutUserInteraction to opt in to that behavior.
+
+        * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
+        * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+        (WTR::TestRunner::setStatisticsShouldBlockThirdPartyCookies):
+        * WebKitTestRunner/InjectedBundle/TestRunner.h:
+        * WebKitTestRunner/TestController.cpp:
+        (WTR::TestController::setStatisticsShouldBlockThirdPartyCookies):
+        * WebKitTestRunner/TestController.h:
+        * WebKitTestRunner/TestInvocation.cpp:
+        (WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):
+
 2019-11-23  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r252805.
index b2ec8c6..08989bf 100644 (file)
@@ -342,7 +342,7 @@ interface TestRunner {
     void statisticsResetToConsistentState(object completionHandler);
     boolean hasStatisticsIsolatedSession(DOMString hostName);
     void setStatisticsShouldDowngradeReferrer(boolean value, object callback);
-    void setStatisticsShouldBlockThirdPartyCookies(boolean value, object callback);
+    void setStatisticsShouldBlockThirdPartyCookies(boolean value, object callback, optional boolean onlyOnSitesWithoutUserInteraction);
 
     // Injected bundle form client.
     void installTextDidChangeInTextFieldCallback(object callback);
index 3025b9a..284bb88 100644 (file)
@@ -33,6 +33,7 @@
 #include "StringFunctions.h"
 #include "TestController.h"
 #include <JavaScriptCore/JSCTestRunnerUtils.h>
+#include <WebCore/NetworkStorageSession.h>
 #include <WebCore/ResourceLoadObserver.h>
 #include <WebKit/WKBundle.h>
 #include <WebKit/WKBundleBackForwardList.h>
@@ -2223,13 +2224,15 @@ void TestRunner::statisticsCallDidSetShouldDowngradeReferrerCallback()
     m_hasSetDowngradeReferrerCallback = false;
 }
 
-void TestRunner::setStatisticsShouldBlockThirdPartyCookies(bool value, JSValueRef completionHandler)
+void TestRunner::setStatisticsShouldBlockThirdPartyCookies(bool value, JSValueRef completionHandler, bool onlyOnSitesWithoutUserInteraction)
 {
     if (m_hasSetBlockThirdPartyCookiesCallback)
         return;
-    
+
     cacheTestRunnerCallback(StatisticsDidSetShouldBlockThirdPartyCookiesCallbackID, completionHandler);
     WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetStatisticsShouldBlockThirdPartyCookies"));
+    if (onlyOnSitesWithoutUserInteraction)
+        messageName = adoptWK(WKStringCreateWithUTF8CString("SetStatisticsShouldBlockThirdPartyCookiesOnSitesWithoutUserInteraction"));
     WKRetainPtr<WKBooleanRef> messageBody = adoptWK(WKBooleanCreate(value));
     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
     m_hasSetBlockThirdPartyCookiesCallback = true;
index 642c59d..5f3cbe8 100644 (file)
@@ -442,7 +442,7 @@ public:
     bool hasStatisticsIsolatedSession(JSStringRef hostName);
     void setStatisticsShouldDowngradeReferrer(bool, JSValueRef callback);
     void statisticsCallDidSetShouldDowngradeReferrerCallback();
-    void setStatisticsShouldBlockThirdPartyCookies(bool, JSValueRef callback);
+    void setStatisticsShouldBlockThirdPartyCookies(bool value, JSValueRef callback, bool onlyOnSitesWithoutUserInteraction);
     void statisticsCallDidSetShouldBlockThirdPartyCookiesCallback();
     void statisticsResetToConsistentState(JSValueRef completionHandler);
     void statisticsCallDidResetToConsistentStateCallback();
index 3a07c13..80582c4 100644 (file)
@@ -3567,10 +3567,10 @@ void TestController::setStatisticsShouldDowngradeReferrer(bool value)
     m_currentInvocation->didSetShouldDowngradeReferrer();
 }
 
-void TestController::setStatisticsShouldBlockThirdPartyCookies(bool value)
+void TestController::setStatisticsShouldBlockThirdPartyCookies(bool value, bool onlyOnSitesWithoutUserInteraction)
 {
     ResourceStatisticsCallbackContext context(*this);
-    WKWebsiteDataStoreSetResourceLoadStatisticsShouldBlockThirdPartyCookiesForTesting(TestController::websiteDataStore(), value, &context, resourceStatisticsVoidResultCallback);
+    WKWebsiteDataStoreSetResourceLoadStatisticsShouldBlockThirdPartyCookiesForTesting(TestController::websiteDataStore(), value, onlyOnSitesWithoutUserInteraction, &context, resourceStatisticsVoidResultCallback);
     runUntil(context.done, noTimeout);
     m_currentInvocation->didSetShouldBlockThirdPartyCookies();
 }
index 1b261bc..e99d83f 100644 (file)
@@ -253,7 +253,7 @@ public:
     void setStatisticsCacheMaxAgeCap(double seconds);
     bool hasStatisticsIsolatedSession(WKStringRef hostName);
     void setStatisticsShouldDowngradeReferrer(bool value);
-    void setStatisticsShouldBlockThirdPartyCookies(bool value);
+    void setStatisticsShouldBlockThirdPartyCookies(bool value, bool onlyOnSitesWithoutUserInteraction);
     void statisticsResetToConsistentState();
 
     void getAllStorageAccessEntries();
index 5bbeb57..7b27da1 100644 (file)
@@ -1549,10 +1549,17 @@ WKRetainPtr<WKTypeRef> TestInvocation::didReceiveSynchronousMessageFromInjectedB
         return nullptr;
     }
     
+    if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsShouldBlockThirdPartyCookiesOnSitesWithoutUserInteraction")) {
+        ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
+        WKBooleanRef value = static_cast<WKBooleanRef>(messageBody);
+        TestController::singleton().setStatisticsShouldBlockThirdPartyCookies(WKBooleanGetValue(value), true);
+        return nullptr;
+    }
+    
     if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsShouldBlockThirdPartyCookies")) {
         ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
         WKBooleanRef value = static_cast<WKBooleanRef>(messageBody);
-        TestController::singleton().setStatisticsShouldBlockThirdPartyCookies(WKBooleanGetValue(value));
+        TestController::singleton().setStatisticsShouldBlockThirdPartyCookies(WKBooleanGetValue(value), false);
         return nullptr;
     }