Title: [260668] trunk
Revision
260668
Author
[email protected]
Date
2020-04-24 14:08:10 -0700 (Fri, 24 Apr 2020)

Log Message

Removing website data for a domain should delete corresponding ITP entry
https://bugs.webkit.org/show_bug.cgi?id=210864
<rdar://problem/59473193>

Reviewed by John Wilander.

Source/WebKit:

Tests: http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-link-decoration-database.html
       http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-link-decoration.html
       http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-mixed-statistics-entries-database.html
       http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-mixed-statistics-entries.html
       http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-third-party-script-loads-database.html
       http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-third-party-script-loads.html

In the database store: deletes domain from the ObservedDomains table
when website data is deleted for that domain. This deletes every
instance of the domainID in the database due to cascading deletions.

In the memory store: deletes every instance of the domain in the
statistics map, which will update the plist.

* NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp:
(WebKit::ResourceLoadStatisticsDatabaseStore::removeDataForDomain):
(WebKit::ResourceLoadStatisticsDatabaseStore::domainIDExistsInDatabase):
Needed a new function to check for the existence of domainID in any
table. Existing queries rely on the ObservedDomains entry, which means
testing using those could result in a false positive if the domainID
was deleted from ObservedDomains but is floating around in another
table.

* NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h:
* NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.cpp:
(WebKit::ResourceLoadStatisticsMemoryStore::removeDataForDomain):
* NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.h:
* NetworkProcess/Classifier/ResourceLoadStatisticsStore.h:
* NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::domainIDExistsInDatabase):
(WebKit::WebResourceLoadStatisticsStore::removeDataForDomain):
* NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h:
* NetworkProcess/NetworkProcess.cpp:
(WebKit::NetworkProcess::domainIDExistsInDatabase):
(WebKit::NetworkProcess::deleteWebsiteDataForOrigins):
Pass RegistrableDomains vector to deleteWebsiteDataForOrigins,
captured based on the WebsiteData display name.

* NetworkProcess/NetworkProcess.h:
* NetworkProcess/NetworkProcess.messages.in:
* UIProcess/API/C/WKWebsiteDataStoreRef.cpp:
(WKWebsiteDataStoreRemoveITPDataForDomain):
(WKWebsiteDataStoreDoesStatisticsDomainIDExistInDatabase):
* UIProcess/API/C/WKWebsiteDataStoreRef.h:
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::deleteWebsiteDataForOrigins):
(WebKit::NetworkProcessProxy::domainIDExistsInDatabase):
* UIProcess/Network/NetworkProcessProxy.h:
* UIProcess/WebsiteData/WebsiteDataStore.cpp:
(WebKit::WebsiteDataStore::removeData):
(WebKit::WebsiteDataStore::domainIDExistsInDatabase):
* UIProcess/WebsiteData/WebsiteDataStore.h:

Tools:

Created 2 new APIs for testing. One to mimic clearing website data
for a domain, and one to check if the domain exists in the database
after a deletion was requested.

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

LayoutTests:

Inserts values into the ITP database then tests removing the domain's
website data will remove all instances of that domain in the ITP
database.

Database store expectations will reflect the result of the new
domainIDExistsInDatabase function. Memory store tests will use the
dump output which should not include the deleted information.

* http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-link-decoration-database-expected.txt: Added.
* http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-link-decoration-database.html: Added.
* http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-link-decoration-expected.txt: Added.
* http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-link-decoration.html: Added.
* http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-mixed-statistics-entries-database-expected.txt: Added.
* http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-mixed-statistics-entries-database.html: Added.
* http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-mixed-statistics-entries-expected.txt: Added.
* http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-mixed-statistics-entries.html: Added.
* http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-third-party-script-loads-database-expected.txt: Added.
* http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-third-party-script-loads-database.html: Added.
* http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-third-party-script-loads-expected.txt: Added.
* http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-third-party-script-loads.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (260667 => 260668)


--- trunk/LayoutTests/ChangeLog	2020-04-24 21:02:48 UTC (rev 260667)
+++ trunk/LayoutTests/ChangeLog	2020-04-24 21:08:10 UTC (rev 260668)
@@ -1,3 +1,32 @@
+2020-04-24  Kate Cheney  <[email protected]>
+
+        Removing website data for a domain should delete corresponding ITP entry
+        https://bugs.webkit.org/show_bug.cgi?id=210864
+        <rdar://problem/59473193>
+
+        Reviewed by John Wilander.
+
+        Inserts values into the ITP database then tests removing the domain's
+        website data will remove all instances of that domain in the ITP
+        database.
+
+        Database store expectations will reflect the result of the new
+        domainIDExistsInDatabase function. Memory store tests will use the
+        dump output which should not include the deleted information.
+
+        * http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-link-decoration-database-expected.txt: Added.
+        * http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-link-decoration-database.html: Added.
+        * http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-link-decoration-expected.txt: Added.
+        * http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-link-decoration.html: Added.
+        * http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-mixed-statistics-entries-database-expected.txt: Added.
+        * http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-mixed-statistics-entries-database.html: Added.
+        * http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-mixed-statistics-entries-expected.txt: Added.
+        * http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-mixed-statistics-entries.html: Added.
+        * http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-third-party-script-loads-database-expected.txt: Added.
+        * http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-third-party-script-loads-database.html: Added.
+        * http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-third-party-script-loads-expected.txt: Added.
+        * http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-third-party-script-loads.html: Added.
+
 2020-04-24  Antoine Quint  <[email protected]>
 
         Update the css/css-animations WPT tests

Added: trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-link-decoration-database-expected.txt (0 => 260668)


--- trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-link-decoration-database-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-link-decoration-database-expected.txt	2020-04-24 21:08:10 UTC (rev 260668)
@@ -0,0 +1,5 @@
+PASS successfullyParsed is true
+
+TEST COMPLETE
+PASS Domain ID was successfully deleted from the database.
+

Added: trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-link-decoration-database.html (0 => 260668)


--- trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-link-decoration-database.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-link-decoration-database.html	2020-04-24 21:08:10 UTC (rev 260668)
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src=""
+    <script src=""
+</head>
+<body _onload_="setTimeout('runTest()', 0)">
+<div id="output"></div>
+<script>
+    if (window.testRunner) {
+        testRunner.setUseITPDatabase(true);
+        testRunner.waitUntilDone();
+        testRunner.dumpAsText();
+    }
+
+    function navigateCrossOrigin() {
+        document.location.href = "" + "/resourceLoadStatistics/remove-website-data-for-origin-deletes-link-decoration-database.html?link=decoration";
+    }
+
+    const host = "localhost";
+    const destinationOrigin = "http://localhost:8000";
+    const prevalentResourceOrigin = "http://127.0.0.1:8000";
+    const testOrigin = "http://127.0.0.2:8000";
+    function runTest() {
+        if (document.location.origin === prevalentResourceOrigin) {
+            setEnableFeature(true, function () {
+                testRunner.setStatisticsPrevalentResource(prevalentResourceOrigin, true, function() {
+                    if (!testRunner.isStatisticsPrevalentResource(prevalentResourceOrigin))
+                        testFailed("Host did not get set as prevalent resource.");
+                        testRunner.setStatisticsCrossSiteLoadWithLinkDecoration(testOrigin, destinationOrigin);
+                    testRunner.statisticsUpdateCookieBlocking(navigateCrossOrigin);
+                });
+
+            });
+        } else {
+            testRunner.clearStatisticsDataForDomain(host);
+            // Must use domainID to ensure this was properly
+            // deleted, otherwise the lack of registrable domain --> domainID mapping
+            // could create a false-positive test result even when the domainID persists.
+            if (testRunner.doesStatisticsDomainIDExistInDatabase(2))
+                testFailed("Domain ID was not deleted from the database.");
+            else
+                testPassed("Domain ID was successfully deleted from the database.")
+
+            setEnableFeature(false, function () {
+                testRunner.notifyDone();
+            });
+        }
+    }
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-link-decoration-expected.txt (0 => 260668)


--- trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-link-decoration-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-link-decoration-expected.txt	2020-04-24 21:08:10 UTC (rev 260668)
@@ -0,0 +1,11 @@
+
+Resource load statistics:
+
+Registrable domain: 127.0.0.1
+    hadUserInteraction: No
+    mostRecentUserInteraction: -1
+    grandfathered: No
+    gotLinkDecorationFromPrevalentResource: No
+    isPrevalentResource: Yes
+    isVeryPrevalentResource: No
+    dataRecordsRemoved: 0

Added: trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-link-decoration.html (0 => 260668)


--- trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-link-decoration.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-link-decoration.html	2020-04-24 21:08:10 UTC (rev 260668)
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src=""
+</head>
+<body _onload_="setTimeout('runTest()', 0)">
+<div id="output"></div>
+<script>
+    if (window.testRunner) {
+        testRunner.waitUntilDone();
+        testRunner.dumpAsText();
+    }
+
+    function navigateCrossOrigin() {
+        document.location.href = "" + "/resourceLoadStatistics/remove-website-data-for-origin-deletes-link-decoration.html?link=decoration";
+    }
+
+    const host = "localhost";
+    const destinationOrigin = "http://localhost:8000";
+    const prevalentResourceOrigin = "http://127.0.0.1:8000";
+    function runTest() {
+        if (document.location.origin === prevalentResourceOrigin) {
+            setEnableFeature(true, function () {
+                testRunner.setStatisticsPrevalentResource(prevalentResourceOrigin, true, function() {
+                    if (!testRunner.isStatisticsPrevalentResource(prevalentResourceOrigin))
+                        testFailed("Host did not get set as prevalent resource.");
+                    testRunner.statisticsUpdateCookieBlocking(navigateCrossOrigin);
+                });
+
+            });
+        } else {
+            testRunner.clearStatisticsDataForDomain(host);
+            testRunner.dumpResourceLoadStatistics();
+            setEnableFeature(false, function () {
+                testRunner.notifyDone();
+            });
+        }
+    }
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-mixed-statistics-entries-database-expected.txt (0 => 260668)


--- trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-mixed-statistics-entries-database-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-mixed-statistics-entries-database-expected.txt	2020-04-24 21:08:10 UTC (rev 260668)
@@ -0,0 +1,5 @@
+PASS Domain ID was successfully deleted from the database.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-mixed-statistics-entries-database.html (0 => 260668)


--- trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-mixed-statistics-entries-database.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-mixed-statistics-entries-database.html	2020-04-24 21:08:10 UTC (rev 260668)
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Tests that removal of website data deletes ITP data</title>
+    <script src=""
+    <script src=""
+</head>
+<body>
+<script>
+    const hostUnderTest = "127.0.0.1";
+    const statisticsUrl = "http://" + hostUnderTest + "/temp";
+    const topFrameOrigin1 = "http://127.0.0.2:8000/temp";
+    const topFrameOrigin2 = "http://127.0.0.3:8000/temp";
+    const topFrameOrigin3 = "http://127.0.0.4:8000/temp";
+    const topFrameOrigin4 = "http://127.0.0.5:8000/temp";
+
+    function completeTest() {
+        testRunner.clearStatisticsDataForDomain(hostUnderTest);
+        // Must use domainID to ensure this was properly
+        // deleted, otherwise the lack of registrable domain --> domainID mapping
+        // could create a false-positive test result even when the domainID persists.
+        if (testRunner.doesStatisticsDomainIDExistInDatabase(1))
+            testFailed("Domain ID was not deleted from the database.");
+        else
+            testPassed("Domain ID was successfully deleted from the database.")
+        setEnableFeature(false, function() {
+            testRunner.notifyDone();
+        });
+    }
+
+    function runTestRunnerTest() {
+        // Create entries in multiple database tables with the hostUnderTest.
+        testRunner.setStatisticsSubframeUnderTopFrameOrigin(statisticsUrl, topFrameOrigin1);
+        testRunner.setStatisticsSubresourceUnderTopFrameOrigin(topFrameOrigin2, statisticsUrl);
+        testRunner.setStatisticsSubresourceUnderTopFrameOrigin(statisticsUrl, topFrameOrigin3);
+        testRunner.setStatisticsSubresourceUniqueRedirectTo(statisticsUrl, topFrameOrigin4);
+
+        if (!testRunner.isStatisticsRegisteredAsSubFrameUnder(statisticsUrl, topFrameOrigin1)
+                || !testRunner.isStatisticsRegisteredAsSubresourceUnder(topFrameOrigin2, statisticsUrl)
+                || !testRunner.isStatisticsRegisteredAsSubresourceUnder(statisticsUrl, topFrameOrigin3)
+                || !testRunner.isStatisticsRegisteredAsRedirectingTo(statisticsUrl, topFrameOrigin4))
+            testFailed("Failed to register subStatistics.");
+
+        completeTest();
+    }
+
+    if (window.testRunner && window.internals) {
+        testRunner.setUseITPDatabase(true);
+        testRunner.waitUntilDone();
+        setEnableFeature(true, runTestRunnerTest);
+    }
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-mixed-statistics-entries-expected.txt (0 => 260668)


--- trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-mixed-statistics-entries-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-mixed-statistics-entries-expected.txt	2020-04-24 21:08:10 UTC (rev 260668)
@@ -0,0 +1,5 @@
+PASS Host deleted from memory store.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-mixed-statistics-entries.html (0 => 260668)


--- trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-mixed-statistics-entries.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-mixed-statistics-entries.html	2020-04-24 21:08:10 UTC (rev 260668)
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Tests that removal of website data deletes ITP data</title>
+    <script src=""
+    <script src=""
+</head>
+<body>
+<script>
+    const hostUnderTest = "127.0.0.1";
+    const statisticsUrl = "http://" + hostUnderTest + "/temp";
+    const topFrameOrigin1 = "http://127.0.0.2:8000/temp";
+    const topFrameOrigin2 = "http://127.0.0.3:8000/temp";
+    const topFrameOrigin3 = "http://127.0.0.4:8000/temp";
+    const topFrameOrigin4 = "http://127.0.0.5:8000/temp";
+
+    function completeTest() {
+        if (testRunner.isStatisticsRegisteredAsSubFrameUnder(statisticsUrl, topFrameOrigin1)
+                || testRunner.isStatisticsRegisteredAsSubresourceUnder(topFrameOrigin2, statisticsUrl)
+                || testRunner.isStatisticsRegisteredAsSubresourceUnder(statisticsUrl, topFrameOrigin3)
+                || testRunner.isStatisticsRegisteredAsRedirectingTo(statisticsUrl, topFrameOrigin4))
+            testFailed("Host not deleted from memory store.");
+        else
+            testPassed("Host deleted from memory store.");
+
+        setEnableFeature(false, function() {
+            testRunner.notifyDone();
+        });
+    }
+
+    function runTestRunnerTest() {
+        // Create entries in multiple database tables with the hostUnderTest.
+        testRunner.setStatisticsSubframeUnderTopFrameOrigin(statisticsUrl, topFrameOrigin1);
+        testRunner.setStatisticsSubresourceUnderTopFrameOrigin(topFrameOrigin2, statisticsUrl);
+        testRunner.setStatisticsSubresourceUnderTopFrameOrigin(statisticsUrl, topFrameOrigin3);
+        testRunner.setStatisticsSubresourceUniqueRedirectTo(statisticsUrl, topFrameOrigin4);
+
+        if (!testRunner.isStatisticsRegisteredAsSubFrameUnder(statisticsUrl, topFrameOrigin1)
+                || !testRunner.isStatisticsRegisteredAsSubresourceUnder(topFrameOrigin2, statisticsUrl)
+                || !testRunner.isStatisticsRegisteredAsSubresourceUnder(statisticsUrl, topFrameOrigin3)
+                || !testRunner.isStatisticsRegisteredAsRedirectingTo(statisticsUrl, topFrameOrigin4))
+            testFailed("Failed to register subStatistics.");
+
+        testRunner.clearStatisticsDataForDomain(hostUnderTest);
+        completeTest();
+    }
+
+    if (window.testRunner && window.internals) {
+        testRunner.waitUntilDone();
+        setEnableFeature(true, runTestRunnerTest);
+    }
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-third-party-script-loads-database-expected.txt (0 => 260668)


--- trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-third-party-script-loads-database-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-third-party-script-loads-database-expected.txt	2020-04-24 21:08:10 UTC (rev 260668)
@@ -0,0 +1,5 @@
+PASS successfullyParsed is true
+
+TEST COMPLETE
+PASS Domain ID was successfully deleted from the database.
+

Added: trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-third-party-script-loads-database.html (0 => 260668)


--- trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-third-party-script-loads-database.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-third-party-script-loads-database.html	2020-04-24 21:08:10 UTC (rev 260668)
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Tests that removal of website data deletes ITP data</title>
+    <script src=""
+    <script src=""
+</head>
+<body _onload_="runTest()">
+<script>
+    const host = "localhost";
+    const thirdPartyOrigin = "http://localhost:8000";
+    const thirdPartyBaseUrl = thirdPartyOrigin + "/resourceLoadStatistics/resources";
+
+    function finishTest() {
+        testRunner.clearStatisticsDataForDomain(host);
+        // Must use domainID to ensure this was properly
+        // deleted, otherwise the lack of registrable domain --> domainID mapping
+        // could create a false-positive test result even when the domainID persists.
+        if (testRunner.doesStatisticsDomainIDExistInDatabase(1))
+            testFailed("Domain ID was not deleted from the database.");
+        else
+            testPassed("Domain ID was successfully deleted from the database.")
+        setEnableFeature(false, function() {
+            testRunner.notifyDone();
+        });
+    }
+
+    function runTest() {
+        switch (document.location.hash) {
+            case "":
+                if (window.testRunner && window.internals) {
+                    testRunner.waitUntilDone();
+                    testRunner.setUseITPDatabase(true);
+                    setEnableFeature(true, function() {
+                        testRunner.setStatisticsNotifyPagesWhenDataRecordsWereScanned(true);
+                        testRunner.installStatisticsDidScanDataRecordsCallback(finishTest);
+                        document.location.hash = "step1";
+                        runTest();
+                    });
+                }
+                break;
+            case "#step1":
+                document.location.hash = "step2";
+                let scriptElement = document.createElement("script");
+                scriptElement._onload_ = runTest;
+                scriptElement.src = "" + "/dummy.js?dummyParam=" + Math.random();
+                document.body.appendChild(scriptElement);
+                break;
+            case "#step2":
+                testRunner.statisticsNotifyObserver();
+                break;
+        }
+    }
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-third-party-script-loads-expected.txt (0 => 260668)


--- trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-third-party-script-loads-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-third-party-script-loads-expected.txt	2020-04-24 21:08:10 UTC (rev 260668)
@@ -0,0 +1,14 @@
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+Resource load statistics:
+
+Registrable domain: 127.0.0.1
+    hadUserInteraction: No
+    mostRecentUserInteraction: -1
+    grandfathered: No
+    gotLinkDecorationFromPrevalentResource: No
+    isPrevalentResource: No
+    isVeryPrevalentResource: No
+    dataRecordsRemoved: 0

Added: trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-third-party-script-loads.html (0 => 260668)


--- trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-third-party-script-loads.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-third-party-script-loads.html	2020-04-24 21:08:10 UTC (rev 260668)
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Tests that removal of website data deletes ITP data</title>
+    <script src=""
+    <script src=""
+</head>
+<body _onload_="runTest()">
+<script>
+    const host = "localhost";
+    const thirdPartyOrigin = "http://localhost:8000";
+    const thirdPartyBaseUrl = thirdPartyOrigin + "/resourceLoadStatistics/resources";
+
+    function finishTest() {
+        testRunner.clearStatisticsDataForDomain(host);
+        testRunner.dumpResourceLoadStatistics();
+        setEnableFeature(false, function() {
+            testRunner.notifyDone();
+        });
+    }
+
+    function runTest() {
+        switch (document.location.hash) {
+            case "":
+                if (window.testRunner && window.internals) {
+                    testRunner.waitUntilDone();
+                    setEnableFeature(true, function() {
+                        testRunner.setStatisticsNotifyPagesWhenDataRecordsWereScanned(true);
+                        testRunner.installStatisticsDidScanDataRecordsCallback(finishTest);
+                        document.location.hash = "step1";
+                        runTest();
+                    });
+                }
+                break;
+            case "#step1":
+                document.location.hash = "step2";
+                let scriptElement = document.createElement("script");
+                scriptElement._onload_ = runTest;
+                scriptElement.src = "" + "/dummy.js?dummyParam=" + Math.random();
+                document.body.appendChild(scriptElement);
+                break;
+            case "#step2":
+                testRunner.statisticsNotifyObserver();
+                break;
+        }
+    }
+</script>
+</body>
+</html>

Modified: trunk/Source/WebKit/ChangeLog (260667 => 260668)


--- trunk/Source/WebKit/ChangeLog	2020-04-24 21:02:48 UTC (rev 260667)
+++ trunk/Source/WebKit/ChangeLog	2020-04-24 21:08:10 UTC (rev 260668)
@@ -1,3 +1,64 @@
+2020-04-24  Kate Cheney  <[email protected]>
+
+        Removing website data for a domain should delete corresponding ITP entry
+        https://bugs.webkit.org/show_bug.cgi?id=210864
+        <rdar://problem/59473193>
+
+        Reviewed by John Wilander.
+
+        Tests: http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-link-decoration-database.html
+               http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-link-decoration.html
+               http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-mixed-statistics-entries-database.html
+               http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-mixed-statistics-entries.html
+               http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-third-party-script-loads-database.html
+               http/tests/resourceLoadStatistics/remove-website-data-for-origin-deletes-third-party-script-loads.html
+
+        In the database store: deletes domain from the ObservedDomains table
+        when website data is deleted for that domain. This deletes every
+        instance of the domainID in the database due to cascading deletions.
+
+        In the memory store: deletes every instance of the domain in the
+        statistics map, which will update the plist.
+
+        * NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp:
+        (WebKit::ResourceLoadStatisticsDatabaseStore::removeDataForDomain):
+        (WebKit::ResourceLoadStatisticsDatabaseStore::domainIDExistsInDatabase):
+        Needed a new function to check for the existence of domainID in any
+        table. Existing queries rely on the ObservedDomains entry, which means
+        testing using those could result in a false positive if the domainID
+        was deleted from ObservedDomains but is floating around in another
+        table.
+
+        * NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h:
+        * NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.cpp:
+        (WebKit::ResourceLoadStatisticsMemoryStore::removeDataForDomain):
+        * NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.h:
+        * NetworkProcess/Classifier/ResourceLoadStatisticsStore.h:
+        * NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp:
+        (WebKit::WebResourceLoadStatisticsStore::domainIDExistsInDatabase):
+        (WebKit::WebResourceLoadStatisticsStore::removeDataForDomain):
+        * NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h:
+        * NetworkProcess/NetworkProcess.cpp:
+        (WebKit::NetworkProcess::domainIDExistsInDatabase):
+        (WebKit::NetworkProcess::deleteWebsiteDataForOrigins):
+        Pass RegistrableDomains vector to deleteWebsiteDataForOrigins,
+        captured based on the WebsiteData display name.
+
+        * NetworkProcess/NetworkProcess.h:
+        * NetworkProcess/NetworkProcess.messages.in:
+        * UIProcess/API/C/WKWebsiteDataStoreRef.cpp:
+        (WKWebsiteDataStoreRemoveITPDataForDomain):
+        (WKWebsiteDataStoreDoesStatisticsDomainIDExistInDatabase):
+        * UIProcess/API/C/WKWebsiteDataStoreRef.h:
+        * UIProcess/Network/NetworkProcessProxy.cpp:
+        (WebKit::NetworkProcessProxy::deleteWebsiteDataForOrigins):
+        (WebKit::NetworkProcessProxy::domainIDExistsInDatabase):
+        * UIProcess/Network/NetworkProcessProxy.h:
+        * UIProcess/WebsiteData/WebsiteDataStore.cpp:
+        (WebKit::WebsiteDataStore::removeData):
+        (WebKit::WebsiteDataStore::domainIDExistsInDatabase):
+        * UIProcess/WebsiteData/WebsiteDataStore.h:
+
 2020-04-24  David Kilzer  <[email protected]>
 
         Use CocoaImage platform abstraction for NSImage/UIImage

Modified: trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp (260667 => 260668)


--- trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp	2020-04-24 21:02:48 UTC (rev 260667)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp	2020-04-24 21:08:10 UTC (rev 260668)
@@ -135,6 +135,17 @@
     "UNION ALL SELECT topFrameDomainID FROM SubresourceUnderTopFrameDomains WHERE subresourceDomainID = ?"
     "UNION ALL SELECT toDomainID FROM SubresourceUniqueRedirectsTo WHERE subresourceDomainID = ?"_s;
 
+// EXISTS for testing queries
+constexpr auto linkDecorationExistsQuery = "SELECT EXISTS (SELECT * FROM TopFrameLinkDecorationsFrom WHERE toDomainID = ? OR fromDomainID = ?)"_s;
+constexpr auto scriptLoadExistsQuery = "SELECT EXISTS (SELECT * FROM TopFrameLoadedThirdPartyScripts WHERE topFrameDomainID = ? OR subresourceDomainID = ?)"_s;
+constexpr auto subFrameExistsQuery = "SELECT EXISTS (SELECT * FROM SubframeUnderTopFrameDomains WHERE subFrameDomainID = ? OR topFrameDomainID = ?)"_s;
+constexpr auto subResourceExistsQuery = "SELECT EXISTS (SELECT * FROM SubresourceUnderTopFrameDomains WHERE subresourceDomainID = ? OR topFrameDomainID = ?)"_s;
+constexpr auto uniqueRedirectExistsQuery = "SELECT EXISTS (SELECT * FROM SubresourceUniqueRedirectsTo WHERE subresourceDomainID = ? OR toDomainID = ?)"_s;
+constexpr auto observedDomainsExistsQuery = "SELECT EXISTS (SELECT * FROM ObservedDomains WHERE domainID = ?)"_s;
+
+// DELETE Queries
+constexpr auto removeAllDataQuery = "DELETE FROM ObservedDomains WHERE domainID = ?"_s;
+
 const char* tables[] = {
     "ObservedDomains",
     "TopLevelDomains",
@@ -290,6 +301,13 @@
     , m_getAllSubStatisticsStatement(m_database, getAllSubStatisticsUnderDomainQuery)
     , m_storageAccessExistsStatement(m_database, storageAccessExistsQuery)
     , m_getMostRecentlyUpdatedTimestampStatement(m_database, getMostRecentlyUpdatedTimestampQuery)
+    , m_linkDecorationExistsStatement(m_database, linkDecorationExistsQuery)
+    , m_scriptLoadExistsStatement(m_database, scriptLoadExistsQuery)
+    , m_subFrameExistsStatement(m_database, subFrameExistsQuery)
+    , m_subResourceExistsStatement(m_database, subResourceExistsQuery)
+    , m_uniqueRedirectExistsStatement(m_database, uniqueRedirectExistsQuery)
+    , m_observedDomainsExistsStatement(m_database, observedDomainsExistsQuery)
+    , m_removeAllDataStatement(m_database, removeAllDataQuery)
     , m_sessionID(sessionID)
 {
     ASSERT(!RunLoop::isMain());
@@ -631,6 +649,13 @@
         || m_getAllSubStatisticsStatement.prepare() != SQLITE_OK
         || m_storageAccessExistsStatement.prepare() != SQLITE_OK
         || m_getMostRecentlyUpdatedTimestampStatement.prepare() != SQLITE_OK
+        || m_linkDecorationExistsStatement.prepare() != SQLITE_OK
+        || m_scriptLoadExistsStatement.prepare() != SQLITE_OK
+        || m_subFrameExistsStatement.prepare() != SQLITE_OK
+        || m_subResourceExistsStatement.prepare() != SQLITE_OK
+        || m_uniqueRedirectExistsStatement.prepare() != SQLITE_OK
+        || m_observedDomainsExistsStatement.prepare() != SQLITE_OK
+        || m_removeAllDataStatement.prepare() != SQLITE_OK
         ) {
         RELEASE_LOG_ERROR(Network, "%p - ResourceLoadStatisticsDatabaseStore::prepareStatements failed to prepare, error message: %" PUBLIC_LOG_STRING, this, m_database.lastErrorMsg());
         ASSERT_NOT_REACHED();
@@ -2243,6 +2268,21 @@
     }
 }
 
+void ResourceLoadStatisticsDatabaseStore::removeDataForDomain(const RegistrableDomain& domain)
+{
+    auto domainIDToRemove = domainID(domain);
+    if (!domainIDToRemove)
+        return;
+
+    if (m_removeAllDataStatement.bindInt(1, *domainIDToRemove) != SQLITE_OK
+        || m_removeAllDataStatement.step() != SQLITE_DONE) {
+        RELEASE_LOG_ERROR_IF_ALLOWED(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::removeDataForDomain failed, error message: %{private}s", this, m_database.lastErrorMsg());
+        ASSERT_NOT_REACHED();
+    }
+    
+    resetStatement(m_removeAllDataStatement);
+}
+
 void ResourceLoadStatisticsDatabaseStore::clear(CompletionHandler<void()>&& completionHandler)
 {
     ASSERT(!RunLoop::isMain());
@@ -2889,6 +2929,45 @@
     resetStatement(m_getResourceDataByDomainNameStatement);
 }
 
+bool ResourceLoadStatisticsDatabaseStore::domainIDExistsInDatabase(int domainID)
+{
+    if (m_linkDecorationExistsStatement.bindInt(1, domainID) != SQLITE_OK
+        || m_linkDecorationExistsStatement.bindInt(2, domainID) != SQLITE_OK
+        || m_scriptLoadExistsStatement.bindInt(1, domainID) != SQLITE_OK
+        || m_scriptLoadExistsStatement.bindInt(2, domainID) != SQLITE_OK
+        || m_subFrameExistsStatement.bindInt(1, domainID) != SQLITE_OK
+        || m_subFrameExistsStatement.bindInt(2, domainID) != SQLITE_OK
+        || m_subResourceExistsStatement.bindInt(1, domainID) != SQLITE_OK
+        || m_subResourceExistsStatement.bindInt(2, domainID) != SQLITE_OK
+        || m_uniqueRedirectExistsStatement.bindInt(1, domainID) != SQLITE_OK
+        || m_uniqueRedirectExistsStatement.bindInt(2, domainID) != SQLITE_OK
+        || m_observedDomainsExistsStatement.bindInt(1, domainID) != SQLITE_OK) {
+        RELEASE_LOG_ERROR_IF_ALLOWED(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::domainIDExistsInDatabase failed to bind, error message: %{private}s", this, m_database.lastErrorMsg());
+        ASSERT_NOT_REACHED();
+        return false;
+    }
+
+    if (m_linkDecorationExistsStatement.step() != SQLITE_ROW
+        || m_scriptLoadExistsStatement.step() != SQLITE_ROW
+        || m_subFrameExistsStatement.step() != SQLITE_ROW
+        || m_subResourceExistsStatement.step() != SQLITE_ROW
+        || m_uniqueRedirectExistsStatement.step() != SQLITE_ROW
+        || m_observedDomainsExistsStatement.step() != SQLITE_ROW) {
+        RELEASE_LOG_ERROR_IF_ALLOWED(m_sessionID, "%p - ResourceLoadStatisticsDatabaseStore::domainIDExistsInDatabase failed to step, error message: %{private}s", this, m_database.lastErrorMsg());
+        ASSERT_NOT_REACHED();
+        return false;
+    }
+    
+    resetStatement(m_linkDecorationExistsStatement);
+    resetStatement(m_scriptLoadExistsStatement);
+    resetStatement(m_subFrameExistsStatement);
+    resetStatement(m_subResourceExistsStatement);
+    resetStatement(m_uniqueRedirectExistsStatement);
+    resetStatement(m_observedDomainsExistsStatement);
+
+    return m_linkDecorationExistsStatement.getColumnInt(0) || m_scriptLoadExistsStatement.getColumnInt(0) || m_subFrameExistsStatement.getColumnInt(0) || m_subResourceExistsStatement.getColumnInt(0) || m_uniqueRedirectExistsStatement.getColumnInt(0) || m_observedDomainsExistsStatement.getColumnInt(0);
+}
+
 } // namespace WebKit
 
 #endif

Modified: trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h (260667 => 260668)


--- trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h	2020-04-24 21:02:48 UTC (rev 260667)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h	2020-04-24 21:08:10 UTC (rev 260668)
@@ -138,6 +138,8 @@
     Seconds getMostRecentlyUpdatedTimestamp(const RegistrableDomain&, const TopFrameDomain&) const;
     bool isNewResourceLoadStatisticsDatabaseFile() const { return m_isNewResourceLoadStatisticsDatabaseFile; }
     void setIsNewResourceLoadStatisticsDatabaseFile(bool isNewResourceLoadStatisticsDatabaseFile) { m_isNewResourceLoadStatisticsDatabaseFile = isNewResourceLoadStatisticsDatabaseFile; }
+    void removeDataForDomain(const RegistrableDomain&) override;
+    bool domainIDExistsInDatabase(int);
 
 private:
     void openITPDatabase();
@@ -263,6 +265,13 @@
     mutable WebCore::SQLiteStatement m_getAllSubStatisticsStatement;
     mutable WebCore::SQLiteStatement m_storageAccessExistsStatement;
     mutable WebCore::SQLiteStatement m_getMostRecentlyUpdatedTimestampStatement;
+    mutable WebCore::SQLiteStatement m_linkDecorationExistsStatement;
+    mutable WebCore::SQLiteStatement m_scriptLoadExistsStatement;
+    mutable WebCore::SQLiteStatement m_subFrameExistsStatement;
+    mutable WebCore::SQLiteStatement m_subResourceExistsStatement;
+    mutable WebCore::SQLiteStatement m_uniqueRedirectExistsStatement;
+    mutable WebCore::SQLiteStatement m_observedDomainsExistsStatement;
+    mutable WebCore::SQLiteStatement m_removeAllDataStatement;
     PAL::SessionID m_sessionID;
     bool m_isNewResourceLoadStatisticsDatabaseFile { false };
 };

Modified: trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.cpp (260667 => 260668)


--- trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.cpp	2020-04-24 21:02:48 UTC (rev 260667)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.cpp	2020-04-24 21:08:10 UTC (rev 260668)
@@ -1042,6 +1042,23 @@
     statistics.lastSeen = WallTime::fromRawSeconds(seconds.seconds());
 }
 
+void ResourceLoadStatisticsMemoryStore::removeDataForDomain(const RegistrableDomain& domain)
+{
+    m_resourceStatisticsMap.remove(domain);
+    
+    for (auto& statistic : m_resourceStatisticsMap) {
+        statistic.value.topFrameUniqueRedirectsTo.remove(domain);
+        statistic.value.topFrameUniqueRedirectsToSinceSameSiteStrictEnforcement.remove(domain);
+        statistic.value.topFrameUniqueRedirectsFrom.remove(domain);
+        statistic.value.topFrameLinkDecorationsFrom.remove(domain);
+        statistic.value.topFrameLoadedThirdPartyScripts.remove(domain);
+        statistic.value.subframeUnderTopFrameDomains.remove(domain);
+        statistic.value.subresourceUnderTopFrameDomains.remove(domain);
+        statistic.value.subresourceUniqueRedirectsTo.remove(domain);
+        statistic.value.subresourceUniqueRedirectsFrom.remove(domain);
+    }
+}
+
 void ResourceLoadStatisticsMemoryStore::setPrevalentResource(const RegistrableDomain& domain)
 {
     ASSERT(!RunLoop::isMain());

Modified: trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.h (260667 => 260668)


--- trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.h	2020-04-24 21:02:48 UTC (rev 260667)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsMemoryStore.h	2020-04-24 21:08:10 UTC (rev 260668)
@@ -112,6 +112,7 @@
     bool hasHadUserInteraction(const RegistrableDomain&, OperatingDatesWindow) override;
 
     void setLastSeen(const RegistrableDomain&, Seconds) override;
+    void removeDataForDomain(const RegistrableDomain&) override;
 
 private:
     static bool shouldBlockAndKeepCookies(const ResourceLoadStatistics&);

Modified: trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsStore.h (260667 => 260668)


--- trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsStore.h	2020-04-24 21:02:48 UTC (rev 260667)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsStore.h	2020-04-24 21:08:10 UTC (rev 260668)
@@ -184,6 +184,8 @@
 
     virtual void setLastSeen(const RegistrableDomain& primaryDomain, Seconds) = 0;
 
+    virtual void removeDataForDomain(const RegistrableDomain&) = 0;
+    
     void didCreateNetworkProcess();
 
     const WebResourceLoadStatisticsStore& store() const { return m_store; }

Modified: trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp (260667 => 260668)


--- trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp	2020-04-24 21:02:48 UTC (rev 260667)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp	2020-04-24 21:08:10 UTC (rev 260668)
@@ -1155,6 +1155,23 @@
     completionHandler();
 }
 
+void WebResourceLoadStatisticsStore::domainIDExistsInDatabase(int domainID, CompletionHandler<void(bool)>&& completionHandler)
+{
+    ASSERT(RunLoop::isMain());
+
+    postTask([this, domainID, completionHandler = WTFMove(completionHandler)]() mutable {
+        if (!m_statisticsStore || !is<ResourceLoadStatisticsDatabaseStore>(*m_statisticsStore)) {
+            completionHandler(false);
+            return;
+        }
+        auto& databaseStore = downcast<ResourceLoadStatisticsDatabaseStore>(*m_statisticsStore);
+        bool domainIDExists = databaseStore.domainIDExistsInDatabase(domainID);
+        postTaskReply([domainIDExists, completionHandler = WTFMove(completionHandler)]() mutable {
+            completionHandler(domainIDExists);
+        });
+    });
+}
+
 void WebResourceLoadStatisticsStore::setTimeToLiveUserInteraction(Seconds seconds, CompletionHandler<void()>&& completionHandler)
 {
     ASSERT(RunLoop::isMain());
@@ -1283,6 +1300,17 @@
     m_networkSession = nullptr;
 }
 
+void WebResourceLoadStatisticsStore::removeDataForDomain(RegistrableDomain domain, CompletionHandler<void()>&& completionHandler)
+{
+    ASSERT(RunLoop::isMain());
+    postTask([this, domain = WTFMove(domain), completionHandler = WTFMove(completionHandler)]() mutable {
+        if (m_statisticsStore)
+            m_statisticsStore->removeDataForDomain(domain);
+
+        postTaskReply(WTFMove(completionHandler));
+    });
+}
+
 void WebResourceLoadStatisticsStore::deleteAndRestrictWebsiteDataForRegistrableDomains(OptionSet<WebsiteDataType> dataTypes, RegistrableDomainsToDeleteOrRestrictWebsiteDataFor&& domainsToDeleteAndRestrictWebsiteDataFor, bool shouldNotifyPage, CompletionHandler<void(const HashSet<RegistrableDomain>&)>&& completionHandler)
 {
     ASSERT(RunLoop::isMain());

Modified: trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h (260667 => 260668)


--- trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h	2020-04-24 21:02:48 UTC (rev 260667)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h	2020-04-24 21:08:10 UTC (rev 260668)
@@ -218,6 +218,7 @@
     void logUserInteraction(const TopFrameDomain&, CompletionHandler<void()>&&);
     void logCrossSiteLoadWithLinkDecoration(const NavigatedFromDomain&, const NavigatedToDomain&, CompletionHandler<void()>&&);
     void clearUserInteraction(const TopFrameDomain&, CompletionHandler<void()>&&);
+    void removeDataForDomain(const RegistrableDomain, CompletionHandler<void()>&&);
     void deleteAndRestrictWebsiteDataForRegistrableDomains(OptionSet<WebsiteDataType>, RegistrableDomainsToDeleteOrRestrictWebsiteDataFor&&, bool shouldNotifyPage, CompletionHandler<void(const HashSet<RegistrableDomain>&)>&&);
     void registrableDomainsWithWebsiteData(OptionSet<WebsiteDataType>, bool shouldNotifyPage, CompletionHandler<void(HashSet<RegistrableDomain>&&)>&&);
     StorageAccessWasGranted grantStorageAccess(const SubFrameDomain&, const TopFrameDomain&, Optional<WebCore::FrameIdentifier>, WebCore::PageIdentifier);
@@ -254,6 +255,7 @@
     void scheduleClearInMemoryAndPersistent(ShouldGrandfatherStatistics, CompletionHandler<void()>&&);
     void scheduleClearInMemoryAndPersistent(WallTime modifiedSince, ShouldGrandfatherStatistics, CompletionHandler<void()>&&);
     void clearInMemoryEphemeral(CompletionHandler<void()>&&);
+    void domainIDExistsInDatabase(int domainID, CompletionHandler<void(bool)>&&);
 
     void setTimeToLiveUserInteraction(Seconds, CompletionHandler<void()>&&);
     void setMinimumTimeBetweenDataRecordsRemoval(Seconds, CompletionHandler<void()>&&);

Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp (260667 => 260668)


--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp	2020-04-24 21:02:48 UTC (rev 260667)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp	2020-04-24 21:08:10 UTC (rev 260668)
@@ -990,6 +990,19 @@
     }
 }
 
+void NetworkProcess::domainIDExistsInDatabase(PAL::SessionID sessionID, int domainID, CompletionHandler<void(bool)>&& completionHandler)
+{
+    if (auto* networkSession = this->networkSession(sessionID)) {
+        if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
+            resourceLoadStatistics->domainIDExistsInDatabase(domainID, WTFMove(completionHandler));
+        else
+            completionHandler(false);
+    } else {
+        ASSERT_NOT_REACHED();
+        completionHandler(false);
+    }
+}
+
 void NetworkProcess::mergeStatisticForTesting(PAL::SessionID sessionID, const RegistrableDomain& domain, const RegistrableDomain& topFrameDomain1, const RegistrableDomain& topFrameDomain2, Seconds lastSeen, bool hadUserInteraction, Seconds mostRecentUserInteraction, bool isGrandfathered, bool isPrevalent, bool isVeryPrevalent, unsigned dataRecordsRemoved, CompletionHandler<void()>&& completionHandler)
 {
     if (auto* networkSession = this->networkSession(sessionID)) {
@@ -1604,7 +1617,7 @@
     });
 }
 
-void NetworkProcess::deleteWebsiteDataForOrigins(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, const Vector<SecurityOriginData>& originDatas, const Vector<String>& cookieHostNames, const Vector<String>& HSTSCacheHostNames, CallbackID callbackID)
+void NetworkProcess::deleteWebsiteDataForOrigins(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, const Vector<SecurityOriginData>& originDatas, const Vector<String>& cookieHostNames, const Vector<String>& HSTSCacheHostNames, const Vector<RegistrableDomain>& registrableDomains, CallbackID callbackID)
 {
     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
         if (auto* networkStorageSession = storageSession(sessionID))
@@ -1678,6 +1691,17 @@
         }
         WebCore::CredentialStorage::removeSessionCredentialsWithOrigins(originDatas);
     }
+
+#if ENABLE(RESOURCE_LOAD_STATISTICS)
+    if (websiteDataTypes.contains(WebsiteDataType::ResourceLoadStatistics)) {
+        if (auto* networkSession = this->networkSession(sessionID)) {
+            for (auto& domain : registrableDomains) {
+                if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
+                    resourceLoadStatistics->removeDataForDomain(domain, [clearTasksHandler = clearTasksHandler.copyRef()] { });
+            }
+        }
+    }
+#endif
 }
 
 #if ENABLE(RESOURCE_LOAD_STATISTICS)

Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.h (260667 => 260668)


--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.h	2020-04-24 21:02:48 UTC (rev 260667)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.h	2020-04-24 21:08:10 UTC (rev 260668)
@@ -241,6 +241,7 @@
     void setCacheMaxAgeCapForPrevalentResources(PAL::SessionID, Seconds, CompletionHandler<void()>&&);
     void setGrandfatheringTime(PAL::SessionID, Seconds, CompletionHandler<void()>&&);
     void setLastSeen(PAL::SessionID, const RegistrableDomain&, Seconds, CompletionHandler<void()>&&);
+    void domainIDExistsInDatabase(PAL::SessionID, int domainID, CompletionHandler<void(bool)>&&);
     void mergeStatisticForTesting(PAL::SessionID, const RegistrableDomain&, const TopFrameDomain& topFrameDomain1, const TopFrameDomain& topFrameDomain2, Seconds lastSeen, bool hadUserInteraction, Seconds mostRecentUserInteraction, bool isGrandfathered, bool isPrevalent, bool isVeryPrevalent, unsigned dataRecordsRemoved, CompletionHandler<void()>&&);
     void setMinimumTimeBetweenDataRecordsRemoval(PAL::SessionID, Seconds, CompletionHandler<void()>&&);
     void setNotifyPagesWhenDataRecordsWereScanned(PAL::SessionID, bool value, CompletionHandler<void()>&&);
@@ -399,7 +400,7 @@
 
     void fetchWebsiteData(PAL::SessionID, OptionSet<WebsiteDataType>, OptionSet<WebsiteDataFetchOption>, CallbackID);
     void deleteWebsiteData(PAL::SessionID, OptionSet<WebsiteDataType>, WallTime modifiedSince, CallbackID);
-    void deleteWebsiteDataForOrigins(PAL::SessionID, OptionSet<WebsiteDataType>, const Vector<WebCore::SecurityOriginData>& origins, const Vector<String>& cookieHostNames, const Vector<String>& HSTSCacheHostnames, CallbackID);
+    void deleteWebsiteDataForOrigins(PAL::SessionID, OptionSet<WebsiteDataType>, const Vector<WebCore::SecurityOriginData>& origins, const Vector<String>& cookieHostNames, const Vector<String>& HSTSCacheHostnames, const Vector<RegistrableDomain>&, CallbackID);
 
     void clearCachedCredentials();
 

Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in (260667 => 260668)


--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in	2020-04-24 21:02:48 UTC (rev 260667)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in	2020-04-24 21:08:10 UTC (rev 260668)
@@ -45,7 +45,7 @@
 
     FetchWebsiteData(PAL::SessionID sessionID, OptionSet<WebKit::WebsiteDataType> websiteDataTypes, OptionSet<WebKit::WebsiteDataFetchOption> fetchOptions, WebKit::CallbackID callbackID)
     DeleteWebsiteData(PAL::SessionID sessionID, OptionSet<WebKit::WebsiteDataType> websiteDataTypes, WallTime modifiedSince, WebKit::CallbackID callbackID)
-    DeleteWebsiteDataForOrigins(PAL::SessionID sessionID, OptionSet<WebKit::WebsiteDataType> websiteDataTypes, Vector<WebCore::SecurityOriginData> origins, Vector<String> cookieHostNames, Vector<String> HSTSCacheHostNames, WebKit::CallbackID callbackID)
+    DeleteWebsiteDataForOrigins(PAL::SessionID sessionID, OptionSet<WebKit::WebsiteDataType> websiteDataTypes, Vector<WebCore::SecurityOriginData> origins, Vector<String> cookieHostNames, Vector<String> HSTSCacheHostNames, Vector<WebCore::RegistrableDomain> registrableDomains, WebKit::CallbackID callbackID)
 
     DownloadRequest(PAL::SessionID sessionID, WebKit::DownloadID downloadID, WebCore::ResourceRequest request, enum:bool Optional<WebKit::NavigatingToAppBoundDomain> isNavigatingToAppBoundDomain, String suggestedFilename)
     ResumeDownload(PAL::SessionID sessionID, WebKit::DownloadID downloadID, IPC::DataReference resumeData, String path, WebKit::SandboxExtension::Handle sandboxExtensionHandle)
@@ -104,6 +104,7 @@
     IsRegisteredAsRedirectingTo(PAL::SessionID sessionID, WebCore::RegistrableDomain redirectedFromDomain, WebCore::RegistrableDomain redirectedToDomain) -> (bool isRedirectingTo) Async
     IsRegisteredAsSubFrameUnder(PAL::SessionID sessionID, WebCore::RegistrableDomain subFrameDomain, WebCore::RegistrableDomain topFrameDomain) -> (bool isSubframeUnder) Async
     IsRegisteredAsSubresourceUnder(PAL::SessionID sessionID, WebCore::RegistrableDomain subresourceDomain, WebCore::RegistrableDomain topFrameDomain) -> (bool isSubresourceUnder) Async
+    DomainIDExistsInDatabase(PAL::SessionID sessionID, int domainID) -> (bool exists) Async
     LogFrameNavigation(PAL::SessionID sessionID, WebCore::RegistrableDomain targetDomain, WebCore::RegistrableDomain topFrameDomain, WebCore::RegistrableDomain sourceDomain, bool isRedirect, bool isMainFrame, Seconds delayAfterMainFrameDocumentLoad, bool wasPotentiallyInitiatedByUser)
     LogUserInteraction(PAL::SessionID sessionID, WebCore::RegistrableDomain topFrameDomain) -> () Async
     ResetParametersToDefaultValues(PAL::SessionID sessionID) -> () Async

Modified: trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp (260667 => 260668)


--- trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp	2020-04-24 21:02:48 UTC (rev 260667)
+++ trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp	2020-04-24 21:08:10 UTC (rev 260668)
@@ -66,6 +66,30 @@
     return WebKit::toAPI(&WebKit::WebsiteDataStore::create(*WebKit::toImpl(configuration), sessionID).leakRef());
 }
 
+void WKWebsiteDataStoreRemoveITPDataForDomain(WKWebsiteDataStoreRef dataStoreRef, WKStringRef host, void* context, WKWebsiteDataStoreRemoveITPDataForDomainFunction callback)
+{
+    WebKit::WebsiteDataRecord dataRecord;
+    dataRecord.types.add(WebKit::WebsiteDataType::ResourceLoadStatistics);
+    dataRecord.displayName = WebKit::toImpl(host)->string();
+    Vector<WebKit::WebsiteDataRecord> dataRecords = { WTFMove(dataRecord) };
+
+    OptionSet<WebKit::WebsiteDataType> dataTypes = WebKit::WebsiteDataType::ResourceLoadStatistics;
+    WebKit::toImpl(dataStoreRef)->removeData(dataTypes, dataRecords, [context, callback] {
+        callback(context);
+    });
+}
+
+void WKWebsiteDataStoreDoesStatisticsDomainIDExistInDatabase(WKWebsiteDataStoreRef dataStoreRef, int domainID, void* context, WKWebsiteDataStoreDoesStatisticsDomainIDExistInDatabaseFunction callback)
+{
+#if ENABLE(RESOURCE_LOAD_STATISTICS)
+    WebKit::toImpl(dataStoreRef)->domainIDExistsInDatabase(domainID, [context, callback](bool exists) {
+        callback(exists, context);
+    });
+#else
+    callback(false, context);
+#endif
+}
+
 void WKWebsiteDataStoreSetResourceLoadStatisticsEnabled(WKWebsiteDataStoreRef dataStoreRef, bool enable)
 {
     auto* websiteDataStore = WebKit::toImpl(dataStoreRef);

Modified: trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.h (260667 => 260668)


--- trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.h	2020-04-24 21:02:48 UTC (rev 260667)
+++ trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.h	2020-04-24 21:08:10 UTC (rev 260668)
@@ -136,6 +136,11 @@
 WK_EXPORT void WKWebsiteDataStoreRemoveFetchCacheForOrigin(WKWebsiteDataStoreRef dataStoreRef, WKSecurityOriginRef origin, void* context, WKWebsiteDataStoreRemoveFetchCacheRemovalFunction callback);
 WK_EXPORT void WKWebsiteDataStoreRemoveAllFetchCaches(WKWebsiteDataStoreRef dataStoreRef, void* context, WKWebsiteDataStoreRemoveFetchCacheRemovalFunction callback);
 
+typedef void (*WKWebsiteDataStoreRemoveITPDataForDomainFunction)(void* functionContext);
+WK_EXPORT void WKWebsiteDataStoreRemoveITPDataForDomain(WKWebsiteDataStoreRef dataStoreRef, WKStringRef origin, void* context, WKWebsiteDataStoreRemoveITPDataForDomainFunction callback);
+typedef void (*WKWebsiteDataStoreDoesStatisticsDomainIDExistInDatabaseFunction)(bool domainExistsInDatabase, void* functionContext);
+WK_EXPORT void WKWebsiteDataStoreDoesStatisticsDomainIDExistInDatabase(WKWebsiteDataStoreRef dataStoreRef, int domainID, void* context, WKWebsiteDataStoreDoesStatisticsDomainIDExistInDatabaseFunction callback);
+
 typedef void (*WKWebsiteDataStoreRemoveAllServiceWorkerRegistrationsCallback)(void* functionContext);
 WK_EXPORT void WKWebsiteDataStoreRemoveAllServiceWorkerRegistrations(WKWebsiteDataStoreRef dataStoreRef, void* context, WKWebsiteDataStoreRemoveAllServiceWorkerRegistrationsCallback callback);
 

Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp (260667 => 260668)


--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp	2020-04-24 21:02:48 UTC (rev 260667)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp	2020-04-24 21:08:10 UTC (rev 260668)
@@ -198,7 +198,7 @@
     send(Messages::NetworkProcess::DeleteWebsiteData(sessionID, dataTypes, modifiedSince, callbackID), 0);
 }
 
-void NetworkProcessProxy::deleteWebsiteDataForOrigins(PAL::SessionID sessionID, OptionSet<WebsiteDataType> dataTypes, const Vector<WebCore::SecurityOriginData>& origins, const Vector<String>& cookieHostNames, const Vector<String>& HSTSCacheHostNames, CompletionHandler<void()>&& completionHandler)
+void NetworkProcessProxy::deleteWebsiteDataForOrigins(PAL::SessionID sessionID, OptionSet<WebsiteDataType> dataTypes, const Vector<WebCore::SecurityOriginData>& origins, const Vector<String>& cookieHostNames, const Vector<String>& HSTSCacheHostNames, const Vector<RegistrableDomain>& registrableDomains, CompletionHandler<void()>&& completionHandler)
 {
     ASSERT(canSendMessage());
 
@@ -214,7 +214,7 @@
         RELEASE_LOG_IF(sessionID.isAlwaysOnLoggingAllowed(), ProcessSuspension, "%p - NetworkProcessProxy is releasing a background assertion because the Network process is done deleting Website data for several origins", this);
     });
 
-    send(Messages::NetworkProcess::DeleteWebsiteDataForOrigins(sessionID, dataTypes, origins, cookieHostNames, HSTSCacheHostNames, callbackID), 0);
+    send(Messages::NetworkProcess::DeleteWebsiteDataForOrigins(sessionID, dataTypes, origins, cookieHostNames, HSTSCacheHostNames, registrableDomains, callbackID), 0);
 }
 
 void NetworkProcessProxy::networkProcessCrashed()
@@ -574,6 +574,16 @@
     sendWithAsyncReply(Messages::NetworkProcess::SetLastSeen(sessionID, resourceDomain, lastSeen), WTFMove(completionHandler));
 }
 
+void NetworkProcessProxy::domainIDExistsInDatabase(PAL::SessionID sessionID, int domainID, CompletionHandler<void(bool)>&& completionHandler)
+{
+    if (!canSendMessage()) {
+        completionHandler(false);
+        return;
+    }
+    
+    sendWithAsyncReply(Messages::NetworkProcess::DomainIDExistsInDatabase(sessionID, domainID), WTFMove(completionHandler));
+}
+
 void NetworkProcessProxy::mergeStatisticForTesting(PAL::SessionID sessionID, const RegistrableDomain& resourceDomain, const RegistrableDomain& topFrameDomain1, const RegistrableDomain& topFrameDomain2, Seconds lastSeen, bool hadUserInteraction, Seconds mostRecentUserInteraction, bool isGrandfathered, bool isPrevalent, bool isVeryPrevalent, unsigned dataRecordsRemoved, CompletionHandler<void()>&& completionHandler)
 {
     sendWithAsyncReply(Messages::NetworkProcess::MergeStatisticForTesting(sessionID, resourceDomain, topFrameDomain1, topFrameDomain2, lastSeen, hadUserInteraction, mostRecentUserInteraction, isGrandfathered, isPrevalent, isVeryPrevalent, dataRecordsRemoved), WTFMove(completionHandler));

Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h (260667 => 260668)


--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h	2020-04-24 21:02:48 UTC (rev 260667)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h	2020-04-24 21:08:10 UTC (rev 260668)
@@ -107,7 +107,7 @@
 
     void fetchWebsiteData(PAL::SessionID, OptionSet<WebsiteDataType>, OptionSet<WebsiteDataFetchOption>, CompletionHandler<void(WebsiteData)>&&);
     void deleteWebsiteData(PAL::SessionID, OptionSet<WebsiteDataType>, WallTime modifiedSince, CompletionHandler<void()>&& completionHandler);
-    void deleteWebsiteDataForOrigins(PAL::SessionID, OptionSet<WebKit::WebsiteDataType>, const Vector<WebCore::SecurityOriginData>& origins, const Vector<String>& cookieHostNames, const Vector<String>& HSTSCacheHostNames, CompletionHandler<void()>&&);
+    void deleteWebsiteDataForOrigins(PAL::SessionID, OptionSet<WebKit::WebsiteDataType>, const Vector<WebCore::SecurityOriginData>& origins, const Vector<String>& cookieHostNames, const Vector<String>& HSTSCacheHostNames, const Vector<RegistrableDomain>&, CompletionHandler<void()>&&);
 
     void getLocalStorageDetails(PAL::SessionID, CompletionHandler<void(Vector<LocalStorageDatabaseTracker::OriginDetails>&&)>&&);
 
@@ -130,6 +130,7 @@
     void logUserInteraction(PAL::SessionID, const RegistrableDomain&, CompletionHandler<void()>&&);
     void scheduleStatisticsAndDataRecordsProcessing(PAL::SessionID, CompletionHandler<void()>&&);
     void setLastSeen(PAL::SessionID, const RegistrableDomain&, Seconds, CompletionHandler<void()>&&);
+    void domainIDExistsInDatabase(PAL::SessionID, int domainID, CompletionHandler<void(bool)>&&);
     void mergeStatisticForTesting(PAL::SessionID, const RegistrableDomain&, const TopFrameDomain& topFrameDomain1, const TopFrameDomain& topFrameDomain2, Seconds lastSeen, bool hadUserInteraction, Seconds mostRecentUserInteraction, bool isGrandfathered, bool isPrevalent, bool isVeryPrevalent, unsigned dataRecordsRemoved, CompletionHandler<void()>&&);
     void setAgeCapForClientSideCookies(PAL::SessionID, Optional<Seconds>, CompletionHandler<void()>&&);
     void setCacheMaxAgeCap(PAL::SessionID, Seconds, CompletionHandler<void()>&&);

Modified: trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp (260667 => 260668)


--- trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp	2020-04-24 21:02:48 UTC (rev 260667)
+++ trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp	2020-04-24 21:08:10 UTC (rev 260668)
@@ -990,15 +990,17 @@
 
             Vector<String> cookieHostNames;
             Vector<String> HSTSCacheHostNames;
+            Vector<WebCore::RegistrableDomain> registrableDomains;
             for (const auto& dataRecord : dataRecords) {
                 for (auto& hostName : dataRecord.cookieHostNames)
                     cookieHostNames.append(hostName);
                 for (auto& hostName : dataRecord.HSTSCacheHostNames)
                     HSTSCacheHostNames.append(hostName);
+                registrableDomains.append(WebCore::RegistrableDomain::uncheckedCreateFromHost(dataRecord.displayName));
             }
 
             callbackAggregator->addPendingCallback();
-            processPool->networkProcess()->deleteWebsiteDataForOrigins(m_sessionID, dataTypes, origins, cookieHostNames, HSTSCacheHostNames, [callbackAggregator, processPool] {
+            processPool->networkProcess()->deleteWebsiteDataForOrigins(m_sessionID, dataTypes, origins, cookieHostNames, HSTSCacheHostNames, registrableDomains, [callbackAggregator, processPool] {
                 callbackAggregator->removePendingCallback();
             });
         }
@@ -1596,6 +1598,18 @@
     }
 }
 
+void WebsiteDataStore::domainIDExistsInDatabase(int domainID, CompletionHandler<void(bool)>&& completionHandler)
+{
+    ASSERT(RunLoop::isMain());
+
+    for (auto& processPool : processPools()) {
+        if (auto* process = processPool->networkProcess()) {
+            process->domainIDExistsInDatabase(m_sessionID, domainID, WTFMove(completionHandler));
+            break;
+        }
+    }
+}
+
 void WebsiteDataStore::mergeStatisticForTesting(const URL& url , const URL& topFrameUrl1, const URL& topFrameUrl2, Seconds lastSeen, bool hadUserInteraction, Seconds mostRecentUserInteraction, bool isGrandfathered, bool isPrevalent, bool isVeryPrevalent, unsigned dataRecordsRemoved, CompletionHandler<void()>&& completionHandler)
 {
     if (url.protocolIsAbout() || url.isEmpty()) {

Modified: trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h (260667 => 260668)


--- trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h	2020-04-24 21:02:48 UTC (rev 260667)
+++ trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h	2020-04-24 21:08:10 UTC (rev 260668)
@@ -167,6 +167,7 @@
     void setUseITPDatabase(bool, CompletionHandler<void()>&&);
     void setGrandfatheringTime(Seconds, CompletionHandler<void()>&&);
     void setLastSeen(const URL&, Seconds, CompletionHandler<void()>&&);
+    void domainIDExistsInDatabase(int domainID, CompletionHandler<void(bool)>&&);
     void mergeStatisticForTesting(const URL&, const URL& topFrameUrl1, const URL& topFrameUrl2, Seconds lastSeen, bool hadUserInteraction, Seconds mostRecentUserInteraction, bool isGrandfathered, bool isPrevalent, bool isVeryPrevalent, unsigned dataRecordsRemoved, CompletionHandler<void()>&&);
     void setNotifyPagesWhenDataRecordsWereScanned(bool, CompletionHandler<void()>&&);
     void setIsRunningResourceLoadStatisticsTest(bool, CompletionHandler<void()>&&);

Modified: trunk/Tools/ChangeLog (260667 => 260668)


--- trunk/Tools/ChangeLog	2020-04-24 21:02:48 UTC (rev 260667)
+++ trunk/Tools/ChangeLog	2020-04-24 21:08:10 UTC (rev 260668)
@@ -1,3 +1,27 @@
+2020-04-24  Kate Cheney  <[email protected]>
+
+        Removing website data for a domain should delete corresponding ITP entry
+        https://bugs.webkit.org/show_bug.cgi?id=210864
+        <rdar://problem/59473193>
+
+        Reviewed by John Wilander.
+
+        Created 2 new APIs for testing. One to mimic clearing website data
+        for a domain, and one to check if the domain exists in the database
+        after a deletion was requested.
+
+        * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
+        * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+        (WTR::TestRunner::doesStatisticsDomainIDExistInDatabase):
+        (WTR::TestRunner::domainIDExistsInDatabase): Deleted.
+        * WebKitTestRunner/InjectedBundle/TestRunner.h:
+        * WebKitTestRunner/TestController.cpp:
+        (WTR::TestController::doesStatisticsDomainIDExistInDatabase):
+        (WTR::TestController::domainIDExistsInDatabase): Deleted.
+        * WebKitTestRunner/TestController.h:
+        * WebKitTestRunner/TestInvocation.cpp:
+        (WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):
+
 2020-04-24  Antoine Quint  <[email protected]>
 
         Update the css/css-animations WPT tests

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl (260667 => 260668)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl	2020-04-24 21:02:48 UTC (rev 260667)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl	2020-04-24 21:08:10 UTC (rev 260668)
@@ -292,6 +292,8 @@
     void disconnectMockGamepad(unsigned long index);
 
     // Resource Load Statistics
+    void clearStatisticsDataForDomain(DOMString domain);
+    boolean doesStatisticsDomainIDExistInDatabase(unsigned long domainID);
     void setStatisticsEnabled(boolean value);
     boolean isStatisticsEphemeral();
     void installStatisticsDidModifyDataRecordsCallback(object callback);

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp (260667 => 260668)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp	2020-04-24 21:02:48 UTC (rev 260667)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp	2020-04-24 21:08:10 UTC (rev 260668)
@@ -1415,6 +1415,37 @@
     callTestRunnerCallback(DidRemoveSwipeSnapshotCallbackID);
 }
 
+void TestRunner::clearStatisticsDataForDomain(JSStringRef domain)
+{
+    WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("ClearStatisticsDataForDomain"));
+    WKRetainPtr<WKStringRef> messageBody = adoptWK(WKStringCreateWithJSString(domain));
+    WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
+}
+
+bool TestRunner::doesStatisticsDomainIDExistInDatabase(unsigned domainID)
+{
+    Vector<WKRetainPtr<WKStringRef>> keys;
+    Vector<WKRetainPtr<WKTypeRef>> values;
+
+    keys.append(adoptWK(WKStringCreateWithUTF8CString("DomainID")));
+    values.append(adoptWK(WKUInt64Create(domainID)));
+
+    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("DoesStatisticsDomainIDExistInDatabase"));
+    WKRetainPtr<WKDictionaryRef> messageBody = adoptWK(WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
+    WKTypeRef returnData = nullptr;
+    WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
+    ASSERT(WKGetTypeID(returnData) == WKBooleanGetTypeID());
+    return WKBooleanGetValue(adoptWK(static_cast<WKBooleanRef>(returnData)).get());
+}
+
 void TestRunner::setStatisticsEnabled(bool value)
 {
     WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("SetStatisticsEnabled"));

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h (260667 => 260668)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h	2020-04-24 21:02:48 UTC (rev 260667)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h	2020-04-24 21:08:10 UTC (rev 260668)
@@ -380,6 +380,8 @@
     void setMockGamepadButtonValue(unsigned index, unsigned buttonIndex, double value);
     
     // Resource Load Statistics
+    void clearStatisticsDataForDomain(JSStringRef domain);
+    bool doesStatisticsDomainIDExistInDatabase(unsigned domainID);
     void setStatisticsEnabled(bool value);
     bool isStatisticsEphemeral();
     void installStatisticsDidModifyDataRecordsCallback(JSValueRef callback);

Modified: trunk/Tools/WebKitTestRunner/TestController.cpp (260667 => 260668)


--- trunk/Tools/WebKitTestRunner/TestController.cpp	2020-04-24 21:02:48 UTC (rev 260667)
+++ trunk/Tools/WebKitTestRunner/TestController.cpp	2020-04-24 21:08:10 UTC (rev 260668)
@@ -3417,6 +3417,22 @@
     context->testController.notifyDone();
 }
 
+void TestController::clearStatisticsDataForDomain(WKStringRef domain)
+{
+    ResourceStatisticsCallbackContext context(*this);
+
+    WKWebsiteDataStoreRemoveITPDataForDomain(TestController::defaultWebsiteDataStore(), domain, &context, resourceStatisticsVoidResultCallback);
+    runUntil(context.done, noTimeout);
+}
+
+bool TestController::doesStatisticsDomainIDExistInDatabase(unsigned domainID)
+{
+    ResourceStatisticsCallbackContext context(*this);
+    WKWebsiteDataStoreDoesStatisticsDomainIDExistInDatabase(websiteDataStore(), domainID, &context, resourceStatisticsBooleanResultCallback);
+    runUntil(context.done, noTimeout);
+    return context.result;
+}
+
 void TestController::setStatisticsEnabled(bool value)
 {
     WKWebsiteDataStoreSetResourceLoadStatisticsEnabled(websiteDataStore(), value);

Modified: trunk/Tools/WebKitTestRunner/TestController.h (260667 => 260668)


--- trunk/Tools/WebKitTestRunner/TestController.h	2020-04-24 21:02:48 UTC (rev 260667)
+++ trunk/Tools/WebKitTestRunner/TestController.h	2020-04-24 21:08:10 UTC (rev 260668)
@@ -214,6 +214,8 @@
     void setShouldDownloadUndisplayableMIMETypes(bool value) { m_shouldDownloadUndisplayableMIMETypes = value; }
     void setShouldAllowDeviceOrientationAndMotionAccess(bool value) { m_shouldAllowDeviceOrientationAndMotionAccess = value; }
 
+    void clearStatisticsDataForDomain(WKStringRef domain);
+    bool doesStatisticsDomainIDExistInDatabase(unsigned domainID);
     void setStatisticsEnabled(bool value);
     bool isStatisticsEphemeral();
     void setStatisticsDebugMode(bool value);

Modified: trunk/Tools/WebKitTestRunner/TestInvocation.cpp (260667 => 260668)


--- trunk/Tools/WebKitTestRunner/TestInvocation.cpp	2020-04-24 21:02:48 UTC (rev 260667)
+++ trunk/Tools/WebKitTestRunner/TestInvocation.cpp	2020-04-24 21:08:10 UTC (rev 260668)
@@ -1288,7 +1288,25 @@
         WKRetainPtr<WKTypeRef> result = adoptWK(WKBooleanCreate(TestController::singleton().isDoingMediaCapture()));
         return result;
     }
+    
+    if (WKStringIsEqualToUTF8CString(messageName, "ClearStatisticsDataForDomain")) {
+        ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
+        WKStringRef domain = static_cast<WKStringRef>(messageBody);
 
+        TestController::singleton().clearStatisticsDataForDomain(domain);
+        return nullptr;
+    }
+
+    if (WKStringIsEqualToUTF8CString(messageName, "DoesStatisticsDomainIDExistInDatabase")) {
+        ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
+        WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
+        WKRetainPtr<WKStringRef> domainIDKey = adoptWK(WKStringCreateWithUTF8CString("DomainID"));
+        WKUInt64Ref domainID = static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, domainIDKey.get()));
+        bool domainIDExists = TestController::singleton().doesStatisticsDomainIDExistInDatabase(WKUInt64GetValue(domainID));
+        WKRetainPtr<WKTypeRef> result = adoptWK(WKBooleanCreate(domainIDExists));
+        return result;
+    }
+
     if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsEnabled")) {
         ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
         WKBooleanRef value = static_cast<WKBooleanRef>(messageBody);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to