Storage Access API: document.hasStorageAccess() should return true when the cookie...
authorwilander@apple.com <wilander@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 2 Oct 2019 01:18:48 +0000 (01:18 +0000)
committerwilander@apple.com <wilander@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 2 Oct 2019 01:18:48 +0000 (01:18 +0000)
https://bugs.webkit.org/show_bug.cgi?id=202435
<rdar://problem/55718526>

Reviewed by Brent Fulgham.

Source/WebCore:

WebKit's Storage Access API implementation has so far only looked at whether ITP is
blocking cookie access or not. However, the default cookie policy is still in
effect underneath ITP. document.hasStorageAccess() should return true if the
third-party:
a) is not classified by ITP, and
b) has cookies which implies it can use cookies as third-party according to the
default cookie policy.

Tests: http/tests/storageAccess/has-storage-access-false-by-default-ephemeral.html
       http/tests/storageAccess/has-storage-access-true-if-third-party-has-cookies-ephemeral.html
       http/tests/storageAccess/has-storage-access-true-if-third-party-has-cookies.html

* platform/network/NetworkStorageSession.h:
* platform/network/cocoa/NetworkStorageSessionCocoa.mm:
(WebCore::NetworkStorageSession::hasCookies const):
* platform/network/curl/NetworkStorageSessionCurl.cpp:
(WebCore::NetworkStorageSession::hasCookies const):
    Not yet implemented. Always says false.
* platform/network/soup/NetworkStorageSessionSoup.cpp:
(WebCore::NetworkStorageSession::hasCookies const):
    Not yet implemented. Always says false.

Source/WebKit:

WebKit's Storage Access API implementation has so far only looked at whether ITP is
blocking cookie access or not. However, the default cookie policy is still in
effect underneath ITP. document.hasStorageAccess() should return true if the
third-party:
a) is not classified by ITP, and
b) has cookies which implies it can use cookies as third-party according to the
default cookie policy.

* NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.cpp:
(WebKit::ResourceLoadStatisticsMemoryStore::hasStorageAccess):
* NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::hasCookies):
* NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h:
* NetworkProcess/NetworkConnectionToWebProcess.cpp:
(WebKit::NetworkConnectionToWebProcess::hasStorageAccess):
* NetworkProcess/NetworkProcess.cpp:
(WebKit::NetworkProcess::registrableDomainsWithWebsiteData):

Tools:

This change makes sure topPrivatelyControlledDomain() correctly handles domains
with leading dots, as often used in cookie domains.

* TestWebKitAPI/Tests/WebCore/PublicSuffix.cpp:
(TestWebKitAPI::TEST_F):

LayoutTests:

WebKit's Storage Access API implementation has so far only looked at whether ITP is
blocking cookie access or not. However, the default cookie policy is still in
effect underneath ITP. document.hasStorageAccess() should return true if the
third-party:
a) is not classified by ITP, and
b) has cookies which implies it can use cookies as third-party according to the
default cookie policy.

* http/tests/storageAccess/has-storage-access-false-by-default-ephemeral-expected.txt: Added.
* http/tests/storageAccess/has-storage-access-false-by-default-ephemeral.html: Copied from LayoutTests/http/tests/storageAccess/has-storage-access-true-if-feature-off.html.
* http/tests/storageAccess/has-storage-access-true-if-third-party-has-cookies-ephemeral-expected.txt: Added.
* http/tests/storageAccess/has-storage-access-true-if-third-party-has-cookies-ephemeral.html: Copied from LayoutTests/http/tests/storageAccess/has-storage-access-true-if-feature-off.html.
* http/tests/storageAccess/has-storage-access-true-if-third-party-has-cookies-expected.txt: Added.
* http/tests/storageAccess/has-storage-access-true-if-third-party-has-cookies.html: Renamed from LayoutTests/http/tests/storageAccess/has-storage-access-true-if-feature-off.html.
* platform/ios/TestExpectations:
* platform/mac-wk2/TestExpectations:

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

22 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/storageAccess/has-storage-access-false-by-default-ephemeral-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/storageAccess/has-storage-access-false-by-default-ephemeral.html [new file with mode: 0644]
LayoutTests/http/tests/storageAccess/has-storage-access-true-if-third-party-has-cookies-ephemeral-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/storageAccess/has-storage-access-true-if-third-party-has-cookies-ephemeral.html [moved from LayoutTests/http/tests/storageAccess/has-storage-access-true-if-feature-off.html with 71% similarity]
LayoutTests/http/tests/storageAccess/has-storage-access-true-if-third-party-has-cookies-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/storageAccess/has-storage-access-true-if-third-party-has-cookies.html [new file with mode: 0644]
LayoutTests/platform/ios/TestExpectations
LayoutTests/platform/mac-wk2/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/platform/network/NetworkStorageSession.h
Source/WebCore/platform/network/cocoa/NetworkStorageSessionCocoa.mm
Source/WebCore/platform/network/curl/NetworkStorageSessionCurl.cpp
Source/WebCore/platform/network/soup/NetworkStorageSessionSoup.cpp
Source/WebKit/ChangeLog
Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.cpp
Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp
Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h
Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp
Source/WebKit/NetworkProcess/NetworkProcess.cpp
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WebCore/PublicSuffix.cpp

index 685a514..e78674e 100644 (file)
@@ -1,3 +1,28 @@
+2019-10-01  John Wilander  <wilander@apple.com>
+
+        Storage Access API: document.hasStorageAccess() should return true when the cookie policy allows access
+        https://bugs.webkit.org/show_bug.cgi?id=202435
+        <rdar://problem/55718526>
+
+        Reviewed by Brent Fulgham.
+
+        WebKit's Storage Access API implementation has so far only looked at whether ITP is
+        blocking cookie access or not. However, the default cookie policy is still in
+        effect underneath ITP. document.hasStorageAccess() should return true if the
+        third-party:
+        a) is not classified by ITP, and
+        b) has cookies which implies it can use cookies as third-party according to the
+        default cookie policy.
+
+        * http/tests/storageAccess/has-storage-access-false-by-default-ephemeral-expected.txt: Added.
+        * http/tests/storageAccess/has-storage-access-false-by-default-ephemeral.html: Copied from LayoutTests/http/tests/storageAccess/has-storage-access-true-if-feature-off.html.
+        * http/tests/storageAccess/has-storage-access-true-if-third-party-has-cookies-ephemeral-expected.txt: Added.
+        * http/tests/storageAccess/has-storage-access-true-if-third-party-has-cookies-ephemeral.html: Copied from LayoutTests/http/tests/storageAccess/has-storage-access-true-if-feature-off.html.
+        * http/tests/storageAccess/has-storage-access-true-if-third-party-has-cookies-expected.txt: Added.
+        * http/tests/storageAccess/has-storage-access-true-if-third-party-has-cookies.html: Renamed from LayoutTests/http/tests/storageAccess/has-storage-access-true-if-feature-off.html.
+        * platform/ios/TestExpectations:
+        * platform/mac-wk2/TestExpectations:
+
 2019-10-01  Rob Buis  <rbuis@igalia.com>
 
         [Mac] Layout Test imported/w3c/web-platform-tests/fetch/api/redirect/redirect-location.any.html fails
diff --git a/LayoutTests/http/tests/storageAccess/has-storage-access-false-by-default-ephemeral-expected.txt b/LayoutTests/http/tests/storageAccess/has-storage-access-false-by-default-ephemeral-expected.txt
new file mode 100644 (file)
index 0000000..725e814
--- /dev/null
@@ -0,0 +1,10 @@
+Tests that document.hasStorageAccess() returns false for a 3rd-party iframe by default (ephemeral session).
+
+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 successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/storageAccess/has-storage-access-false-by-default-ephemeral.html b/LayoutTests/http/tests/storageAccess/has-storage-access-false-by-default-ephemeral.html
new file mode 100644 (file)
index 0000000..8f4e7e0
--- /dev/null
@@ -0,0 +1,36 @@
+<!-- webkit-test-runner [ useEphemeralSession=true ] -->
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script src="/resourceLoadStatistics/resources/util.js"></script>
+    <script>
+        description("Tests that document.hasStorageAccess() returns false for a 3rd-party iframe by default (ephemeral session).");
+        jsTestIsAsync = true;
+
+        window.addEventListener("message", receiveMessage, false);
+
+        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);
+            finishJSTest();
+        }
+
+        const hostUnderTest = "localhost:8000";
+        const statisticsUrl = "http://" + hostUnderTest + "/temp";
+        function runTest() {
+            let iframeElement = document.createElement("iframe");
+            iframeElement.id = "TheIframeThatRequestsStorageAccess";
+            iframeElement.src = "http://localhost:8000/storageAccess/resources/has-storage-access-iframe.html#policyShouldDenyAccess";
+            document.body.appendChild(iframeElement);
+        }
+    </script>
+</head>
+<body onload="runTest()">
+</body>
+</html>
diff --git a/LayoutTests/http/tests/storageAccess/has-storage-access-true-if-third-party-has-cookies-ephemeral-expected.txt b/LayoutTests/http/tests/storageAccess/has-storage-access-true-if-third-party-has-cookies-ephemeral-expected.txt
new file mode 100644 (file)
index 0000000..ee54049
--- /dev/null
@@ -0,0 +1,10 @@
+Tests that document.hasStorageAccess() returns true for a 3rd-party iframe if the 3rd-party has cookies set.
+
+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 successfullyParsed is true
+
+TEST COMPLETE
+
@@ -3,10 +3,9 @@
 <html>
 <head>
     <script src="/js-test-resources/js-test.js"></script>
-    <script src="/js-test-resources/ui-helper.js"></script>
     <script src="/resourceLoadStatistics/resources/util.js"></script>
     <script>
-        description("Tests that document.hasStorageAccess() returns true for a 3rd-party iframe if there is no way to request access (feature off).");
+        description("Tests that document.hasStorageAccess() returns true for a 3rd-party iframe if the 3rd-party has cookies set (ephemeral session).");
         jsTestIsAsync = true;
 
         window.addEventListener("message", receiveMessage, false);
                     testFailed(event.data.replace("FAIL ", ""));
             } else
                 testFailed("Received a message from an unexpected origin: " + event.origin);
-            setEnableFeature(false, finishJSTest);
+            finishJSTest();
         }
 
         const hostUnderTest = "localhost:8000";
-        const statisticsUrl = "http://" + hostUnderTest + "/temp";
+        const statisticsUrl = "http://" + hostUnderTest;
         function runTest() {
-            setEnableFeature(false, function() {
+            if (document.location.hash !== "#firstPartyCookieSet") {
+                document.location.href = statisticsUrl + "/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 {
                 let iframeElement = document.createElement("iframe");
                 iframeElement.id = "TheIframeThatRequestsStorageAccess";
                 iframeElement.src = "http://localhost:8000/storageAccess/resources/has-storage-access-iframe.html#policyShouldGrantAccess";
                 document.body.appendChild(iframeElement);
-            });
+            }
         }
     </script>
 </head>
diff --git a/LayoutTests/http/tests/storageAccess/has-storage-access-true-if-third-party-has-cookies-expected.txt b/LayoutTests/http/tests/storageAccess/has-storage-access-true-if-third-party-has-cookies-expected.txt
new file mode 100644 (file)
index 0000000..ee54049
--- /dev/null
@@ -0,0 +1,10 @@
+Tests that document.hasStorageAccess() returns true for a 3rd-party iframe if the 3rd-party has cookies set.
+
+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 successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/storageAccess/has-storage-access-true-if-third-party-has-cookies.html b/LayoutTests/http/tests/storageAccess/has-storage-access-true-if-third-party-has-cookies.html
new file mode 100644 (file)
index 0000000..292de29
--- /dev/null
@@ -0,0 +1,42 @@
+<!-- webkit-test-runner [ useEphemeralSession=true ] -->
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script src="/resourceLoadStatistics/resources/util.js"></script>
+    <script>
+        description("Tests that document.hasStorageAccess() returns true for a 3rd-party iframe if the 3rd-party has cookies set.");
+        jsTestIsAsync = true;
+
+        window.addEventListener("message", receiveMessage, false);
+
+        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);
+            setEnableFeature(false, finishJSTest);
+        }
+
+        const hostUnderTest = "localhost:8000";
+        const statisticsUrl = "http://" + hostUnderTest;
+        function runTest() {
+            if (document.location.hash !== "#firstPartyCookieSet") {
+                setEnableFeature(false, function() {
+                    document.location.href = statisticsUrl + "/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 {
+                let iframeElement = document.createElement("iframe");
+                iframeElement.id = "TheIframeThatRequestsStorageAccess";
+                iframeElement.src = "http://localhost:8000/storageAccess/resources/has-storage-access-iframe.html#policyShouldGrantAccess";
+                document.body.appendChild(iframeElement);
+            }
+        }
+    </script>
+</head>
+<body onload="runTest()">
+</body>
+</html>
index 49c7251..fd074a9 100644 (file)
@@ -2799,7 +2799,9 @@ http/tests/storageAccess/deny-storage-access-under-opener.html [ Pass ]
 http/tests/storageAccess/deny-storage-access-under-opener-if-auto-dismiss.html [ Pass ]
 http/tests/resourceLoadStatistics/cap-cache-max-age-for-prevalent-resource.html [ Pass ]
 http/tests/storageAccess/has-storage-access-false-by-default.html [ Pass ]
-
+http/tests/storageAccess/has-storage-access-false-by-default-ephemeral.html [ Pass ]
+http/tests/storageAccess/has-storage-access-true-if-third-party-has-cookies-ephemeral.html [ Pass ]
+http/tests/storageAccess/has-storage-access-true-if-third-party-has-cookies.html [ Pass ]
 
 # Skipped in general expectations since they only work on iOS and Mac, WK2.
 http/tests/security/strip-referrer-to-origin-for-third-party-redirects-in-private-mode.html [ Pass ]
index ad5366f..c4f7f6d 100644 (file)
@@ -711,8 +711,10 @@ webkit.org/b/198670 [ HighSierra+ ] http/tests/storageAccess/request-and-grant-a
 [ HighSierra+ ] http/tests/storageAccess/grant-with-prompt-preserves-gesture.html [ Pass ]
 [ HighSierra+ ] http/tests/storageAccess/deny-with-prompt-does-not-preserve-gesture.html [ Skip ]
 [ HighSierra+ ] http/tests/storageAccess/deny-without-prompt-preserves-gesture.html [ Pass ]
-[ HighSierra+ ] http/tests/storageAccess/has-storage-access-true-if-feature-off.html [ Pass ]
 [ HighSierra+ ] http/tests/storageAccess/has-storage-access-false-by-default.html [ Pass ]
+[ HighSierra+ ] http/tests/storageAccess/has-storage-access-false-by-default-ephemeral.html [ Pass ]
+[ HighSierra+ ] http/tests/storageAccess/has-storage-access-true-if-third-party-has-cookies-ephemeral.html [ Pass ]
+[ HighSierra+ ] http/tests/storageAccess/has-storage-access-true-if-third-party-has-cookies.html [ Pass ]
 
 # As of https://trac.webkit.org/changeset/227762 the timestampResolution is just 5 seconds which makes this test flaky
 http/tests/resourceLoadStatistics/user-interaction-only-reported-once-within-short-period-of-time.html [ Skip ]
index e404fe5..dc57496 100644 (file)
@@ -1,3 +1,33 @@
+2019-10-01  John Wilander  <wilander@apple.com>
+
+        Storage Access API: document.hasStorageAccess() should return true when the cookie policy allows access
+        https://bugs.webkit.org/show_bug.cgi?id=202435
+        <rdar://problem/55718526>
+
+        Reviewed by Brent Fulgham.
+
+        WebKit's Storage Access API implementation has so far only looked at whether ITP is
+        blocking cookie access or not. However, the default cookie policy is still in
+        effect underneath ITP. document.hasStorageAccess() should return true if the
+        third-party:
+        a) is not classified by ITP, and
+        b) has cookies which implies it can use cookies as third-party according to the
+        default cookie policy.
+
+        Tests: http/tests/storageAccess/has-storage-access-false-by-default-ephemeral.html
+               http/tests/storageAccess/has-storage-access-true-if-third-party-has-cookies-ephemeral.html
+               http/tests/storageAccess/has-storage-access-true-if-third-party-has-cookies.html
+
+        * platform/network/NetworkStorageSession.h:
+        * platform/network/cocoa/NetworkStorageSessionCocoa.mm:
+        (WebCore::NetworkStorageSession::hasCookies const):
+        * platform/network/curl/NetworkStorageSessionCurl.cpp:
+        (WebCore::NetworkStorageSession::hasCookies const):
+            Not yet implemented. Always says false.
+        * platform/network/soup/NetworkStorageSessionSoup.cpp:
+        (WebCore::NetworkStorageSession::hasCookies const):
+            Not yet implemented. Always says false.
+
 2019-10-01  Tim Horton  <timothy_horton@apple.com>
 
         Clean up some includes to make the build a bit faster
index 54ff45d..5bb8437 100644 (file)
@@ -30,6 +30,7 @@
 #include "PageIdentifier.h"
 #include "RegistrableDomain.h"
 #include <pal/SessionID.h>
+#include <wtf/CompletionHandler.h>
 #include <wtf/Function.h>
 #include <wtf/HashMap.h>
 #include <wtf/HashSet.h>
@@ -133,6 +134,7 @@ public:
     WEBCORE_EXPORT void deleteCookiesForHostnames(const Vector<String>& cookieHostNames, IncludeHttpOnlyCookies);
     WEBCORE_EXPORT Vector<Cookie> getAllCookies();
     WEBCORE_EXPORT Vector<Cookie> getCookies(const URL&);
+    WEBCORE_EXPORT void hasCookies(const RegistrableDomain&, CompletionHandler<void(bool)>&&) const;
     WEBCORE_EXPORT bool getRawCookies(const URL& firstParty, const SameSiteInfo&, const URL&, Optional<FrameIdentifier>, Optional<PageIdentifier>, Vector<Cookie>&) const;
     WEBCORE_EXPORT void flushCookieStore();
     WEBCORE_EXPORT void getHostnamesWithCookies(HashSet<String>& hostnames);
index 3276192..ddca2c6 100644 (file)
@@ -102,6 +102,20 @@ Vector<Cookie> NetworkStorageSession::getCookies(const URL& url)
     return nsCookiesToCookieVector([nsCookieStorage() cookiesForURL:(NSURL *)url]);
 }
 
+void NetworkStorageSession::hasCookies(const RegistrableDomain& domain, CompletionHandler<void(bool)>&& completionHandler) const
+{
+    ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
+    
+    for (NSHTTPCookie *nsCookie in nsCookieStorage().cookies) {
+        if (RegistrableDomain::uncheckedCreateFromHost(nsCookie.domain) == domain) {
+            completionHandler(true);
+            return;
+        }
+    }
+
+    completionHandler(false);
+}
+
 void NetworkStorageSession::flushCookieStore()
 {
     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
index 04aaf35..f2a1903 100644 (file)
@@ -154,6 +154,12 @@ Vector<Cookie> NetworkStorageSession::getCookies(const URL&)
     return { };
 }
 
+void NetworkStorageSession::hasCookies(const RegistrableDomain&, CompletionHandler<void(bool)>&& completionHandler) const
+{
+    // FIXME: Implement.
+    completionHandler(false);
+}
+
 bool NetworkStorageSession::getRawCookies(const URL& firstParty, const SameSiteInfo& sameSiteInfo, const URL& url, Optional<FrameIdentifier> frameID, Optional<PageIdentifier> pageID, Vector<Cookie>& rawCookies) const
 {
     return cookieStorage().getRawCookies(*this, firstParty, sameSiteInfo, url, frameID, pageID, rawCookies);
index 0b1b7cf..dfc490d 100644 (file)
@@ -414,6 +414,12 @@ Vector<Cookie> NetworkStorageSession::getCookies(const URL& url)
     return cookies;
 }
 
+void NetworkStorageSession::hasCookies(const RegistrableDomain&, CompletionHandler<void(bool)>&& completionHandler) const
+{
+    // FIXME: Implement.
+    completionHandler(false);
+}
+
 bool NetworkStorageSession::getRawCookies(const URL& firstParty, const SameSiteInfo&, const URL& url, Optional<FrameIdentifier> frameID, Optional<PageIdentifier> pageID, Vector<Cookie>& rawCookies) const
 {
     UNUSED_PARAM(firstParty);
index bd9d45b..166958e 100644 (file)
@@ -1,3 +1,29 @@
+2019-10-01  John Wilander  <wilander@apple.com>
+
+        Storage Access API: document.hasStorageAccess() should return true when the cookie policy allows access
+        https://bugs.webkit.org/show_bug.cgi?id=202435
+        <rdar://problem/55718526>
+
+        Reviewed by Brent Fulgham.
+
+        WebKit's Storage Access API implementation has so far only looked at whether ITP is
+        blocking cookie access or not. However, the default cookie policy is still in
+        effect underneath ITP. document.hasStorageAccess() should return true if the
+        third-party:
+        a) is not classified by ITP, and
+        b) has cookies which implies it can use cookies as third-party according to the
+        default cookie policy.
+
+        * NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.cpp:
+        (WebKit::ResourceLoadStatisticsMemoryStore::hasStorageAccess):
+        * NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp:
+        (WebKit::WebResourceLoadStatisticsStore::hasCookies):
+        * NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h:
+        * NetworkProcess/NetworkConnectionToWebProcess.cpp:
+        (WebKit::NetworkConnectionToWebProcess::hasStorageAccess):
+        * NetworkProcess/NetworkProcess.cpp:
+        (WebKit::NetworkProcess::registrableDomainsWithWebsiteData):
+
 2019-10-01  Antti Koivisto  <antti@apple.com>
 
         [CSS Shadow Parts] Parse 'part' attribute
index 65b8780..f5e6663 100644 (file)
@@ -217,11 +217,22 @@ void ResourceLoadStatisticsMemoryStore::hasStorageAccess(const SubFrameDomain& s
 
     auto& subFrameStatistic = ensureResourceStatisticsForRegistrableDomain(subFrameDomain);
     // Return false if this domain cannot ask for storage access.
-    if (shouldBlockAndPurgeCookies(subFrameStatistic) || !shouldBlockAndKeepCookies(subFrameStatistic)) {
+    if (shouldBlockAndPurgeCookies(subFrameStatistic)) {
         completionHandler(false);
         return;
     }
 
+    if (!shouldBlockAndKeepCookies(subFrameStatistic)) {
+        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;
+    }
+
     RunLoop::main().dispatch([store = makeRef(store()), subFrameDomain = subFrameDomain.isolatedCopy(), topFrameDomain = topFrameDomain.isolatedCopy(), frameID, pageID, completionHandler = WTFMove(completionHandler)]() mutable {
         store->callHasStorageAccessForFrameHandler(subFrameDomain, topFrameDomain, frameID.value(), pageID, [store = store.copyRef(), completionHandler = WTFMove(completionHandler)](bool result) mutable {
             store->statisticsQueue().dispatch([completionHandler = WTFMove(completionHandler), result] () mutable {
index 2bbedcb..94f0168 100644 (file)
@@ -434,6 +434,20 @@ void WebResourceLoadStatisticsStore::callGrantStorageAccessHandler(const Registr
     completionHandler(grantStorageAccess(subFrameDomain, topFrameDomain, frameID, pageID));
 }
 
+void WebResourceLoadStatisticsStore::hasCookies(const RegistrableDomain& domain, CompletionHandler<void(bool)>&& completionHandler)
+{
+    ASSERT(RunLoop::isMain());
+
+    if (m_networkSession) {
+        if (auto* storageSession = m_networkSession->networkStorageSession()) {
+            storageSession->hasCookies(domain, WTFMove(completionHandler));
+            return;
+        }
+    }
+    
+    completionHandler(false);
+}
+
 void WebResourceLoadStatisticsStore::didCreateNetworkProcess()
 {
     ASSERT(RunLoop::isMain());
index 2c7d378..7eae1a7 100644 (file)
@@ -176,6 +176,8 @@ public:
     void callRemoveDomainsHandler(const Vector<RegistrableDomain>&);
     void callHasStorageAccessForFrameHandler(const SubFrameDomain&, const TopFrameDomain&, WebCore::FrameIdentifier, WebCore::PageIdentifier, CompletionHandler<void(bool)>&&);
 
+    void hasCookies(const RegistrableDomain&, CompletionHandler<void(bool)>&&);
+
     void didCreateNetworkProcess();
 
     void notifyResourceLoadStatisticsProcessed();
index 7eee7e0..3c2a5e8 100644 (file)
@@ -716,10 +716,13 @@ void NetworkConnectionToWebProcess::hasStorageAccess(const RegistrableDomain& su
         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics()) {
             resourceLoadStatistics->hasStorageAccess(subFrameDomain, topFrameDomain, frameID, pageID, WTFMove(completionHandler));
             return;
+        } else {
+            storageSession()->hasCookies(subFrameDomain, WTFMove(completionHandler));
+            return;
         }
     }
 
-    completionHandler(true);
+    completionHandler(false);
 }
 
 void NetworkConnectionToWebProcess::requestStorageAccess(const RegistrableDomain& subFrameDomain, const RegistrableDomain& topFrameDomain, FrameIdentifier frameID, PageIdentifier webPageID, WebPageProxyIdentifier webPageProxyID, CompletionHandler<void(WebCore::StorageAccessWasGranted wasGranted, WebCore::StorageAccessPromptWasShown promptWasShown)>&& completionHandler)
index f52f40f..4cd38c2 100644 (file)
@@ -1838,13 +1838,11 @@ void NetworkProcess::registrableDomainsWithWebsiteData(PAL::SessionID sessionID,
     
     auto& websiteDataStore = callbackAggregator->m_websiteData;
     
-    Vector<String> hostnamesWithCookiesToDelete;
     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
         if (auto* networkStorageSession = storageSession(sessionID))
             networkStorageSession->getHostnamesWithCookies(websiteDataStore.hostNamesWithCookies);
     }
     
-    Vector<String> hostnamesWithHSTSToDelete;
 #if PLATFORM(COCOA) || USE(SOUP)
     if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
         if (auto* networkStorageSession = storageSession(sessionID))
index 9eded3d..f85549c 100644 (file)
@@ -1,3 +1,17 @@
+2019-10-01  John Wilander  <wilander@apple.com>
+
+        Storage Access API: document.hasStorageAccess() should return true when the cookie policy allows access
+        https://bugs.webkit.org/show_bug.cgi?id=202435
+        <rdar://problem/55718526>
+
+        Reviewed by Brent Fulgham.
+
+        This change makes sure topPrivatelyControlledDomain() correctly handles domains
+        with leading dots, as often used in cookie domains.
+
+        * TestWebKitAPI/Tests/WebCore/PublicSuffix.cpp:
+        (TestWebKitAPI::TEST_F):
+
 2019-10-01  Jonathan Bedard  <jbedard@apple.com>
 
         results.webkit.org: Standardize styles in the drawer
index 9411c5c..dfe1d0a 100644 (file)
@@ -179,6 +179,7 @@ TEST_F(PublicSuffix, TopPrivatelyControlledDomain)
     EXPECT_EQ(String("localhost"), topPrivatelyControlledDomain("LocalHost"));
     EXPECT_EQ(String("åäö"), topPrivatelyControlledDomain("åäö"));
     EXPECT_EQ(String("ÅÄÖ"), topPrivatelyControlledDomain("ÅÄÖ"));
+    EXPECT_EQ(String("test.com"), topPrivatelyControlledDomain(".test.com"));
 }
 
 }