Resource Load Statistics: Block cookies for prevalent resources without user interaction
authorwilander@apple.com <wilander@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 17 Jan 2018 19:16:23 +0000 (19:16 +0000)
committerwilander@apple.com <wilander@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 17 Jan 2018 19:16:23 +0000 (19:16 +0000)
https://bugs.webkit.org/show_bug.cgi?id=177394
<rdar://problem/34613960>

Reviewed by Alex Christensen.

Source/WebCore:

Tests: http/tests/resourceLoadStatistics/add-blocking-to-redirect.html
       http/tests/resourceLoadStatistics/non-prevalent-resources-can-access-cookies-in-a-third-party-context.html
       http/tests/resourceLoadStatistics/remove-blocking-in-redirect.html
       http/tests/resourceLoadStatistics/remove-partitioning-in-redirect.html

* platform/network/NetworkStorageSession.h:
    Now exports NetworkStorageSession::nsCookieStorage().
* platform/network/cf/NetworkStorageSessionCFNet.cpp:
(WebCore::NetworkStorageSession::setPrevalentDomainsToPartitionOrBlockCookies):
    Fixes the FIXME.

Source/WebCore/PAL:

* pal/spi/cf/CFNetworkSPI.h:
    Declaration of _initWithIdentifier() on NSHTTPCookieStorage.

Source/WebKit:

* NetworkProcess/cocoa/NetworkDataTaskCocoa.h:
    Now has m_hasBeenSetToUseStatelessCookieStorage to handle
    cookie blocking.
* NetworkProcess/cocoa/NetworkDataTaskCocoa.mm:
(WebKit::NetworkDataTaskCocoa::statelessCookieStorage):
    Returns singleton empty, deny-all cookie storage for cookie blocking.
(WebKit::NetworkDataTaskCocoa::applyCookieBlockingPolicy):
    Instead of just decision making, this now applies the policy.
(WebKit::NetworkDataTaskCocoa::applyCookiePartitioningPolicy):
    New method.
(WebKit::NetworkDataTaskCocoa::NetworkDataTaskCocoa):
    Now blocks cookies for domains where cookies will be purged anyway.
(WebKit::NetworkDataTaskCocoa::willPerformHTTPRedirection):
    Now blocks cookies for domains where cookies will be purged anyway.
(WebKit::shouldChangePartition): Deleted.
* NetworkProcess/cocoa/NetworkSessionCocoa.mm:
(-[WKNetworkSessionDelegate URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:]):
    Now downgrades for blocked cookies instead of partitioned cookies.
(-[WKNetworkSessionDelegate URLSession:task:_schemeUpgraded:completionHandler:]):
    Now downgrades for blocked cookies instead of partitioned cookies.

LayoutTests:

* http/tests/resourceLoadStatistics/add-blocking-to-redirect-expected.txt: Added.
* http/tests/resourceLoadStatistics/add-blocking-to-redirect.html: Added.
* http/tests/resourceLoadStatistics/add-partitioning-to-redirect.html:
* http/tests/resourceLoadStatistics/non-prevalent-resources-can-access-cookies-in-a-third-party-context-expected.txt: Added.
* http/tests/resourceLoadStatistics/non-prevalent-resources-can-access-cookies-in-a-third-party-context.html: Added.
* http/tests/resourceLoadStatistics/partitioned-and-unpartitioned-cookie-with-partitioning-timeout.html:
* http/tests/resourceLoadStatistics/remove-blocking-in-redirect-expected.txt: Added.
* http/tests/resourceLoadStatistics/remove-blocking-in-redirect.html: Added.
* http/tests/resourceLoadStatistics/remove-partitioning-from-redirect-expected.txt: Removed.
* http/tests/resourceLoadStatistics/remove-partitioning-from-redirect.html: Removed.
    Test case reworked and is now remove-partitioning-in-redirect.html.
* http/tests/resourceLoadStatistics/remove-partitioning-in-redirect-expected.txt: Added.
* http/tests/resourceLoadStatistics/remove-partitioning-in-redirect.html: Added.
* platform/ios/TestExpectations:
    New tests marked as [ Pass ] for iOS.
* platform/mac-wk2/TestExpectations:
    New tests marked as [ Pass ] for High Sierra+.
* platform/wk2/TestExpectations:
    New tests skipped for WK2 in general.

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

24 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/resourceLoadStatistics/add-blocking-to-redirect-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/resourceLoadStatistics/add-blocking-to-redirect.html [new file with mode: 0644]
LayoutTests/http/tests/resourceLoadStatistics/add-partitioning-to-redirect.html
LayoutTests/http/tests/resourceLoadStatistics/non-prevalent-resources-can-access-cookies-in-a-third-party-context-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/resourceLoadStatistics/non-prevalent-resources-can-access-cookies-in-a-third-party-context.html [new file with mode: 0644]
LayoutTests/http/tests/resourceLoadStatistics/partitioned-and-unpartitioned-cookie-with-partitioning-timeout.html
LayoutTests/http/tests/resourceLoadStatistics/remove-blocking-in-redirect-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/resourceLoadStatistics/remove-blocking-in-redirect.html [new file with mode: 0644]
LayoutTests/http/tests/resourceLoadStatistics/remove-partitioning-from-redirect-expected.txt [deleted file]
LayoutTests/http/tests/resourceLoadStatistics/remove-partitioning-in-redirect-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/resourceLoadStatistics/remove-partitioning-in-redirect.html [moved from LayoutTests/http/tests/resourceLoadStatistics/remove-partitioning-from-redirect.html with 54% similarity]
LayoutTests/platform/ios/TestExpectations
LayoutTests/platform/mac-wk2/TestExpectations
LayoutTests/platform/wk2/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/PAL/ChangeLog
Source/WebCore/PAL/pal/spi/cf/CFNetworkSPI.h
Source/WebCore/platform/network/NetworkStorageSession.h
Source/WebCore/platform/network/cf/NetworkStorageSessionCFNet.cpp
Source/WebKit/ChangeLog
Source/WebKit/NetworkProcess/cocoa/NetworkDataTaskCocoa.h
Source/WebKit/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm
Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm

index 8026385..9683fc3 100644 (file)
@@ -1,3 +1,31 @@
+2018-01-17  John Wilander  <wilander@apple.com>
+
+        Resource Load Statistics: Block cookies for prevalent resources without user interaction
+        https://bugs.webkit.org/show_bug.cgi?id=177394
+        <rdar://problem/34613960>
+
+        Reviewed by Alex Christensen.
+
+        * http/tests/resourceLoadStatistics/add-blocking-to-redirect-expected.txt: Added.
+        * http/tests/resourceLoadStatistics/add-blocking-to-redirect.html: Added.
+        * http/tests/resourceLoadStatistics/add-partitioning-to-redirect.html:
+        * http/tests/resourceLoadStatistics/non-prevalent-resources-can-access-cookies-in-a-third-party-context-expected.txt: Added.
+        * http/tests/resourceLoadStatistics/non-prevalent-resources-can-access-cookies-in-a-third-party-context.html: Added.
+        * http/tests/resourceLoadStatistics/partitioned-and-unpartitioned-cookie-with-partitioning-timeout.html:
+        * http/tests/resourceLoadStatistics/remove-blocking-in-redirect-expected.txt: Added.
+        * http/tests/resourceLoadStatistics/remove-blocking-in-redirect.html: Added.
+        * http/tests/resourceLoadStatistics/remove-partitioning-from-redirect-expected.txt: Removed.
+        * http/tests/resourceLoadStatistics/remove-partitioning-from-redirect.html: Removed.
+            Test case reworked and is now remove-partitioning-in-redirect.html.
+        * http/tests/resourceLoadStatistics/remove-partitioning-in-redirect-expected.txt: Added.
+        * http/tests/resourceLoadStatistics/remove-partitioning-in-redirect.html: Added.
+        * platform/ios/TestExpectations:
+            New tests marked as [ Pass ] for iOS.
+        * platform/mac-wk2/TestExpectations:
+            New tests marked as [ Pass ] for High Sierra+.
+        * platform/wk2/TestExpectations:
+            New tests skipped for WK2 in general.
+
 2018-01-17  Daniel Bates  <dabates@apple.com>
 
         REGRESSION (r222795): Cardiogram never signs in
diff --git a/LayoutTests/http/tests/resourceLoadStatistics/add-blocking-to-redirect-expected.txt b/LayoutTests/http/tests/resourceLoadStatistics/add-blocking-to-redirect-expected.txt
new file mode 100644 (file)
index 0000000..53a1e75
--- /dev/null
@@ -0,0 +1,63 @@
+Tests that blocking is added mid-flight in redirects.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+
+--------
+Frame: '<!--framePath //<!--frame0-->-->'
+--------
+Should receive first-party cookie.
+Received cookie named 'firstPartyCookie'.
+Did not receive cookie named 'partitionedCookie'.
+Client-side document.cookie: firstPartyCookie=value
+
+--------
+Frame: '<!--framePath //<!--frame1-->-->'
+--------
+Redirect case 1, should receive first-party cookie.
+Received cookie named 'firstPartyCookie'.
+Did not receive cookie named 'partitionedCookie'.
+Client-side document.cookie: firstPartyCookie=value
+
+--------
+Frame: '<!--framePath //<!--frame2-->-->'
+--------
+Should receive no cookies.
+Did not receive cookie named 'firstPartyCookie'.
+Did not receive cookie named 'partitionedCookie'.
+Client-side document.cookie:
+
+--------
+Frame: '<!--framePath //<!--frame3-->-->'
+--------
+Redirect case 2, should receive no cookie.
+Did not receive cookie named 'firstPartyCookie'.
+Did not receive cookie named 'partitionedCookie'.
+Client-side document.cookie:
+
+--------
+Frame: '<!--framePath //<!--frame4-->-->'
+--------
+Try to set third-party cookie in blocked mode.
+
+
+--------
+Frame: '<!--framePath //<!--frame5-->-->'
+--------
+After attempted cookie creation, should receive no cookie.
+Did not receive cookie named 'firstPartyCookie'.
+Did not receive cookie named 'partitionedCookie'.
+Client-side document.cookie:
+
+--------
+Frame: '<!--framePath //<!--frame6-->-->'
+--------
+Redirect case 3, after attempted cookie creation, should receive no cookie.
+Did not receive cookie named 'firstPartyCookie'.
+Did not receive cookie named 'partitionedCookie'.
+Client-side document.cookie:
diff --git a/LayoutTests/http/tests/resourceLoadStatistics/add-blocking-to-redirect.html b/LayoutTests/http/tests/resourceLoadStatistics/add-blocking-to-redirect.html
new file mode 100644 (file)
index 0000000..c33ec08
--- /dev/null
@@ -0,0 +1,108 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <script src="/js-test-resources/js-test.js"></script>
+</head>
+<body onload="runTest()">
+<script>
+    description("Tests that blocking is added mid-flight in redirects.");
+    jsTestIsAsync = true;
+
+    function setEnableFeature(enable) {
+        if (!enable)
+            testRunner.statisticsResetToConsistentState();
+        internals.setResourceLoadStatisticsEnabled(enable);
+        testRunner.setCookieStoragePartitioningEnabled(enable);
+    }
+
+    if (document.location.hash === "") {
+        setEnableFeature(true);
+        if (testRunner.isStatisticsPrevalentResource("http://localhost"))
+            testFailed("Localhost was classified as prevalent resource before the test starts.");
+        // Make sure the network process is up-to-date.
+        testRunner.statisticsSetShouldPartitionCookiesForHost("localhost", false);
+        testRunner.dumpChildFramesAsText();
+        document.location.hash = "step1";
+    }
+
+    const partitionHost = "127.0.0.1:8000";
+    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 partitionedCookieName = "partitionedCookie";
+    const subPathToSetPartitionedCookie = "/set-cookie.php?name=" + partitionedCookieName + "&value=value";
+    const returnUrl = "http://" + partitionHost + "/resourceLoadStatistics/add-blocking-to-redirect.html";
+    const subPathToGetCookies = "/get-cookies.php?name1=" + firstPartyCookieName + "&name2=" + partitionedCookieName;
+    const redirectChainUrl = "http://" + partitionHost + resourcePath + "/redirect.php?redirectTo=" + thirdPartyBaseUrl + subPathToGetCookies;
+
+    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":
+                // Check that the cookie gets sent for localhost under 127.0.0.1 since localhost is not prevalent.
+                document.location.hash = "step3";
+                openIframe(thirdPartyBaseUrl + subPathToGetCookies + "&message=Should receive first-party cookie.", runTest);
+                break;
+            case "#step3":
+                document.location.hash = "step4";
+                // Load an iframe in a redirect chain that starts with 127.0.0.1 and ends with localhost. Expect a cookie for localhost.
+                openIframe(redirectChainUrl + "&message=Redirect case 1, should receive first-party cookie.", runTest);
+                break;
+            case "#step4":
+                // Set localhost as prevalent and with no user interaction to put it in the blocking category.
+                document.location.hash = "step5";
+                testRunner.setStatisticsPrevalentResource("http://localhost", true);
+                testRunner.statisticsUpdateCookiePartitioning();
+                if (!testRunner.isStatisticsPrevalentResource("http://localhost"))
+                    testFailed("Host did not get set as prevalent resource.");
+                runTest();
+                break;
+            case "#step5":
+                // Check that no cookie gets sent for localhost under 127.0.0.1 since localhost's cookies are blocked.
+                document.location.hash = "step6";
+                openIframe(thirdPartyBaseUrl + subPathToGetCookies +  "&message=Should receive no cookies.", runTest);
+                break;
+            case "#step6":
+                // Load an iframe in a redirect chain that starts with 127.0.0.1 and ends with localhost. Expect no cookie for localhost.
+                document.location.hash = "step7";
+                openIframe(redirectChainUrl + "&message=Redirect case 2, should receive no cookie.", runTest);
+                break;
+            case "#step7":
+                // Try to set cookie for localhost under 127.0.0.1.
+                document.location.hash = "step8";
+                openIframe(thirdPartyBaseUrl + subPathToSetPartitionedCookie + "&message=Try to set third-party cookie in blocked mode.", runTest);
+                break;
+            case "#step8":
+                // Check that no cookie gets sent for localhost under 127.0.0.1 since localhost's cookies are blocked.
+                document.location.hash = "step9";
+                openIframe(thirdPartyBaseUrl + subPathToGetCookies +  "&message=After attempted cookie creation, should receive no cookie.", runTest);
+                break;
+            case "#step9":
+                // Load an iframe in a redirect chain that starts with 127.0.0.1 and ends with localhost. Expect no cookie for localhost.
+                document.location.hash = "step10";
+                openIframe(redirectChainUrl + "&message=Redirect case 3, after attempted cookie creation, should receive no cookie.", runTest);
+                break;
+            case "#step10":
+                setEnableFeature(false);
+                finishJSTest();
+                break;
+        }
+    }
+</script>
+</body>
+</html>
index 5fc3f87..7412921 100644 (file)
                 openIframe(redirectChainUrl + "&message=Redirect case, should receive first-party cookie.", runTest);
                 break;
             case "#step4":
-                // Set localhost as prevalent.
+                // Set localhost as prevalent and with non-recent user interaction to put it in the partitioning category.
                 document.location.hash = "step5";
                 testRunner.setStatisticsPrevalentResource("http://localhost", true);
+                testRunner.setStatisticsHasHadNonRecentUserInteraction("http://localhost");
                 testRunner.statisticsUpdateCookiePartitioning();
                 if (!testRunner.isStatisticsPrevalentResource("http://localhost"))
                     testFailed("Host did not get set as prevalent resource.");
diff --git a/LayoutTests/http/tests/resourceLoadStatistics/non-prevalent-resources-can-access-cookies-in-a-third-party-context-expected.txt b/LayoutTests/http/tests/resourceLoadStatistics/non-prevalent-resources-can-access-cookies-in-a-third-party-context-expected.txt
new file mode 100644 (file)
index 0000000..74e311d
--- /dev/null
@@ -0,0 +1,34 @@
+PASS successfullyParsed is true
+
+TEST COMPLETE
+  
+
+--------
+Frame: '<!--framePath //<!--frame0-->-->'
+--------
+Should receive one cookie.
+Received cookie named 'firstPartyCookie'.
+Did not receive cookie named 'partitionedCookie'.
+Client-side document.cookie: firstPartyCookie=value
+
+--------
+Frame: '<!--framePath //<!--frame1-->-->'
+--------
+Setting partitioned, third party cookie.
+
+
+--------
+Frame: '<!--framePath //<!--frame2-->-->'
+--------
+Should receive one partitioned, third party cookie.
+Did not receive cookie named 'firstPartyCookie'.
+Received cookie named 'partitionedCookie'.
+Client-side document.cookie: partitionedCookie=value
+
+--------
+Frame: '<!--framePath //<!--frame3-->-->'
+--------
+After user interaction, should receive one non-partitioned, first party cookie.
+Received cookie named 'firstPartyCookie'.
+Did not receive cookie named 'partitionedCookie'.
+Client-side document.cookie: firstPartyCookie=value
diff --git a/LayoutTests/http/tests/resourceLoadStatistics/non-prevalent-resources-can-access-cookies-in-a-third-party-context.html b/LayoutTests/http/tests/resourceLoadStatistics/non-prevalent-resources-can-access-cookies-in-a-third-party-context.html
new file mode 100644 (file)
index 0000000..787d7b9
--- /dev/null
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Test to ensure non-prevalent resources can access their cookies in a third party context</title>
+    <script src="/js-test-resources/js-test.js"></script>
+</head>
+<body>
+<script>
+    const partitionHost = "127.0.0.1:8000";
+    const thirdPartyHostname = "localhost";
+    const thirdPartyOrigin = "http://" + thirdPartyHostname + ":8000";
+    const thirdPartyBaseUrl = thirdPartyOrigin + "/resourceLoadStatistics/resources";
+    const firstPartyCookieName = "firstPartyCookie";
+    const subPathToSetFirstPartyCookie = "/set-cookie.php?name=" + firstPartyCookieName + "&value=value";
+    const partitionedCookieName = "partitionedCookie";
+    const subPathToSetPartitionedCookie = "/set-cookie.php?name=" + partitionedCookieName + "&value=value";
+    const fragmentWithReturnUrl = "http://127.0.0.1:8000/resourceLoadStatistics/non-prevalent-resources-can-access-cookies-in-a-third-party-context.html";
+    const subPathToGetCookies = "/get-cookies.php?name1=" + firstPartyCookieName + "&name2=" + partitionedCookieName;
+
+    function setEnableFeature(enable) {
+        if (!enable) {
+            testRunner.statisticsResetToConsistentState();
+        }
+        testRunner.setStatisticsNotifyPagesWhenDataRecordsWereScanned(enable);
+        internals.setResourceLoadStatisticsEnabled(enable);
+        testRunner.setCookieStoragePartitioningEnabled(enable);
+    }
+
+    function finishTest() {
+        setEnableFeature(false);
+        testRunner.notifyDone();
+    }
+
+    function openIframe(url, onLoadHandler) {
+        const element = document.createElement("iframe");
+        element.src = url;
+        if (onLoadHandler) {
+            element.onload = onLoadHandler;
+        }
+        document.body.appendChild(element);
+    }
+
+    function setUserInteractionAndContinue() {
+        testRunner.setStatisticsHasHadUserInteraction(thirdPartyOrigin, true);
+        if (!testRunner.isStatisticsHasHadUserInteraction(thirdPartyOrigin))
+            testFailed("Third party did not get logged for user interaction.");
+        runTest();
+    }
+
+    function runTest() {
+        switch (document.location.hash) {
+            case "#step1":
+                // Set a first-party cookie for localhost.
+                document.location.href = thirdPartyBaseUrl + subPathToSetFirstPartyCookie + "#" + fragmentWithReturnUrl + "#step2";
+                break;
+            case "#step2":
+                // Load localhost under 127.0.0.1 and check that it gets its cookie.
+                document.location.hash = "step3";
+                openIframe(thirdPartyBaseUrl + subPathToGetCookies + "&message=Should receive one cookie.", runTest);
+                break;
+            case "#step3":
+                // Setup localhost for partitioning and set a partitioned cookie for localhost under 127.0.0.1.
+                document.location.hash = "step4";
+                testRunner.statisticsSetShouldPartitionCookiesForHost(thirdPartyHostname, true);
+                openIframe(thirdPartyBaseUrl + subPathToSetPartitionedCookie + "&message=Setting partitioned, third party cookie.", runTest);
+                break;
+            case "#step4":
+                // Load localhost under 127.0.0.1 and check that it gets only the partitioned cookie. End by aquiring user interaction for localhost.
+                document.location.hash = "step5";
+                openIframe(thirdPartyBaseUrl + subPathToGetCookies + "&message=Should receive one partitioned, third party cookie.", setUserInteractionAndContinue);
+                break;
+            case "#step5":
+                // Load localhost under 127.0.0.1 and check that it gets its non-partitioned cookie after user interaction.
+                openIframe(thirdPartyBaseUrl + subPathToGetCookies + "&message=After user interaction, should receive one non-partitioned, first party cookie.", finishTest);
+                break;
+        }
+    }
+
+    if (document.location.host === partitionHost && document.location.hash == "" && window.testRunner && window.internals) {
+        setEnableFeature(true);
+
+        testRunner.setStatisticsPrevalentResource(thirdPartyHostname, false);
+        testRunner.setStatisticsHasHadUserInteraction(thirdPartyOrigin, false);
+        testRunner.statisticsSetShouldPartitionCookiesForHost(thirdPartyHostname, false);
+
+        testRunner.waitUntilDone();
+        testRunner.dumpChildFramesAsText();
+        document.location.hash = "step1";
+    }
+
+    runTest();
+</script>
+</body>
+</html>
index 3faf8be..01b3708 100644 (file)
     if (document.location.hash === "" && window.testRunner && window.internals) {
         setEnableFeature(true);
 
+        // Set localhost as prevalent and with non-recent user interaction to put it in the partitioning category.
         testRunner.setStatisticsPrevalentResource("http://localhost", true);
         if (!testRunner.isStatisticsPrevalentResource("http://localhost"))
             testFailed("Host did not get set as prevalent resource.");
+        testRunner.setStatisticsHasHadNonRecentUserInteraction("http://localhost");
 
         testRunner.statisticsUpdateCookiePartitioning();
 
diff --git a/LayoutTests/http/tests/resourceLoadStatistics/remove-blocking-in-redirect-expected.txt b/LayoutTests/http/tests/resourceLoadStatistics/remove-blocking-in-redirect-expected.txt
new file mode 100644 (file)
index 0000000..8fa51fa
--- /dev/null
@@ -0,0 +1,47 @@
+Tests that blocking is removed mid-flight in redirects.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+
+--------
+Frame: '<!--framePath //<!--frame0-->-->'
+--------
+Should receive first-party cookie.
+Received cookie named 'firstPartyCookie'.
+Did not receive cookie named 'partitionedCookie'.
+Client-side document.cookie: firstPartyCookie=value
+
+--------
+Frame: '<!--framePath //<!--frame1-->-->'
+--------
+Redirect case 1, should receive first-party cookie for 127.0.0.1.
+Received cookie named 'firstPartyCookie'.
+Did not receive cookie named 'partitionedCookie'.
+Client-side document.cookie: firstPartyCookie=127.0.0.1
+
+--------
+Frame: '<!--framePath //<!--frame2-->-->'
+--------
+Set partitioned, third-party cookie.
+
+
+--------
+Frame: '<!--framePath //<!--frame3-->-->'
+--------
+Should receive no cookie.
+Did not receive cookie named 'firstPartyCookie'.
+Did not receive cookie named 'partitionedCookie'.
+Client-side document.cookie:
+
+--------
+Frame: '<!--framePath //<!--frame4-->-->'
+--------
+Redirect case 2, should receive first-party cookie for 127.0.0.1.
+Received cookie named 'firstPartyCookie'.
+Did not receive cookie named 'partitionedCookie'.
+Client-side document.cookie: firstPartyCookie=127.0.0.1
diff --git a/LayoutTests/http/tests/resourceLoadStatistics/remove-blocking-in-redirect.html b/LayoutTests/http/tests/resourceLoadStatistics/remove-blocking-in-redirect.html
new file mode 100644 (file)
index 0000000..f771870
--- /dev/null
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <script src="/js-test-resources/js-test.js"></script>
+</head>
+<body onload="runTest()">
+<script>
+    description("Tests that blocking is removed mid-flight in redirects.");
+    jsTestIsAsync = true;
+
+    function setEnableFeature(enable) {
+        if (!enable)
+            testRunner.statisticsResetToConsistentState();
+        internals.setResourceLoadStatisticsEnabled(enable);
+        testRunner.setCookieStoragePartitioningEnabled(enable);
+    }
+
+    if (document.location.hash === "") {
+        setEnableFeature(true);
+        if (testRunner.isStatisticsPrevalentResource("http://localhost"))
+            testFailed("Localhost was classified as prevalent resource before the test starts.");
+        // Make sure the network process is up-to-date.
+        testRunner.statisticsSetShouldPartitionCookiesForHost("localhost", false);
+        testRunner.dumpChildFramesAsText();
+        document.location.hash = "step1";
+    }
+
+    const partitionHost = "127.0.0.1:8000";
+    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 partitionedCookieName = "partitionedCookie";
+    const subPathToSetPartitionedCookie = "/set-cookie.php?name=" + partitionedCookieName + "&value=value";
+    const returnUrl = "http://" + partitionHost + "/resourceLoadStatistics/remove-blocking-in-redirect.html";
+    const subPathToGetCookies = "/get-cookies.php?name1=" + firstPartyCookieName + "&name2=" + partitionedCookieName;
+    const redirectChainUrl = thirdPartyOrigin + resourcePath + "/redirect.php?redirectTo=http://" + partitionHost + resourcePath + subPathToGetCookies;
+
+    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 cookies for 127.0.0.1 and localhost.
+                document.cookie = firstPartyCookieName + "=127.0.0.1;path='/'";
+                document.location.href = thirdPartyBaseUrl + subPathToSetFirstPartyCookie + "#" + returnUrl + "#step2";
+                break;
+            case "#step2":
+                // Check that the cookie gets sent for localhost under 127.0.0.1 since localhost is not prevalent.
+                document.location.hash = "step3";
+                openIframe(thirdPartyBaseUrl + subPathToGetCookies + "&message=Should receive first-party cookie.", runTest);
+                break;
+            case "#step3":
+                document.location.hash = "step4";
+                // Load an iframe in a redirect chain that starts with localhost and ends with 127.0.0.1. Expect a cookie for 127.0.0.1.
+                openIframe(redirectChainUrl + "&message=Redirect case 1, should receive first-party cookie for 127.0.0.1.", runTest);
+                break;
+            case "#step4":
+                // Set localhost as prevalent and with non-recent user interaction to put it in the blocking category.
+                document.location.hash = "step5";
+                testRunner.setStatisticsPrevalentResource("http://localhost", true);
+                testRunner.statisticsUpdateCookiePartitioning();
+                if (!testRunner.isStatisticsPrevalentResource("http://localhost"))
+                    testFailed("Host did not get set as prevalent resource.");
+                runTest();
+                break;
+            case "#step5":
+                // Set partitioned cookie for localhost under 127.0.0.1.
+                document.location.hash = "step6";
+                openIframe(thirdPartyBaseUrl + subPathToSetPartitionedCookie + "&message=Set partitioned, third-party cookie.", runTest);
+                break;
+            case "#step6":
+                // Check that no cookie gets sent for localhost under 127.0.0.1 since localhost's cookies are blocked.
+                document.location.hash = "step7";
+                openIframe(thirdPartyBaseUrl + subPathToGetCookies +  "&message=Should receive no cookie.", runTest);
+                break;
+            case "#step7":
+                // Load an iframe in a redirect chain that starts with localhost and ends with 127.0.0.1. Expect a cookie for 127.0.0.1.
+                document.location.hash = "step8";
+                openIframe(redirectChainUrl + "&message=Redirect case 2, should receive first-party cookie for 127.0.0.1.", runTest);
+                break;
+            case "#step8":
+                setEnableFeature(false);
+                finishJSTest();
+                break;
+        }
+    }
+</script>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/resourceLoadStatistics/remove-partitioning-from-redirect-expected.txt b/LayoutTests/http/tests/resourceLoadStatistics/remove-partitioning-from-redirect-expected.txt
deleted file mode 100644 (file)
index 6922b06..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-Tests that partitioning is removed mid-flight in redirects.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
-
---------
-Frame: '<!--framePath //<!--frame0-->-->'
---------
-Should receive first-party cookie.
-Received cookie named 'firstPartyCookie'.
-Did not receive cookie named 'partitionedCookie'.
-Client-side document.cookie: firstPartyCookie=value
-
---------
-Frame: '<!--framePath //<!--frame1-->-->'
---------
-Redirect case, should receive first-party cookie.
-Received cookie named 'firstPartyCookie'.
-Did not receive cookie named 'partitionedCookie'.
-Client-side document.cookie: firstPartyCookie=value
diff --git a/LayoutTests/http/tests/resourceLoadStatistics/remove-partitioning-in-redirect-expected.txt b/LayoutTests/http/tests/resourceLoadStatistics/remove-partitioning-in-redirect-expected.txt
new file mode 100644 (file)
index 0000000..95a3ff0
--- /dev/null
@@ -0,0 +1,47 @@
+Tests that partitioning is removed mid-flight in redirects.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+
+--------
+Frame: '<!--framePath //<!--frame0-->-->'
+--------
+Should receive first-party cookie.
+Received cookie named 'firstPartyCookie'.
+Did not receive cookie named 'partitionedCookie'.
+Client-side document.cookie: firstPartyCookie=value
+
+--------
+Frame: '<!--framePath //<!--frame1-->-->'
+--------
+Redirect case 1, should receive first-party cookie for 127.0.0.1.
+Received cookie named 'firstPartyCookie'.
+Did not receive cookie named 'partitionedCookie'.
+Client-side document.cookie: firstPartyCookie=127.0.0.1
+
+--------
+Frame: '<!--framePath //<!--frame2-->-->'
+--------
+Set partitioned, third-party cookie.
+
+
+--------
+Frame: '<!--framePath //<!--frame3-->-->'
+--------
+Should receive partitioned cookie.
+Did not receive cookie named 'firstPartyCookie'.
+Received cookie named 'partitionedCookie'.
+Client-side document.cookie: partitionedCookie=value
+
+--------
+Frame: '<!--framePath //<!--frame4-->-->'
+--------
+Redirect case 2, should receive first-party cookie for 127.0.0.1.
+Received cookie named 'firstPartyCookie'.
+Did not receive cookie named 'partitionedCookie'.
+Client-side document.cookie: firstPartyCookie=127.0.0.1
@@ -20,6 +20,8 @@
         setEnableFeature(true);
         if (testRunner.isStatisticsPrevalentResource("http://localhost"))
             testFailed("Localhost was classified as prevalent resource before the test starts.");
+        // Make sure the network process is up-to-date.
+        testRunner.statisticsSetShouldPartitionCookiesForHost("localhost", false);
         testRunner.dumpChildFramesAsText();
         document.location.hash = "step1";
     }
     const thirdPartyOrigin = "http://localhost:8000";
     const resourcePath = "/resourceLoadStatistics/resources";
     const thirdPartyBaseUrl = thirdPartyOrigin + resourcePath;
-    const partitionBaseUrl = "http://" + partitionHost + resourcePath;
     const firstPartyCookieName = "firstPartyCookie";
     const subPathToSetFirstPartyCookie = "/set-cookie.php?name=" + firstPartyCookieName + "&value=value";
     const partitionedCookieName = "partitionedCookie";
-    const returnUrl = "http://" + partitionHost + "/resourceLoadStatistics/remove-partitioning-from-redirect.html";
+    const subPathToSetPartitionedCookie = "/set-cookie.php?name=" + partitionedCookieName + "&value=value";
+    const returnUrl = "http://" + partitionHost + "/resourceLoadStatistics/remove-partitioning-in-redirect.html";
     const subPathToGetCookies = "/get-cookies.php?name1=" + firstPartyCookieName + "&name2=" + partitionedCookieName;
-    const redirectChainUrl = thirdPartyBaseUrl + "/redirect.php?redirectTo=" + partitionBaseUrl + subPathToGetCookies;
+    const redirectChainUrl = thirdPartyOrigin + resourcePath + "/redirect.php?redirectTo=http://" + partitionHost + resourcePath + subPathToGetCookies;
 
     function openIframe(url, onLoadHandler) {
         const element = document.createElement("iframe");
     function runTest() {
         switch (document.location.hash) {
             case "#step1":
-                // Set localhost as prevalent.
-                document.location.hash = "step2";
-                testRunner.setStatisticsPrevalentResource("http://localhost", true);
-                testRunner.statisticsUpdateCookiePartitioning();
-                if (!testRunner.isStatisticsPrevalentResource("http://localhost"))
-                    testFailed("Host did not get set as prevalent resource.");
-                runTest();
+                // Set first-party cookies for 127.0.0.1 and localhost.
+                document.cookie = firstPartyCookieName + "=127.0.0.1;path='/'";
+                document.location.href = thirdPartyBaseUrl + subPathToSetFirstPartyCookie + "#" + returnUrl + "#step2";
                 break;
             case "#step2":
-                // Set first-party cookie for 127.0.0.1.
-                document.location.href = partitionBaseUrl + subPathToSetFirstPartyCookie + "#" + returnUrl + "#step3";
+                // Check that the cookie gets sent for localhost under 127.0.0.1 since localhost is not prevalent.
+                document.location.hash = "step3";
+                openIframe(thirdPartyBaseUrl + subPathToGetCookies + "&message=Should receive first-party cookie.", runTest);
                 break;
             case "#step3":
-                // Check that the cookie gets sent for 127.0.0.1 under 127.0.0.1.
                 document.location.hash = "step4";
-                openIframe(partitionBaseUrl + subPathToGetCookies + "&message=Should receive first-party cookie.", runTest);
+                // Load an iframe in a redirect chain that starts with localhost and ends with 127.0.0.1. Expect a cookie for 127.0.0.1.
+                openIframe(redirectChainUrl + "&message=Redirect case 1, should receive first-party cookie for 127.0.0.1.", runTest);
                 break;
             case "#step4":
+                // Set localhost as prevalent and with non-recent user interaction to put it in the partitioning category.
                 document.location.hash = "step5";
-                // Load an iframe in a redirect chain that starts with localhost and ends with 127.0.0.1. Expect a cookie for 127.0.0.1.
-                openIframe(redirectChainUrl + "&message=Redirect case, should receive first-party cookie.", runTest);
+                testRunner.setStatisticsPrevalentResource("http://localhost", true);
+                testRunner.setStatisticsHasHadNonRecentUserInteraction("http://localhost");
+                testRunner.statisticsUpdateCookiePartitioning();
+                if (!testRunner.isStatisticsPrevalentResource("http://localhost"))
+                    testFailed("Host did not get set as prevalent resource.");
+                runTest();
                 break;
             case "#step5":
+                // Set partitioned cookie for localhost under 127.0.0.1.
+                document.location.hash = "step6";
+                openIframe(thirdPartyBaseUrl + subPathToSetPartitionedCookie + "&message=Set partitioned, third-party cookie.", runTest);
+                break;
+            case "#step6":
+                // Check that partitioned cookie gets sent for localhost under 127.0.0.1 since localhost is partitioned.
+                document.location.hash = "step7";
+                openIframe(thirdPartyBaseUrl + subPathToGetCookies +  "&message=Should receive partitioned cookie.", runTest);
+                break;
+            case "#step7":
+                // Load an iframe in a redirect chain that starts with localhost and ends with 127.0.0.1. Expect a cookie for 127.0.0.1.
+                document.location.hash = "step8";
+                openIframe(redirectChainUrl + "&message=Redirect case 2, should receive first-party cookie for 127.0.0.1.", runTest);
+                break;
+            case "#step8":
                 setEnableFeature(false);
                 finishJSTest();
                 break;
index 964a5fe..d5a4689 100644 (file)
@@ -2977,12 +2977,15 @@ webkit.org/b/174120 http/tests/resourceLoadStatistics/user-interaction-in-cross-
 http/tests/resourceLoadStatistics/user-interaction-only-reported-once-within-short-period-of-time.html [ Skip ]
 http/tests/resourceLoadStatistics/user-interaction-reported-after-website-data-removal.html [ Skip ]
 # Skipped in WK2 expectations because cookie partitioning is only available in macOS High Sierra and iOS 11.
-http/tests/resourceLoadStatistics/add-partitioning-to-redirect.html [ Pass ]
-http/tests/resourceLoadStatistics/remove-partitioning-from-redirect.html [ Pass ]
 http/tests/resourceLoadStatistics/partitioned-and-unpartitioned-cookie-deletion.html [ Pass ]
 http/tests/resourceLoadStatistics/partitioned-and-unpartitioned-cookie-with-partitioning-timeout.html [ Pass ]
 http/tests/resourceLoadStatistics/partitioned-cookies-with-and-without-user-interaction.html [ Pass ]
 http/tests/resourceLoadStatistics/third-party-cookie-with-and-without-user-interaction.html [ Pass ]
+http/tests/resourceLoadStatistics/non-prevalent-resources-can-access-cookies-in-a-third-party-context.html [ Pass ]
+http/tests/resourceLoadStatistics/add-partitioning-to-redirect.html [ Pass ]
+http/tests/resourceLoadStatistics/add-blocking-to-redirect.html [ Pass ]
+http/tests/resourceLoadStatistics/remove-partitioning-in-redirect.html [ Pass ]
+http/tests/resourceLoadStatistics/remove-blocking-in-redirect.html [ Pass ]
 
 webkit.org/b/175273 imported/w3c/web-platform-tests/html/browsers/windows/noreferrer-window-name.html [ Failure ]
 
index 15a6073..c03764c 100644 (file)
@@ -803,8 +803,11 @@ webkit.org/b/176122 media/video-controls-drop-and-restore-timeline.html [ Pass F
 [ HighSierra+ ] http/tests/resourceLoadStatistics/partitioned-and-unpartitioned-cookie-with-partitioning-timeout.html [ Pass ]
 [ HighSierra+ ] http/tests/resourceLoadStatistics/third-party-cookie-with-and-without-user-interaction.html [ Pass ]
 [ HighSierra+ ] http/tests/resourceLoadStatistics/partitioned-and-unpartitioned-cookie-deletion.html [ Pass Timeout ]
+[ HighSierra+ ] http/tests/resourceLoadStatistics/non-prevalent-resources-can-access-cookies-in-a-third-party-context.html [ Pass ]
 [ HighSierra+ ] http/tests/resourceLoadStatistics/add-partitioning-to-redirect.html [ Pass ]
-[ HighSierra+ ] http/tests/resourceLoadStatistics/remove-partitioning-from-redirect.html [ Pass ]
+[ HighSierra+ ] http/tests/resourceLoadStatistics/add-blocking-to-redirect.html [ Pass ]
+[ HighSierra+ ] http/tests/resourceLoadStatistics/remove-partitioning-in-redirect.html [ Pass ]
+[ HighSierra+ ] http/tests/resourceLoadStatistics/remove-blocking-in-redirect.html [ Pass ]
 
 # <rdar://problem/33555759>
 webkit.org/b/177616 [ HighSierra+ ] http/tests/media/video-buffered-range-contains-currentTime.html [ Pass Timeout ]
index 83b141d..b19c51d 100644 (file)
@@ -691,12 +691,15 @@ webkit.org/b/180703 http/tests/resourceLoadStatistics/telemetry-generation.html
 http/tests/resourceLoadStatistics/prune-statistics.html [ Pass ]
 http/tests/resourceLoadStatistics [ Pass ]
 # Cookie partitioning is only supported in macOS High Sierra and iOS 11.
-http/tests/resourceLoadStatistics/add-partitioning-to-redirect.html [ Skip ]
-http/tests/resourceLoadStatistics/remove-partitioning-from-redirect.html [ Skip ]
 http/tests/resourceLoadStatistics/partitioned-and-unpartitioned-cookie-deletion.html [ Skip ]
 http/tests/resourceLoadStatistics/partitioned-and-unpartitioned-cookie-with-partitioning-timeout.html [ Skip ]
 http/tests/resourceLoadStatistics/partitioned-cookies-with-and-without-user-interaction.html [ Skip ]
 http/tests/resourceLoadStatistics/third-party-cookie-with-and-without-user-interaction.html [ Skip ]
+http/tests/resourceLoadStatistics/non-prevalent-resources-can-access-cookies-in-a-third-party-context.html [ Skip ]
+http/tests/resourceLoadStatistics/add-partitioning-to-redirect.html [ Skip ]
+http/tests/resourceLoadStatistics/add-blocking-to-redirect.html [ Skip ]
+http/tests/resourceLoadStatistics/remove-partitioning-in-redirect.html [ Skip ]
+http/tests/resourceLoadStatistics/remove-blocking-in-redirect.html [ Skip ]
 
 ### END OF (5) Progressions, expected successes that are expected failures in WebKit1.
 ########################################
index 99da245..82dde7f 100644 (file)
@@ -1,3 +1,22 @@
+2018-01-17  John Wilander  <wilander@apple.com>
+
+        Resource Load Statistics: Block cookies for prevalent resources without user interaction
+        https://bugs.webkit.org/show_bug.cgi?id=177394
+        <rdar://problem/34613960>
+
+        Reviewed by Alex Christensen.
+
+        Tests: http/tests/resourceLoadStatistics/add-blocking-to-redirect.html
+               http/tests/resourceLoadStatistics/non-prevalent-resources-can-access-cookies-in-a-third-party-context.html
+               http/tests/resourceLoadStatistics/remove-blocking-in-redirect.html
+               http/tests/resourceLoadStatistics/remove-partitioning-in-redirect.html
+
+        * platform/network/NetworkStorageSession.h:
+            Now exports NetworkStorageSession::nsCookieStorage().
+        * platform/network/cf/NetworkStorageSessionCFNet.cpp:
+        (WebCore::NetworkStorageSession::setPrevalentDomainsToPartitionOrBlockCookies):
+            Fixes the FIXME.
+
 2018-01-17  Daniel Bates  <dabates@apple.com>
 
         REGRESSION (r222795): Cardiogram never signs in
index e5e5d9e..bc9b763 100644 (file)
@@ -1,3 +1,14 @@
+2018-01-17  John Wilander  <wilander@apple.com>
+
+        Resource Load Statistics: Block cookies for prevalent resources without user interaction
+        https://bugs.webkit.org/show_bug.cgi?id=177394
+        <rdar://problem/34613960>
+
+        Reviewed by Alex Christensen.
+
+        * pal/spi/cf/CFNetworkSPI.h:
+            Declaration of _initWithIdentifier() on NSHTTPCookieStorage.
+
 2018-01-16  Michael Catanzaro  <mcatanzaro@igalia.com>
 
         PAL should link to JavaScriptCore rather than WTF
index 3109e2f..f74c95f 100644 (file)
@@ -179,6 +179,7 @@ typedef void (^CFCachedURLResponseCallBackBlock)(CFCachedURLResponseRef);
 
 @interface NSHTTPCookieStorage ()
 - (void)_getCookiesForURL:(NSURL *)url mainDocumentURL:(NSURL *)mainDocumentURL partition:(NSString *)partition completionHandler:(void (^)(NSArray *))completionHandler;
+- (id)_initWithIdentifier:(NSString *)identifier private:(bool)isPrivate;
 @end
 
 @interface NSURLSessionTask ()
index a6580b5..fd0b6eb 100644 (file)
@@ -74,7 +74,7 @@ public:
     CredentialStorage& credentialStorage() { return m_credentialStorage; }
 
 #ifdef __OBJC__
-    NSHTTPCookieStorage *nsCookieStorage() const;
+    WEBCORE_EXPORT NSHTTPCookieStorage *nsCookieStorage() const;
 #endif
 
     const String& cacheStorageDirectory() const { return m_cacheStorageDirectory; }
index 2880968..7850cdc 100644 (file)
@@ -260,11 +260,9 @@ void NetworkStorageSession::setPrevalentDomainsToPartitionOrBlockCookies(const V
     }
 
     for (auto& domain : domainsToBlock) {
-        // FIXME: https://bugs.webkit.org/show_bug.cgi?id=177394
-        // m_topPrivatelyControlledDomainsToBlock.add(domain);
-        // if (!clearFirst)
-        //     m_topPrivatelyControlledDomainsToPartition.remove(domain);
-        m_topPrivatelyControlledDomainsToPartition.add(domain);
+        m_topPrivatelyControlledDomainsToBlock.add(domain);
+        if (!clearFirst)
+            m_topPrivatelyControlledDomainsToPartition.remove(domain);
     }
     
     if (!clearFirst) {
index 474d35c..0101c9d 100644 (file)
@@ -1,3 +1,32 @@
+2018-01-17  John Wilander  <wilander@apple.com>
+
+        Resource Load Statistics: Block cookies for prevalent resources without user interaction
+        https://bugs.webkit.org/show_bug.cgi?id=177394
+        <rdar://problem/34613960>
+
+        Reviewed by Alex Christensen.
+
+        * NetworkProcess/cocoa/NetworkDataTaskCocoa.h:
+            Now has m_hasBeenSetToUseStatelessCookieStorage to handle
+            cookie blocking.
+        * NetworkProcess/cocoa/NetworkDataTaskCocoa.mm:
+        (WebKit::NetworkDataTaskCocoa::statelessCookieStorage):
+            Returns singleton empty, deny-all cookie storage for cookie blocking.
+        (WebKit::NetworkDataTaskCocoa::applyCookieBlockingPolicy):
+            Instead of just decision making, this now applies the policy.
+        (WebKit::NetworkDataTaskCocoa::applyCookiePartitioningPolicy):
+            New method.
+        (WebKit::NetworkDataTaskCocoa::NetworkDataTaskCocoa):
+            Now blocks cookies for domains where cookies will be purged anyway.
+        (WebKit::NetworkDataTaskCocoa::willPerformHTTPRedirection):
+            Now blocks cookies for domains where cookies will be purged anyway.
+        (WebKit::shouldChangePartition): Deleted.
+        * NetworkProcess/cocoa/NetworkSessionCocoa.mm:
+        (-[WKNetworkSessionDelegate URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:]):
+            Now downgrades for blocked cookies instead of partitioned cookies.
+        (-[WKNetworkSessionDelegate URLSession:task:_schemeUpgraded:completionHandler:]):
+            Now downgrades for blocked cookies instead of partitioned cookies.
+
 2018-01-17  Daniel Bates  <dabates@apple.com>
 
         REGRESSION (r222795): Cardiogram never signs in
index debb6f1..1ebaa60 100644 (file)
@@ -32,6 +32,7 @@
 #include <WebCore/NetworkLoadMetrics.h>
 #include <wtf/RetainPtr.h>
 
+OBJC_CLASS NSHTTPCookieStorage;
 OBJC_CLASS NSURLSessionDataTask;
 
 namespace WebKit {
@@ -78,11 +79,21 @@ private:
     bool tryPasswordBasedAuthentication(const WebCore::AuthenticationChallenge&, ChallengeCompletionHandler&);
     void applySniffingPoliciesAndBindRequestToInferfaceIfNeeded(NSURLRequest*&, bool shouldContentSniff, bool shouldContentEncodingSniff);
 
+#if HAVE(CFNETWORK_STORAGE_PARTITIONING)
+    static NSHTTPCookieStorage *statelessCookieStorage();
+    void applyCookieBlockingPolicy(bool shouldBlock);
+    void applyCookiePartitioningPolicy(const String& requiredStoragePartition, const String& currentStoragePartition);
+#endif
+
     RefPtr<SandboxExtension> m_sandboxExtension;
     RetainPtr<NSURLSessionDataTask> m_task;
     WebCore::NetworkLoadMetrics m_networkLoadMetrics;
     uint64_t m_frameID;
     uint64_t m_pageID;
+
+#if HAVE(CFNETWORK_STORAGE_PARTITIONING)
+    bool m_hasBeenSetToUseStatelessCookieStorage { false };
+#endif
 };
 
 WebCore::Credential serverTrustCredential(const WebCore::AuthenticationChallenge&);
index 6c3b22d..8e27f6a 100644 (file)
@@ -101,6 +101,41 @@ void NetworkDataTaskCocoa::applySniffingPoliciesAndBindRequestToInferfaceIfNeede
     nsRequest = mutableRequest.autorelease();
 }
 
+#if HAVE(CFNETWORK_STORAGE_PARTITIONING)
+NSHTTPCookieStorage *NetworkDataTaskCocoa::statelessCookieStorage()
+{
+    static NeverDestroyed<RetainPtr<NSHTTPCookieStorage>> statelessCookieStorage;
+    if (!statelessCookieStorage.get()) {
+        statelessCookieStorage.get() = adoptNS([[NSHTTPCookieStorage alloc] _initWithIdentifier:nil private:YES]);
+        statelessCookieStorage.get().get().cookieAcceptPolicy = NSHTTPCookieAcceptPolicyNever;
+    }
+    ASSERT(statelessCookieStorage.get().get().cookies.count == 0);
+    return statelessCookieStorage.get().get();
+}
+
+void NetworkDataTaskCocoa::applyCookieBlockingPolicy(bool shouldBlock)
+{
+    if (shouldBlock == m_hasBeenSetToUseStatelessCookieStorage)
+        return;
+
+    NSHTTPCookieStorage *storage = shouldBlock ? statelessCookieStorage(): m_session->networkStorageSession().nsCookieStorage();
+    [m_task performSelector:NSSelectorFromString(@"_setExplicitCookieStorage:") withObject:(NSObject*)storage._cookieStorage];
+    m_hasBeenSetToUseStatelessCookieStorage = shouldBlock;
+}
+
+void NetworkDataTaskCocoa::applyCookiePartitioningPolicy(const String& requiredStoragePartition, const String& currentStoragePartition)
+{
+    // The need for a partion change is according to the following:
+    //      currentStoragePartition:  null  ""    abc
+    // requiredStoragePartition: ""   false false true
+    //                           abc  true  true  false
+    //                           xyz  true  true  true
+    auto shouldChangePartition = !((requiredStoragePartition.isEmpty() && currentStoragePartition.isEmpty()) || currentStoragePartition == requiredStoragePartition);
+    if (shouldChangePartition)
+        m_task.get()._storagePartitionIdentifier = requiredStoragePartition;
+}
+#endif
+
 NetworkDataTaskCocoa::NetworkDataTaskCocoa(NetworkSession& session, NetworkDataTaskClient& client, const WebCore::ResourceRequest& requestWithCredentials, uint64_t frameID, uint64_t pageID, WebCore::StoredCredentialsPolicy storedCredentialsPolicy, WebCore::ContentSniffingPolicy shouldContentSniff, WebCore::ContentEncodingSniffingPolicy shouldContentEncodingSniff, bool shouldClearReferrerOnHTTPSToHTTPRedirect, PreconnectOnly shouldPreconnectOnly)
     : NetworkDataTask(session, client, requestWithCredentials, storedCredentialsPolicy, shouldClearReferrerOnHTTPSToHTTPRedirect)
     , m_frameID(frameID)
@@ -135,11 +170,6 @@ NetworkDataTaskCocoa::NetworkDataTaskCocoa(NetworkSession& session, NetworkDataT
     NSURLRequest *nsRequest = request.nsURLRequest(WebCore::UpdateHTTPBody);
     applySniffingPoliciesAndBindRequestToInferfaceIfNeeded(nsRequest, shouldContentSniff == WebCore::SniffContent && !url.isLocalFile(), shouldContentEncodingSniff == WebCore::ContentEncodingSniffingPolicy::Sniff);
 
-    if (session.networkStorageSession().shouldBlockCookies(request)) {
-        storedCredentialsPolicy = WebCore::StoredCredentialsPolicy::DoNotUse;
-        m_storedCredentialsPolicy = WebCore::StoredCredentialsPolicy::DoNotUse;
-    }
-
     auto& cocoaSession = static_cast<NetworkSessionCocoa&>(m_session.get());
     if (storedCredentialsPolicy == WebCore::StoredCredentialsPolicy::Use) {
         m_task = [cocoaSession.m_sessionWithCredentialStorage dataTaskWithRequest:nsRequest];
@@ -162,11 +192,14 @@ NetworkDataTaskCocoa::NetworkDataTaskCocoa(NetworkSession& session, NetworkDataT
     }
 
 #if HAVE(CFNETWORK_STORAGE_PARTITIONING)
-    if (storedCredentialsPolicy == WebCore::StoredCredentialsPolicy::Use) {
-        String storagePartition = session.networkStorageSession().cookieStoragePartition(request, m_frameID, m_pageID);
+    if (auto shouldBlockCookies = session.networkStorageSession().shouldBlockCookies(request)) {
+        LOG(NetworkSession, "%llu Blocking cookies for URL %s", [m_task taskIdentifier], nsRequest.URL.absoluteString.UTF8String);
+        applyCookieBlockingPolicy(shouldBlockCookies);
+    } else {
+        auto storagePartition = session.networkStorageSession().cookieStoragePartition(request, m_frameID, m_pageID);
         if (!storagePartition.isEmpty()) {
             LOG(NetworkSession, "%llu Partitioning cookies for URL %s", [m_task taskIdentifier], nsRequest.URL.absoluteString.UTF8String);
-            m_task.get()._storagePartitionIdentifier = storagePartition;
+            applyCookiePartitioningPolicy(storagePartition, emptyString());
         }
     }
 #endif
@@ -221,16 +254,6 @@ void NetworkDataTaskCocoa::didReceiveData(Ref<WebCore::SharedBuffer>&& data)
         m_client->didReceiveData(WTFMove(data));
 }
 
-static bool shouldChangePartition(const String& requiredStoragePartition, const String& currentStoragePartition)
-{
-    // The need for a partion change is according to the following:
-    //      currentStoragePartition:  null  ""    abc
-    // requiredStoragePartition: ""   false false true
-    //                           abc  true  true  false
-    //                           xyz  true  true  true
-    return !((requiredStoragePartition.isEmpty() && currentStoragePartition.isEmpty()) || currentStoragePartition == requiredStoragePartition);
-}
-
 void NetworkDataTaskCocoa::willPerformHTTPRedirection(WebCore::ResourceResponse&& redirectResponse, WebCore::ResourceRequest&& request, RedirectCompletionHandler&& completionHandler)
 {
     if (redirectResponse.httpStatusCode() == 307 || redirectResponse.httpStatusCode() == 308) {
@@ -276,12 +299,14 @@ void NetworkDataTaskCocoa::willPerformHTTPRedirection(WebCore::ResourceResponse&
     }
     
 #if HAVE(CFNETWORK_STORAGE_PARTITIONING)
-    if (m_storedCredentialsPolicy == WebCore::StoredCredentialsPolicy::Use) {
-        String requiredStoragePartition = m_session->networkStorageSession().cookieStoragePartition(request, m_frameID, m_pageID);
-        if (shouldChangePartition(requiredStoragePartition, m_task.get()._storagePartitionIdentifier)) {
-            LOG(NetworkSession, "%llu %s cookies for redirected URL %s", [m_task taskIdentifier], (requiredStoragePartition.isEmpty() ? "Not partitioning" : "Partitioning"), request.url().string().utf8().data());
-            m_task.get()._storagePartitionIdentifier = requiredStoragePartition;
-        }
+    auto shouldBlockCookies = m_session->networkStorageSession().shouldBlockCookies(request);
+    LOG(NetworkSession, "%llu %s cookies for redirect URL %s", [m_task taskIdentifier], (shouldBlockCookies ? "Blocking" : "Not blocking"), request.url().string().utf8().data());
+    applyCookieBlockingPolicy(shouldBlockCookies);
+
+    if (!shouldBlockCookies) {
+        auto requiredStoragePartition = m_session->networkStorageSession().cookieStoragePartition(request, m_frameID, m_pageID);
+        LOG(NetworkSession, "%llu %s cookies for redirect URL %s", [m_task taskIdentifier], (requiredStoragePartition.isEmpty() ? "Not partitioning" : "Partitioning"), request.url().string().utf8().data());
+        applyCookiePartitioningPolicy(requiredStoragePartition, m_task.get()._storagePartitionIdentifier);
     }
 #endif
 
index 57ef946..b73582a 100644 (file)
@@ -215,7 +215,7 @@ static NSURLRequest* updateIgnoreStrictTransportSecuritySettingIfNecessary(NSURL
 
         bool shouldIgnoreHSTS = false;
 #if USE(CFNETWORK_IGNORE_HSTS)
-        shouldIgnoreHSTS = schemeWasUpgradedDueToDynamicHSTS(request) && !(WebCore::NetworkStorageSession::storageSession(_session->sessionID())->cookieStoragePartition(request, networkDataTask->frameID(), networkDataTask->pageID())).isEmpty();
+        shouldIgnoreHSTS = schemeWasUpgradedDueToDynamicHSTS(request) && WebCore::NetworkStorageSession::storageSession(_session->sessionID())->shouldBlockCookies(request);
         if (shouldIgnoreHSTS) {
             request = downgradeRequest(request);
             ASSERT([request.URL.scheme isEqualToString:@"http"]);
@@ -248,7 +248,7 @@ static NSURLRequest* updateIgnoreStrictTransportSecuritySettingIfNecessary(NSURL
     if (auto* networkDataTask = [self existingTask:task]) {
         bool shouldIgnoreHSTS = false;
 #if USE(CFNETWORK_IGNORE_HSTS)
-        shouldIgnoreHSTS = schemeWasUpgradedDueToDynamicHSTS(request) && !(WebCore::NetworkStorageSession::storageSession(_session->sessionID())->cookieStoragePartition(request, networkDataTask->frameID(), networkDataTask->pageID())).isEmpty();
+        shouldIgnoreHSTS = schemeWasUpgradedDueToDynamicHSTS(request) && WebCore::NetworkStorageSession::storageSession(_session->sessionID())->shouldBlockCookies(request);
         if (shouldIgnoreHSTS) {
             request = downgradeRequest(request);
             ASSERT([request.URL.scheme isEqualToString:@"http"]);