Storage Access API: Add testRunner.getAllStorageAccessEntries() to make testing easie...
authorwilander@apple.com <wilander@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 5 Feb 2018 19:35:13 +0000 (19:35 +0000)
committerwilander@apple.com <wilander@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 5 Feb 2018 19:35:13 +0000 (19:35 +0000)
https://bugs.webkit.org/show_bug.cgi?id=181601
<rdar://problem/36475837>

Reviewed by Alex Christensen.

Source/WebCore:

No new tests. Existing test updated.

http/tests/storageAccess/request-and-grant-access-then-detach-should-not-have-access.html
was found to be flaky. With the testRunner.hasStorageAccessEntry() getter
it's possible to check access even if a frame doesn't respond timely to
postMessage after detach and attach.

* platform/network/NetworkStorageSession.h:
* platform/network/cf/NetworkStorageSessionCFNet.cpp:
(WebCore::NetworkStorageSession::getAllStorageAccessEntries const):

Source/WebKit:

http/tests/storageAccess/request-and-grant-access-then-detach-should-not-have-access.html
was found to be flaky. With the testRunner.hasStorageAccessEntry() getter
it's possible to check access even if a frame doesn't respond timely to
postMessage after detach and attach.

* NetworkProcess/NetworkProcess.cpp:
(WebKit::NetworkProcess::getAllStorageAccessEntries):
* NetworkProcess/NetworkProcess.h:
* NetworkProcess/NetworkProcess.messages.in:
* UIProcess/API/Cocoa/WKWebsiteDataStore.mm:
(-[WKWebsiteDataStore _getAllStorageAccessEntries:]):
* UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h:
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::getAllStorageAccessEntries):
(WebKit::NetworkProcessProxy::allStorageAccessEntriesResult):
* UIProcess/Network/NetworkProcessProxy.h:
* UIProcess/Network/NetworkProcessProxy.messages.in:
* UIProcess/WebsiteData/WebsiteDataStore.cpp:
(WebKit::WebsiteDataStore::getAllStorageAccessEntries):
* UIProcess/WebsiteData/WebsiteDataStore.h:

Tools:

http/tests/storageAccess/request-and-grant-access-then-detach-should-not-have-access.html
was found to be flaky. With the testRunner.hasStorageAccessEntry() getter
it's possible to check access even if a frame doesn't respond timely to
postMessage after detach and attach.

* WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
* WebKitTestRunner/InjectedBundle/InjectedBundle.cpp:
(WTR::InjectedBundle::didReceiveMessageToPage):
* WebKitTestRunner/InjectedBundle/TestRunner.cpp:
(WTR::TestRunner::setStorageAccessAPIEnabled):
    Just moved for source file grouping.
(WTR::TestRunner::getAllStorageAccessEntries):
(WTR::TestRunner::callDidReceiveAllStorageAccessEntriesCallback):
* WebKitTestRunner/InjectedBundle/TestRunner.h:
* WebKitTestRunner/TestController.cpp:
(WTR::TestController::getAllStorageAccessEntries):
    Note that this is just stubbed out, i.e. not implemented.
* WebKitTestRunner/TestController.h:
* WebKitTestRunner/TestInvocation.cpp:
(WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):
(WTR::TestInvocation::didReceiveAllStorageAccessEntries):
* WebKitTestRunner/TestInvocation.h:
* WebKitTestRunner/cocoa/TestControllerCocoa.mm:
(WTR::TestController::getAllStorageAccessEntries):
    This is the Cocoa-specific version of this test infrastructure.

LayoutTests:

http/tests/storageAccess/request-and-grant-access-then-detach-should-not-have-access.html
was found to be flaky. With the testRunner.hasStorageAccessEntry() getter
it's possible to check access even if a frame doesn't respond timely to
postMessage after detach and attach.

* http/tests/storageAccess/request-and-grant-access-then-detach-should-not-have-access-expected.txt:
* http/tests/storageAccess/request-and-grant-access-then-detach-should-not-have-access.html:
* platform/mac-wk2/TestExpectations:
    http/tests/storageAccess/request-and-grant-access-then-navigate-should-not-have-access.html
    no longer marked as flaky. Note that the wrong test was marked flaky. It should have been
    http/tests/storageAccess/request-and-grant-access-then-detach-should-not-have-access.html.

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

28 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/storageAccess/request-and-grant-access-then-detach-should-not-have-access-expected.txt
LayoutTests/http/tests/storageAccess/request-and-grant-access-then-detach-should-not-have-access.html
LayoutTests/platform/mac-wk2/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/platform/network/NetworkStorageSession.h
Source/WebCore/platform/network/cf/NetworkStorageSessionCFNet.cpp
Source/WebKit/ChangeLog
Source/WebKit/NetworkProcess/NetworkProcess.cpp
Source/WebKit/NetworkProcess/NetworkProcess.h
Source/WebKit/NetworkProcess/NetworkProcess.messages.in
Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm
Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h
Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp
Source/WebKit/UIProcess/Network/NetworkProcessProxy.h
Source/WebKit/UIProcess/Network/NetworkProcessProxy.messages.in
Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp
Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h
Tools/ChangeLog
Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl
Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp
Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp
Tools/WebKitTestRunner/InjectedBundle/TestRunner.h
Tools/WebKitTestRunner/TestController.cpp
Tools/WebKitTestRunner/TestController.h
Tools/WebKitTestRunner/TestInvocation.cpp
Tools/WebKitTestRunner/TestInvocation.h
Tools/WebKitTestRunner/cocoa/TestControllerCocoa.mm

index ba443ed..dbb520b 100644 (file)
@@ -1,3 +1,23 @@
+2018-02-05  John Wilander  <wilander@apple.com>
+
+        Storage Access API: Add testRunner.getAllStorageAccessEntries() to make testing easier and more explicit
+        https://bugs.webkit.org/show_bug.cgi?id=181601
+        <rdar://problem/36475837>
+
+        Reviewed by Alex Christensen.
+
+        http/tests/storageAccess/request-and-grant-access-then-detach-should-not-have-access.html
+        was found to be flaky. With the testRunner.hasStorageAccessEntry() getter
+        it's possible to check access even if a frame doesn't respond timely to
+        postMessage after detach and attach.
+
+        * http/tests/storageAccess/request-and-grant-access-then-detach-should-not-have-access-expected.txt:
+        * http/tests/storageAccess/request-and-grant-access-then-detach-should-not-have-access.html:
+        * platform/mac-wk2/TestExpectations:
+            http/tests/storageAccess/request-and-grant-access-then-navigate-should-not-have-access.html
+            no longer marked as flaky. Note that the wrong test was marked flaky. It should have been
+            http/tests/storageAccess/request-and-grant-access-then-detach-should-not-have-access.html.
+
 2018-02-05  Matt Lewis  <jlewis3@apple.com>
 
         Skipped imported/w3c/web-platform-tests/2dcontext/imagebitmap/createImageBitmap-origin.sub.html
index 7379163..ac424e4 100644 (file)
@@ -4,7 +4,8 @@ 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 PASS. document.cookie == , cookies seen server-side == "No cookies"
+PASS There is a storage access entry for localhost.
+PASS There is no storage access entry for localhost after iframe detach.
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 69f161d..1ed3bd3 100644 (file)
         }
 
         const iframeID = "TheIframeThatRequestsStorageAccess";
-        function askIframeIfItHasStorageAccess() {
-            var iframeContentWindow = document.getElementById(iframeID).contentWindow;
-            iframeContentWindow.postMessage("reportBackCookies", "http://localhost:8000");
+        function askIfIframeStillHasStorageAccess() {
+            testRunner.getAllStorageAccessEntries(function (arrayOfDomains) {
+                var passed = true;
+                for (var i = 0; i < arrayOfDomains.length; ++i) {
+                    if (arrayOfDomains[i] === "localhost") {
+                        passed = false;
+                        break;
+                    }
+                }
+                if (passed)
+                    testPassed("There is no storage access entry for localhost after iframe detach.");
+                else
+                    testFailed("There is still a storage access entry for localhost after iframe detach.");
+                finishTest();
+            });
         }
 
-        function detachIframeAndAskWhetherItStillHasStorageAccess() {
-            var theIframe = document.getElementById(iframeID);
-            theIframe.onload = askIframeIfItHasStorageAccess;
-            document.getElementsByTagName('body')[0].appendChild(theIframe);
+        function detachIframeAndCheckWhetherItStillHasStorageAccess() {
+            testRunner.getAllStorageAccessEntries(function (arrayOfDomains) {
+                var passed = false;
+                for (var i = 0; i < arrayOfDomains.length; ++i) {
+                    if (arrayOfDomains[i] === "localhost") {
+                        passed = true;
+                        break;
+                    }
+                }
+                if (passed)
+                    testPassed("There is a storage access entry for localhost.");
+                else
+                    testFailed("There is no storage access entry for localhost.");
+                var theIframe = document.getElementById(iframeID);
+                theIframe.onload = askIfIframeStillHasStorageAccess;
+                document.getElementsByTagName('body')[0].appendChild(theIframe);
+            });
         }
 
-        const expectedPassMessages = 2;
-        var passMessagesReceived = 0;
         function receiveMessage(event) {
             if (event.origin === "http://localhost:8000") {
                 if (event.data.indexOf("PASS") !== -1) {
                     testPassed(event.data.replace("PASS ", ""));
-                    passMessagesReceived++;
-                    if (passMessagesReceived >= expectedPassMessages)
-                        finishTest();
-                    else
-                        detachIframeAndAskWhetherItStillHasStorageAccess();
+                    detachIframeAndCheckWhetherItStillHasStorageAccess();
                 } else {
                     testFailed(event.data);
                     finishTest();
             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.");
-                        finishTest();
-                    }
-                },
+                function () { },
                 function () {
                     testFailed("Promise rejected.");
                     finishTest();
@@ -77,8 +89,8 @@
 
         function runTest() {
             if (document.location.hash !== "#elementActivated") {
-                activateElement(iframeID);
                 document.location.hash = "elementActivated";
+                activateElement(iframeID);
             }
         }
 
     </script>
 </head>
 <body>
-<iframe sandbox="allow-storage-access-by-user-activation allow-scripts allow-same-origin allow-modals" onload="runTest()" id="TheIframeThatRequestsStorageAccess" src="http://localhost:8000/storageAccess/resources/request-storage-access-iframe.html#userShouldGrantAccess,userShouldBeConsulted,policyShouldGrantAccess"></iframe>
+<div>
+    <iframe sandbox="allow-storage-access-by-user-activation allow-scripts allow-same-origin allow-modals" onload="runTest()" id="TheIframeThatRequestsStorageAccess" src="http://localhost:8000/storageAccess/resources/request-storage-access-iframe.html#userShouldGrantAccess,userShouldBeConsulted,policyShouldGrantAccess"></iframe>
+</div>
 </body>
 </html>
\ No newline at end of file
index f0ebc91..41a5e72 100644 (file)
@@ -760,8 +760,7 @@ http/tests/resourceLoadStatistics/user-interaction-reported-after-website-data-r
 [ HighSierra+ ] http/tests/storageAccess/has-storage-access-from-prevalent-domain-with-non-recent-user-interaction.html [ Pass ]
 [ HighSierra+ ] http/tests/storageAccess/has-storage-access-from-prevalent-domain-with-recent-user-interaction.html [ Pass ]
 [ HighSierra+ ] http/tests/storageAccess/request-and-grant-access-then-detach-should-not-have-access.html [ Pass ]
-
-webkit.org/b/181601 [ HighSierra+ Release ] http/tests/storageAccess/request-and-grant-access-then-navigate-should-not-have-access.html [ Pass Failure ]
+[ HighSierra+ ] http/tests/storageAccess/request-and-grant-access-then-navigate-should-not-have-access.html [ Pass ]
 
 webkit.org/b/173861 [ Release ] http/tests/webrtc/filtering-ice-candidate-same-origin-frame.html [ Pass Timeout ]
 webkit.org/b/173861 [ Release ] http/tests/webrtc/filtering-ice-candidate-cross-origin-frame.html [ Pass Timeout ]
index e00df56..61f3ab8 100644 (file)
@@ -1,3 +1,22 @@
+2018-02-05  John Wilander  <wilander@apple.com>
+
+        Storage Access API: Add testRunner.getAllStorageAccessEntries() to make testing easier and more explicit
+        https://bugs.webkit.org/show_bug.cgi?id=181601
+        <rdar://problem/36475837>
+
+        Reviewed by Alex Christensen.
+
+        No new tests. Existing test updated.
+
+        http/tests/storageAccess/request-and-grant-access-then-detach-should-not-have-access.html
+        was found to be flaky. With the testRunner.hasStorageAccessEntry() getter
+        it's possible to check access even if a frame doesn't respond timely to
+        postMessage after detach and attach.
+
+        * platform/network/NetworkStorageSession.h:
+        * platform/network/cf/NetworkStorageSessionCFNet.cpp:
+        (WebCore::NetworkStorageSession::getAllStorageAccessEntries const):
+
 2018-02-05  Youenn Fablet  <youenn@apple.com>
 
         Use downcast in createLinkPreloadResourceClient
index 63c9cf0..65b5f3d 100644 (file)
@@ -106,6 +106,7 @@ public:
     WEBCORE_EXPORT void removePrevalentDomains(const Vector<String>& domains);
     WEBCORE_EXPORT bool hasStorageAccessForFrame(const String& resourceDomain, const String& firstPartyDomain, uint64_t frameID, uint64_t pageID) const;
     WEBCORE_EXPORT bool hasStorageAccessForFrame(const ResourceRequest&, uint64_t frameID, uint64_t pageID) const;
+    WEBCORE_EXPORT Vector<String> getAllStorageAccessEntries() const;
     WEBCORE_EXPORT void grantStorageAccessForFrame(const String& resourceDomain, const String& firstPartyDomain, uint64_t frameID, uint64_t pageID);
     WEBCORE_EXPORT void removeStorageAccessForFrame(uint64_t frameID, uint64_t pageID);
     WEBCORE_EXPORT void removeStorageAccessForAllFramesOnPage(uint64_t pageID);
index c1a0a1c..ef3c46f 100644 (file)
@@ -304,6 +304,17 @@ bool NetworkStorageSession::hasStorageAccessForFrame(const ResourceRequest& requ
     return hasStorageAccessForFrame(getPartitioningDomain(request.url()), getPartitioningDomain(request.firstPartyForCookies()), frameID, pageID);
 }
 
+Vector<String> NetworkStorageSession::getAllStorageAccessEntries() const
+{
+    Vector<String> entries;
+    for (auto& pageID : m_framesGrantedStorageAccess.keys()) {
+        auto it1 = m_framesGrantedStorageAccess.find(pageID);
+        for (auto& frameID : it1->value.keys())
+            entries.append(it1->value.find(frameID)->value);
+    }
+    return entries;
+}
+    
 void NetworkStorageSession::grantStorageAccessForFrame(const String& resourceDomain, const String& firstPartyDomain, uint64_t frameID, uint64_t pageID)
 {
     UNUSED_PARAM(firstPartyDomain);
index 9a3e75d..a4569c5 100644 (file)
@@ -1,3 +1,32 @@
+2018-02-05  John Wilander  <wilander@apple.com>
+
+        Storage Access API: Add testRunner.getAllStorageAccessEntries() to make testing easier and more explicit
+        https://bugs.webkit.org/show_bug.cgi?id=181601
+        <rdar://problem/36475837>
+
+        Reviewed by Alex Christensen.
+
+        http/tests/storageAccess/request-and-grant-access-then-detach-should-not-have-access.html
+        was found to be flaky. With the testRunner.hasStorageAccessEntry() getter
+        it's possible to check access even if a frame doesn't respond timely to
+        postMessage after detach and attach.
+
+        * NetworkProcess/NetworkProcess.cpp:
+        (WebKit::NetworkProcess::getAllStorageAccessEntries):
+        * NetworkProcess/NetworkProcess.h:
+        * NetworkProcess/NetworkProcess.messages.in:
+        * UIProcess/API/Cocoa/WKWebsiteDataStore.mm:
+        (-[WKWebsiteDataStore _getAllStorageAccessEntries:]):
+        * UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h:
+        * UIProcess/Network/NetworkProcessProxy.cpp:
+        (WebKit::NetworkProcessProxy::getAllStorageAccessEntries):
+        (WebKit::NetworkProcessProxy::allStorageAccessEntriesResult):
+        * UIProcess/Network/NetworkProcessProxy.h:
+        * UIProcess/Network/NetworkProcessProxy.messages.in:
+        * UIProcess/WebsiteData/WebsiteDataStore.cpp:
+        (WebKit::WebsiteDataStore::getAllStorageAccessEntries):
+        * UIProcess/WebsiteData/WebsiteDataStore.h:
+
 2018-02-05  Daniel Bates  <dabates@apple.com>
 
         Disallow evaluating JavaScript from NPP_Destroy() in WebKit
index d1d792e..68b70a0 100644 (file)
@@ -361,6 +361,14 @@ void NetworkProcess::hasStorageAccessForFrame(PAL::SessionID sessionID, const St
         ASSERT_NOT_REACHED();
 }
 
+void NetworkProcess::getAllStorageAccessEntries(PAL::SessionID sessionID, uint64_t contextId)
+{
+    if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
+        parentProcessConnection()->send(Messages::NetworkProcessProxy::AllStorageAccessEntriesResult(networkStorageSession->getAllStorageAccessEntries(), contextId), 0);
+    else
+        ASSERT_NOT_REACHED();
+}
+
 void NetworkProcess::grantStorageAccessForFrame(PAL::SessionID sessionID, const String& resourceDomain, const String& firstPartyDomain, uint64_t frameID, uint64_t pageID, uint64_t contextId)
 {
     bool isStorageGranted = false;
index 15a7469..10189e7 100644 (file)
@@ -137,6 +137,7 @@ public:
 #if HAVE(CFNETWORK_STORAGE_PARTITIONING)
     void updatePrevalentDomainsToPartitionOrBlockCookies(PAL::SessionID, const Vector<String>& domainsToPartition, const Vector<String>& domainsToBlock, const Vector<String>& domainsToNeitherPartitionNorBlock, bool shouldClearFirst);
     void hasStorageAccessForFrame(PAL::SessionID, const String& resourceDomain, const String& firstPartyDomain, uint64_t frameID, uint64_t pageID, uint64_t contextId);
+    void getAllStorageAccessEntries(PAL::SessionID, uint64_t contextId);
     void grantStorageAccessForFrame(PAL::SessionID, const String& resourceDomain, const String& firstPartyDomain, uint64_t frameID, uint64_t pageID, uint64_t contextId);
     void removePrevalentDomains(PAL::SessionID, const Vector<String>& domains);
 #endif
index 9610574..0d29e31 100644 (file)
@@ -84,6 +84,7 @@ messages -> NetworkProcess LegacyReceiver {
 #if HAVE(CFNETWORK_STORAGE_PARTITIONING)
     UpdatePrevalentDomainsToPartitionOrBlockCookies(PAL::SessionID sessionID, Vector<String> domainsToPartition, Vector<String> domainsToBlock, Vector<String> domainsToNeitherPartitionNorBlock, bool shouldClearFirst)
     HasStorageAccessForFrame(PAL::SessionID sessionID, String resourceDomain, String firstPartyDomain, uint64_t frameID, uint64_t pageID, uint64_t contextId)
+    GetAllStorageAccessEntries(PAL::SessionID sessionID, uint64_t contextId)
     GrantStorageAccessForFrame(PAL::SessionID sessionID, String resourceDomain, String firstPartyDomain, uint64_t frameID, uint64_t pageID, uint64_t contextId)
     RemovePrevalentDomains(PAL::SessionID sessionID, Vector<String> domainsWithInteraction);
 #endif
index c9ff938..301553d 100644 (file)
@@ -28,6 +28,7 @@
 
 #if WK_API_ENABLED
 
+#import "APIString.h"
 #import "WKHTTPCookieStoreInternal.h"
 #import "WKNSArray.h"
 #import "WKWebsiteDataRecordInternal.h"
@@ -656,6 +657,18 @@ static Vector<WebKit::WebsiteDataRecord> toWebsiteDataRecords(NSArray *dataRecor
     WebKit::WebsiteDataStore::allowWebsiteDataRecordsForAllOrigins();
 }
 
+- (void)_getAllStorageAccessEntries:(void (^)(NSArray<NSString *> *domains))completionHandler
+{
+    _websiteDataStore->websiteDataStore().getAllStorageAccessEntries([completionHandler = makeBlockPtr(completionHandler)](auto domains) {
+        Vector<RefPtr<API::Object>> apiDomains;
+        apiDomains.reserveInitialCapacity(domains.size());
+        for (auto& domain : domains)
+            apiDomains.uncheckedAppend(API::String::create(domain));
+
+        completionHandler(wrapper(API::Array::create(WTFMove(apiDomains))));
+    });
+}
+
 @end
 
 #endif // WK_API_ENABLED
index 6213556..90af782 100644 (file)
@@ -89,6 +89,7 @@ typedef NS_OPTIONS(NSUInteger, _WKWebsiteDataStoreFetchOptions) {
 - (void)_resourceLoadStatisticsClearInMemoryAndPersistentStoreModifiedSinceHours:(unsigned)hours completionHandler:(void (^)(void))completionHandler WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
 - (void)_resourceLoadStatisticsResetToConsistentState WK_API_AVAILABLE(macosx(10.13), ios(11.0));
 - (void)_setResourceLoadStatisticsTestingCallback:(nullable void (^)(WKWebsiteDataStore *, NSString *))callback WK_API_AVAILABLE(macosx(10.13), ios(11.0));
+- (void)_getAllStorageAccessEntries:(void (^)(NSArray<NSString *> *domains))completionHandler WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
 + (void)_allowWebsiteDataRecordsForAllOrigins WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
 @end
 
index 8b3bd40..dd217f1 100644 (file)
@@ -433,6 +433,20 @@ void NetworkProcessProxy::storageAccessRequestResult(bool wasGranted, uint64_t c
     auto callback = m_storageAccessResponseCallbackMap.take(contextId);
     callback(wasGranted);
 }
+
+void NetworkProcessProxy::getAllStorageAccessEntries(PAL::SessionID sessionID, CompletionHandler<void(Vector<String>&& domains)>&& callback)
+{
+    auto contextId = nextRequestStorageAccessContextId();
+    auto addResult = m_allStorageAccessEntriesCallbackMap.add(contextId, WTFMove(callback));
+    ASSERT_UNUSED(addResult, addResult.isNewEntry);
+    send(Messages::NetworkProcess::GetAllStorageAccessEntries(sessionID, contextId), 0);
+}
+
+void NetworkProcessProxy::allStorageAccessEntriesResult(Vector<String>&& domains, uint64_t contextId)
+{
+    auto callback = m_allStorageAccessEntriesCallbackMap.take(contextId);
+    callback(WTFMove(domains));
+}
 #endif
 
 void NetworkProcessProxy::sendProcessWillSuspendImminently()
index e58de24..72f3c16 100644 (file)
@@ -80,6 +80,7 @@ public:
 
 #if HAVE(CFNETWORK_STORAGE_PARTITIONING)
     void hasStorageAccessForFrame(PAL::SessionID, const String& resourceDomain, const String& firstPartyDomain, uint64_t frameID, uint64_t pageID, CompletionHandler<void(bool)>&& callback);
+    void getAllStorageAccessEntries(PAL::SessionID, CompletionHandler<void(Vector<String>&& domains)>&&);
     void grantStorageAccessForFrame(PAL::SessionID, const String& resourceDomain, const String& firstPartyDomain, uint64_t frameID, uint64_t pageID, CompletionHandler<void(bool)>&& callback);
 #endif
 
@@ -134,6 +135,7 @@ private:
 #endif
 #if HAVE(CFNETWORK_STORAGE_PARTITIONING)
     void storageAccessRequestResult(bool wasGranted, uint64_t contextId);
+    void allStorageAccessEntriesResult(Vector<String>&& domains, uint64_t contextId);
 #endif
 
     // ProcessLauncher::Client
@@ -157,6 +159,7 @@ private:
 
     HashMap<uint64_t, CompletionHandler<void(bool success)>> m_writeBlobToFilePathCallbackMap;
     HashMap<uint64_t, WTF::CompletionHandler<void(bool wasGranted)>> m_storageAccessResponseCallbackMap;
+    HashMap<uint64_t, CompletionHandler<void(Vector<String>&& domains)>> m_allStorageAccessEntriesCallbackMap;
 };
 
 } // namespace WebKit
index 7f773ac..6126ea5 100644 (file)
@@ -46,4 +46,5 @@ messages -> NetworkProcessProxy LegacyReceiver {
 #endif
 #if HAVE(CFNETWORK_STORAGE_PARTITIONING)
     StorageAccessRequestResult(bool wasGranted, uint64_t contextId)
+    AllStorageAccessEntriesResult(Vector<String> domains, uint64_t contextId)
 }
index bb0c45a..95704ec 100644 (file)
@@ -1202,6 +1202,12 @@ void WebsiteDataStore::hasStorageAccessForFrameHandler(const String& resourceDom
         processPool->networkProcess()->hasStorageAccessForFrame(m_sessionID, resourceDomain, firstPartyDomain, frameID, pageID, WTFMove(callback));
 }
 
+void WebsiteDataStore::getAllStorageAccessEntries(CompletionHandler<void(Vector<String>&& domains)>&& callback)
+{
+    for (auto& processPool : processPools())
+        processPool->networkProcess()->getAllStorageAccessEntries(m_sessionID, WTFMove(callback));
+}
+
 void WebsiteDataStore::grantStorageAccessForFrameHandler(const String& resourceDomain, const String& firstPartyDomain, uint64_t frameID, uint64_t pageID, WTF::CompletionHandler<void(bool wasGranted)>&& callback)
 {
     for (auto& processPool : processPools())
index 32295fc..e6f4a78 100644 (file)
@@ -125,6 +125,7 @@ public:
 #if HAVE(CFNETWORK_STORAGE_PARTITIONING)
     void updatePrevalentDomainsToPartitionOrBlockCookies(const Vector<String>& domainsToPartition, const Vector<String>& domainsToBlock, const Vector<String>& domainsToNeitherPartitionNorBlock, ShouldClearFirst);
     void hasStorageAccessForFrameHandler(const String& resourceDomain, const String& firstPartyDomain, uint64_t frameID, uint64_t pageID, WTF::CompletionHandler<void(bool hasAccess)>&& callback);
+    void getAllStorageAccessEntries(CompletionHandler<void(Vector<String>&& domains)>&&);
     void grantStorageAccessForFrameHandler(const String& resourceDomain, const String& firstPartyDomain, uint64_t frameID, uint64_t pageID, WTF::CompletionHandler<void(bool wasGranted)>&& callback);
     void removePrevalentDomains(const Vector<String>& domains);
     void hasStorageAccess(String&& subFrameHost, String&& topFrameHost, uint64_t frameID, uint64_t pageID, WTF::CompletionHandler<void (bool)>&& callback);
index 59a20ca..674da56 100644 (file)
@@ -1,3 +1,37 @@
+2018-02-05  John Wilander  <wilander@apple.com>
+
+        Storage Access API: Add testRunner.getAllStorageAccessEntries() to make testing easier and more explicit
+        https://bugs.webkit.org/show_bug.cgi?id=181601
+        <rdar://problem/36475837>
+
+        Reviewed by Alex Christensen.
+
+        http/tests/storageAccess/request-and-grant-access-then-detach-should-not-have-access.html
+        was found to be flaky. With the testRunner.hasStorageAccessEntry() getter
+        it's possible to check access even if a frame doesn't respond timely to
+        postMessage after detach and attach.
+
+        * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
+        * WebKitTestRunner/InjectedBundle/InjectedBundle.cpp:
+        (WTR::InjectedBundle::didReceiveMessageToPage):
+        * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+        (WTR::TestRunner::setStorageAccessAPIEnabled):
+            Just moved for source file grouping.
+        (WTR::TestRunner::getAllStorageAccessEntries):
+        (WTR::TestRunner::callDidReceiveAllStorageAccessEntriesCallback):
+        * WebKitTestRunner/InjectedBundle/TestRunner.h:
+        * WebKitTestRunner/TestController.cpp:
+        (WTR::TestController::getAllStorageAccessEntries):
+            Note that this is just stubbed out, i.e. not implemented.
+        * WebKitTestRunner/TestController.h:
+        * WebKitTestRunner/TestInvocation.cpp:
+        (WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):
+        (WTR::TestInvocation::didReceiveAllStorageAccessEntries):
+        * WebKitTestRunner/TestInvocation.h:
+        * WebKitTestRunner/cocoa/TestControllerCocoa.mm:
+        (WTR::TestController::getAllStorageAccessEntries):
+            This is the Cocoa-specific version of this test infrastructure.
+
 2018-02-05  Basuke Suzuki  <Basuke.Suzuki@sony.com>
 
         [Win] Enable multi CPU building on MSBuild.
index 1ed7af0..368f4af 100644 (file)
@@ -176,7 +176,6 @@ interface TestRunner {
     // Cookies testing
     void setAlwaysAcceptCookies(boolean accept);
     void setCookieStoragePartitioningEnabled(boolean enabled);
-    void setStorageAccessAPIEnabled(boolean enabled);
 
     void overridePreference(DOMString preference, DOMString value);
 
@@ -298,6 +297,10 @@ interface TestRunner {
     void statisticsClearThroughWebsiteDataRemoval(object callback);
     void statisticsResetToConsistentState();
 
+    // Storage Access API
+    void setStorageAccessAPIEnabled(boolean enabled);
+    void getAllStorageAccessEntries(object callback);
+
     // Open panel
     void setOpenPanelFiles(object filesArray);
 
index 72ea3d2..fe52c54 100644 (file)
@@ -250,6 +250,24 @@ void InjectedBundle::didReceiveMessageToPage(WKBundlePageRef page, WKStringRef m
         return;
     }
 
+    if (WKStringIsEqualToUTF8CString(messageName, "CallDidReceiveAllStorageAccessEntries")) {
+        ASSERT(messageBody);
+        ASSERT(WKGetTypeID(messageBody) == WKArrayGetTypeID());
+
+        WKArrayRef domainsArray = static_cast<WKArrayRef>(messageBody);
+        auto size = WKArrayGetSize(domainsArray);
+        Vector<String> domains;
+        domains.reserveInitialCapacity(size);
+        for (size_t i = 0; i < size; ++i) {
+            WKTypeRef item = WKArrayGetItemAtIndex(domainsArray, i);
+            if (item && WKGetTypeID(item) == WKStringGetTypeID())
+                domains.append(toWTFString(static_cast<WKStringRef>(item)));
+        }
+
+        m_testRunner->callDidReceiveAllStorageAccessEntriesCallback(domains);
+        return;
+    }
+
     if (WKStringIsEqualToUTF8CString(messageName, "CallDidRemoveAllSessionCredentialsCallback")) {
         m_testRunner->callDidRemoveAllSessionCredentialsCallback();
         return;
index 270d638..f80b03f 100644 (file)
@@ -652,6 +652,7 @@ enum {
     StatisticsDidRunTelemetryCallbackID,
     StatisticsDidClearThroughWebsiteDataRemovalCallbackID,
     StatisticsDidSetPartitionOrBlockCookiesForHostCallbackID,
+    AllStorageAccessEntriesCallbackID,
     DidRemoveAllSessionCredentialsCallbackID,
     GetApplicationManifestCallbackID,
     FirstUIScriptCallbackID = 100
@@ -785,15 +786,6 @@ void TestRunner::setCookieStoragePartitioningEnabled(bool enabled)
     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
 }
 
-void TestRunner::setStorageAccessAPIEnabled(bool enabled)
-{
-    WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStorageAccessAPIEnabled"));
-    
-    WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(enabled));
-    
-    WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
-}
-    
 double TestRunner::preciseTime()
 {
     return currentTime();
@@ -1685,6 +1677,47 @@ void TestRunner::statisticsResetToConsistentState()
     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), 0, nullptr);
 }
 
+void TestRunner::setStorageAccessAPIEnabled(bool enabled)
+{
+    WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStorageAccessAPIEnabled"));
+    
+    WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(enabled));
+    
+    WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
+}
+
+void TestRunner::getAllStorageAccessEntries(JSValueRef callback)
+{
+    cacheTestRunnerCallback(AllStorageAccessEntriesCallbackID, callback);
+    
+    WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("GetAllStorageAccessEntries"));
+    WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), 0, nullptr);
+}
+
+void TestRunner::callDidReceiveAllStorageAccessEntriesCallback(Vector<String>& domains)
+{
+    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
+    JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
+    
+    StringBuilder stringBuilder;
+    stringBuilder.appendLiteral("[");
+    bool firstDomain = true;
+    for (auto& domain : domains) {
+        if (firstDomain)
+            firstDomain = false;
+        else
+            stringBuilder.appendLiteral(", ");
+        stringBuilder.appendLiteral("\"");
+        stringBuilder.append(domain);
+        stringBuilder.appendLiteral("\"");
+    }
+    stringBuilder.appendLiteral("]");
+    
+    JSValueRef result = JSValueMakeFromJSONString(context, JSStringCreateWithUTF8CString(stringBuilder.toString().utf8().data()));
+
+    callTestRunnerCallback(AllStorageAccessEntriesCallbackID, 1, &result);
+}
+
 #if PLATFORM(MAC)
 void TestRunner::connectMockGamepad(unsigned index)
 {
index cc60415..ac4288c 100644 (file)
@@ -280,7 +280,6 @@ public:
     // Cookies testing
     void setAlwaysAcceptCookies(bool);
     void setCookieStoragePartitioningEnabled(bool);
-    void setStorageAccessAPIEnabled(bool);
 
     // Custom full screen behavior.
     void setHasCustomFullScreenBehavior(bool value) { m_customFullScreenBehavior = value; }
@@ -399,6 +398,11 @@ public:
     void statisticsCallClearThroughWebsiteDataRemovalCallback();
     void statisticsResetToConsistentState();
 
+    // Storage Access API
+    void setStorageAccessAPIEnabled(bool);
+    void getAllStorageAccessEntries(JSValueRef callback);
+    void callDidReceiveAllStorageAccessEntriesCallback(Vector<String>& domains);
+
     // Open panel
     void setOpenPanelFiles(JSValueRef);
 
index fd548ea..2487bb6 100644 (file)
@@ -2698,6 +2698,11 @@ void TestController::statisticsResetToConsistentState()
     WKWebsiteDataStoreStatisticsResetToConsistentState(dataStore);
 }
 
+void TestController::getAllStorageAccessEntries()
+{
+    // FIXME: Implement C API version of this test.
+}
+
 #endif
 
 } // namespace WTR
index 436a80d..1a0940a 100644 (file)
@@ -184,6 +184,8 @@ public:
     void statisticsClearThroughWebsiteDataRemoval();
     void statisticsResetToConsistentState();
 
+    void getAllStorageAccessEntries();
+
     WKArrayRef openPanelFileURLs() const { return m_openPanelFileURLs.get(); }
     void setOpenPanelFileURLs(WKArrayRef fileURLs) { m_openPanelFileURLs = fileURLs; }
 
index 987ade4..b9543f6 100644 (file)
@@ -835,7 +835,12 @@ WKRetainPtr<WKTypeRef> TestInvocation::didReceiveSynchronousMessageFromInjectedB
         WKCookieManagerSetStorageAccessAPIEnabled(WKContextGetCookieManager(TestController::singleton().context()), WKBooleanGetValue(accept));
         return nullptr;
     }
-    
+
+    if (WKStringIsEqualToUTF8CString(messageName, "GetAllStorageAccessEntries")) {
+        TestController::singleton().getAllStorageAccessEntries();
+        return nullptr;
+    }
+
     if (WKStringIsEqualToUTF8CString(messageName, "SetAllowsAnySSLCertificate")) {
         TestController::singleton().setAllowsAnySSLCertificate(WKBooleanGetValue(static_cast<WKBooleanRef>(messageBody)));
         return nullptr;
@@ -1351,6 +1356,17 @@ void TestInvocation::didSetPartitionOrBlockCookiesForHost()
     WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0);
 }
 
+void TestInvocation::didReceiveAllStorageAccessEntries(Vector<String>& domains)
+{
+    WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallDidReceiveAllStorageAccessEntries"));
+    
+    WKRetainPtr<WKMutableArrayRef> messageBody(AdoptWK, WKMutableArrayCreate());
+    for (auto& domain : domains)
+        WKArrayAppendItem(messageBody.get(), adoptWK(WKStringCreateWithUTF8CString(domain.utf8().data())).get());
+    
+    WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), messageBody.get());
+}
+
 void TestInvocation::didRemoveAllSessionCredentials()
 {
     WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallDidRemoveAllSessionCredentialsCallback"));
index 25ce67d..6517740 100644 (file)
@@ -73,6 +73,7 @@ public:
 
     void didClearStatisticsThroughWebsiteDataRemoval();
     void didSetPartitionOrBlockCookiesForHost();
+    void didReceiveAllStorageAccessEntries(Vector<String>& domains);
 
     void didRemoveAllSessionCredentials();
     
index 6fc2509..02bc4dd 100644 (file)
@@ -459,6 +459,18 @@ void TestController::statisticsResetToConsistentState()
 {
     [globalWebViewConfiguration.websiteDataStore _resourceLoadStatisticsResetToConsistentState];
 }
+
+void TestController::getAllStorageAccessEntries()
+{
+    [globalWebViewConfiguration.websiteDataStore _getAllStorageAccessEntries:^(NSArray<NSString *> *nsDomains) {
+        Vector<String> domains;
+        domains.reserveInitialCapacity(nsDomains.count);
+        for (NSString *domain : nsDomains)
+            domains.uncheckedAppend(domain);
+        m_currentInvocation->didReceiveAllStorageAccessEntries(domains);
+    }];
+}
+
 #endif // WK_API_ENABLED
 
 } // namespace WTR