Make ResourceLoadObserver::logWebSocketLoading() handle websockets in detached frames
authorwilander@apple.com <wilander@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 21 Aug 2018 18:02:33 +0000 (18:02 +0000)
committerwilander@apple.com <wilander@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 21 Aug 2018 18:02:33 +0000 (18:02 +0000)
https://bugs.webkit.org/show_bug.cgi?id=188757
<rdar://problem/38713390>

Reviewed by Alex Christensen.

Source/WebCore:

Test: http/tests/websocket/construct-in-detached-frame-resource-load-statistics.html

* Modules/websockets/WebSocket.cpp:
(WebCore::WebSocket::connect):
    Now logs even when a frame doesn't exist.
* loader/ResourceLoadObserver.cpp:
(WebCore::ResourceLoadObserver::shouldLog const):
    Now takes boolean 'usesEphemeralSession' instead of a page to support logging when there is no page.
(WebCore::ResourceLoadObserver::logSubresourceLoading):
    Changed to send a boolean to ResourceLoadObserver::shouldLog().
(WebCore::ResourceLoadObserver::logWebSocketLoading):
    Changed to:
    - receive the main frame's URL and a boolean for ephemeral sessions instead of the Frame.
    - send a boolean to ResourceLoadObserver::shouldLog().
    - No longer call areDomainsAssociated(). It is being removed in https://bugs.webkit.org/show_bug.cgi?id=188756.
(WebCore::ResourceLoadObserver::logUserInteractionWithReducedTimeResolution):
    Changed to send a boolean to ResourceLoadObserver::shouldLog().
* loader/ResourceLoadObserver.h:

Source/WebKit:

These changes are test infrastructure to support the new WebKitTestRunner
function isStatisticsRegisteredAsSubresourceUnder().

* UIProcess/API/C/WKWebsiteDataStoreRef.cpp:
(WKWebsiteDataStoreIsStatisticsRegisteredAsSubresourceUnder):
* UIProcess/API/C/WKWebsiteDataStoreRef.h:
* UIProcess/ResourceLoadStatisticsMemoryStore.cpp:
(WebKit::ResourceLoadStatisticsMemoryStore::isRegisteredAsSubresourceUnder const):
* UIProcess/ResourceLoadStatisticsMemoryStore.h:
* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::isRegisteredAsSubresourceUnder):
* UIProcess/WebResourceLoadStatisticsStore.h:

Tools:

These changes add the new WebKitTestRunner function
isStatisticsRegisteredAsSubresourceUnder().

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

LayoutTests:

* TestExpectations:
    Skipped the new test case since it is only supported on WebKit2.
* http/tests/websocket/construct-in-detached-frame-resource-load-statistics-expected.txt: Added.
* http/tests/websocket/construct-in-detached-frame-resource-load-statistics.html: Added.
* http/tests/websocket/resources/construct-in-detached-frame-resource-load-statistics.html: Added.
* platform/wk2/TestExpectations:
    Marked the new test case as [ Pass ].

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

24 files changed:
LayoutTests/ChangeLog
LayoutTests/TestExpectations
LayoutTests/http/tests/websocket/construct-in-detached-frame-resource-load-statistics-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/websocket/construct-in-detached-frame-resource-load-statistics.html [new file with mode: 0644]
LayoutTests/http/tests/websocket/resources/construct-in-detached-frame-resource-load-statistics.html [new file with mode: 0644]
LayoutTests/platform/wk2/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/Modules/websockets/WebSocket.cpp
Source/WebCore/loader/ResourceLoadObserver.cpp
Source/WebCore/loader/ResourceLoadObserver.h
Source/WebKit/ChangeLog
Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp
Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.h
Source/WebKit/UIProcess/ResourceLoadStatisticsMemoryStore.cpp
Source/WebKit/UIProcess/ResourceLoadStatisticsMemoryStore.h
Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.cpp
Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.h
Tools/ChangeLog
Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl
Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp
Tools/WebKitTestRunner/InjectedBundle/TestRunner.h
Tools/WebKitTestRunner/TestController.cpp
Tools/WebKitTestRunner/TestController.h
Tools/WebKitTestRunner/TestInvocation.cpp

index e8948f4..bbdbdb8 100644 (file)
@@ -1,3 +1,19 @@
+2018-08-21  John Wilander  <wilander@apple.com>
+
+        Make ResourceLoadObserver::logWebSocketLoading() handle websockets in detached frames
+        https://bugs.webkit.org/show_bug.cgi?id=188757
+        <rdar://problem/38713390>
+
+        Reviewed by Alex Christensen.
+
+        * TestExpectations:
+            Skipped the new test case since it is only supported on WebKit2.
+        * http/tests/websocket/construct-in-detached-frame-resource-load-statistics-expected.txt: Added.
+        * http/tests/websocket/construct-in-detached-frame-resource-load-statistics.html: Added.
+        * http/tests/websocket/resources/construct-in-detached-frame-resource-load-statistics.html: Added.
+        * platform/wk2/TestExpectations:
+            Marked the new test case as [ Pass ].
+
 2018-08-21  Daniel Bates  <dabates@apple.com>
 
         Disallow navigations when page cache updates the current document of the frame
index e180442..bef5b5d 100644 (file)
@@ -115,6 +115,7 @@ http/tests/appcache/decide-navigation-policy-after-delay.html [ Skip ]
 http/tests/misc/will-send-request-with-client-provided-http-body.html [ Skip ]
 http/tests/loading/resourceLoadStatistics/ [ Skip ]
 http/tests/resourceLoadStatistics/ [ Skip ]
+http/tests/websocket/construct-in-detached-frame-resource-load-statistics.html [ Skip ]
 http/tests/storageAccess/ [ Skip ]
 http/tests/navigation/process-swap-window-open.html [ Skip ]
 http/tests/navigation/useragent-reload.php [ Skip ]
diff --git a/LayoutTests/http/tests/websocket/construct-in-detached-frame-resource-load-statistics-expected.txt b/LayoutTests/http/tests/websocket/construct-in-detached-frame-resource-load-statistics-expected.txt
new file mode 100644 (file)
index 0000000..848cf21
--- /dev/null
@@ -0,0 +1,5 @@
+PASS localhost registered as subresource under 127.0.0.1.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/websocket/construct-in-detached-frame-resource-load-statistics.html b/LayoutTests/http/tests/websocket/construct-in-detached-frame-resource-load-statistics.html
new file mode 100644 (file)
index 0000000..1f09430
--- /dev/null
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<head>
+    <script src="../resources/js-test-pre.js"></script>
+    <script src="/resourceLoadStatistics/resources/util.js"></script>
+</head>
+<body onload="runTest()">
+<script>
+    description('Construct a WebSocket in a detached frame. The test passes if Resource Load Statistics logs it properly.');
+
+    window.jsTestIsAsync = true;
+
+    function detachIframe() {
+        var testIframe = document.getElementById('testIframe');
+        testIframe.parentNode.remove(testIframe);
+    }
+
+    function completeTest() {
+        if (testRunner.isStatisticsRegisteredAsSubresourceUnder("http://localhost", "http://127.0.0.1"))
+            testPassed("localhost registered as subresource under 127.0.0.1.");
+        else
+            testFailed("localhost not registered as subresource under 127.0.0.1.");
+        setEnableFeature(false, finishJSTest);
+    }
+
+    let dataRecordsScanned = false;
+    function didScanDataRecords() {
+        dataRecordsScanned = true;
+        if (createdWebSocket)
+            completeTest();
+    }
+
+    let createdWebSocket = false;
+    function didCreateWebSocket() {
+        createdWebSocket = true;
+        if (dataRecordsScanned)
+            completeTest();
+    }
+
+    function runTest() {
+        setEnableFeature(true, function() {
+            if (testRunner.isStatisticsRegisteredAsSubresourceUnder("http://localhost", "http://127.0.0.1"))
+                testFailed("localhost already registered as subresource under 127.0.0.1.");
+
+            testRunner.setStatisticsNotifyPagesWhenDataRecordsWereScanned(true);
+            testRunner.installStatisticsDidScanDataRecordsCallback(didScanDataRecords);
+
+            let iframeElement = document.createElement("iframe");
+            iframeElement.src = "resources/construct-in-detached-frame-resource-load-statistics.html";
+            iframeElement.id = "testIframe";
+            document.body.appendChild(iframeElement);
+        });
+    }
+</script>
+<script src="../resources/js-test-post.js"></script>
+</body>
diff --git a/LayoutTests/http/tests/websocket/resources/construct-in-detached-frame-resource-load-statistics.html b/LayoutTests/http/tests/websocket/resources/construct-in-detached-frame-resource-load-statistics.html
new file mode 100644 (file)
index 0000000..ab7518b
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<script>
+    var parentWindow = parent;
+    var webSocketClass = WebSocket;
+
+    parentWindow.detachIframe();
+    try {
+        new webSocketClass('ws://localhost/');
+    } catch (e) {
+        parentWindow.console.log(e.message);
+    }
+    parentWindow.didCreateWebSocket();
+</script>
index 9195b41..925fbd2 100644 (file)
@@ -721,6 +721,7 @@ http/tests/resourceLoadStatistics/grandfathering.html [ Pass ]
 webkit.org/b/180703 http/tests/resourceLoadStatistics/telemetry-generation.html [ Pass Failure ]
 http/tests/resourceLoadStatistics/prune-statistics.html [ Pass ]
 http/tests/resourceLoadStatistics [ Pass ]
+http/tests/websocket/construct-in-detached-frame-resource-load-statistics.html [ Pass ]
 # These are only supported behind a compile time flag in macOS High Sierra + iOS 11, and above.
 http/tests/resourceLoadStatistics/cookie-deletion.html [ Skip ]
 http/tests/resourceLoadStatistics/cookies-with-and-without-user-interaction.html [ Skip ]
index f05937a..f4c755d 100644 (file)
@@ -1,3 +1,30 @@
+2018-08-21  John Wilander  <wilander@apple.com>
+
+        Make ResourceLoadObserver::logWebSocketLoading() handle websockets in detached frames
+        https://bugs.webkit.org/show_bug.cgi?id=188757
+        <rdar://problem/38713390>
+
+        Reviewed by Alex Christensen.
+
+        Test: http/tests/websocket/construct-in-detached-frame-resource-load-statistics.html
+
+        * Modules/websockets/WebSocket.cpp:
+        (WebCore::WebSocket::connect):
+            Now logs even when a frame doesn't exist.
+        * loader/ResourceLoadObserver.cpp:
+        (WebCore::ResourceLoadObserver::shouldLog const):
+            Now takes boolean 'usesEphemeralSession' instead of a page to support logging when there is no page.
+        (WebCore::ResourceLoadObserver::logSubresourceLoading):
+            Changed to send a boolean to ResourceLoadObserver::shouldLog().
+        (WebCore::ResourceLoadObserver::logWebSocketLoading):
+            Changed to:
+            - receive the main frame's URL and a boolean for ephemeral sessions instead of the Frame.
+            - send a boolean to ResourceLoadObserver::shouldLog().
+            - No longer call areDomainsAssociated(). It is being removed in https://bugs.webkit.org/show_bug.cgi?id=188756.
+        (WebCore::ResourceLoadObserver::logUserInteractionWithReducedTimeResolution):
+            Changed to send a boolean to ResourceLoadObserver::shouldLog().
+        * loader/ResourceLoadObserver.h:
+
 2018-08-21  Daniel Bates  <dabates@apple.com>
 
         Disallow navigations when page cache updates the current document of the frame
index c3ddd84..5853621 100644 (file)
@@ -279,6 +279,10 @@ ExceptionOr<void> WebSocket::connect(const String& url, const Vector<String>& pr
         }
     }
 
+    RunLoop::main().dispatch([targetURL = m_url.isolatedCopy(), mainFrameURL = context.url().isolatedCopy(), usesEphemeralSession = context.sessionID().isEphemeral()]() {
+        ResourceLoadObserver::shared().logWebSocketLoading(targetURL, mainFrameURL, usesEphemeralSession);
+    });
+
     if (is<Document>(context)) {
         Document& document = downcast<Document>(context);
         RefPtr<Frame> frame = document.frame();
@@ -307,7 +311,6 @@ ExceptionOr<void> WebSocket::connect(const String& url, const Vector<String>& pr
 #endif
             return { };
         }
-        ResourceLoadObserver::shared().logWebSocketLoading(frame.get(), m_url);
     }
 
     String protocolString;
index 511b912..3a447c7 100644 (file)
@@ -36,6 +36,7 @@
 #include "ResourceLoadStatistics.h"
 #include "ResourceRequest.h"
 #include "ResourceResponse.h"
+#include "ScriptExecutionContext.h"
 #include "SecurityOrigin.h"
 #include "Settings.h"
 #include "URL.h"
@@ -95,13 +96,9 @@ static inline bool is3xxRedirect(const ResourceResponse& response)
     return response.httpStatusCode() >= 300 && response.httpStatusCode() <= 399;
 }
 
-bool ResourceLoadObserver::shouldLog(Page* page) const
+bool ResourceLoadObserver::shouldLog(bool usesEphemeralSession) const
 {
-    // FIXME: Err on the safe side until we have sorted out what to do in worker contexts
-    if (!page)
-        return false;
-
-    return DeprecatedGlobalSettings::resourceLoadStatisticsEnabled() && !page->usesEphemeralSession() && m_notificationCallback;
+    return DeprecatedGlobalSettings::resourceLoadStatisticsEnabled() && !usesEphemeralSession && m_notificationCallback;
 }
 
 void ResourceLoadObserver::logSubresourceLoading(const Frame* frame, const ResourceRequest& newRequest, const ResourceResponse& redirectResponse)
@@ -109,7 +106,7 @@ void ResourceLoadObserver::logSubresourceLoading(const Frame* frame, const Resou
     ASSERT(frame->page());
 
     auto* page = frame->page();
-    if (!shouldLog(page))
+    if (!shouldLog(page->usesEphemeralSession()))
         return;
 
     bool isRedirect = is3xxRedirect(redirectResponse);
@@ -152,19 +149,11 @@ void ResourceLoadObserver::logSubresourceLoading(const Frame* frame, const Resou
         scheduleNotificationIfNeeded();
 }
 
-void ResourceLoadObserver::logWebSocketLoading(const Frame* frame, const URL& targetURL)
+void ResourceLoadObserver::logWebSocketLoading(const URL& targetURL, const URL& mainFrameURL, bool usesEphemeralSession)
 {
-    // FIXME: Web sockets can run in detached frames. Decide how to count such connections.
-    // See LayoutTests/http/tests/websocket/construct-in-detached-frame.html
-    if (!frame)
-        return;
-
-    auto* page = frame->page();
-    if (!shouldLog(page))
+    if (!shouldLog(usesEphemeralSession))
         return;
 
-    auto& mainFrameURL = frame->mainFrame().document()->url();
-
     auto targetHost = targetURL.host();
     auto mainFrameHost = mainFrameURL.host();
     
@@ -173,9 +162,6 @@ void ResourceLoadObserver::logWebSocketLoading(const Frame* frame, const URL& ta
     
     auto targetPrimaryDomain = primaryDomain(targetURL);
     auto mainFramePrimaryDomain = primaryDomain(mainFrameURL);
-    
-    if (areDomainsAssociated(page, targetPrimaryDomain, mainFramePrimaryDomain))
-        return;
 
     auto& targetStatistics = ensureResourceStatisticsForPrimaryDomain(targetPrimaryDomain);
     targetStatistics.lastSeen = ResourceLoadStatistics::reduceTimeResolution(WallTime::now());
@@ -185,11 +171,11 @@ void ResourceLoadObserver::logWebSocketLoading(const Frame* frame, const URL& ta
 
 void ResourceLoadObserver::logUserInteractionWithReducedTimeResolution(const Document& document)
 {
-    if (!shouldLog(document.page()))
-        return;
-
     ASSERT(document.page());
 
+    if (!shouldLog(document.page()->usesEphemeralSession()))
+        return;
+
     auto& url = document.url();
     if (url.isBlankURL() || url.isEmpty())
         return;
index 52570a7..5b6d918 100644 (file)
@@ -44,6 +44,7 @@ class Frame;
 class Page;
 class ResourceRequest;
 class ResourceResponse;
+class ScriptExecutionContext;
 class URL;
 
 struct ResourceLoadStatistics;
@@ -54,7 +55,7 @@ public:
     WEBCORE_EXPORT static ResourceLoadObserver& shared();
 
     void logSubresourceLoading(const Frame*, const ResourceRequest& newRequest, const ResourceResponse& redirectResponse);
-    void logWebSocketLoading(const Frame*, const URL&);
+    void logWebSocketLoading(const URL& targetURL, const URL& mainFrameURL, bool usesEphemeralSession);
     void logUserInteractionWithReducedTimeResolution(const Document&);
     void logWindowCreation(const URL& popupUrl, uint64_t openerPageID, Document& openerDocument);
 
@@ -74,7 +75,7 @@ public:
 private:
     ResourceLoadObserver();
 
-    bool shouldLog(Page*) const;
+    bool shouldLog(bool usesEphemeralSession) const;
     ResourceLoadStatistics& ensureResourceStatisticsForPrimaryDomain(const String&);
 
     void scheduleNotificationIfNeeded();
index 5248e3f..6bf0ad9 100644 (file)
@@ -1,3 +1,24 @@
+2018-08-21  John Wilander  <wilander@apple.com>
+
+        Make ResourceLoadObserver::logWebSocketLoading() handle websockets in detached frames
+        https://bugs.webkit.org/show_bug.cgi?id=188757
+        <rdar://problem/38713390>
+
+        Reviewed by Alex Christensen.
+
+        These changes are test infrastructure to support the new WebKitTestRunner
+        function isStatisticsRegisteredAsSubresourceUnder().
+
+        * UIProcess/API/C/WKWebsiteDataStoreRef.cpp:
+        (WKWebsiteDataStoreIsStatisticsRegisteredAsSubresourceUnder):
+        * UIProcess/API/C/WKWebsiteDataStoreRef.h:
+        * UIProcess/ResourceLoadStatisticsMemoryStore.cpp:
+        (WebKit::ResourceLoadStatisticsMemoryStore::isRegisteredAsSubresourceUnder const):
+        * UIProcess/ResourceLoadStatisticsMemoryStore.h:
+        * UIProcess/WebResourceLoadStatisticsStore.cpp:
+        (WebKit::WebResourceLoadStatisticsStore::isRegisteredAsSubresourceUnder):
+        * UIProcess/WebResourceLoadStatisticsStore.h:
+
 2018-08-21  Daniel Bates  <dabates@apple.com>
 
         Replace TextCheckingTypeMask with OptionSet
index 4d84bce..802d1cd 100644 (file)
@@ -169,6 +169,19 @@ void WKWebsiteDataStoreIsStatisticsVeryPrevalentResource(WKWebsiteDataStoreRef d
     });
 }
 
+void WKWebsiteDataStoreIsStatisticsRegisteredAsSubresourceUnder(WKWebsiteDataStoreRef dataStoreRef, WKStringRef subresourceHost, WKStringRef topFrameHost, void* context, WKWebsiteDataStoreIsStatisticsRegisteredAsSubresourceUnderFunction callback)
+{
+    auto* store = WebKit::toImpl(dataStoreRef)->websiteDataStore().resourceLoadStatistics();
+    if (!store) {
+        callback(false, context);
+        return;
+    }
+    
+    store->isRegisteredAsSubresourceUnder(WebCore::URL(WebCore::URL(), WebKit::toImpl(subresourceHost)->string()), WebCore::URL(WebCore::URL(), WebKit::toImpl(topFrameHost)->string()), [context, callback](bool isRegisteredAsSubresourceUnder) {
+        callback(isRegisteredAsSubresourceUnder, context);
+    });
+}
+
 void WKWebsiteDataStoreIsStatisticsRegisteredAsSubFrameUnder(WKWebsiteDataStoreRef dataStoreRef, WKStringRef subFrameHost, WKStringRef topFrameHost, void* context, WKWebsiteDataStoreIsStatisticsRegisteredAsSubFrameUnderFunction callback)
 {
     auto* store = WebKit::toImpl(dataStoreRef)->websiteDataStore().resourceLoadStatistics();
index 8d01963..0662dcf 100644 (file)
@@ -52,6 +52,8 @@ WK_EXPORT void WKWebsiteDataStoreSetStatisticsVeryPrevalentResource(WKWebsiteDat
 typedef void (*WKWebsiteDataStoreIsStatisticsPrevalentResourceFunction)(bool isPrevalentResource, void* functionContext);
 WK_EXPORT void WKWebsiteDataStoreIsStatisticsPrevalentResource(WKWebsiteDataStoreRef dataStoreRef, WKStringRef host, void* context, WKWebsiteDataStoreIsStatisticsPrevalentResourceFunction callback);
 WK_EXPORT void WKWebsiteDataStoreIsStatisticsVeryPrevalentResource(WKWebsiteDataStoreRef dataStoreRef, WKStringRef host, void* context, WKWebsiteDataStoreIsStatisticsPrevalentResourceFunction callback);
+typedef void (*WKWebsiteDataStoreIsStatisticsRegisteredAsSubresourceUnderFunction)(bool isRegisteredAsSubresourceUnder, void* functionContext);
+WK_EXPORT void WKWebsiteDataStoreIsStatisticsRegisteredAsSubresourceUnder(WKWebsiteDataStoreRef dataStoreRef, WKStringRef subresourceHost, WKStringRef topFrameHost, void* context, WKWebsiteDataStoreIsStatisticsRegisteredAsSubresourceUnderFunction callback);
 typedef void (*WKWebsiteDataStoreIsStatisticsRegisteredAsSubFrameUnderFunction)(bool isRegisteredAsSubFrameUnder, void* functionContext);
 WK_EXPORT void WKWebsiteDataStoreIsStatisticsRegisteredAsSubFrameUnder(WKWebsiteDataStoreRef dataStoreRef, WKStringRef subFrameHost, WKStringRef topFrameHost, void* context, WKWebsiteDataStoreIsStatisticsRegisteredAsSubFrameUnderFunction callback);
 typedef void (*WKWebsiteDataStoreIsStatisticsRegisteredAsRedirectingToFunction)(bool isRegisteredAsRedirectingTo, void* functionContext);
index 348cacd..c2534fd 100644 (file)
@@ -695,6 +695,14 @@ bool ResourceLoadStatisticsMemoryStore::isVeryPrevalentResource(const String& pr
     return mapEntry == m_resourceStatisticsMap.end() ? false : mapEntry->value.isPrevalentResource && mapEntry->value.isVeryPrevalentResource;
 }
 
+bool ResourceLoadStatisticsMemoryStore::isRegisteredAsSubresourceUnder(const String& subresourcePrimaryDomain, const String& topFramePrimaryDomain) const
+{
+    ASSERT(!RunLoop::isMain());
+
+    auto mapEntry = m_resourceStatisticsMap.find(subresourcePrimaryDomain);
+    return mapEntry == m_resourceStatisticsMap.end() ? false : mapEntry->value.subresourceUnderTopFrameOrigins.contains(topFramePrimaryDomain);
+}
+
 bool ResourceLoadStatisticsMemoryStore::isRegisteredAsSubFrameUnder(const String& subFramePrimaryDomain, const String& topFramePrimaryDomain) const
 {
     ASSERT(!RunLoop::isMain());
index 25787f9..40b394b 100644 (file)
@@ -78,6 +78,7 @@ public:
     void grandfatherExistingWebsiteData(CompletionHandler<void()>&&);
     void cancelPendingStatisticsProcessingRequest();
 
+    bool isRegisteredAsSubresourceUnder(const String& subresourcePrimaryDomain, const String& topFramePrimaryDomain) const;
     bool isRegisteredAsSubFrameUnder(const String& subFramePrimaryDomain, const String& topFramePrimaryDomain) const;
     bool isRegisteredAsRedirectingTo(const String& hostRedirectedFromPrimaryDomain, const String& hostRedirectedToPrimaryDomain) const;
 
index 2877cad..8d03721 100644 (file)
@@ -537,6 +537,18 @@ void WebResourceLoadStatisticsStore::isVeryPrevalentResource(const URL& url, Com
     });
 }
 
+void WebResourceLoadStatisticsStore::isRegisteredAsSubresourceUnder(const URL& subresource, const URL& topFrame, CompletionHandler<void(bool)>&& completionHandler)
+{
+    ASSERT(RunLoop::isMain());
+    
+    postTask([this, subresourcePrimaryDomain = isolatedPrimaryDomain(subresource), topFramePrimaryDomain = isolatedPrimaryDomain(topFrame), completionHandler = WTFMove(completionHandler)] () mutable {
+        bool isRegisteredAsSubresourceUnder = m_memoryStore ? m_memoryStore->isRegisteredAsSubresourceUnder(subresourcePrimaryDomain, topFramePrimaryDomain) : false;
+        postTaskReply([isRegisteredAsSubresourceUnder, completionHandler = WTFMove(completionHandler)] () mutable {
+            completionHandler(isRegisteredAsSubresourceUnder);
+        });
+    });
+}
+
 void WebResourceLoadStatisticsStore::isRegisteredAsSubFrameUnder(const URL& subFrame, const URL& topFrame, CompletionHandler<void (bool)>&& completionHandler)
 {
     ASSERT(RunLoop::isMain());
index 244bfa3..fb24408 100644 (file)
@@ -93,6 +93,7 @@ public:
     void setVeryPrevalentResource(const WebCore::URL&, CompletionHandler<void()>&&);
     void isPrevalentResource(const WebCore::URL&, CompletionHandler<void(bool)>&&);
     void isVeryPrevalentResource(const WebCore::URL&, CompletionHandler<void(bool)>&&);
+    void isRegisteredAsSubresourceUnder(const WebCore::URL& subresource, const WebCore::URL& topFrame, CompletionHandler<void(bool)>&&);
     void isRegisteredAsSubFrameUnder(const WebCore::URL& subFrame, const WebCore::URL& topFrame, CompletionHandler<void(bool)>&&);
     void isRegisteredAsRedirectingTo(const WebCore::URL& hostRedirectedFrom, const WebCore::URL& hostRedirectedTo, CompletionHandler<void(bool)>&&);
     void clearPrevalentResource(const WebCore::URL&, CompletionHandler<void()>&&);
index 386901e..0be457f 100644 (file)
@@ -1,3 +1,24 @@
+2018-08-21  John Wilander  <wilander@apple.com>
+
+        Make ResourceLoadObserver::logWebSocketLoading() handle websockets in detached frames
+        https://bugs.webkit.org/show_bug.cgi?id=188757
+        <rdar://problem/38713390>
+
+        Reviewed by Alex Christensen.
+
+        These changes add the new WebKitTestRunner function
+        isStatisticsRegisteredAsSubresourceUnder().
+
+        * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
+        * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+        (WTR::TestRunner::isStatisticsRegisteredAsSubresourceUnder):
+        * WebKitTestRunner/InjectedBundle/TestRunner.h:
+        * WebKitTestRunner/TestController.cpp:
+        (WTR::TestController::isStatisticsRegisteredAsSubresourceUnder):
+        * WebKitTestRunner/TestController.h:
+        * WebKitTestRunner/TestInvocation.cpp:
+        (WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):
+
 2018-08-21  Alex Christensen  <achristensen@webkit.org>
 
         Transition more API tests from WKPageLoaderClient to WKPageNavigationClient
index a9545c6..634d352 100644 (file)
@@ -278,6 +278,7 @@ interface TestRunner {
     void setStatisticsVeryPrevalentResource(DOMString hostName, boolean value, object completionHandler);
     boolean isStatisticsPrevalentResource(DOMString hostName);
     boolean isStatisticsVeryPrevalentResource(DOMString hostName);
+    boolean isStatisticsRegisteredAsSubresourceUnder(DOMString subresourceHost, DOMString topFrameHost);
     boolean isStatisticsRegisteredAsSubFrameUnder(DOMString subFrameHost, DOMString topFrameHost);
     boolean isStatisticsRegisteredAsRedirectingTo(DOMString hostRedirectedFrom, DOMString hostRedirectedTo);
     void setStatisticsHasHadUserInteraction(DOMString hostName, boolean value, object completionHandler);
index 8ea9301..db5cd6d 100644 (file)
@@ -1474,6 +1474,32 @@ bool TestRunner::isStatisticsVeryPrevalentResource(JSStringRef hostName)
     return WKBooleanGetValue(static_cast<WKBooleanRef>(returnData));
 }
 
+bool TestRunner::isStatisticsRegisteredAsSubresourceUnder(JSStringRef subresourceHost, JSStringRef topFrameHost)
+{
+    Vector<WKRetainPtr<WKStringRef>> keys;
+    Vector<WKRetainPtr<WKTypeRef>> values;
+    
+    keys.append({ AdoptWK, WKStringCreateWithUTF8CString("SubresourceHost") });
+    values.append({ AdoptWK, WKStringCreateWithJSString(subresourceHost) });
+    
+    keys.append({ AdoptWK, WKStringCreateWithUTF8CString("TopFrameHost") });
+    values.append({ AdoptWK, WKStringCreateWithJSString(topFrameHost) });
+    
+    Vector<WKStringRef> rawKeys(keys.size());
+    Vector<WKTypeRef> rawValues(values.size());
+    
+    for (size_t i = 0; i < keys.size(); ++i) {
+        rawKeys[i] = keys[i].get();
+        rawValues[i] = values[i].get();
+    }
+    
+    WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("IsStatisticsRegisteredAsSubresourceUnder"));
+    WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
+    WKTypeRef returnData = 0;
+    WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
+    return WKBooleanGetValue(static_cast<WKBooleanRef>(returnData));
+}
+
 bool TestRunner::isStatisticsRegisteredAsSubFrameUnder(JSStringRef subFrameHost, JSStringRef topFrameHost)
 {
     Vector<WKRetainPtr<WKStringRef>> keys;
index a4bfc50..789095f 100644 (file)
@@ -392,6 +392,7 @@ public:
     void statisticsCallDidSetVeryPrevalentResourceCallback();
     bool isStatisticsPrevalentResource(JSStringRef hostName);
     bool isStatisticsVeryPrevalentResource(JSStringRef hostName);
+    bool isStatisticsRegisteredAsSubresourceUnder(JSStringRef subresourceHost, JSStringRef topFrameHost);
     bool isStatisticsRegisteredAsSubFrameUnder(JSStringRef subFrameHost, JSStringRef topFrameHost);
     bool isStatisticsRegisteredAsRedirectingTo(JSStringRef hostRedirectedFrom, JSStringRef hostRedirectedTo);
     void setStatisticsHasHadUserInteraction(JSStringRef hostName, bool value, JSValueRef completionHandler);
index e3a62ea..e0527da 100644 (file)
@@ -2737,6 +2737,15 @@ bool TestController::isStatisticsVeryPrevalentResource(WKStringRef host)
     return context.result;
 }
 
+bool TestController::isStatisticsRegisteredAsSubresourceUnder(WKStringRef subresourceHost, WKStringRef topFrameHost)
+{
+    auto* dataStore = WKContextGetWebsiteDataStore(platformContext());
+    ResourceStatisticsCallbackContext context(*this);
+    WKWebsiteDataStoreIsStatisticsRegisteredAsSubresourceUnder(dataStore, subresourceHost, topFrameHost, &context, resourceStatisticsBooleanResultCallback);
+    runUntil(context.done, noTimeout);
+    return context.result;
+}
+
 bool TestController::isStatisticsRegisteredAsSubFrameUnder(WKStringRef subFrameHost, WKStringRef topFrameHost)
 {
     auto* dataStore = WKContextGetWebsiteDataStore(platformContext());
index 42a2b6f..b07a9b1 100644 (file)
@@ -163,6 +163,7 @@ public:
     void setStatisticsVeryPrevalentResource(WKStringRef hostName, bool value);
     bool isStatisticsPrevalentResource(WKStringRef hostName);
     bool isStatisticsVeryPrevalentResource(WKStringRef hostName);
+    bool isStatisticsRegisteredAsSubresourceUnder(WKStringRef subresourceHost, WKStringRef topFrameHost);
     bool isStatisticsRegisteredAsSubFrameUnder(WKStringRef subFrameHost, WKStringRef topFrameHost);
     bool isStatisticsRegisteredAsRedirectingTo(WKStringRef hostRedirectedFrom, WKStringRef hostRedirectedTo);
     void setStatisticsHasHadUserInteraction(WKStringRef hostName, bool value);
index 7d4fdac..d3e9d8a 100644 (file)
@@ -1105,6 +1105,21 @@ WKRetainPtr<WKTypeRef> TestInvocation::didReceiveSynchronousMessageFromInjectedB
         return result;
     }
     
+    if (WKStringIsEqualToUTF8CString(messageName, "IsStatisticsRegisteredAsSubresourceUnder")) {
+        ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
+        
+        WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
+        WKRetainPtr<WKStringRef> subresourceHostKey(AdoptWK, WKStringCreateWithUTF8CString("SubresourceHost"));
+        WKRetainPtr<WKStringRef> topFrameHostKey(AdoptWK, WKStringCreateWithUTF8CString("TopFrameHost"));
+        
+        WKStringRef subresourceHost = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, subresourceHostKey.get()));
+        WKStringRef topFrameHost = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, topFrameHostKey.get()));
+        
+        bool isRegisteredAsSubresourceUnder = TestController::singleton().isStatisticsRegisteredAsSubresourceUnder(subresourceHost, topFrameHost);
+        WKRetainPtr<WKTypeRef> result(AdoptWK, WKBooleanCreate(isRegisteredAsSubresourceUnder));
+        return result;
+    }
+    
     if (WKStringIsEqualToUTF8CString(messageName, "IsStatisticsRegisteredAsSubFrameUnder")) {
         ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());