Title: [251663] trunk
Revision
251663
Author
[email protected]
Date
2019-10-28 12:45:03 -0700 (Mon, 28 Oct 2019)

Log Message

Storage Access API: Make the API work with the experimental 3rd-party cookie blocking
https://bugs.webkit.org/show_bug.cgi?id=203428
<rdar://problem/56626949>

Reviewed by Alex Christensen.

Source/WebKit:

Tests: http/tests/storageAccess/deny-due-to-no-interaction-under-general-third-party-cookie-blocking.html
       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.html
       http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-without-cookie.html

This patch adds Storage Access API support for the experimental 3rd-party cookie blocking that
landed in <https://trac.webkit.org/changeset/251467>.

There are three policies at play because it can be changed with the experimental setting:
1. The underlying cookie policy.
2. Shipping ITP.
3. The off by default, experimental 3rd-party cookie blocking.

To support them all, a CookieAccess enum was added to encode how the API should respond.
The enum has these values:
CannotRequest - This third-party cannot request storage access based on the current policy.
BasedOnCookiePolicy – This third-party should be treated according to the underlying cookie policy.
OnlyIfGranted – This third-party can and must get access through the Storage Access API.

Here's the truth table I used to work through the logic for both
document.hasStorageAccess() and document.requestStorageAccess():

Access  | Is        | User        | Has    | 3rd-party    |        |
granted | prevalent | interaction | cookie | cookie block | RESULT |
-------------------------------------------------------------------
|       |           |             |        |              | false  |
-------------------------------------------------------------------
|       |           |             |        | true         | false  |
-------------------------------------------------------------------
|       |           |             | true   |              | true   |
-------------------------------------------------------------------
|       |           |             | true   | true         | false  |
-------------------------------------------------------------------
|       |           | true        |        |              | false  |
-------------------------------------------------------------------
|       |           | true        |        | true         | false  |
-------------------------------------------------------------------
|       |           | true        | true   |              | true   |
-------------------------------------------------------------------
|       |           | true        | true   | true         | false  |
-------------------------------------------------------------------
|       | true      | !care       | !care  | !care        | false  |
-------------------------------------------------------------------
| true  | !care     | !care       | !care  | !care        | true   |
-------------------------------------------------------------------

* NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp:
(WebKit::ResourceLoadStatisticsDatabaseStore::cookieAccess const):
(WebKit::ResourceLoadStatisticsDatabaseStore::hasStorageAccess):
(WebKit::ResourceLoadStatisticsDatabaseStore::requestStorageAccess):
(WebKit::ResourceLoadStatisticsDatabaseStore::requestStorageAccessUnderOpener):
    Extra checks removed since there's no harm in granting access
    to a third-party that already has access by way of the underlying
    cookie policy. Also, this is a temporary compatibility fix.
* NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h:
* NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.cpp:
(WebKit::ResourceLoadStatisticsMemoryStore::cookieAccess const):
(WebKit::ResourceLoadStatisticsMemoryStore::hasStorageAccess):
(WebKit::ResourceLoadStatisticsMemoryStore::requestStorageAccess):
(WebKit::ResourceLoadStatisticsMemoryStore::requestStorageAccessUnderOpener):
    Extra checks removed since there's no harm in granting access
    to a third-party that already has access by way of the underlying
    cookie policy. Also, this is a temporary compatibility fix.
* NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.h:
* NetworkProcess/Classifier/ResourceLoadStatisticsStore.h:
(WebKit::ResourceLoadStatisticsStore::setIsThirdPartyCookieBlockingEnabled):
(WebKit::ResourceLoadStatisticsStore::isThirdPartyCookieBlockingEnabled const):
* NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::setIsThirdPartyCookieBlockingEnabled):
    This is now the single path to control this setting in both ITP
    and the network storage session. See comment below.
* NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h:
* NetworkProcess/NetworkProcess.cpp:
(WebKit::NetworkProcess::setShouldBlockThirdPartyCookiesForTesting):
* NetworkProcess/NetworkSession.cpp:
(WebKit::NetworkSession::setResourceLoadStatisticsEnabled):
(WebKit::NetworkSession::setIsThirdPartyCookieBlockingEnabled):
    Restructured these so that they are initiated like the rest of the
    parameters and only have a single path for changes so that a
    reset to consistent state resets all the state.
* NetworkProcess/NetworkSession.h:
* NetworkProcess/cocoa/NetworkSessionCocoa.mm:
(WebKit::NetworkSessionCocoa::NetworkSessionCocoa):

Tools:

* WebKitTestRunner/InjectedBundle/TestRunner.cpp:
(WTR::TestRunner::statisticsCallDidSetShouldDowngradeReferrerCallback):
(WTR::TestRunner::statisticsCallDidSetShouldBlockThirdPartyCookiesCallback):
    Both of these were missing resets of their m_hasSet*Callback booleans.

LayoutTests:

* http/tests/storageAccess/deny-due-to-no-interaction-under-general-third-party-cookie-blocking-database-expected.txt: Added.
* http/tests/storageAccess/deny-due-to-no-interaction-under-general-third-party-cookie-blocking-database.html: Added.
* http/tests/storageAccess/deny-due-to-no-interaction-under-general-third-party-cookie-blocking-expected.txt: Added.
* http/tests/storageAccess/deny-due-to-no-interaction-under-general-third-party-cookie-blocking.html: Added.
* http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking-database-expected.txt: Added.
* http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking-database.html: Added.
* http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking-expected.txt: Added.
* http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking.html: Added.
* http/tests/storageAccess/has-storage-access-true-if-third-party-has-cookies.html:
* http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie-database-expected.txt: Added.
* http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie-database.html: Added.
* http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie-expected.txt: Added.
* http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie.html: Added.
* http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-without-cookie-database-expected.txt: Added.
* http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-without-cookie-database.html: Added.
* http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-without-cookie-expected.txt: Added.
* http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-without-cookie.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (251662 => 251663)


--- trunk/LayoutTests/ChangeLog	2019-10-28 18:56:19 UTC (rev 251662)
+++ trunk/LayoutTests/ChangeLog	2019-10-28 19:45:03 UTC (rev 251663)
@@ -1,3 +1,29 @@
+2019-10-28  John Wilander  <[email protected]>
+
+        Storage Access API: Make the API work with the experimental 3rd-party cookie blocking
+        https://bugs.webkit.org/show_bug.cgi?id=203428
+        <rdar://problem/56626949>
+
+        Reviewed by Alex Christensen.
+
+        * http/tests/storageAccess/deny-due-to-no-interaction-under-general-third-party-cookie-blocking-database-expected.txt: Added.
+        * http/tests/storageAccess/deny-due-to-no-interaction-under-general-third-party-cookie-blocking-database.html: Added.
+        * http/tests/storageAccess/deny-due-to-no-interaction-under-general-third-party-cookie-blocking-expected.txt: Added.
+        * http/tests/storageAccess/deny-due-to-no-interaction-under-general-third-party-cookie-blocking.html: Added.
+        * http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking-database-expected.txt: Added.
+        * http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking-database.html: Added.
+        * http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking-expected.txt: Added.
+        * http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking.html: Added.
+        * http/tests/storageAccess/has-storage-access-true-if-third-party-has-cookies.html:
+        * http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie-database-expected.txt: Added.
+        * http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie-database.html: Added.
+        * http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie-expected.txt: Added.
+        * http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie.html: Added.
+        * http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-without-cookie-database-expected.txt: Added.
+        * http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-without-cookie-database.html: Added.
+        * http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-without-cookie-expected.txt: Added.
+        * http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-without-cookie.html: Added.
+
 2019-10-28  Alex Christensen  <[email protected]>
 
         Remove flaky debug log from WK1 expectations after r251582

Added: trunk/LayoutTests/http/tests/storageAccess/deny-due-to-no-interaction-under-general-third-party-cookie-blocking-database-expected.txt (0 => 251663)


--- trunk/LayoutTests/http/tests/storageAccess/deny-due-to-no-interaction-under-general-third-party-cookie-blocking-database-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/storageAccess/deny-due-to-no-interaction-under-general-third-party-cookie-blocking-database-expected.txt	2019-10-28 19:45:03 UTC (rev 251663)
@@ -0,0 +1,10 @@
+Tests that a cross-site iframe can not request storage access under general third-party cookie blocking if it has not received user interaction as first-party.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Storage access was denied. document.cookie == , cookies seen server-side == "No cookies"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/http/tests/storageAccess/deny-due-to-no-interaction-under-general-third-party-cookie-blocking-database.html (0 => 251663)


--- trunk/LayoutTests/http/tests/storageAccess/deny-due-to-no-interaction-under-general-third-party-cookie-blocking-database.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/storageAccess/deny-due-to-no-interaction-under-general-third-party-cookie-blocking-database.html	2019-10-28 19:45:03 UTC (rev 251663)
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src=""
+    <script src=""
+    <script src=""
+    <script>
+        description("Tests that a cross-site iframe can not request storage access under general third-party cookie blocking if it has not received user interaction as first-party.");
+        jsTestIsAsync = true;
+        testRunner.setUseITPDatabase(true);
+
+        const firstPartyUrl = "http://127.0.0.1:8000";
+        const thirdPartyUrl = "http://localhost:8000";
+
+        function receiveMessage(event) {
+            if (event.origin === "http://localhost:8000") {
+                if (event.data.indexOf("PASS ") !== -1)
+                    testPassed(event.data.replace("PASS ", ""));
+                else
+                    testFailed(event.data.replace("FAIL ", ""));
+            } else
+                testFailed("Received a message from an unexpected origin: " + event.origin);
+            testRunner.setStatisticsShouldBlockThirdPartyCookies(false, function() {
+                setEnableFeature(false, finishJSTest);
+            });
+        }
+
+        window.addEventListener("message", receiveMessage, false);
+
+        function activateElement(elementId) {
+            var element = document.getElementById(elementId);
+            var centerX = element.offsetLeft + element.offsetWidth / 2;
+            var centerY = element.offsetTop + element.offsetHeight / 2;
+            UIHelper.activateAt(centerX, centerY).then(
+                function () {
+                    if (window.eventSender)
+                        eventSender.keyDown("escape");
+                    else {
+                        testFailed("No eventSender.");
+                        testRunner.setStatisticsShouldBlockThirdPartyCookies(false, function() {
+                            setEnableFeature(false, finishJSTest);
+                        });
+                    }
+                },
+                function () {
+                    testFailed("Promise rejected.");
+                    testRunner.setStatisticsShouldBlockThirdPartyCookies(false, function() {
+                        setEnableFeature(false, finishJSTest);
+                    });
+                }
+            );
+        }
+
+        function runTest() {
+            if (document.location.hash !== "#cookieSet") {
+                setEnableFeature(true, function() {
+                    document.location.href = "" + "/storageAccess/resources/set-cookie.php?name=firstPartyCookie&value=value#" + firstPartyUrl + "/storageAccess/deny-due-to-no-interaction-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.");
+                        let iframeElement = document.createElement("iframe");
+                        iframeElement._onload_ = function() {
+                            activateElement("TheIframeThatRequestsStorageAccess");
+                        };
+                        iframeElement.id = "TheIframeThatRequestsStorageAccess";
+                        iframeElement.src = ""
+                        document.body.appendChild(iframeElement);
+                    });
+                });
+            }
+        }
+    </script>
+</head>
+<body _onload_="runTest()">
+</body>
+</html>
\ No newline at end of file

Added: trunk/LayoutTests/http/tests/storageAccess/deny-due-to-no-interaction-under-general-third-party-cookie-blocking-expected.txt (0 => 251663)


--- trunk/LayoutTests/http/tests/storageAccess/deny-due-to-no-interaction-under-general-third-party-cookie-blocking-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/storageAccess/deny-due-to-no-interaction-under-general-third-party-cookie-blocking-expected.txt	2019-10-28 19:45:03 UTC (rev 251663)
@@ -0,0 +1,10 @@
+Tests that a cross-site iframe can not request storage access under general third-party cookie blocking if it has not received user interaction as first-party.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Storage access was denied. document.cookie == , cookies seen server-side == "No cookies"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/http/tests/storageAccess/deny-due-to-no-interaction-under-general-third-party-cookie-blocking.html (0 => 251663)


--- trunk/LayoutTests/http/tests/storageAccess/deny-due-to-no-interaction-under-general-third-party-cookie-blocking.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/storageAccess/deny-due-to-no-interaction-under-general-third-party-cookie-blocking.html	2019-10-28 19:45:03 UTC (rev 251663)
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src=""
+    <script src=""
+    <script src=""
+    <script>
+        description("Tests that a cross-site iframe can not request storage access under general third-party cookie blocking if it has not received user interaction as first-party.");
+        jsTestIsAsync = true;
+
+        const firstPartyUrl = "http://127.0.0.1:8000";
+        const thirdPartyUrl = "http://localhost:8000";
+
+        function receiveMessage(event) {
+            if (event.origin === "http://localhost:8000") {
+                if (event.data.indexOf("PASS ") !== -1)
+                    testPassed(event.data.replace("PASS ", ""));
+                else
+                    testFailed(event.data.replace("FAIL ", ""));
+            } else
+                testFailed("Received a message from an unexpected origin: " + event.origin);
+            testRunner.setStatisticsShouldBlockThirdPartyCookies(false, function() {
+                setEnableFeature(false, finishJSTest);
+            });
+        }
+
+        window.addEventListener("message", receiveMessage, false);
+
+        function activateElement(elementId) {
+            var element = document.getElementById(elementId);
+            var centerX = element.offsetLeft + element.offsetWidth / 2;
+            var centerY = element.offsetTop + element.offsetHeight / 2;
+            UIHelper.activateAt(centerX, centerY).then(
+                function () {
+                    if (window.eventSender)
+                        eventSender.keyDown("escape");
+                    else {
+                        testFailed("No eventSender.");
+                        testRunner.setStatisticsShouldBlockThirdPartyCookies(false, function() {
+                            setEnableFeature(false, finishJSTest);
+                        });
+                    }
+                },
+                function () {
+                    testFailed("Promise rejected.");
+                    testRunner.setStatisticsShouldBlockThirdPartyCookies(false, function() {
+                        setEnableFeature(false, finishJSTest);
+                    });
+                }
+            );
+        }
+
+        function runTest() {
+            if (document.location.hash !== "#cookieSet") {
+                setEnableFeature(true, function() {
+                    document.location.href = "" + "/storageAccess/resources/set-cookie.php?name=firstPartyCookie&value=value#" + firstPartyUrl + "/storageAccess/deny-due-to-no-interaction-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.");
+                        let iframeElement = document.createElement("iframe");
+                        iframeElement._onload_ = function() {
+                            activateElement("TheIframeThatRequestsStorageAccess");
+                        };
+                        iframeElement.id = "TheIframeThatRequestsStorageAccess";
+                        iframeElement.src = ""
+                        document.body.appendChild(iframeElement);
+                    });
+                });
+            }
+        }
+    </script>
+</head>
+<body _onload_="runTest()">
+</body>
+</html>
\ No newline at end of file

Added: trunk/LayoutTests/http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking-database-expected.txt (0 => 251663)


--- trunk/LayoutTests/http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking-database-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking-database-expected.txt	2019-10-28 19:45:03 UTC (rev 251663)
@@ -0,0 +1,10 @@
+Tests that a cross-site iframe can request and be granted storage access under general third-party cookie blocking.
+
+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 successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking-database.html (0 => 251663)


--- trunk/LayoutTests/http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking-database.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking-database.html	2019-10-28 19:45:03 UTC (rev 251663)
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src=""
+    <script src=""
+    <script src=""
+    <script>
+        description("Tests that a cross-site iframe can request and be granted storage access under general third-party cookie blocking.");
+        jsTestIsAsync = true;
+        testRunner.setUseITPDatabase(true);
+
+        const firstPartyUrl = "http://127.0.0.1:8000";
+        const thirdPartyUrl = "http://localhost:8000";
+
+        function receiveMessage(event) {
+            if (event.origin === "http://localhost:8000") {
+                if (event.data.indexOf("PASS ") !== -1)
+                    testPassed(event.data.replace("PASS ", ""));
+                else
+                    testFailed(event.data.replace("FAIL ", ""));
+            } else
+                testFailed("Received a message from an unexpected origin: " + event.origin);
+            testRunner.setStatisticsShouldBlockThirdPartyCookies(false, function() {
+                setEnableFeature(false, finishJSTest);
+            });
+        }
+
+        window.addEventListener("message", receiveMessage, false);
+
+        function activateElement(elementId) {
+            var element = document.getElementById(elementId);
+            var centerX = element.offsetLeft + element.offsetWidth / 2;
+            var centerY = element.offsetTop + element.offsetHeight / 2;
+            UIHelper.activateAt(centerX, centerY).then(
+                function () {
+                    if (window.eventSender)
+                        eventSender.keyDown("escape");
+                    else {
+                        testFailed("No eventSender.");
+                        testRunner.setStatisticsShouldBlockThirdPartyCookies(false, function() {
+                            setEnableFeature(false, finishJSTest);
+                        });
+                    }
+                },
+                function () {
+                    testFailed("Promise rejected.");
+                    testRunner.setStatisticsShouldBlockThirdPartyCookies(false, function() {
+                        setEnableFeature(false, finishJSTest);
+                    });
+                }
+            );
+        }
+
+        function runTest() {
+            if (document.location.hash !== "#cookieSet") {
+                setEnableFeature(true, function() {
+                    document.location.href = "" + "/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.");
+                        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");
+                            };
+                            iframeElement.id = "TheIframeThatRequestsStorageAccess";
+                            iframeElement.src = ""
+                            document.body.appendChild(iframeElement);
+                        });
+                    });
+                });
+            }
+        }
+    </script>
+</head>
+<body _onload_="runTest()">
+</body>
+</html>
\ No newline at end of file

Added: trunk/LayoutTests/http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking-expected.txt (0 => 251663)


--- trunk/LayoutTests/http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking-expected.txt	2019-10-28 19:45:03 UTC (rev 251663)
@@ -0,0 +1,10 @@
+Tests that a cross-site iframe can request and be granted storage access under general third-party cookie blocking.
+
+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 successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking.html (0 => 251663)


--- trunk/LayoutTests/http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/storageAccess/grant-with-prompt-under-general-third-party-cookie-blocking.html	2019-10-28 19:45:03 UTC (rev 251663)
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src=""
+    <script src=""
+    <script src=""
+    <script>
+        description("Tests that a cross-site iframe can request and be granted storage access under general third-party cookie blocking.");
+        jsTestIsAsync = true;
+
+        const firstPartyUrl = "http://127.0.0.1:8000";
+        const thirdPartyUrl = "http://localhost:8000";
+
+        function receiveMessage(event) {
+            if (event.origin === "http://localhost:8000") {
+                if (event.data.indexOf("PASS ") !== -1)
+                    testPassed(event.data.replace("PASS ", ""));
+                else
+                    testFailed(event.data.replace("FAIL ", ""));
+            } else
+                testFailed("Received a message from an unexpected origin: " + event.origin);
+            testRunner.setStatisticsShouldBlockThirdPartyCookies(false, function() {
+                setEnableFeature(false, finishJSTest);
+            });
+        }
+
+        window.addEventListener("message", receiveMessage, false);
+
+        function activateElement(elementId) {
+            var element = document.getElementById(elementId);
+            var centerX = element.offsetLeft + element.offsetWidth / 2;
+            var centerY = element.offsetTop + element.offsetHeight / 2;
+            UIHelper.activateAt(centerX, centerY).then(
+                function () {
+                    if (window.eventSender)
+                        eventSender.keyDown("escape");
+                    else {
+                        testFailed("No eventSender.");
+                        testRunner.setStatisticsShouldBlockThirdPartyCookies(false, function() {
+                            setEnableFeature(false, finishJSTest);
+                        });
+                    }
+                },
+                function () {
+                    testFailed("Promise rejected.");
+                    testRunner.setStatisticsShouldBlockThirdPartyCookies(false, function() {
+                        setEnableFeature(false, finishJSTest);
+                    });
+                }
+            );
+        }
+
+        function runTest() {
+            if (document.location.hash !== "#cookieSet") {
+                setEnableFeature(true, function() {
+                    document.location.href = "" + "/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.");
+                        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");
+                            };
+                            iframeElement.id = "TheIframeThatRequestsStorageAccess";
+                            iframeElement.src = ""
+                            document.body.appendChild(iframeElement);
+                        });
+                    });
+                });
+            }
+        }
+    </script>
+</head>
+<body _onload_="runTest()">
+</body>
+</html>
\ No newline at end of file

Modified: trunk/LayoutTests/http/tests/storageAccess/has-storage-access-true-if-third-party-has-cookies.html (251662 => 251663)


--- trunk/LayoutTests/http/tests/storageAccess/has-storage-access-true-if-third-party-has-cookies.html	2019-10-28 18:56:19 UTC (rev 251662)
+++ trunk/LayoutTests/http/tests/storageAccess/has-storage-access-true-if-third-party-has-cookies.html	2019-10-28 19:45:03 UTC (rev 251663)
@@ -1,4 +1,3 @@
-<!-- webkit-test-runner [ useEphemeralSession=true ] -->
 <!DOCTYPE html>
 <html>
 <head>
@@ -25,7 +24,7 @@
         const statisticsUrl = "http://" + hostUnderTest;
         function runTest() {
             if (document.location.hash !== "#firstPartyCookieSet") {
-                setEnableFeature(false, function() {
+                setEnableFeature(true, function() {
                     document.location.href = "" + "/storageAccess/resources/set-cookie.php?name=firstPartyCookie&value=value#http://127.0.0.1:8000/storageAccess/has-storage-access-true-if-third-party-has-cookies.html#firstPartyCookieSet";
                 });
             } else {

Added: trunk/LayoutTests/http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie-database-expected.txt (0 => 251663)


--- trunk/LayoutTests/http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie-database-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie-database-expected.txt	2019-10-28 19:45:03 UTC (rev 251663)
@@ -0,0 +1,14 @@
+Tests document.hasStorageAccess() for a 3rd-party with cookies under general third-party cookie blocking.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Has storage access. document.cookie == firstPartyCookie=value, cookies seen server-side == {"firstPartyCookie":"value"}
+PASS Has storage access. document.cookie == firstPartyCookie=value, cookies seen server-side == {"firstPartyCookie":"value"}
+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 successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie-database.html (0 => 251663)


--- trunk/LayoutTests/http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie-database.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie-database.html	2019-10-28 19:45:03 UTC (rev 251663)
@@ -0,0 +1,106 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src=""
+    <script src=""
+    <script>
+        description("Tests document.hasStorageAccess() for a 3rd-party with cookies under general third-party cookie blocking.");
+        jsTestIsAsync = true;
+        testRunner.setUseITPDatabase(true);
+
+        const firstPartyUrl = "http://127.0.0.1:8000";
+        const thirdPartyUrl = "http://localhost:8000";
+
+        window.addEventListener("message", receiveMessage, false);
+
+        function receiveMessage(event) {
+            if (event.origin === thirdPartyUrl) {
+                if (event.data.indexOf("PASS") !== -1)
+                    testPassed(event.data.replace("PASS ", ""));
+                else
+                    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);
+                });
+            } else
+                runTests();
+        }
+
+        function runTests() {
+            switch (document.location.hash) {
+                case "":
+                    setEnableFeature(true, function () {
+                        if (testRunner.isStatisticsPrevalentResource(thirdPartyUrl))
+                            testFailed("Third-party started out as prevalent resource.");
+                        if (testRunner.isStatisticsHasHadUserInteraction(thirdPartyUrl))
+                            testFailed("Third-party started out logged for user interaction.");
+                        if (testRunner.isStatisticsHasHadUserInteraction(firstPartyUrl))
+                            testFailed("First-party started out logged for user interaction.");
+                        document.location.hash = "step1";
+
+                        // Set a cookie for the third-party and continue.
+                        document.location.href = "" + "/storageAccess/resources/set-cookie.php?name=firstPartyCookie&value=value#" + firstPartyUrl + "/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie.html#step1";
+                    });
+                    break;
+
+                case "#step1":
+                    document.location.hash = "step2";
+                    // No general third-party cookie blocking, no user interaction, not prevalent.
+                    let iframeElement = document.createElement("iframe");
+                    iframeElement.src = "" + "/storageAccess/resources/has-storage-access-iframe.html#policyShouldGrantAccess";
+                    document.body.appendChild(iframeElement);
+                    break;
+                case "#step2":
+                    document.location.hash = "step3";
+                    // No general third-party cookie blocking, third-party user interaction, not prevalent.
+                    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.src = "" + "/storageAccess/resources/has-storage-access-iframe.html#policyShouldGrantAccess";
+                        document.body.appendChild(iframeElement);
+                    });
+                    break;
+                case "#step3":
+                    document.location.hash = "step4";
+                    // No general third-party cookie blocking, first- and third-party user interaction, not prevalent.
+                    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 = "" + "/storageAccess/resources/has-storage-access-iframe.html#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.
+                    testRunner.setStatisticsShouldBlockThirdPartyCookies(true, function() {
+                        let iframeElement = document.createElement("iframe");
+                        iframeElement.src = "" + "/storageAccess/resources/has-storage-access-iframe.html#policyShouldNotGrantAccess";
+                        document.body.appendChild(iframeElement);
+                    });
+                    break;
+                case "#step5":
+                    document.location.hash = "lastStep";
+                    // General third-party cookie blocking, first- and third-party user interaction, prevalent.
+                    testRunner.setStatisticsPrevalentResource(thirdPartyUrl, true, function() {
+                        if (!testRunner.isStatisticsPrevalentResource(thirdPartyUrl))
+                            testFailed("Third-party not set as prevalent resource.");
+                        testRunner.statisticsUpdateCookieBlocking(function() {
+                            let iframeElement = document.createElement("iframe");
+                            iframeElement.src = "" + "/storageAccess/resources/has-storage-access-iframe.html#policyShouldNotGrantAccess";
+                            document.body.appendChild(iframeElement);
+                        });
+                    });
+                    break;
+            }
+        }
+    </script>
+</head>
+<body _onload_="runTests()">
+</body>
+</html>
\ No newline at end of file

Added: trunk/LayoutTests/http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie-expected.txt (0 => 251663)


--- trunk/LayoutTests/http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie-expected.txt	2019-10-28 19:45:03 UTC (rev 251663)
@@ -0,0 +1,14 @@
+Tests document.hasStorageAccess() for a 3rd-party with cookies under general third-party cookie blocking.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Has storage access. document.cookie == firstPartyCookie=value, cookies seen server-side == {"firstPartyCookie":"value"}
+PASS Has storage access. document.cookie == firstPartyCookie=value, cookies seen server-side == {"firstPartyCookie":"value"}
+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 successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie.html (0 => 251663)


--- trunk/LayoutTests/http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie.html	2019-10-28 19:45:03 UTC (rev 251663)
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src=""
+    <script src=""
+    <script>
+        description("Tests document.hasStorageAccess() for a 3rd-party with cookies under general third-party cookie blocking.");
+        jsTestIsAsync = true;
+
+        const firstPartyUrl = "http://127.0.0.1:8000";
+        const thirdPartyUrl = "http://localhost:8000";
+
+        window.addEventListener("message", receiveMessage, false);
+
+        function receiveMessage(event) {
+            if (event.origin === thirdPartyUrl) {
+                if (event.data.indexOf("PASS") !== -1)
+                    testPassed(event.data.replace("PASS ", ""));
+                else
+                    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);
+                });
+            } else
+                runTests();
+        }
+
+        function runTests() {
+            switch (document.location.hash) {
+                case "":
+                    setEnableFeature(true, function () {
+                        if (testRunner.isStatisticsPrevalentResource(thirdPartyUrl))
+                            testFailed("Third-party started out as prevalent resource.");
+                        if (testRunner.isStatisticsHasHadUserInteraction(thirdPartyUrl))
+                            testFailed("Third-party started out logged for user interaction.");
+                        if (testRunner.isStatisticsHasHadUserInteraction(firstPartyUrl))
+                            testFailed("First-party started out logged for user interaction.");
+                        document.location.hash = "step1";
+
+                        // Set a cookie for the third-party and continue.
+                        document.location.href = "" + "/storageAccess/resources/set-cookie.php?name=firstPartyCookie&value=value#" + firstPartyUrl + "/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-with-cookie.html#step1";
+                    });
+                    break;
+
+                case "#step1":
+                    document.location.hash = "step2";
+                    // No general third-party cookie blocking, no user interaction, not prevalent.
+                    let iframeElement = document.createElement("iframe");
+                    iframeElement.src = "" + "/storageAccess/resources/has-storage-access-iframe.html#policyShouldGrantAccess";
+                    document.body.appendChild(iframeElement);
+                    break;
+                case "#step2":
+                    document.location.hash = "step3";
+                    // No general third-party cookie blocking, third-party user interaction, not prevalent.
+                    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.src = "" + "/storageAccess/resources/has-storage-access-iframe.html#policyShouldGrantAccess";
+                        document.body.appendChild(iframeElement);
+                    });
+                    break;
+                case "#step3":
+                    document.location.hash = "step4";
+                    // No general third-party cookie blocking, first- and third-party user interaction, not prevalent.
+                    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 = "" + "/storageAccess/resources/has-storage-access-iframe.html#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.
+                    testRunner.setStatisticsShouldBlockThirdPartyCookies(true, function() {
+                        let iframeElement = document.createElement("iframe");
+                        iframeElement.src = "" + "/storageAccess/resources/has-storage-access-iframe.html#policyShouldNotGrantAccess";
+                        document.body.appendChild(iframeElement);
+                    });
+                    break;
+                case "#step5":
+                    document.location.hash = "lastStep";
+                    // General third-party cookie blocking, first- and third-party user interaction, prevalent.
+                    testRunner.setStatisticsPrevalentResource(thirdPartyUrl, true, function() {
+                        if (!testRunner.isStatisticsPrevalentResource(thirdPartyUrl))
+                            testFailed("Third-party not set as prevalent resource.");
+                        testRunner.statisticsUpdateCookieBlocking(function() {
+                            let iframeElement = document.createElement("iframe");
+                            iframeElement.src = "" + "/storageAccess/resources/has-storage-access-iframe.html#policyShouldNotGrantAccess";
+                            document.body.appendChild(iframeElement);
+                        });
+                    });
+                    break;
+            }
+        }
+    </script>
+</head>
+<body _onload_="runTests()">
+</body>
+</html>
\ No newline at end of file

Added: trunk/LayoutTests/http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-without-cookie-database-expected.txt (0 => 251663)


--- trunk/LayoutTests/http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-without-cookie-database-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-without-cookie-database-expected.txt	2019-10-28 19:45:03 UTC (rev 251663)
@@ -0,0 +1,14 @@
+Tests document.hasStorageAccess() for a 3rd-party without cookies under general third-party cookie blocking.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+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 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
+

Added: trunk/LayoutTests/http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-without-cookie-database.html (0 => 251663)


--- trunk/LayoutTests/http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-without-cookie-database.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-without-cookie-database.html	2019-10-28 19:45:03 UTC (rev 251663)
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src=""
+    <script src=""
+    <script>
+        description("Tests document.hasStorageAccess() for a 3rd-party without cookies under general third-party cookie blocking.");
+        jsTestIsAsync = true;
+        testRunner.setUseITPDatabase(true);
+
+        const firstPartyUrl = "http://127.0.0.1:8000";
+        const thirdPartyUrl = "http://localhost:8000";
+
+        window.addEventListener("message", receiveMessage, false);
+
+        function receiveMessage(event) {
+            if (event.origin === thirdPartyUrl) {
+                if (event.data.indexOf("PASS") !== -1)
+                    testPassed(event.data.replace("PASS ", ""));
+                else
+                    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);
+                });
+            } else
+                runTests();
+        }
+
+        function runTests() {
+            switch (document.location.hash) {
+                case "":
+                    setEnableFeature(true, function () {
+                        if (testRunner.isStatisticsPrevalentResource(thirdPartyUrl))
+                            testFailed("Third-party started out as prevalent resource.");
+                        if (testRunner.isStatisticsHasHadUserInteraction(thirdPartyUrl))
+                            testFailed("Third-party started out logged for user interaction.");
+                        if (testRunner.isStatisticsHasHadUserInteraction(firstPartyUrl))
+                            testFailed("First-party started out logged for user interaction.");
+                        document.location.hash = "step1";
+                        runTests();
+                    });
+                    break;
+
+                case "#step1":
+                    document.location.hash = "step2";
+                    // No general third-party cookie blocking, no user interaction, not prevalent.
+                    let iframeElement = document.createElement("iframe");
+                    iframeElement.src = "" + "/storageAccess/resources/has-storage-access-iframe.html#policyShouldNotGrantAccess";
+                    document.body.appendChild(iframeElement);
+                    break;
+                case "#step2":
+                    document.location.hash = "step3";
+                    // No general third-party cookie blocking, third-party user interaction, not prevalent.
+                    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.src = "" + "/storageAccess/resources/has-storage-access-iframe.html#policyShouldNotGrantAccess";
+                        document.body.appendChild(iframeElement);
+                    });
+                    break;
+                case "#step3":
+                    document.location.hash = "step4";
+                    // No general third-party cookie blocking, first- and third-party user interaction, not prevalent.
+                    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 = "" + "/storageAccess/resources/has-storage-access-iframe.html#policyShouldNotGrantAccess";
+                        document.body.appendChild(iframeElement);
+                    });
+                    break;
+                case "#step4":
+                    document.location.hash = "step5";
+                    // General third-party cookie blocking, first- and third-party user interaction, not prevalent.
+                    testRunner.setStatisticsShouldBlockThirdPartyCookies(true, function() {
+                        let iframeElement = document.createElement("iframe");
+                        iframeElement.src = "" + "/storageAccess/resources/has-storage-access-iframe.html#policyShouldNotGrantAccess";
+                        document.body.appendChild(iframeElement);
+                    });
+                    break;
+                case "#step5":
+                    document.location.hash = "lastStep";
+                    // General third-party cookie blocking, first- and third-party user interaction, prevalent.
+                    testRunner.setStatisticsPrevalentResource(thirdPartyUrl, true, function() {
+                        if (!testRunner.isStatisticsPrevalentResource(thirdPartyUrl))
+                            testFailed("Third-party not set as prevalent resource.");
+                        testRunner.statisticsUpdateCookieBlocking(function() {
+                            let iframeElement = document.createElement("iframe");
+                            iframeElement.src = "" + "/storageAccess/resources/has-storage-access-iframe.html#policyShouldNotGrantAccess";
+                            document.body.appendChild(iframeElement);
+                        });
+                    });
+                    break;
+            }
+        }
+    </script>
+</head>
+<body _onload_="runTests()">
+</body>
+</html>
\ No newline at end of file

Added: trunk/LayoutTests/http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-without-cookie-expected.txt (0 => 251663)


--- trunk/LayoutTests/http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-without-cookie-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-without-cookie-expected.txt	2019-10-28 19:45:03 UTC (rev 251663)
@@ -0,0 +1,14 @@
+Tests document.hasStorageAccess() for a 3rd-party without cookies under general third-party cookie blocking.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+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 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
+

Added: trunk/LayoutTests/http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-without-cookie.html (0 => 251663)


--- trunk/LayoutTests/http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-without-cookie.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-without-cookie.html	2019-10-28 19:45:03 UTC (rev 251663)
@@ -0,0 +1,103 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src=""
+    <script src=""
+    <script>
+        description("Tests document.hasStorageAccess() for a 3rd-party without cookies under general third-party cookie blocking.");
+        jsTestIsAsync = true;
+
+        const firstPartyUrl = "http://127.0.0.1:8000";
+        const thirdPartyUrl = "http://localhost:8000";
+
+        window.addEventListener("message", receiveMessage, false);
+
+        function receiveMessage(event) {
+            if (event.origin === thirdPartyUrl) {
+                if (event.data.indexOf("PASS") !== -1)
+                    testPassed(event.data.replace("PASS ", ""));
+                else
+                    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);
+                });
+            } else
+                runTests();
+        }
+
+        function runTests() {
+            switch (document.location.hash) {
+                case "":
+                    setEnableFeature(true, function () {
+                        if (testRunner.isStatisticsPrevalentResource(thirdPartyUrl))
+                            testFailed("Third-party started out as prevalent resource.");
+                        if (testRunner.isStatisticsHasHadUserInteraction(thirdPartyUrl))
+                            testFailed("Third-party started out logged for user interaction.");
+                        if (testRunner.isStatisticsHasHadUserInteraction(firstPartyUrl))
+                            testFailed("First-party started out logged for user interaction.");
+                        document.location.hash = "step1";
+                        runTests();
+                    });
+                    break;
+
+                case "#step1":
+                    document.location.hash = "step2";
+                    // No general third-party cookie blocking, no user interaction, not prevalent.
+                    let iframeElement = document.createElement("iframe");
+                    iframeElement.src = "" + "/storageAccess/resources/has-storage-access-iframe.html#policyShouldNotGrantAccess";
+                    document.body.appendChild(iframeElement);
+                    break;
+                case "#step2":
+                    document.location.hash = "step3";
+                    // No general third-party cookie blocking, third-party user interaction, not prevalent.
+                    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.src = "" + "/storageAccess/resources/has-storage-access-iframe.html#policyShouldNotGrantAccess";
+                        document.body.appendChild(iframeElement);
+                    });
+                    break;
+                case "#step3":
+                    document.location.hash = "step4";
+                    // No general third-party cookie blocking, first- and third-party user interaction, not prevalent.
+                    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 = "" + "/storageAccess/resources/has-storage-access-iframe.html#policyShouldNotGrantAccess";
+                        document.body.appendChild(iframeElement);
+                    });
+                    break;
+                case "#step4":
+                    document.location.hash = "step5";
+                    // General third-party cookie blocking, first- and third-party user interaction, not prevalent.
+                    testRunner.setStatisticsShouldBlockThirdPartyCookies(true, function() {
+                        let iframeElement = document.createElement("iframe");
+                        iframeElement.src = "" + "/storageAccess/resources/has-storage-access-iframe.html#policyShouldNotGrantAccess";
+                        document.body.appendChild(iframeElement);
+                    });
+                    break;
+                case "#step5":
+                    document.location.hash = "lastStep";
+                    // General third-party cookie blocking, first- and third-party user interaction, prevalent.
+                    testRunner.setStatisticsPrevalentResource(thirdPartyUrl, true, function() {
+                        if (!testRunner.isStatisticsPrevalentResource(thirdPartyUrl))
+                            testFailed("Third-party not set as prevalent resource.");
+                        testRunner.statisticsUpdateCookieBlocking(function() {
+                            let iframeElement = document.createElement("iframe");
+                            iframeElement.src = "" + "/storageAccess/resources/has-storage-access-iframe.html#policyShouldNotGrantAccess";
+                            document.body.appendChild(iframeElement);
+                        });
+                    });
+                    break;
+            }
+        }
+    </script>
+</head>
+<body _onload_="runTests()">
+</body>
+</html>
\ No newline at end of file

Modified: trunk/Source/WebKit/ChangeLog (251662 => 251663)


--- trunk/Source/WebKit/ChangeLog	2019-10-28 18:56:19 UTC (rev 251662)
+++ trunk/Source/WebKit/ChangeLog	2019-10-28 19:45:03 UTC (rev 251663)
@@ -1,3 +1,95 @@
+2019-10-28  John Wilander  <[email protected]>
+
+        Storage Access API: Make the API work with the experimental 3rd-party cookie blocking
+        https://bugs.webkit.org/show_bug.cgi?id=203428
+        <rdar://problem/56626949>
+
+        Reviewed by Alex Christensen.
+
+        Tests: http/tests/storageAccess/deny-due-to-no-interaction-under-general-third-party-cookie-blocking.html
+               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.html
+               http/tests/storageAccess/has-storage-access-under-general-third-party-cookie-blocking-without-cookie.html
+
+        This patch adds Storage Access API support for the experimental 3rd-party cookie blocking that
+        landed in <https://trac.webkit.org/changeset/251467>.
+
+        There are three policies at play because it can be changed with the experimental setting:
+        1. The underlying cookie policy.
+        2. Shipping ITP.
+        3. The off by default, experimental 3rd-party cookie blocking.
+
+        To support them all, a CookieAccess enum was added to encode how the API should respond.
+        The enum has these values:
+        CannotRequest - This third-party cannot request storage access based on the current policy.
+        BasedOnCookiePolicy – This third-party should be treated according to the underlying cookie policy.
+        OnlyIfGranted – This third-party can and must get access through the Storage Access API.
+
+        Here's the truth table I used to work through the logic for both
+        document.hasStorageAccess() and document.requestStorageAccess():
+
+        Access  | Is        | User        | Has    | 3rd-party    |        |
+        granted | prevalent | interaction | cookie | cookie block | RESULT |
+        -------------------------------------------------------------------
+        |       |           |             |        |              | false  |
+        -------------------------------------------------------------------
+        |       |           |             |        | true         | false  |
+        -------------------------------------------------------------------
+        |       |           |             | true   |              | true   |
+        -------------------------------------------------------------------
+        |       |           |             | true   | true         | false  |
+        -------------------------------------------------------------------
+        |       |           | true        |        |              | false  |
+        -------------------------------------------------------------------
+        |       |           | true        |        | true         | false  |
+        -------------------------------------------------------------------
+        |       |           | true        | true   |              | true   |
+        -------------------------------------------------------------------
+        |       |           | true        | true   | true         | false  |
+        -------------------------------------------------------------------
+        |       | true      | !care       | !care  | !care        | false  |
+        -------------------------------------------------------------------
+        | true  | !care     | !care       | !care  | !care        | true   |
+        -------------------------------------------------------------------
+
+        * NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp:
+        (WebKit::ResourceLoadStatisticsDatabaseStore::cookieAccess const):
+        (WebKit::ResourceLoadStatisticsDatabaseStore::hasStorageAccess):
+        (WebKit::ResourceLoadStatisticsDatabaseStore::requestStorageAccess):
+        (WebKit::ResourceLoadStatisticsDatabaseStore::requestStorageAccessUnderOpener):
+            Extra checks removed since there's no harm in granting access
+            to a third-party that already has access by way of the underlying
+            cookie policy. Also, this is a temporary compatibility fix.
+        * NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h:
+        * NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.cpp:
+        (WebKit::ResourceLoadStatisticsMemoryStore::cookieAccess const):
+        (WebKit::ResourceLoadStatisticsMemoryStore::hasStorageAccess):
+        (WebKit::ResourceLoadStatisticsMemoryStore::requestStorageAccess):
+        (WebKit::ResourceLoadStatisticsMemoryStore::requestStorageAccessUnderOpener):
+            Extra checks removed since there's no harm in granting access
+            to a third-party that already has access by way of the underlying
+            cookie policy. Also, this is a temporary compatibility fix.
+        * NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.h:
+        * NetworkProcess/Classifier/ResourceLoadStatisticsStore.h:
+        (WebKit::ResourceLoadStatisticsStore::setIsThirdPartyCookieBlockingEnabled):
+        (WebKit::ResourceLoadStatisticsStore::isThirdPartyCookieBlockingEnabled const):
+        * NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp:
+        (WebKit::WebResourceLoadStatisticsStore::setIsThirdPartyCookieBlockingEnabled):
+            This is now the single path to control this setting in both ITP
+            and the network storage session. See comment below.
+        * NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h:
+        * NetworkProcess/NetworkProcess.cpp:
+        (WebKit::NetworkProcess::setShouldBlockThirdPartyCookiesForTesting):
+        * NetworkProcess/NetworkSession.cpp:
+        (WebKit::NetworkSession::setResourceLoadStatisticsEnabled):
+        (WebKit::NetworkSession::setIsThirdPartyCookieBlockingEnabled):
+            Restructured these so that they are initiated like the rest of the
+            parameters and only have a single path for changes so that a
+            reset to consistent state resets all the state.
+        * NetworkProcess/NetworkSession.h:
+        * NetworkProcess/cocoa/NetworkSessionCocoa.mm:
+        (WebKit::NetworkSessionCocoa::NetworkSessionCocoa):
+
 2019-10-28  Alex Christensen  <[email protected]>
 
         Remove unused NetworkProcessCreationParameters.urlSchemesRegisteredAsCanDisplayOnlyIfCanRequest

Modified: trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp (251662 => 251663)


--- trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp	2019-10-28 18:56:19 UTC (rev 251662)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp	2019-10-28 19:45:03 UTC (rev 251663)
@@ -1193,16 +1193,21 @@
 
     ensureResourceStatisticsForRegistrableDomain(subFrameDomain);
 
-    switch (cookieTreatmentForOrigin(subFrameDomain)) {
-    case CookieTreatmentResult::BlockAndPurge:
+    switch (cookieAccess(subFrameDomain)) {
+    case CookieAccess::CannotRequest:
         completionHandler(false);
         return;
-    case CookieTreatmentResult::Allow:
-        // We should only return true if the context has asked for and been granted access.
-        completionHandler(false);
+    case CookieAccess::BasedOnCookiePolicy:
+        RunLoop::main().dispatch([store = makeRef(store()), subFrameDomain = subFrameDomain.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
+            store->hasCookies(subFrameDomain, [store = store.copyRef(), completionHandler = WTFMove(completionHandler)](bool result) mutable {
+                store->statisticsQueue().dispatch([completionHandler = WTFMove(completionHandler), result] () mutable {
+                    completionHandler(result);
+                });
+            });
+        });
         return;
-    case CookieTreatmentResult::BlockAndKeep:
-        // Do nothing. The below dispatch will complete the task.
+    case CookieAccess::OnlyIfGranted:
+        // Handled below.
         break;
     };
 
@@ -1220,18 +1225,19 @@
     ASSERT(!RunLoop::isMain());
 
     auto subFrameStatus = ensureResourceStatisticsForRegistrableDomain(subFrameDomain);
-    auto cookieTreatmentResult = cookieTreatmentForOrigin(subFrameDomain);
     
-    if (cookieTreatmentResult == CookieTreatmentResult::BlockAndPurge) {
+    switch (cookieAccess(subFrameDomain)) {
+    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);
         return;
-    }
-    
-    if (cookieTreatmentResult != CookieTreatmentResult::BlockAndKeep) {
-        RELEASE_LOG_INFO_IF(debugLoggingEnabled(), ITPDebug, "No need to grant storage access to %{private}s since its cookies are not blocked in third-party contexts.", subFrameDomain.string().utf8().data());
+    case CookieAccess::BasedOnCookiePolicy:
+        RELEASE_LOG_INFO_IF(debugLoggingEnabled(), ITPDebug, "No need to grant storage access to %{private}s since its cookies are not blocked in third-party contexts. Note that the underlying cookie policy may still block this third-party from setting cookies.", subFrameDomain.string().utf8().data());
         completionHandler(StorageAccessStatus::HasAccess);
         return;
+    case CookieAccess::OnlyIfGranted:
+        // Handled below.
+        break;
     }
 
     auto userWasPromptedEarlier = hasUserGrantedStorageAccessThroughPrompt(subFrameStatus.second, topFrameDomain);
@@ -1266,10 +1272,6 @@
     if (domainInNeedOfStorageAccess == openerDomain)
         return;
 
-    ensureResourceStatisticsForRegistrableDomain(domainInNeedOfStorageAccess);
-    if (cookieTreatmentForOrigin(domainInNeedOfStorageAccess) == CookieTreatmentResult::Allow)
-        return;
-
     RELEASE_LOG_INFO_IF(debugLoggingEnabled(), ITPDebug, "[Temporary combatibility fix] Storage access was granted for %{private}s under opener page from %{private}s, with user interaction in the opened window.", domainInNeedOfStorageAccess.string().utf8().data(), openerDomain.string().utf8().data());
     grantStorageAccessInternal(WTFMove(domainInNeedOfStorageAccess), WTFMove(openerDomain), WTF::nullopt, openerPageID, StorageAccessPromptWasShown::No, [](StorageAccessWasGranted) { });
 }
@@ -1788,7 +1790,7 @@
     updateCookieBlockingForDomains(domainsToBlock, [callbackAggregator = callbackAggregator.copyRef()] { });
 }
 
-ResourceLoadStatisticsDatabaseStore::CookieTreatmentResult ResourceLoadStatisticsDatabaseStore::cookieTreatmentForOrigin(const RegistrableDomain& domain) const
+CookieAccess ResourceLoadStatisticsDatabaseStore::cookieAccess(const RegistrableDomain& domain) const
 {
     ASSERT(!RunLoop::isMain());
 
@@ -1795,21 +1797,28 @@
     SQLiteStatement statement(m_database, "SELECT isPrevalent, hadUserInteraction FROM ObservedDomains WHERE registrableDomain = ?");
     if (statement.prepare() != SQLITE_OK
         || statement.bindText(1, domain.string()) != SQLITE_OK) {
-        RELEASE_LOG_ERROR_IF_ALLOWED(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::cookieTreatmentForOrigin failed to bind, error message: %{private}s", this, m_database.lastErrorMsg());
+        RELEASE_LOG_ERROR_IF_ALLOWED(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::cookieAccess failed to bind, error message: %{private}s", this, m_database.lastErrorMsg());
         ASSERT_NOT_REACHED();
     }
     
-    if (statement.step() != SQLITE_ROW)
-        return CookieTreatmentResult::Allow;
-    
+    bool hasNoEntry = statement.step() != SQLITE_ROW;
+    if (hasNoEntry) {
+        if (isThirdPartyCookieBlockingEnabled())
+            return CookieAccess::OnlyIfGranted;
+        return CookieAccess::BasedOnCookiePolicy;
+    }
+
     bool isPrevalent = !!statement.getColumnInt(0);
-    if (!isPrevalent)
-        return CookieTreatmentResult::Allow;
+    if (!isPrevalent && !isThirdPartyCookieBlockingEnabled())
+        return CookieAccess::BasedOnCookiePolicy;
 
     bool hadUserInteraction = statement.getColumnInt(1) ? true : false;
-    return hadUserInteraction ? CookieTreatmentResult::BlockAndKeep : CookieTreatmentResult::BlockAndPurge;
+    if (!hadUserInteraction)
+        return CookieAccess::CannotRequest;
+
+    return CookieAccess::OnlyIfGranted;
 }
-    
+
 StorageAccessPromptWasShown ResourceLoadStatisticsDatabaseStore::hasUserGrantedStorageAccessThroughPrompt(unsigned requestingDomainID, const RegistrableDomain& firstPartyDomain) const
 {
     ASSERT(!RunLoop::isMain());

Modified: trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h (251662 => 251663)


--- trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h	2019-10-28 18:56:19 UTC (rev 251662)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h	2019-10-28 19:45:03 UTC (rev 251663)
@@ -193,8 +193,7 @@
 
     bool predicateValueForDomain(WebCore::SQLiteStatement&, const RegistrableDomain&) const;
 
-    enum class CookieTreatmentResult { Allow, BlockAndKeep, BlockAndPurge };
-    CookieTreatmentResult cookieTreatmentForOrigin(const RegistrableDomain&) const;
+    CookieAccess cookieAccess(const RegistrableDomain&) const;
     
     void setPrevalentResource(const RegistrableDomain&, ResourceLoadPrevalence);
     unsigned recursivelyFindNonPrevalentDomainsThatRedirectedToThisDomain(unsigned primaryDomainID, StdSet<unsigned>& nonPrevalentRedirectionSources, unsigned numberOfRecursiveCalls);

Modified: trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.cpp (251662 => 251663)


--- trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.cpp	2019-10-28 18:56:19 UTC (rev 251662)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.cpp	2019-10-28 19:45:03 UTC (rev 251663)
@@ -212,18 +212,27 @@
         m_persistentStorage->scheduleOrWriteMemoryStore(ResourceLoadStatisticsPersistentStorage::ForceImmediateWrite::Yes);
 }
 
+CookieAccess ResourceLoadStatisticsMemoryStore::cookieAccess(const ResourceLoadStatistics& resourceStatistic) const
+{
+    if (!isThirdPartyCookieBlockingEnabled() && !resourceStatistic.isPrevalentResource)
+        return CookieAccess::BasedOnCookiePolicy;
+
+    if (!resourceStatistic.hadUserInteraction)
+        return CookieAccess::CannotRequest;
+    
+    return CookieAccess::OnlyIfGranted;
+}
+
 void ResourceLoadStatisticsMemoryStore::hasStorageAccess(const SubFrameDomain& subFrameDomain, const TopFrameDomain& topFrameDomain, Optional<FrameIdentifier> frameID, PageIdentifier pageID, CompletionHandler<void(bool)>&& completionHandler)
 {
     ASSERT(!RunLoop::isMain());
 
     auto& subFrameStatistic = ensureResourceStatisticsForRegistrableDomain(subFrameDomain);
-    // Return false if this domain cannot ask for storage access.
-    if (shouldBlockAndPurgeCookies(subFrameStatistic)) {
+    switch (cookieAccess(subFrameStatistic)) {
+    case CookieAccess::CannotRequest:
         completionHandler(false);
         return;
-    }
-
-    if (!shouldBlockAndKeepCookies(subFrameStatistic)) {
+    case CookieAccess::BasedOnCookiePolicy:
         RunLoop::main().dispatch([store = makeRef(store()), subFrameDomain = subFrameDomain.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
             store->hasCookies(subFrameDomain, [store = store.copyRef(), completionHandler = WTFMove(completionHandler)](bool result) mutable {
                 store->statisticsQueue().dispatch([completionHandler = WTFMove(completionHandler), result] () mutable {
@@ -232,6 +241,9 @@
             });
         });
         return;
+    case CookieAccess::OnlyIfGranted:
+        // Handled below.
+        break;
     }
 
     RunLoop::main().dispatch([store = makeRef(store()), subFrameDomain = subFrameDomain.isolatedCopy(), topFrameDomain = topFrameDomain.isolatedCopy(), frameID, pageID, completionHandler = WTFMove(completionHandler)]() mutable {
@@ -248,16 +260,18 @@
     ASSERT(!RunLoop::isMain());
 
     auto& subFrameStatistic = ensureResourceStatisticsForRegistrableDomain(subFrameDomain);
-    if (shouldBlockAndPurgeCookies(subFrameStatistic)) {
+    switch (cookieAccess(subFrameStatistic)) {
+    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);
         return;
-    }
-
-    if (!shouldBlockAndKeepCookies(subFrameStatistic)) {
-        RELEASE_LOG_INFO_IF(debugLoggingEnabled(), ITPDebug, "No need to grant storage access to %{public}s since its cookies are not blocked in third-party contexts.", subFrameDomain.string().utf8().data());
+    case CookieAccess::BasedOnCookiePolicy:
+        RELEASE_LOG_INFO_IF(debugLoggingEnabled(), ITPDebug, "No need to grant storage access to %{public}s since its cookies are not blocked in third-party contexts. Note that the underlying cookie policy may still block this third-party from setting cookies.", subFrameDomain.string().utf8().data());
         completionHandler(StorageAccessStatus::HasAccess);
         return;
+    case CookieAccess::OnlyIfGranted:
+        // Handled below.
+        break;
     }
 
     auto userWasPromptedEarlier = hasUserGrantedStorageAccessThroughPrompt(subFrameStatistic, topFrameDomain);
@@ -285,13 +299,6 @@
     if (domainInNeedOfStorageAccess == openerDomain)
         return;
 
-    auto& domainInNeedOfStorageAccessStatistic = ensureResourceStatisticsForRegistrableDomain(domainInNeedOfStorageAccess);
-    auto cookiesBlockedAndPurged = shouldBlockAndPurgeCookies(domainInNeedOfStorageAccessStatistic);
-
-    // The domain already has access if its cookies are not blocked.
-    if (!cookiesBlockedAndPurged && !shouldBlockAndKeepCookies(domainInNeedOfStorageAccessStatistic))
-        return;
-
     RELEASE_LOG_INFO_IF(debugLoggingEnabled(), ITPDebug, "[Temporary combatibility fix] Storage access was granted for %{public}s under opener page from %{public}s, with user interaction in the opened window.", domainInNeedOfStorageAccess.string().utf8().data(), openerDomain.string().utf8().data());
     grantStorageAccessInternal(WTFMove(domainInNeedOfStorageAccess), WTFMove(openerDomain), WTF::nullopt, openerPageID, StorageAccessPromptWasShown::No, [](StorageAccessWasGranted) { });
 }

Modified: trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.h (251662 => 251663)


--- trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.h	2019-10-28 18:56:19 UTC (rev 251662)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.h	2019-10-28 19:45:03 UTC (rev 251663)
@@ -97,6 +97,7 @@
 
     void calculateAndSubmitTelemetry() const override;
 
+    CookieAccess cookieAccess(const ResourceLoadStatistics&) const;
     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;

Modified: trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsStore.h (251662 => 251663)


--- trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsStore.h	2019-10-28 18:56:19 UTC (rev 251662)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsStore.h	2019-10-28 19:45:03 UTC (rev 251663)
@@ -75,6 +75,7 @@
 };
 
 enum class OperatingDatesWindow : bool { Long, Short };
+enum class CookieAccess : uint8_t { CannotRequest, BasedOnCookiePolicy, OnlyIfGranted };
 
 // This is always constructed / used / destroyed on the WebResourceLoadStatisticsStore's statistics queue.
 class ResourceLoadStatisticsStore : public CanMakeWeakPtr<ResourceLoadStatisticsStore> {
@@ -160,6 +161,8 @@
     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; };
 
     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;
@@ -267,6 +270,7 @@
     const RegistrableDomain m_debugStaticPrevalentResource { URL { URL(), "https://3rdpartytestwebkit.org"_s } };
     bool m_debugLoggingEnabled { false };
     bool m_debugModeEnabled { false };
+    bool m_thirdPartyCookieBlockingEnabled { false };
     bool m_dataRecordsBeingRemoved { false };
     ShouldIncludeLocalhost m_shouldIncludeLocalhost { ShouldIncludeLocalhost::Yes };
 };

Modified: trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp (251662 => 251663)


--- trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp	2019-10-28 18:56:19 UTC (rev 251662)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp	2019-10-28 19:45:03 UTC (rev 251663)
@@ -446,6 +446,25 @@
     completionHandler(false);
 }
 
+void WebResourceLoadStatisticsStore::setIsThirdPartyCookieBlockingEnabled(bool enabled)
+{
+    ASSERT(RunLoop::isMain());
+
+    if (m_networkSession) {
+        if (auto* storageSession = m_networkSession->networkStorageSession())
+            storageSession->setIsThirdPartyCookieBlockingEnabled(enabled);
+        else
+            ASSERT_NOT_REACHED();
+    }
+
+    postTask([this, enabled]() {
+        if (!m_statisticsStore)
+            return;
+
+        m_statisticsStore->setIsThirdPartyCookieBlockingEnabled(enabled);
+    });
+}
+
 void WebResourceLoadStatisticsStore::didCreateNetworkProcess()
 {
     ASSERT(RunLoop::isMain());

Modified: trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h (251662 => 251663)


--- trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h	2019-10-28 18:56:19 UTC (rev 251662)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h	2019-10-28 19:45:03 UTC (rev 251663)
@@ -178,7 +178,7 @@
     void callHasStorageAccessForFrameHandler(const SubFrameDomain&, const TopFrameDomain&, WebCore::FrameIdentifier, WebCore::PageIdentifier, CompletionHandler<void(bool)>&&);
 
     void hasCookies(const RegistrableDomain&, CompletionHandler<void(bool)>&&);
-
+    void setIsThirdPartyCookieBlockingEnabled(bool);
     void didCreateNetworkProcess();
 
     void notifyResourceLoadStatisticsProcessed();

Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp (251662 => 251663)


--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp	2019-10-28 18:56:19 UTC (rev 251662)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp	2019-10-28 19:45:03 UTC (rev 251663)
@@ -1255,8 +1255,8 @@
 
 void NetworkProcess::setShouldBlockThirdPartyCookiesForTesting(PAL::SessionID sessionID, bool enabled, CompletionHandler<void()>&& completionHandler)
 {
-    if (auto* networkStorageSession = storageSession(sessionID))
-        networkStorageSession->setIsThirdPartyCookieBlockingEnabled(enabled);
+    if (auto* networkSession = this->networkSession(sessionID))
+        networkSession->setIsThirdPartyCookieBlockingEnabled(enabled);
     else
         ASSERT_NOT_REACHED();
     completionHandler();

Modified: trunk/Source/WebKit/NetworkProcess/NetworkSession.cpp (251662 => 251663)


--- trunk/Source/WebKit/NetworkProcess/NetworkSession.cpp	2019-10-28 18:56:19 UTC (rev 251662)
+++ trunk/Source/WebKit/NetworkProcess/NetworkSession.cpp	2019-10-28 19:45:03 UTC (rev 251663)
@@ -170,6 +170,7 @@
     // 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);
 }
 
 void NetworkSession::recreateResourceLoadStatisticStore()
@@ -218,6 +219,13 @@
     return m_downgradeReferrer;
 }
 
+void NetworkSession::setIsThirdPartyCookieBlockingEnabled(bool enabled)
+{
+    ASSERT(m_resourceLoadStatistics);
+    m_thirdPartyCookieBlockingEnabled = enabled;
+    if (m_resourceLoadStatistics)
+        m_resourceLoadStatistics->setIsThirdPartyCookieBlockingEnabled(m_thirdPartyCookieBlockingEnabled);
+}
 #endif // ENABLE(RESOURCE_LOAD_STATISTICS)
 
 void NetworkSession::storeAdClickAttribution(WebCore::AdClickAttribution&& adClickAttribution)

Modified: trunk/Source/WebKit/NetworkProcess/NetworkSession.h (251662 => 251663)


--- trunk/Source/WebKit/NetworkProcess/NetworkSession.h	2019-10-28 18:56:19 UTC (rev 251662)
+++ trunk/Source/WebKit/NetworkProcess/NetworkSession.h	2019-10-28 19:45:03 UTC (rev 251663)
@@ -97,7 +97,7 @@
     virtual void clearIsolatedSessions() { }
     void setShouldDowngradeReferrerForTesting(bool);
     bool shouldDowngradeReferrer() const;
-    void setShouldBlockThirdPartyCookiesForTesting(bool);
+    void setIsThirdPartyCookieBlockingEnabled(bool);
 #endif
     void storeAdClickAttribution(WebCore::AdClickAttribution&&);
     void handleAdClickAttributionConversion(WebCore::AdClickAttribution::Conversion&&, const URL& requestURL, const WebCore::ResourceRequest& redirectRequest);
@@ -142,6 +142,7 @@
     WebCore::RegistrableDomain m_resourceLoadStatisticsManualPrevalentResource;
     bool m_enableResourceLoadStatisticsLogTestingEvent;
     bool m_downgradeReferrer { true };
+    bool m_thirdPartyCookieBlockingEnabled { false };
 #endif
     UniqueRef<AdClickAttributionManager> m_adClickAttribution;
 

Modified: trunk/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm (251662 => 251663)


--- trunk/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm	2019-10-28 18:56:19 UTC (rev 251662)
+++ trunk/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm	2019-10-28 19:45:03 UTC (rev 251663)
@@ -1109,7 +1109,7 @@
     m_shouldIncludeLocalhostInResourceLoadStatistics = parameters.shouldIncludeLocalhostInResourceLoadStatistics ? ShouldIncludeLocalhost::Yes : ShouldIncludeLocalhost::No;
     m_enableResourceLoadStatisticsDebugMode = parameters.enableResourceLoadStatisticsDebugMode ? EnableResourceLoadStatisticsDebugMode::Yes : EnableResourceLoadStatisticsDebugMode::No;
     m_resourceLoadStatisticsManualPrevalentResource = parameters.resourceLoadStatisticsManualPrevalentResource;
-    storageSession->setIsThirdPartyCookieBlockingEnabled(parameters.enableThirdPartyCookieBlocking);
+    m_thirdPartyCookieBlockingEnabled = parameters.enableThirdPartyCookieBlocking;
     setResourceLoadStatisticsEnabled(parameters.enableResourceLoadStatistics);
 #endif
 

Modified: trunk/Tools/ChangeLog (251662 => 251663)


--- trunk/Tools/ChangeLog	2019-10-28 18:56:19 UTC (rev 251662)
+++ trunk/Tools/ChangeLog	2019-10-28 19:45:03 UTC (rev 251663)
@@ -1,3 +1,16 @@
+2019-10-28  John Wilander  <[email protected]>
+
+        Storage Access API: Make the API work with the experimental 3rd-party cookie blocking
+        https://bugs.webkit.org/show_bug.cgi?id=203428
+        <rdar://problem/56626949>
+
+        Reviewed by Alex Christensen.
+
+        * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+        (WTR::TestRunner::statisticsCallDidSetShouldDowngradeReferrerCallback):
+        (WTR::TestRunner::statisticsCallDidSetShouldBlockThirdPartyCookiesCallback):
+            Both of these were missing resets of their m_hasSet*Callback booleans.
+
 2019-10-28  Jonathan Bedard  <[email protected]>
 
         results.webkit.org: Report more descriptive configurations for non-Apple ports

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp (251662 => 251663)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp	2019-10-28 18:56:19 UTC (rev 251662)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp	2019-10-28 19:45:03 UTC (rev 251663)
@@ -2207,6 +2207,7 @@
 void TestRunner::statisticsCallDidSetShouldDowngradeReferrerCallback()
 {
     callTestRunnerCallback(StatisticsDidSetShouldDowngradeReferrerCallbackID);
+    m_hasSetDowngradeReferrerCallback = false;
 }
 
 void TestRunner::setStatisticsShouldBlockThirdPartyCookies(bool value, JSValueRef completionHandler)
@@ -2224,6 +2225,7 @@
 void TestRunner::statisticsCallDidSetShouldBlockThirdPartyCookiesCallback()
 {
     callTestRunnerCallback(StatisticsDidSetShouldBlockThirdPartyCookiesCallbackID);
+    m_hasSetBlockThirdPartyCookiesCallback = false;
 }
 
 void TestRunner::statisticsCallClearThroughWebsiteDataRemovalCallback()
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to