Resource Load Statistics: Make it possible to purge only script-accessible cookies
authorwilander@apple.com <wilander@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 7 Mar 2019 17:22:27 +0000 (17:22 +0000)
committerwilander@apple.com <wilander@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 7 Mar 2019 17:22:27 +0000 (17:22 +0000)
https://bugs.webkit.org/show_bug.cgi?id=195383
<rdar://problem/48570136>

Reviewed by Brent Fulgham.

Source/WebCore:

Test: http/tests/resourceLoadStatistics/delete-script-accessible-cookies.html

This patch provides the ability to purge all script-accessible cookies while leaving
HttpOnly cookies in place.

* loader/CookieJar.h:
    Added boolean enum IncludeHttpOnlyCookies for use as function parameter.
* platform/network/NetworkStorageSession.h:
* platform/network/cocoa/NetworkStorageSessionCocoa.mm:
(WebCore::NetworkStorageSession::deleteCookiesForHostnames):
    Support for the new IncludeHttpOnlyCookies flag.
* platform/network/curl/NetworkStorageSessionCurl.cpp:
(WebCore::NetworkStorageSession::deleteCookiesForHostnames):
    Stubbed out the new function and added a FIXME comment.
* platform/network/soup/NetworkStorageSessionSoup.cpp:
(WebCore::NetworkStorageSession::deleteCookiesForHostnames):
    Stubbed out the new function and added a FIXME comment.

Source/WebKit:

This patch provides the ability to purge all script-accessible cookies while leaving
HttpOnly cookies in place.

* NetworkProcess/Classifier/ResourceLoadStatisticsStore.cpp:
(WebKit::ResourceLoadStatisticsStore::removeDataRecords):
* NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::deleteWebsiteDataForRegistrableDomainsInAllPersistentDataStores):
    Support for a new boolean flag on whether or not to include HttpOnly Cookies.
* NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h:
* NetworkProcess/NetworkProcess.cpp:
(WebKit::NetworkProcess::deleteWebsiteDataForRegistrableDomainsInAllPersistentDataStores):
    Support for a new boolean flag on whether or not to include HttpOnly Cookies.
(WebKit::NetworkProcess::deleteCookiesForTesting):
    Test infrastructure.
* NetworkProcess/NetworkProcess.h:
* NetworkProcess/NetworkProcess.messages.in:
* NetworkProcess/NetworkSession.cpp:
(WebKit::NetworkSession::deleteWebsiteDataForRegistrableDomainsInAllPersistentDataStores):
    Support for a new boolean flag on whether or not to include HttpOnly Cookies.
* NetworkProcess/NetworkSession.h:
* UIProcess/API/C/WKWebsiteDataStoreRef.cpp:
(WKWebsiteDataStoreStatisticsDeleteCookiesForTesting):
    Test infrastructure.
* UIProcess/API/C/WKWebsiteDataStoreRef.h:
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::deleteCookiesForTesting):
    Test infrastructure.
* UIProcess/Network/NetworkProcessProxy.h:
* UIProcess/WebsiteData/WebsiteDataStore.cpp:
(WebKit::WebsiteDataStore::deleteCookiesForTesting):
    Test infrastructure.
* UIProcess/WebsiteData/WebsiteDataStore.h:

Tools:

This patch adds test infrastructure to purge only script-accessible cookies,
including a new testRunner function called statisticsDeleteCookiesForHost().git a

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

LayoutTests:

* http/tests/cookies/resources/set-http-only-cookie.php: Added.
* http/tests/resourceLoadStatistics/delete-script-accessible-cookies-expected.txt: Added.
* http/tests/resourceLoadStatistics/delete-script-accessible-cookies.html: Added.

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

32 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/cookies/resources/set-http-only-cookie.php [new file with mode: 0644]
LayoutTests/http/tests/resourceLoadStatistics/delete-script-accessible-cookies-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/resourceLoadStatistics/delete-script-accessible-cookies.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/loader/CookieJar.h
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/ResourceLoadStatisticsStore.cpp
Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp
Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h
Source/WebKit/NetworkProcess/NetworkProcess.cpp
Source/WebKit/NetworkProcess/NetworkProcess.h
Source/WebKit/NetworkProcess/NetworkProcess.messages.in
Source/WebKit/NetworkProcess/NetworkSession.cpp
Source/WebKit/NetworkProcess/NetworkSession.h
Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp
Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.h
Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp
Source/WebKit/UIProcess/Network/NetworkProcessProxy.h
Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp
Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.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 e43904b..c472848 100644 (file)
@@ -1,3 +1,15 @@
+2019-03-07  John Wilander  <wilander@apple.com>
+
+        Resource Load Statistics: Make it possible to purge only script-accessible cookies
+        https://bugs.webkit.org/show_bug.cgi?id=195383
+        <rdar://problem/48570136>
+
+        Reviewed by Brent Fulgham.
+
+        * http/tests/cookies/resources/set-http-only-cookie.php: Added.
+        * http/tests/resourceLoadStatistics/delete-script-accessible-cookies-expected.txt: Added.
+        * http/tests/resourceLoadStatistics/delete-script-accessible-cookies.html: Added.
+
 2019-03-07  Frederic Wang  <fwang@igalia.com>
 
         Update WPT tests for embedded content
diff --git a/LayoutTests/http/tests/cookies/resources/set-http-only-cookie.php b/LayoutTests/http/tests/cookies/resources/set-http-only-cookie.php
new file mode 100644 (file)
index 0000000..410e6fe
--- /dev/null
@@ -0,0 +1,10 @@
+<?php
+if ($_GET['cookieName']) {
+  setcookie($_GET['cookieName'], "1", time() + 86400, "/", "", FALSE, TRUE);
+  echo "Yeah";
+} else {
+  header("HTTP/1.0 200 OK");
+  echo "FAILED: No cookieName parameter found.\n";
+}
+
+?>
diff --git a/LayoutTests/http/tests/resourceLoadStatistics/delete-script-accessible-cookies-expected.txt b/LayoutTests/http/tests/resourceLoadStatistics/delete-script-accessible-cookies-expected.txt
new file mode 100644 (file)
index 0000000..63407dc
--- /dev/null
@@ -0,0 +1,14 @@
+Check that only HttpOnly cookies remain if all script-accessible cookies are deleted.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Before script-accessible deletion: Client-side cookie exists.
+PASS Before script-accessible deletion: HttpOnly cookie exists.
+PASS Before script-accessible deletion: Regular server-side cookie exists.
+PASS After script-accessible deletion:  HttpOnly cookie exists.
+PASS After full deletion:               All cookies are gone.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/resourceLoadStatistics/delete-script-accessible-cookies.html b/LayoutTests/http/tests/resourceLoadStatistics/delete-script-accessible-cookies.html
new file mode 100644 (file)
index 0000000..85feada
--- /dev/null
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+</head>
+<body onload="runTest()">
+<script>
+    description("Check that only HttpOnly cookies remain if all script-accessible cookies are deleted.");
+    jsTestIsAsync = true;
+
+    const httpOnlyCookieName = "http-only-cookie";
+    const serverSideCookieName = "server-side-cookie";
+    const clientSideCookieName = "client-side-cookie";
+
+    function sortStringArray(a, b) {
+        a = a.toLowerCase();
+        b = b.toLowerCase();
+
+        return a > b ? 1 : b > a ? -1 : 0;
+    }
+
+    function checkCookies(isAfterScriptAccessibleDeletion) {
+        let unsortedTestPassedMessages = [];
+        let cookies = internals.getCookies();
+        if (!cookies.length)
+            testFailed((isAfterScriptAccessibleDeletion ? "After" : "Before") + " script-accessible deletion: No cookies found.");
+        for (let cookie of cookies) {
+            switch (cookie.name) {
+                case httpOnlyCookieName:
+                    unsortedTestPassedMessages.push((isAfterScriptAccessibleDeletion ? "After" : "Before") + " script-accessible deletion: " + (isAfterScriptAccessibleDeletion ? " " : "") + "HttpOnly cookie exists.");
+                    break;
+                case serverSideCookieName:
+                    if (isAfterScriptAccessibleDeletion)
+                        testFailed("After script-accessible deletion:  Regular server-side cookie exists.");
+                    else
+                        unsortedTestPassedMessages.push("Before script-accessible deletion: Regular server-side cookie exists.");
+                    break;
+                case clientSideCookieName:
+                    if (isAfterScriptAccessibleDeletion)
+                        testFailed("After script-accessible deletion:  Client-side cookie exists.");
+                    else
+                        unsortedTestPassedMessages.push("Before script-accessible deletion: Client-side cookie exists.");
+                    break;
+            }
+        }
+        let sortedTestPassedMessages = unsortedTestPassedMessages.sort(sortStringArray);
+        for (let testPassedMessage of sortedTestPassedMessages)
+            testPassed(testPassedMessage);
+    }
+
+    async function runTest() {
+        if (!testRunner || !internals) {
+            testFailed("No testRunner or no internals.");
+            return;
+        }
+
+        await fetch("/cookies/resources/set-http-only-cookie.php?cookieName=" + httpOnlyCookieName, { credentials: "same-origin" });
+        await fetch("/cookies/resources/setCookies.cgi", { headers: { "Set-Cookie": serverSideCookieName + "=1; path=/;" }, credentials: "same-origin" });
+        document.cookie = clientSideCookieName + "=1";
+        checkCookies(false);
+        testRunner.statisticsDeleteCookiesForHost("http://127.0.0.1", false);
+        checkCookies(true);
+        testRunner.statisticsDeleteCookiesForHost("http://127.0.0.1", true);
+        let cookiesLeft = internals.getCookies().length;
+        if (cookiesLeft === 0)
+            testPassed("After full deletion:               All cookies are gone.");
+        else
+            testFailed("After full deletion:              " + cookiesLeft + " cookie(s) left.");
+        finishJSTest();
+    }
+</script>
+</body>
+</html>
index 01ee655..808d141 100644 (file)
@@ -1,3 +1,29 @@
+2019-03-07  John Wilander  <wilander@apple.com>
+
+        Resource Load Statistics: Make it possible to purge only script-accessible cookies
+        https://bugs.webkit.org/show_bug.cgi?id=195383
+        <rdar://problem/48570136>
+
+        Reviewed by Brent Fulgham.
+
+        Test: http/tests/resourceLoadStatistics/delete-script-accessible-cookies.html
+
+        This patch provides the ability to purge all script-accessible cookies while leaving
+        HttpOnly cookies in place.
+
+        * loader/CookieJar.h:
+            Added boolean enum IncludeHttpOnlyCookies for use as function parameter.
+        * platform/network/NetworkStorageSession.h:
+        * platform/network/cocoa/NetworkStorageSessionCocoa.mm:
+        (WebCore::NetworkStorageSession::deleteCookiesForHostnames):
+            Support for the new IncludeHttpOnlyCookies flag.
+        * platform/network/curl/NetworkStorageSessionCurl.cpp:
+        (WebCore::NetworkStorageSession::deleteCookiesForHostnames):
+            Stubbed out the new function and added a FIXME comment.
+        * platform/network/soup/NetworkStorageSessionSoup.cpp:
+        (WebCore::NetworkStorageSession::deleteCookiesForHostnames):
+            Stubbed out the new function and added a FIXME comment.
+
 2019-03-06  Mark Lam  <mark.lam@apple.com>
 
         Exception is a JSCell, not a JSObject.
index d4b50e9..0db07c6 100644 (file)
@@ -35,6 +35,7 @@ class SessionID;
 namespace WebCore {
 
 enum class IncludeSecureCookies : bool { No, Yes };
+enum class IncludeHttpOnlyCookies : bool { No, Yes };
 enum class SecureCookiesAccessed : bool { No, Yes };
 
 class Document;
index 8de4249..030200d 100644 (file)
@@ -71,6 +71,7 @@ struct CookieRequestHeaderFieldProxy;
 struct SameSiteInfo;
 
 enum class IncludeSecureCookies : bool;
+enum class IncludeHttpOnlyCookies : bool;
 
 class NetworkStorageSession {
     WTF_MAKE_NONCOPYABLE(NetworkStorageSession); WTF_MAKE_FAST_ALLOCATED;
@@ -130,6 +131,7 @@ public:
     WEBCORE_EXPORT void deleteAllCookies();
     WEBCORE_EXPORT void deleteAllCookiesModifiedSince(WallTime);
     WEBCORE_EXPORT void deleteCookiesForHostnames(const Vector<String>& cookieHostNames);
+    WEBCORE_EXPORT void deleteCookiesForHostnames(const Vector<String>& cookieHostNames, IncludeHttpOnlyCookies);
     WEBCORE_EXPORT Vector<Cookie> getAllCookies();
     WEBCORE_EXPORT Vector<Cookie> getCookies(const URL&);
     WEBCORE_EXPORT bool getRawCookies(const URL& firstParty, const SameSiteInfo&, const URL&, Optional<uint64_t> frameID, Optional<uint64_t> pageID, Vector<Cookie>&) const;
index 318f53e..6374035 100644 (file)
@@ -500,6 +500,11 @@ void NetworkStorageSession::deleteAllCookies()
 
 void NetworkStorageSession::deleteCookiesForHostnames(const Vector<String>& hostnames)
 {
+    deleteCookiesForHostnames(hostnames, IncludeHttpOnlyCookies::Yes);
+}
+
+void NetworkStorageSession::deleteCookiesForHostnames(const Vector<String>& hostnames, IncludeHttpOnlyCookies includeHttpOnlyCookies)
+{
     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
 
     BEGIN_BLOCK_OBJC_EXCEPTIONS;
@@ -511,7 +516,7 @@ void NetworkStorageSession::deleteCookiesForHostnames(const Vector<String>& host
 
     HashMap<String, Vector<RetainPtr<NSHTTPCookie>>> cookiesByDomain;
     for (NSHTTPCookie *cookie in cookies) {
-        if (!cookie.domain)
+        if (!cookie.domain || (includeHttpOnlyCookies == IncludeHttpOnlyCookies::No && cookie.isHTTPOnly))
             continue;
         cookiesByDomain.ensure(cookie.domain, [] {
             return Vector<RetainPtr<NSHTTPCookie>>();
index 1ac4e02..894c86a 100644 (file)
@@ -125,6 +125,13 @@ void NetworkStorageSession::deleteAllCookiesModifiedSince(WallTime since)
     cookieStorage().deleteAllCookiesModifiedSince(*this, since);
 }
 
+void NetworkStorageSession::deleteCookiesForHostnames(const Vector<String>& hostnames, IncludeHttpOnlyCookies includeHttpOnlyCookies)
+{
+    // FIXME: Not yet implemented.
+    UNUSED_PARAM(includeHttpOnlyCookies);
+    deleteCookiesForHostnames(hostnames);
+}
+
 void NetworkStorageSession::deleteCookiesForHostnames(const Vector<String>& cookieHostNames)
 {
     cookieStorage().deleteCookiesForHostnames(*this, cookieHostNames);
index 3dae1b0..1f75877 100644 (file)
@@ -387,6 +387,13 @@ void NetworkStorageSession::deleteAllCookiesModifiedSince(WallTime timestamp)
         g_warning("Deleting cookies modified since a given time span is not supported yet");
 }
 
+void NetworkStorageSession::deleteCookiesForHostnames(const Vector<String>& hostnames, IncludeHttpOnlyCookies includeHttpOnlyCookies)
+{
+    // FIXME: Not yet implemented.
+    UNUSED_PARAM(includeHttpOnlyCookies);
+    deleteCookiesForHostnames(hostnames);
+}
+
 void NetworkStorageSession::deleteCookiesForHostnames(const Vector<String>& hostnames)
 {
     SoupCookieJar* cookieJar = cookieStorage();
index c1df212..447f064 100644 (file)
@@ -1,3 +1,44 @@
+2019-03-07  John Wilander  <wilander@apple.com>
+
+        Resource Load Statistics: Make it possible to purge only script-accessible cookies
+        https://bugs.webkit.org/show_bug.cgi?id=195383
+        <rdar://problem/48570136>
+
+        Reviewed by Brent Fulgham.
+
+        This patch provides the ability to purge all script-accessible cookies while leaving
+        HttpOnly cookies in place.
+
+        * NetworkProcess/Classifier/ResourceLoadStatisticsStore.cpp:
+        (WebKit::ResourceLoadStatisticsStore::removeDataRecords):
+        * NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp:
+        (WebKit::WebResourceLoadStatisticsStore::deleteWebsiteDataForRegistrableDomainsInAllPersistentDataStores):
+            Support for a new boolean flag on whether or not to include HttpOnly Cookies.
+        * NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h:
+        * NetworkProcess/NetworkProcess.cpp:
+        (WebKit::NetworkProcess::deleteWebsiteDataForRegistrableDomainsInAllPersistentDataStores):
+            Support for a new boolean flag on whether or not to include HttpOnly Cookies.
+        (WebKit::NetworkProcess::deleteCookiesForTesting):
+            Test infrastructure.
+        * NetworkProcess/NetworkProcess.h:
+        * NetworkProcess/NetworkProcess.messages.in:
+        * NetworkProcess/NetworkSession.cpp:
+        (WebKit::NetworkSession::deleteWebsiteDataForRegistrableDomainsInAllPersistentDataStores):
+            Support for a new boolean flag on whether or not to include HttpOnly Cookies.
+        * NetworkProcess/NetworkSession.h:
+        * UIProcess/API/C/WKWebsiteDataStoreRef.cpp:
+        (WKWebsiteDataStoreStatisticsDeleteCookiesForTesting):
+            Test infrastructure.
+        * UIProcess/API/C/WKWebsiteDataStoreRef.h:
+        * UIProcess/Network/NetworkProcessProxy.cpp:
+        (WebKit::NetworkProcessProxy::deleteCookiesForTesting):
+            Test infrastructure.
+        * UIProcess/Network/NetworkProcessProxy.h:
+        * UIProcess/WebsiteData/WebsiteDataStore.cpp:
+        (WebKit::WebsiteDataStore::deleteCookiesForTesting):
+            Test infrastructure.
+        * UIProcess/WebsiteData/WebsiteDataStore.h:
+
 2019-03-07  Carlos Garcia Campos  <cgarcia@igalia.com>
 
         REGRESSION(r242364): [WPE] Do not stop the compositing run loop update timer on suspend
index 1f92324..04c4790 100644 (file)
@@ -37,6 +37,7 @@
 #include "WebProcessProxy.h"
 #include "WebResourceLoadStatisticsTelemetry.h"
 #include "WebsiteDataStore.h"
+#include <WebCore/CookieJar.h>
 #include <WebCore/KeyedCoding.h>
 #include <WebCore/NetworkStorageSession.h>
 #include <WebCore/ResourceLoadStatistics.h>
@@ -175,7 +176,7 @@ void ResourceLoadStatisticsStore::removeDataRecords(CompletionHandler<void()>&&
             return;
         }
 
-        weakThis->m_store.deleteWebsiteDataForRegistrableDomainsInAllPersistentDataStores(WebResourceLoadStatisticsStore::monitoredDataTypes(), WTFMove(prevalentResourceDomains), shouldNotifyPagesWhenDataRecordsWereScanned, [callback = WTFMove(callback), weakThis = WTFMove(weakThis), workQueue = workQueue.copyRef()](const HashSet<RegistrableDomain>& domainsWithDeletedWebsiteData) mutable {
+        weakThis->m_store.deleteWebsiteDataForRegistrableDomainsInAllPersistentDataStores(WebResourceLoadStatisticsStore::monitoredDataTypes(), WTFMove(prevalentResourceDomains), shouldNotifyPagesWhenDataRecordsWereScanned, IncludeHttpOnlyCookies::Yes, [callback = WTFMove(callback), weakThis = WTFMove(weakThis), workQueue = workQueue.copyRef()](const HashSet<RegistrableDomain>& domainsWithDeletedWebsiteData) mutable {
             workQueue->dispatch([domainsWithDeletedWebsiteData = crossThreadCopy(domainsWithDeletedWebsiteData), callback = WTFMove(callback), weakThis = WTFMove(weakThis)] () mutable {
                 if (!weakThis) {
                     callback();
index 3713f9b..68949dd 100644 (file)
@@ -45,6 +45,7 @@
 #include "WebResourceLoadStatisticsStoreMessages.h"
 #include "WebResourceLoadStatisticsTelemetry.h"
 #include "WebsiteDataFetchOption.h"
+#include <WebCore/CookieJar.h>
 #include <WebCore/DiagnosticLoggingClient.h>
 #include <WebCore/DiagnosticLoggingKeys.h>
 #include <WebCore/NetworkStorageSession.h>
@@ -988,12 +989,12 @@ void WebResourceLoadStatisticsStore::notifyResourceLoadStatisticsProcessed()
         m_networkSession->notifyResourceLoadStatisticsProcessed();
 }
 
-void WebResourceLoadStatisticsStore::deleteWebsiteDataForRegistrableDomainsInAllPersistentDataStores(OptionSet<WebsiteDataType> dataTypes, Vector<RegistrableDomain>&& domains, bool shouldNotifyPage, CompletionHandler<void(const HashSet<RegistrableDomain>&)>&& completionHandler)
+void WebResourceLoadStatisticsStore::deleteWebsiteDataForRegistrableDomainsInAllPersistentDataStores(OptionSet<WebsiteDataType> dataTypes, Vector<RegistrableDomain>&& domains, bool shouldNotifyPage, IncludeHttpOnlyCookies includeHttpOnlyCookies, CompletionHandler<void(const HashSet<RegistrableDomain>&)>&& completionHandler)
 {
     ASSERT(RunLoop::isMain());
     
     if (m_networkSession) {
-        m_networkSession->deleteWebsiteDataForRegistrableDomainsInAllPersistentDataStores(dataTypes, WTFMove(domains), shouldNotifyPage, WTFMove(completionHandler));
+        m_networkSession->deleteWebsiteDataForRegistrableDomainsInAllPersistentDataStores(dataTypes, WTFMove(domains), shouldNotifyPage, includeHttpOnlyCookies, WTFMove(completionHandler));
         return;
     }
 
index 0a1a303..6a5650d 100644 (file)
@@ -47,6 +47,7 @@ namespace WebCore {
 class ResourceRequest;
 struct ResourceLoadStatistics;
 enum class ShouldSample : bool;
+enum class IncludeHttpOnlyCookies : bool;
 }
 
 namespace WebKit {
@@ -103,7 +104,7 @@ public:
     void logSubresourceLoading(const SubResourceDomain&, const TopFrameDomain&, WallTime lastSeen, CompletionHandler<void()>&&);
     void logSubresourceRedirect(const RedirectedFromDomain&, const RedirectedToDomain&, CompletionHandler<void()>&&);
     void clearUserInteraction(const TopFrameDomain&, CompletionHandler<void()>&&);
-    void deleteWebsiteDataForRegistrableDomainsInAllPersistentDataStores(OptionSet<WebsiteDataType>, Vector<RegistrableDomain>&&, bool shouldNotifyPage, CompletionHandler<void(const HashSet<RegistrableDomain>&)>&&);
+    void deleteWebsiteDataForRegistrableDomainsInAllPersistentDataStores(OptionSet<WebsiteDataType>, Vector<RegistrableDomain>&&, bool shouldNotifyPage, WebCore::IncludeHttpOnlyCookies, CompletionHandler<void(const HashSet<RegistrableDomain>&)>&&);
     void registrableDomainsWithWebsiteData(OptionSet<WebsiteDataType>, bool shouldNotifyPage, CompletionHandler<void(HashSet<RegistrableDomain>&&)>&&);
     bool grantStorageAccess(const SubFrameDomain&, const TopFrameDomain&, Optional<FrameID>, PageID);
     void hasHadUserInteraction(const RegistrableDomain&, CompletionHandler<void(bool)>&&);
index 1e642ea..1a3a239 100644 (file)
@@ -63,6 +63,7 @@
 #include "WebsiteDataStore.h"
 #include "WebsiteDataStoreParameters.h"
 #include "WebsiteDataType.h"
+#include <WebCore/CookieJar.h>
 #include <WebCore/DNS.h>
 #include <WebCore/DeprecatedGlobalSettings.h>
 #include <WebCore/DiagnosticLoggingClient.h>
@@ -1466,7 +1467,7 @@ static Vector<WebsiteData::Entry> filterForRegistrableDomains(const Vector<Regis
     return result;
 }
 
-void NetworkProcess::deleteWebsiteDataForRegistrableDomainsInAllPersistentDataStores(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, Vector<RegistrableDomain>&& domains, bool shouldNotifyPage, CompletionHandler<void(const HashSet<RegistrableDomain>&)>&& completionHandler)
+void NetworkProcess::deleteWebsiteDataForRegistrableDomainsInAllPersistentDataStores(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, Vector<RegistrableDomain>&& domains, bool shouldNotifyPage, IncludeHttpOnlyCookies includeHttpOnlyCookies, CompletionHandler<void(const HashSet<RegistrableDomain>&)>&& completionHandler)
 {
     OptionSet<WebsiteDataFetchOption> fetchOptions = WebsiteDataFetchOption::DoNotCreateProcesses;
 
@@ -1513,7 +1514,7 @@ void NetworkProcess::deleteWebsiteDataForRegistrableDomainsInAllPersistentDataSt
         if (auto* networkStorageSession = storageSession(sessionID)) {
             networkStorageSession->getHostnamesWithCookies(websiteDataStore.hostNamesWithCookies);
             hostnamesWithCookiesToDelete = filterForRegistrableDomains(domains, websiteDataStore.hostNamesWithCookies);
-            networkStorageSession->deleteCookiesForHostnames(hostnamesWithCookiesToDelete);
+            networkStorageSession->deleteCookiesForHostnames(hostnamesWithCookiesToDelete, includeHttpOnlyCookies);
         }
     }
 
@@ -1598,6 +1599,16 @@ void NetworkProcess::deleteWebsiteDataForRegistrableDomainsInAllPersistentDataSt
     }
 }
 
+void NetworkProcess::deleteCookiesForTesting(PAL::SessionID sessionID, RegistrableDomain domain, bool includeHttpOnlyCookies, CompletionHandler<void()>&& completionHandler)
+{
+    OptionSet<WebsiteDataType> cookieType = WebsiteDataType::Cookies;
+
+    deleteWebsiteDataForRegistrableDomainsInAllPersistentDataStores(sessionID, cookieType, { domain }, true, includeHttpOnlyCookies ? IncludeHttpOnlyCookies::Yes : IncludeHttpOnlyCookies::No, [completionHandler = WTFMove(completionHandler)] (const HashSet<RegistrableDomain>& domainsDeletedFor) mutable {
+        UNUSED_PARAM(domainsDeletedFor);
+        completionHandler();
+    });
+}
+
 void NetworkProcess::registrableDomainsWithWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, bool shouldNotifyPage, CompletionHandler<void(HashSet<RegistrableDomain>&&)>&& completionHandler)
 {
     OptionSet<WebsiteDataFetchOption> fetchOptions = WebsiteDataFetchOption::DoNotCreateProcesses;
index c4e720e..0ec500e 100644 (file)
@@ -72,6 +72,7 @@ class DownloadID;
 class NetworkStorageSession;
 class ResourceError;
 class SWServer;
+enum class IncludeHttpOnlyCookies : bool;
 enum class StoredCredentialsPolicy : bool;
 struct ClientOrigin;
 struct MessageWithMessagePorts;
@@ -202,7 +203,8 @@ public:
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
     void clearPrevalentResource(PAL::SessionID, const RegistrableDomain&, CompletionHandler<void()>&&);
     void clearUserInteraction(PAL::SessionID, const RegistrableDomain&, CompletionHandler<void()>&&);
-    void deleteWebsiteDataForRegistrableDomainsInAllPersistentDataStores(PAL::SessionID, OptionSet<WebsiteDataType>, Vector<RegistrableDomain>&&, bool shouldNotifyPage, CompletionHandler<void(const HashSet<RegistrableDomain>&)>&&);
+    void deleteWebsiteDataForRegistrableDomainsInAllPersistentDataStores(PAL::SessionID, OptionSet<WebsiteDataType>, Vector<RegistrableDomain>&&, bool shouldNotifyPage, WebCore::IncludeHttpOnlyCookies, CompletionHandler<void(const HashSet<RegistrableDomain>&)>&&);
+    void deleteCookiesForTesting(PAL::SessionID, RegistrableDomain, bool includeHttpOnlyCookies, CompletionHandler<void()>&&);
     void dumpResourceLoadStatistics(PAL::SessionID, CompletionHandler<void(String)>&&);
     void updatePrevalentDomainsToBlockCookiesFor(PAL::SessionID, const Vector<RegistrableDomain>& domainsToBlock, CompletionHandler<void()>&&);
     void isGrandfathered(PAL::SessionID, const RegistrableDomain&, CompletionHandler<void(bool)>&&);
index 8cd4020..4130d8e 100644 (file)
@@ -134,6 +134,7 @@ messages -> NetworkProcess LegacyReceiver {
     ResetCacheMaxAgeCapForPrevalentResources(PAL::SessionID sessionID) -> () Async
     CommittedCrossSiteLoadWithLinkDecoration(PAL::SessionID sessionID, WebCore::RegistrableDomain fromDomain, WebCore::RegistrableDomain toDomain, uint64_t pageID)
     ResetCrossSiteLoadsWithLinkDecorationForTesting(PAL::SessionID sessionID) -> () Async
+    DeleteCookiesForTesting(PAL::SessionID sessionID, WebCore::RegistrableDomain domain, bool includeHttpOnlyCookies) -> () Async
 #endif
 
     SetSessionIsControlledByAutomation(PAL::SessionID sessionID, bool controlled);
index 328130d..d854113 100644 (file)
@@ -32,6 +32,7 @@
 #include "WebProcessProxy.h"
 #include "WebResourceLoadStatisticsStore.h"
 #include <WebCore/AdClickAttribution.h>
+#include <WebCore/CookieJar.h>
 #include <WebCore/NetworkStorageSession.h>
 
 #if PLATFORM(COCOA)
@@ -117,16 +118,16 @@ void NetworkSession::notifyPageStatisticsTelemetryFinished(unsigned totalPrevale
     m_networkProcess->parentProcessConnection()->send(Messages::NetworkProcessProxy::NotifyResourceLoadStatisticsTelemetryFinished(totalPrevalentResources, totalPrevalentResourcesWithUserInteraction, top3SubframeUnderTopFrameOrigins), 0);
 }
 
-void NetworkSession::deleteWebsiteDataForRegistrableDomainsInAllPersistentDataStores(OptionSet<WebsiteDataType> dataTypes, Vector<RegistrableDomain>&& domains, bool shouldNotifyPage, CompletionHandler<void(const HashSet<RegistrableDomain>&)>&& completionHandler)
+void NetworkSession::deleteWebsiteDataForRegistrableDomainsInAllPersistentDataStores(OptionSet<WebsiteDataType> dataTypes, Vector<RegistrableDomain>&& domains, bool shouldNotifyPage, IncludeHttpOnlyCookies includeHttpOnlyCookies, CompletionHandler<void(const HashSet<RegistrableDomain>&)>&& completionHandler)
 {
-    m_networkProcess->deleteWebsiteDataForRegistrableDomainsInAllPersistentDataStores(m_sessionID, dataTypes, WTFMove(domains), shouldNotifyPage, WTFMove(completionHandler));
+    m_networkProcess->deleteWebsiteDataForRegistrableDomainsInAllPersistentDataStores(m_sessionID, dataTypes, WTFMove(domains), shouldNotifyPage, includeHttpOnlyCookies, WTFMove(completionHandler));
 }
 
 void NetworkSession::registrableDomainsWithWebsiteData(OptionSet<WebsiteDataType> dataTypes, bool shouldNotifyPage, CompletionHandler<void(HashSet<RegistrableDomain>&&)>&& completionHandler)
 {
     m_networkProcess->registrableDomainsWithWebsiteData(m_sessionID, dataTypes, shouldNotifyPage, WTFMove(completionHandler));
 }
-#endif
+#endif // ENABLE(RESOURCE_LOAD_STATISTICS)
 
 void NetworkSession::storeAdClickAttribution(WebCore::AdClickAttribution&& adClickAttribution)
 {
index 0852d6b..8723d63 100644 (file)
@@ -38,6 +38,7 @@
 namespace WebCore {
 class AdClickAttribution;
 class NetworkStorageSession;
+enum class IncludeHttpOnlyCookies : bool;
 enum class ShouldSample : bool;
 }
 
@@ -72,7 +73,7 @@ public:
     WebResourceLoadStatisticsStore* resourceLoadStatistics() const { return m_resourceLoadStatistics.get(); }
     void setResourceLoadStatisticsEnabled(bool);
     void notifyResourceLoadStatisticsProcessed();
-    void deleteWebsiteDataForRegistrableDomainsInAllPersistentDataStores(OptionSet<WebsiteDataType>, Vector<WebCore::RegistrableDomain>&&, bool shouldNotifyPage, CompletionHandler<void(const HashSet<WebCore::RegistrableDomain>&)>&&);
+    void deleteWebsiteDataForRegistrableDomainsInAllPersistentDataStores(OptionSet<WebsiteDataType>, Vector<WebCore::RegistrableDomain>&&, bool shouldNotifyPage, WebCore::IncludeHttpOnlyCookies, CompletionHandler<void(const HashSet<WebCore::RegistrableDomain>&)>&&);
     void registrableDomainsWithWebsiteData(OptionSet<WebsiteDataType>, bool shouldNotifyPage, CompletionHandler<void(HashSet<WebCore::RegistrableDomain>&&)>&&);
     void logDiagnosticMessageWithValue(const String& message, const String& description, unsigned value, unsigned significantFigures, WebCore::ShouldSample);
     void notifyPageStatisticsTelemetryFinished(unsigned totalPrevalentResources, unsigned totalPrevalentResourcesWithUserInteraction, unsigned top3SubframeUnderTopFrameOrigins);
index c0ebb87..41e5a4e 100644 (file)
@@ -408,6 +408,17 @@ void WKWebsiteDataStoreStatisticsClearThroughWebsiteDataRemoval(WKWebsiteDataSto
     });
 }
 
+void WKWebsiteDataStoreStatisticsDeleteCookiesForTesting(WKWebsiteDataStoreRef dataStoreRef, WKStringRef host, bool includeHttpOnlyCookies, void* context, WKWebsiteDataStoreStatisticsDeleteCookiesForTestingFunction callback)
+{
+#if ENABLE(RESOURCE_LOAD_STATISTICS)
+    WebKit::toImpl(dataStoreRef)->websiteDataStore().deleteCookiesForTesting(URL(URL(), WebKit::toImpl(host)->string()), includeHttpOnlyCookies, [context, callback] {
+        callback(context);
+    });
+#else
+    callback(context);
+#endif
+}
+
 void WKWebsiteDataStoreSetStatisticsCacheMaxAgeCap(WKWebsiteDataStoreRef dataStoreRef, double seconds, void* context, WKWebsiteDataStoreSetStatisticsCacheMaxAgeCapFunction callback)
 {
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
index 93e5218..5b88b67 100644 (file)
@@ -91,6 +91,8 @@ typedef void (*WKWebsiteDataStoreStatisticsClearInMemoryAndPersistentStoreModifi
 WK_EXPORT void WKWebsiteDataStoreStatisticsClearInMemoryAndPersistentStoreModifiedSinceHours(WKWebsiteDataStoreRef dataStoreRef, unsigned hours, void* context, WKWebsiteDataStoreStatisticsClearInMemoryAndPersistentStoreModifiedSinceHoursFunction callback);
 typedef void (*WKWebsiteDataStoreStatisticsClearThroughWebsiteDataRemovalFunction)(void* functionContext);
 WK_EXPORT void WKWebsiteDataStoreStatisticsClearThroughWebsiteDataRemoval(WKWebsiteDataStoreRef dataStoreRef, void* context, WKWebsiteDataStoreStatisticsClearThroughWebsiteDataRemovalFunction callback);
+typedef void (*WKWebsiteDataStoreStatisticsDeleteCookiesForTestingFunction)(void* functionContext);
+WK_EXPORT void WKWebsiteDataStoreStatisticsDeleteCookiesForTesting(WKWebsiteDataStoreRef dataStoreRef, WKStringRef host, bool includeHttpOnlyCookies, void* context, WKWebsiteDataStoreStatisticsDeleteCookiesForTestingFunction callback);
 typedef void (*WKWebsiteDataStoreSetStatisticsCacheMaxAgeCapFunction)(void* functionContext);
 WK_EXPORT void WKWebsiteDataStoreSetStatisticsCacheMaxAgeCap(WKWebsiteDataStoreRef dataStoreRef, double seconds, void* context, WKWebsiteDataStoreSetStatisticsCacheMaxAgeCapFunction);
 typedef void (*WKWebsiteDataStoreStatisticsResetToConsistentStateFunction)(void* functionContext);
index a1f9172..ffeb0c1 100644 (file)
@@ -941,6 +941,16 @@ void NetworkProcessProxy::resetCrossSiteLoadsWithLinkDecorationForTesting(PAL::S
     
     sendWithAsyncReply(Messages::NetworkProcess::ResetCrossSiteLoadsWithLinkDecorationForTesting(sessionID), WTFMove(completionHandler));
 }
+
+void NetworkProcessProxy::deleteCookiesForTesting(PAL::SessionID sessionID, const RegistrableDomain& domain, bool includeHttpOnlyCookies, CompletionHandler<void()>&& completionHandler)
+{
+    if (!canSendMessage()) {
+        completionHandler();
+        return;
+    }
+    
+    sendWithAsyncReply(Messages::NetworkProcess::DeleteCookiesForTesting(sessionID, domain, includeHttpOnlyCookies), WTFMove(completionHandler));
+}
 #endif // ENABLE(RESOURCE_LOAD_STATISTICS)
 
 void NetworkProcessProxy::sendProcessWillSuspendImminently()
index 0cfa1f0..56cf3fa 100644 (file)
@@ -145,6 +145,7 @@ public:
     void setShouldClassifyResourcesBeforeDataRecordsRemoval(PAL::SessionID, bool, CompletionHandler<void()>&&);
     void resetCacheMaxAgeCapForPrevalentResources(PAL::SessionID, CompletionHandler<void()>&&);
     void resetCrossSiteLoadsWithLinkDecorationForTesting(PAL::SessionID, CompletionHandler<void()>&&);
+    void deleteCookiesForTesting(PAL::SessionID, const RegistrableDomain&, bool includeHttpOnlyCookies, CompletionHandler<void()>&&);
 #endif
 
     void processReadyToSuspend();
index edd7663..8f8f39f 100644 (file)
@@ -1765,6 +1765,16 @@ void WebsiteDataStore::resetCrossSiteLoadsWithLinkDecorationForTesting(Completio
             networkProcess->resetCrossSiteLoadsWithLinkDecorationForTesting(m_sessionID, [callbackAggregator = callbackAggregator.copyRef()] { });
     }
 }
+
+void WebsiteDataStore::deleteCookiesForTesting(const URL& url, bool includeHttpOnlyCookies, CompletionHandler<void()>&& completionHandler)
+{
+    auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
+    
+    for (auto& processPool : processPools()) {
+        if (auto* networkProcess = processPool->networkProcess())
+            networkProcess->deleteCookiesForTesting(m_sessionID, RegistrableDomain { url }, includeHttpOnlyCookies, [callbackAggregator = callbackAggregator.copyRef()] { });
+    }
+}
 #endif // ENABLE(RESOURCE_LOAD_STATISTICS)
 
 void WebsiteDataStore::setCacheMaxAgeCapForPrevalentResources(Seconds seconds, CompletionHandler<void()>&& completionHandler)
index e375d15..f6149db 100644 (file)
@@ -168,6 +168,7 @@ public:
     void grantStorageAccess(String&& subFrameHost, String&& topFrameHost, uint64_t frameID, uint64_t pageID, bool userWasPrompted, CompletionHandler<void(bool)>&&);
     void setSubframeUnderTopFrameDomain(const URL& subframe, const URL& topFrame);
     void resetCrossSiteLoadsWithLinkDecorationForTesting(CompletionHandler<void()>&&);
+    void deleteCookiesForTesting(const URL&, bool includeHttpOnlyCookies, CompletionHandler<void()>&&);
 #endif
     void setCacheMaxAgeCapForPrevalentResources(Seconds, CompletionHandler<void()>&&);
     void resetCacheMaxAgeCapForPrevalentResources(CompletionHandler<void()>&&);
index 8a948d1..0aa3881 100644 (file)
@@ -1,3 +1,24 @@
+2019-03-07  John Wilander  <wilander@apple.com>
+
+        Resource Load Statistics: Make it possible to purge only script-accessible cookies
+        https://bugs.webkit.org/show_bug.cgi?id=195383
+        <rdar://problem/48570136>
+
+        Reviewed by Brent Fulgham.
+
+        This patch adds test infrastructure to purge only script-accessible cookies,
+        including a new testRunner function called statisticsDeleteCookiesForHost().git a
+
+        * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
+        * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+        (WTR::TestRunner::statisticsDeleteCookiesForHost):
+        * WebKitTestRunner/InjectedBundle/TestRunner.h:
+        * WebKitTestRunner/TestController.cpp:
+        (WTR::TestController::statisticsDeleteCookiesForHost):
+        * WebKitTestRunner/TestController.h:
+        * WebKitTestRunner/TestInvocation.cpp:
+        (WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):
+
 2019-03-07  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r242354.
index 0e79d80..9cf4493 100644 (file)
@@ -315,6 +315,7 @@ interface TestRunner {
     void statisticsClearInMemoryAndPersistentStore(object callback);
     void statisticsClearInMemoryAndPersistentStoreModifiedSinceHours(unsigned long hours, object callback);
     void statisticsClearThroughWebsiteDataRemoval(object callback);
+    void statisticsDeleteCookiesForHost(DOMString hostName, boolean includeHttpOnlyCookies);
     void setStatisticsCacheMaxAgeCap(double seconds);
     void statisticsResetToConsistentState(object completionHandler);
 
index d462246..824a5f6 100644 (file)
@@ -2007,6 +2007,32 @@ void TestRunner::statisticsClearThroughWebsiteDataRemoval(JSValueRef callback)
     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), nullptr, nullptr);
 }
 
+void TestRunner::statisticsDeleteCookiesForHost(JSStringRef hostName, bool includeHttpOnlyCookies)
+{
+    Vector<WKRetainPtr<WKStringRef>> keys;
+    Vector<WKRetainPtr<WKTypeRef>> values;
+
+    keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
+    values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
+
+    keys.append({ AdoptWK, WKStringCreateWithUTF8CString("IncludeHttpOnlyCookies") });
+    values.append({ AdoptWK, WKBooleanCreate(includeHttpOnlyCookies) });
+
+    Vector<WKStringRef> rawKeys;
+    Vector<WKTypeRef> rawValues;
+    rawKeys.resize(keys.size());
+    rawValues.resize(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("StatisticsDeleteCookiesForHost"));
+    WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
+    WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
+}
+
 void TestRunner::setStatisticsCacheMaxAgeCap(double seconds)
 {
     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsCacheMaxAgeCap"));
index 713a943..6d11648 100644 (file)
@@ -426,6 +426,7 @@ public:
     void statisticsClearInMemoryAndPersistentStore(JSValueRef callback);
     void statisticsClearInMemoryAndPersistentStoreModifiedSinceHours(unsigned hours, JSValueRef callback);
     void statisticsClearThroughWebsiteDataRemoval(JSValueRef callback);
+    void statisticsDeleteCookiesForHost(JSStringRef hostName, bool includeHttpOnlyCookies);
     void statisticsCallClearThroughWebsiteDataRemovalCallback();
     void setStatisticsCacheMaxAgeCap(double seconds);
     void statisticsResetToConsistentState(JSValueRef completionHandler);
index 4558ba2..554e03a 100644 (file)
@@ -3332,6 +3332,14 @@ void TestController::statisticsClearThroughWebsiteDataRemoval()
     m_currentInvocation->didClearStatisticsThroughWebsiteDataRemoval();
 }
 
+void TestController::statisticsDeleteCookiesForHost(WKStringRef host, bool includeHttpOnlyCookies)
+{
+    auto* dataStore = WKContextGetWebsiteDataStore(platformContext());
+    ResourceStatisticsCallbackContext context(*this);
+    WKWebsiteDataStoreStatisticsDeleteCookiesForTesting(dataStore, host, includeHttpOnlyCookies, &context, resourceStatisticsVoidResultCallback);
+    runUntil(context.done, noTimeout);
+}
+
 void TestController::setStatisticsCacheMaxAgeCap(double seconds)
 {
     auto* dataStore = WKContextGetWebsiteDataStore(platformContext());
index 1d13b55..4b353db 100644 (file)
@@ -235,6 +235,7 @@ public:
     void statisticsClearInMemoryAndPersistentStore();
     void statisticsClearInMemoryAndPersistentStoreModifiedSinceHours(unsigned);
     void statisticsClearThroughWebsiteDataRemoval();
+    void statisticsDeleteCookiesForHost(WKStringRef host, bool includeHttpOnlyCookies);
     void setStatisticsCacheMaxAgeCap(double seconds);
     void statisticsResetToConsistentState();
 
index 6660cdc..0bdc417 100644 (file)
@@ -1384,7 +1384,21 @@ WKRetainPtr<WKTypeRef> TestInvocation::didReceiveSynchronousMessageFromInjectedB
         TestController::singleton().statisticsClearThroughWebsiteDataRemoval();
         return nullptr;
     }
-    
+
+    if (WKStringIsEqualToUTF8CString(messageName, "StatisticsDeleteCookiesForHost")) {
+        ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
+        
+        WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
+        WKRetainPtr<WKStringRef> hostNameKey(AdoptWK, WKStringCreateWithUTF8CString("HostName"));
+        WKRetainPtr<WKStringRef> valueKey(AdoptWK, WKStringCreateWithUTF8CString("IncludeHttpOnlyCookies"));
+        
+        WKStringRef hostName = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, hostNameKey.get()));
+        WKBooleanRef includeHttpOnlyCookies = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, valueKey.get()));
+        
+        TestController::singleton().statisticsDeleteCookiesForHost(hostName, WKBooleanGetValue(includeHttpOnlyCookies));
+        return nullptr;
+    }
+
     if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsCacheMaxAgeCap")) {
         ASSERT(WKGetTypeID(messageBody) == WKDoubleGetTypeID());
         WKDoubleRef seconds = static_cast<WKDoubleRef>(messageBody);