Title: [250866] trunk
Revision
250866
Author
commit-qu...@webkit.org
Date
2019-10-08 15:13:39 -0700 (Tue, 08 Oct 2019)

Log Message

Implement Telemetry and Dumping Routines for SQLite backend (195088)
https://bugs.webkit.org/show_bug.cgi?id=195088
<rdar://problem/54213407>

Patch by Kate Cheney <katherine_che...@apple.com> on 2019-10-08
Reviewed by John Wilander.

Source/WebKit:

Implemented database telemetry calculating for ITP. Mimicked
ResourceLoadStatisticsMemoryStore telemetry logging behavior using
SQLite Queries as opposed to vector sorting/manipulation. Once fully
integrated, this will simplify analysis of ITP data by transitioning
ITP data storage from a plist to a SQLite database.

* NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp:
(WebKit::ResourceLoadStatisticsDatabaseStore::ResourceLoadStatisticsDatabaseStore):
Added SQL queries to be initialized in the constructor. These queries
are needed to mimic the telemetry calculations done in
ResourceLoadStatisticsMemoryStore.

(WebKit::resetStatement):
To reduce code duplication, this function holds common code to reset
a SQL query.

(WebKit::ResourceLoadStatisticsDatabaseStore::prepareStatements):
Added SQL queries needed for telemetry calculations to be prepared.

(WebKit::joinSubStatisticsForSorting):
This function returns the query string for sorting resources that is
shared by many queries.

(WebKit::ResourceLoadStatisticsDatabaseStore::getMedianOfPrevalentResourcesWithUserInteraction const):
Implemented a function to take the median days since user interaction
from all prevalent resources in the database with user interaction
(sorted by max count of subframes, subresources and unique redirects under
the top frame domain).

(WebKit::ResourceLoadStatisticsDatabaseStore::getNumberOfPrevalentResources const):
Executes a SQL query to get the number of prevalent resources to log as
telemetry.

(WebKit::ResourceLoadStatisticsDatabaseStore::getNumberOfPrevalentResourcesWithUI const):
Executes a SQL query to get the number of prevalent resources with user
interaction to log as telemetry.

(WebKit::ResourceLoadStatisticsDatabaseStore::getTopPrevelentResourceDaysSinceUI const):
Prepares and executes a SQL query to get the days since user
interaction from the top prevalent resource to be recorded as
telemetry data.

(WebKit::ResourceLoadStatisticsDatabaseStore::getMedianStatisticOfPrevalentResourceWithoutUserInteraction const):
Implemented a function which takes a statistic and returns the value
of that statistic for the median prevalent resource without user
interaction to be recorded as telemetry data.

(WebKit::ResourceLoadStatisticsDatabaseStore::getNumberOfPrevalentResourcesInTopResources const):
Returns the count of prevalent resources in the top x resources
sorted by sum of substatistics again to be logged as telemetry.

(WebKit::ResourceLoadStatisticsDatabaseStore::calculateTelemetryData const):
Function which executes all functions which populate the struct with
telemetry data. This struct will then be passed to
WebResourceLoadStatisticsTelemetry to be logged.

(WebKit::ResourceLoadStatisticsDatabaseStore::calculateAndSubmitTelemetry const):
Initializes the telemetry struct and calls the function to populate
it, then passes it to the WebResourceLoadStatisticsTelemetry object
to be recorded.

* NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h:
Describe PrevalentResourceDatabaseTelemetry Struct to be passed and
logged as telemetry data.

* NetworkProcess/Classifier/WebResourceLoadStatisticsTelemetry.cpp:
(WebKit::databaseSubmitTopLists):
Logging telemetry data by looping through 2D array of statistics for
the top 1, 3, 10, 50, and 100 prevalent resources sorted by the sum
of substatistics under the top frame domain. This matches the logging
already done in ResourceLoadStatisticsMemoryStore.

(WebKit::WebResourceLoadStatisticsTelemetry::submitTelemetry):
Submits data to the webPageProxy logs and plists.

* NetworkProcess/Classifier/WebResourceLoadStatisticsTelemetry.h:
Added new submitTopList function to accomodate database telemetry
logging.

* NetworkProcess/NetworkSession.cpp:
(WebKit::NetworkSession::notifyPageStatisticsTelemetryFinished):
* NetworkProcess/NetworkSession.h:
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::notifyResourceLoadStatisticsTelemetryFinished):
* UIProcess/Network/NetworkProcessProxy.h:
* UIProcess/Network/NetworkProcessProxy.messages.in:
Updated the current testing for telemetry which only tested 3
statistics. With this patch it now tests 10 statistics.

Tools:

Updated the current testing for telemetry which only tested 3
statistics. With this patch it now tests 10 statistics.
* WebKitTestRunner/InjectedBundle/InjectedBundle.cpp:
(WTR::InjectedBundle::didReceiveMessageToPage):
* WebKitTestRunner/InjectedBundle/TestRunner.cpp:
(WTR::TestRunner::statisticsDidRunTelemetryCallback):
* WebKitTestRunner/InjectedBundle/TestRunner.h:

LayoutTests:

Updated the current testing for telemetry which only tested 3
statistics. With this patch it now tests 10 statistics.
* http/tests/resourceLoadStatistics/telemetry-generation-advanced-functionality-database-expected.txt: Added.
* http/tests/resourceLoadStatistics/telemetry-generation-advanced-functionality-database.html: Added.
* http/tests/resourceLoadStatistics/telemetry-generation-basic-functionality-database-expected.txt: Added.
* http/tests/resourceLoadStatistics/telemetry-generation-basic-functionality-database.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (250865 => 250866)


--- trunk/LayoutTests/ChangeLog	2019-10-08 22:00:48 UTC (rev 250865)
+++ trunk/LayoutTests/ChangeLog	2019-10-08 22:13:39 UTC (rev 250866)
@@ -1,3 +1,18 @@
+2019-10-08  Kate Cheney  <katherine_che...@apple.com>
+
+        Implement Telemetry and Dumping Routines for SQLite backend (195088)
+        https://bugs.webkit.org/show_bug.cgi?id=195088
+        <rdar://problem/54213407>
+
+        Reviewed by John Wilander.
+
+        Updated the current testing for telemetry which only tested 3
+        statistics. With this patch it now tests 10 statistics.
+        * http/tests/resourceLoadStatistics/telemetry-generation-advanced-functionality-database-expected.txt: Added.
+        * http/tests/resourceLoadStatistics/telemetry-generation-advanced-functionality-database.html: Added.
+        * http/tests/resourceLoadStatistics/telemetry-generation-basic-functionality-database-expected.txt: Added.
+        * http/tests/resourceLoadStatistics/telemetry-generation-basic-functionality-database.html: Added.
+
 2019-10-08  Antti Koivisto  <an...@apple.com>
 
         [CSS Shadow Parts] Add test for exportparts list syntax

Added: trunk/LayoutTests/http/tests/resourceLoadStatistics/telemetry-generation-advanced-functionality-database-expected.txt (0 => 250866)


--- trunk/LayoutTests/http/tests/resourceLoadStatistics/telemetry-generation-advanced-functionality-database-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/resourceLoadStatistics/telemetry-generation-advanced-functionality-database-expected.txt	2019-10-08 22:13:39 UTC (rev 250866)
@@ -0,0 +1,20 @@
+Tests that advanced telemetry for prevalent resources in the SQLite Database is calculated correctly.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Hosts classified correctly.
+PASS testResult.numberOfPrevalentResources is 5
+PASS testResult.numberOfPrevalentResourcesWithUserInteraction is 2
+PASS testResult.numberOfPrevalentResourcesWithoutUserInteraction is 3
+PASS testResult.topPrevalentResourceWithUserInteractionDaysSinceUserInteraction is 0
+PASS testResult.medianDaysSinceUserInteractionPrevalentResourceWithUserInteraction is 1
+PASS testResult.top3NumberOfPrevalentResourcesWithUI is 2
+PASS testResult.top3MedianSubFrameWithoutUI is 5
+PASS testResult.top3MedianSubResourceWithoutUI is 5
+PASS testResult.top3MedianUniqueRedirectsWithoutUI is 4
+PASS testResult.top3MedianDataRecordsRemovedWithoutUI is 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/http/tests/resourceLoadStatistics/telemetry-generation-advanced-functionality-database.html (0 => 250866)


--- trunk/LayoutTests/http/tests/resourceLoadStatistics/telemetry-generation-advanced-functionality-database.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/resourceLoadStatistics/telemetry-generation-advanced-functionality-database.html	2019-10-08 22:13:39 UTC (rev 250866)
@@ -0,0 +1,157 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="UTF-8">
+    <title>Test for Advanced Telemetry Generation</title>
+    <script src=""
+    <script src=""
+</head>
+<body>
+<script>
+    testRunner.setUseITPDatabase(true);
+    description("Tests that advanced telemetry for prevalent resources in the SQLite Database is calculated correctly.");
+    jsTestIsAsync = true;
+
+    const topFrameUrl = "http://127.0.0.5:8000/temp";
+    const topResourceUrl = "http://127.0.0.6:8000/temp";
+    const toUniqueRedirectUrl = "http://127.0.0.7:8000/temp";
+    
+    const topFrameUrl1 = "http://127.0.0.1:8000/temp";
+    const topFrameUrl2 = "http://127.0.0.2:8000/temp";
+    const topFrameUrl3 = "http://127.0.0.3:8000/temp";
+    const topFrameUrl4 = "http://127.0.0.4:8000/temp";
+    
+    
+    const url1 = "http://127.0.1.1:8000/temp";
+    const url2 = "http://127.0.1.2:8000/temp";
+    const url3 = "http://127.0.1.3:8000/temp";
+    const url4 = "http://127.0.1.4:8000/temp";
+    const url5 = "http://127.0.1.5:8000/temp";
+    
+    const twoDaysOld = Math.round((new Date()).getTime() / 1000) - 180000;
+
+    function checkClassificationAndContinue() {
+        if (!testRunner.isStatisticsPrevalentResource(url1)) {
+            testFailed("Host 1 did not get classified as prevalent resource.");
+            setEnableFeature(false, finishJSTest);
+        } else if (!testRunner.isStatisticsPrevalentResource(url2)) {
+            testFailed("Host 2 did not get classified as prevalent resource.");
+            setEnableFeature(false, finishJSTest);
+        } else if (!testRunner.isStatisticsPrevalentResource(url3)) {
+            testFailed("Host 3 did not get classified as prevalent resource.");
+            setEnableFeature(false, finishJSTest);
+        } else if (!testRunner.isStatisticsPrevalentResource(url4)) {
+            testFailed("Host 4 did not get classified as prevalent resource.");
+            setEnableFeature(false, finishJSTest);
+        } else if (!testRunner.isStatisticsPrevalentResource(url5)) {
+            testFailed("Host 5 did not get classified as prevalent resource.");
+            setEnableFeature(false, finishJSTest);
+        } else if (!testRunner.isStatisticsHasHadUserInteraction(url1)) {
+            testFailed("Host 1 did not get classified as having user interaction.");
+            setEnableFeature(false, finishJSTest);
+        } else if (!testRunner.isStatisticsHasHadUserInteraction(url2)) {
+            testFailed("Host 2 did not get classified as having user interaction.");
+            setEnableFeature(false, finishJSTest);
+        } else if (!testRunner.isStatisticsRegisteredAsSubFrameUnder(url1, topFrameUrl)) {
+            testFailed("Host 1 did not get set as subframe.");
+            setEnableFeature(false, finishJSTest);
+        } else if (!testRunner.isStatisticsRegisteredAsSubresourceUnder(url1, topResourceUrl)) {
+            testFailed("Host 1 did not get set as subresource.");
+            setEnableFeature(false, finishJSTest);
+        } else if (!testRunner.isStatisticsRegisteredAsSubFrameUnder(url2, topFrameUrl)) {
+            testFailed("Host 2 did not get set as subframe.");
+            setEnableFeature(false, finishJSTest);
+        } else if (!testRunner.isStatisticsRegisteredAsSubFrameUnder(url3, topFrameUrl)) {
+            testFailed("Host 3 did not get set as subframe.");
+            setEnableFeature(false, finishJSTest);
+        } else if (!testRunner.isStatisticsRegisteredAsSubresourceUnder(url3, topResourceUrl)) {
+            testFailed("Host 3 did not get set as subresource.");
+            setEnableFeature(false, finishJSTest);
+        } else if (!testRunner.isStatisticsRegisteredAsSubFrameUnder(url4, topFrameUrl)) {
+            testFailed("Host 4 did not get set as subframe.");
+            setEnableFeature(false, finishJSTest);
+        } else {
+            testPassed("Hosts classified correctly.");
+            runTelemetryAndContinue();
+        }
+    }
+                             
+    function makeUrlPrevalent(prevalentResourceUrl) {
+        testRunner.setStatisticsSubframeUnderTopFrameOrigin(prevalentResourceUrl, topFrameUrl1);
+        testRunner.setStatisticsSubframeUnderTopFrameOrigin(prevalentResourceUrl, topFrameUrl2);
+        testRunner.setStatisticsSubframeUnderTopFrameOrigin(prevalentResourceUrl, topFrameUrl3);
+        testRunner.setStatisticsSubframeUnderTopFrameOrigin(prevalentResourceUrl, topFrameUrl4);
+
+        testRunner.setStatisticsSubresourceUniqueRedirectTo(prevalentResourceUrl, topFrameUrl1);
+        testRunner.setStatisticsSubresourceUniqueRedirectTo(prevalentResourceUrl, topFrameUrl2);
+        testRunner.setStatisticsSubresourceUniqueRedirectTo(prevalentResourceUrl, topFrameUrl3);
+        testRunner.setStatisticsSubresourceUniqueRedirectTo(prevalentResourceUrl, topFrameUrl4);
+
+        testRunner.setStatisticsSubresourceUnderTopFrameOrigin(prevalentResourceUrl, topFrameUrl1);
+        testRunner.setStatisticsSubresourceUnderTopFrameOrigin(prevalentResourceUrl, topFrameUrl2);
+        testRunner.setStatisticsSubresourceUnderTopFrameOrigin(prevalentResourceUrl, topFrameUrl3);
+        testRunner.setStatisticsSubresourceUnderTopFrameOrigin(prevalentResourceUrl, topFrameUrl4);
+    }
+
+    function setUpStatisticsAndContinue() {
+        // merge statistic arguments: hostName, topFrameDomain, lastSeen, hadUserInteraction, mostRecentUserInteraction, isGrandfathered, isPrevalent, isVeryPrevalent, dataRecordsRemoved
+         makeUrlPrevalent(url1);
+         testRunner.setStatisticsSubframeUnderTopFrameOrigin(url1, topFrameUrl);
+         testRunner.setStatisticsSubresourceUnderTopFrameOrigin(url1, topResourceUrl);
+         testRunner.setStatisticsSubresourceUniqueRedirectTo(url1, toUniqueRedirectUrl);
+                             
+         makeUrlPrevalent(url2);
+         testRunner.setStatisticsSubframeUnderTopFrameOrigin(url2, topFrameUrl);
+         testRunner.setStatisticsSubresourceUniqueRedirectTo(url2, toUniqueRedirectUrl);
+
+         makeUrlPrevalent(url3);
+         testRunner.setStatisticsSubframeUnderTopFrameOrigin(url3, topFrameUrl);
+         testRunner.setStatisticsSubresourceUnderTopFrameOrigin(url3, topResourceUrl);
+         testRunner.setStatisticsSubresourceUniqueRedirectTo(url3, toUniqueRedirectUrl);
+                             
+         makeUrlPrevalent(url4);
+         testRunner.setStatisticsSubframeUnderTopFrameOrigin(url4, topFrameUrl);
+         testRunner.setStatisticsSubresourceUnderTopFrameOrigin(url4, topResourceUrl);
+
+         makeUrlPrevalent(url5);
+
+        // set URLs 1 and 2 to have user interaction. UI for url 2 will be set to be 2 days old.
+        testRunner.setStatisticsHasHadUserInteraction(url1, true, function() {
+            testRunner.setStatisticsMergeStatistic(url2, topFrameUrl, "", twoDaysOld, true, twoDaysOld, false, true, false, 0, function() {
+                testRunner.installStatisticsDidScanDataRecordsCallback(checkClassificationAndContinue);
+                testRunner.installStatisticsDidRunTelemetryCallback(checkTelemetry);
+                testRunner.statisticsProcessStatisticsAndDataRecords();
+            });
+        });
+    }
+
+    function runTelemetryAndContinue() {
+        testRunner.statisticsSubmitTelemetry();
+    }
+
+    var testResult;
+    function checkTelemetry(result) {
+        testResult = result;
+        shouldBe("testResult.numberOfPrevalentResources", "5");
+        shouldBe("testResult.numberOfPrevalentResourcesWithUserInteraction", "2");
+        shouldBe("testResult.numberOfPrevalentResourcesWithoutUserInteraction", "3");
+        shouldBe("testResult.topPrevalentResourceWithUserInteractionDaysSinceUserInteraction", "0");
+        shouldBe("testResult.medianDaysSinceUserInteractionPrevalentResourceWithUserInteraction", "1");
+        shouldBe("testResult.top3NumberOfPrevalentResourcesWithUI", "2");
+        shouldBe("testResult.top3MedianSubFrameWithoutUI", "5");
+        shouldBe("testResult.top3MedianSubResourceWithoutUI", "5");
+        shouldBe("testResult.top3MedianUniqueRedirectsWithoutUI", "4");
+        shouldBe("testResult.top3MedianDataRecordsRemovedWithoutUI", "0");
+        setEnableFeature(false, finishJSTest);
+    }
+
+    if (window.testRunner) {
+        setEnableFeature(true, function() {
+            testRunner.setStatisticsNotifyPagesWhenDataRecordsWereScanned(true);
+            testRunner.setStatisticsNotifyPagesWhenTelemetryWasCaptured(true);
+            setUpStatisticsAndContinue();
+        });
+    }
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/http/tests/resourceLoadStatistics/telemetry-generation-basic-functionality-database-expected.txt (0 => 250866)


--- trunk/LayoutTests/http/tests/resourceLoadStatistics/telemetry-generation-basic-functionality-database-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/resourceLoadStatistics/telemetry-generation-basic-functionality-database-expected.txt	2019-10-08 22:13:39 UTC (rev 250866)
@@ -0,0 +1,31 @@
+Tests that basic telemetry for prevalent resources in the SQLite Database is calculated correctly.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Hosts classified as prevalent resources.
+PASS testResult.numberOfPrevalentResources is 0
+PASS testResult.numberOfPrevalentResourcesWithUserInteraction is 0
+PASS testResult.numberOfPrevalentResourcesWithoutUserInteraction is 0
+PASS testResult.topPrevalentResourceWithUserInteractionDaysSinceUserInteraction is 0
+PASS testResult.medianDaysSinceUserInteractionPrevalentResourceWithUserInteraction is 0
+PASS testResult.top3NumberOfPrevalentResourcesWithUI is 0
+PASS testResult.top3MedianSubFrameWithoutUI is 0
+PASS testResult.top3MedianSubResourceWithoutUI is 0
+PASS testResult.top3MedianUniqueRedirectsWithoutUI is 0
+PASS testResult.top3MedianDataRecordsRemovedWithoutUI is 0
+PASS Hosts classified as prevalent resources.
+PASS testResult.numberOfPrevalentResources is 4
+PASS testResult.numberOfPrevalentResourcesWithUserInteraction is 1
+PASS testResult.numberOfPrevalentResourcesWithoutUserInteraction is 3
+PASS testResult.topPrevalentResourceWithUserInteractionDaysSinceUserInteraction is 0
+PASS testResult.medianDaysSinceUserInteractionPrevalentResourceWithUserInteraction is 0
+PASS testResult.top3NumberOfPrevalentResourcesWithUI is 0
+PASS testResult.top3MedianSubFrameWithoutUI is 4
+PASS testResult.top3MedianSubResourceWithoutUI is 4
+PASS testResult.top3MedianUniqueRedirectsWithoutUI is 4
+PASS testResult.top3MedianDataRecordsRemovedWithoutUI is 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/http/tests/resourceLoadStatistics/telemetry-generation-basic-functionality-database.html (0 => 250866)


--- trunk/LayoutTests/http/tests/resourceLoadStatistics/telemetry-generation-basic-functionality-database.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/resourceLoadStatistics/telemetry-generation-basic-functionality-database.html	2019-10-08 22:13:39 UTC (rev 250866)
@@ -0,0 +1,137 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="UTF-8">
+    <title>Test for Basic Telemetry Generation</title>
+    <script src=""
+    <script src=""
+</head>
+<body>
+<script>
+    testRunner.setUseITPDatabase(true);
+    description("Tests that basic telemetry for prevalent resources in the SQLite Database is calculated correctly.");
+    jsTestIsAsync = true;
+
+    const topFrameUrl1 = "http://127.0.0.1:8000/temp";
+    const topFrameUrl2 = "http://127.0.0.2:8000/temp";
+    const topFrameUrl3 = "http://127.0.0.3:8000/temp";
+    const topFrameUrl4 = "http://127.0.0.4:8000/temp";
+    const prevalentResourceUrl1 = "http://127.0.1.1:8000/temp";
+    const prevalentResourceUrl2 = "http://127.0.1.2:8000/temp";
+    const prevalentResourceUrl3 = "http://127.0.1.3:8000/temp";
+    const prevalentResourceUrl4 = "http://127.0.1.4:8000/temp";
+
+    function checkInsufficientClassificationAndContinue() {
+        if (!testRunner.isStatisticsPrevalentResource(prevalentResourceUrl1)) {
+            testFailed("Host 1 did not get classified as prevalent resource.");
+            setEnableFeature(false, finishJSTest);
+        } else if (!testRunner.isStatisticsPrevalentResource(prevalentResourceUrl2)) {
+            testFailed("Host 2 did not get classified as prevalent resource.");
+            setEnableFeature(false, finishJSTest);
+        } else {
+            testPassed("Hosts classified as prevalent resources.");
+            runTelemetryAndContinue();
+        }
+    }
+
+    function checkSufficientClassificationAndContinue() {
+        if (!testRunner.isStatisticsPrevalentResource(prevalentResourceUrl1)) {
+            testFailed("Host 1 did not get classified as prevalent resource.");
+            setEnableFeature(false, finishJSTest);
+        } else if (!testRunner.isStatisticsPrevalentResource(prevalentResourceUrl2)) {
+            testFailed("Host 2 did not get classified as prevalent resource.");
+            setEnableFeature(false, finishJSTest);
+        } else if (!testRunner.isStatisticsPrevalentResource(prevalentResourceUrl3)) {
+            testFailed("Host 3 did not get classified as prevalent resource.");
+            setEnableFeature(false, finishJSTest);
+        } else if (!testRunner.isStatisticsPrevalentResource(prevalentResourceUrl4)) {
+            testFailed("Host 4 did not get classified as prevalent resource.");
+            setEnableFeature(false, finishJSTest);
+        } else {
+            testPassed("Hosts classified as prevalent resources.");
+            runTelemetryAndContinue();
+        }
+    }
+
+    function makeUrlPrevalent(prevalentResourceUrl) {
+        testRunner.setStatisticsSubframeUnderTopFrameOrigin(prevalentResourceUrl, topFrameUrl1);
+        testRunner.setStatisticsSubframeUnderTopFrameOrigin(prevalentResourceUrl, topFrameUrl2);
+        testRunner.setStatisticsSubframeUnderTopFrameOrigin(prevalentResourceUrl, topFrameUrl3);
+        testRunner.setStatisticsSubframeUnderTopFrameOrigin(prevalentResourceUrl, topFrameUrl4);
+
+        testRunner.setStatisticsSubresourceUniqueRedirectTo(prevalentResourceUrl, topFrameUrl1);
+        testRunner.setStatisticsSubresourceUniqueRedirectTo(prevalentResourceUrl, topFrameUrl2);
+        testRunner.setStatisticsSubresourceUniqueRedirectTo(prevalentResourceUrl, topFrameUrl3);
+        testRunner.setStatisticsSubresourceUniqueRedirectTo(prevalentResourceUrl, topFrameUrl4);
+
+        testRunner.setStatisticsSubresourceUnderTopFrameOrigin(prevalentResourceUrl, topFrameUrl1);
+        testRunner.setStatisticsSubresourceUnderTopFrameOrigin(prevalentResourceUrl, topFrameUrl2);
+        testRunner.setStatisticsSubresourceUnderTopFrameOrigin(prevalentResourceUrl, topFrameUrl3);
+        testRunner.setStatisticsSubresourceUnderTopFrameOrigin(prevalentResourceUrl, topFrameUrl4);
+    }
+
+    function setUpInsufficientStatisticsAndContinue() {
+        makeUrlPrevalent(prevalentResourceUrl1);
+        makeUrlPrevalent(prevalentResourceUrl2);
+
+        testRunner.installStatisticsDidScanDataRecordsCallback(checkInsufficientClassificationAndContinue);
+        testRunner.installStatisticsDidRunTelemetryCallback(checkInsufficientTelemetry);
+        testRunner.statisticsProcessStatisticsAndDataRecords();
+    }
+
+    function setUpSufficientStatisticsAndContinue() {
+        makeUrlPrevalent(prevalentResourceUrl3);
+        makeUrlPrevalent(prevalentResourceUrl4);
+
+        testRunner.setStatisticsHasHadUserInteraction(prevalentResourceUrl4, true, function() {
+            testRunner.installStatisticsDidScanDataRecordsCallback(checkSufficientClassificationAndContinue);
+            testRunner.installStatisticsDidRunTelemetryCallback(checkSufficientTelemetry);
+            testRunner.statisticsProcessStatisticsAndDataRecords();
+        });
+    }
+
+    function runTelemetryAndContinue() {
+        testRunner.statisticsSubmitTelemetry();
+    }
+
+    var testResult;
+    function checkInsufficientTelemetry(result) {
+        testResult = result;
+        shouldBe("testResult.numberOfPrevalentResources", "0");
+        shouldBe("testResult.numberOfPrevalentResourcesWithUserInteraction", "0");
+        shouldBe("testResult.numberOfPrevalentResourcesWithoutUserInteraction", "0");
+        shouldBe("testResult.topPrevalentResourceWithUserInteractionDaysSinceUserInteraction", "0");
+        shouldBe("testResult.medianDaysSinceUserInteractionPrevalentResourceWithUserInteraction", "0");
+        shouldBe("testResult.top3NumberOfPrevalentResourcesWithUI", "0");
+        shouldBe("testResult.top3MedianSubFrameWithoutUI", "0");
+        shouldBe("testResult.top3MedianSubResourceWithoutUI", "0");
+        shouldBe("testResult.top3MedianUniqueRedirectsWithoutUI", "0");
+        shouldBe("testResult.top3MedianDataRecordsRemovedWithoutUI", "0");
+        setUpSufficientStatisticsAndContinue();
+    }
+
+    function checkSufficientTelemetry(result) {
+        testResult = result;
+        shouldBe("testResult.numberOfPrevalentResources", "4");
+        shouldBe("testResult.numberOfPrevalentResourcesWithUserInteraction", "1");
+        shouldBe("testResult.numberOfPrevalentResourcesWithoutUserInteraction", "3");
+        shouldBe("testResult.topPrevalentResourceWithUserInteractionDaysSinceUserInteraction", "0");
+        shouldBe("testResult.medianDaysSinceUserInteractionPrevalentResourceWithUserInteraction", "0");
+        shouldBe("testResult.top3NumberOfPrevalentResourcesWithUI", "0");
+        shouldBe("testResult.top3MedianSubFrameWithoutUI", "4");
+        shouldBe("testResult.top3MedianSubResourceWithoutUI", "4");
+        shouldBe("testResult.top3MedianUniqueRedirectsWithoutUI", "4");
+        shouldBe("testResult.top3MedianDataRecordsRemovedWithoutUI", "0");
+        setEnableFeature(false, finishJSTest);
+    }
+
+    if (window.testRunner) {
+        setEnableFeature(true, function() {
+            testRunner.setStatisticsNotifyPagesWhenDataRecordsWereScanned(true);
+            testRunner.setStatisticsNotifyPagesWhenTelemetryWasCaptured(true);
+            setUpInsufficientStatisticsAndContinue();
+        });
+    }
+</script>
+</body>
+</html>

Modified: trunk/Source/WebKit/ChangeLog (250865 => 250866)


--- trunk/Source/WebKit/ChangeLog	2019-10-08 22:00:48 UTC (rev 250865)
+++ trunk/Source/WebKit/ChangeLog	2019-10-08 22:13:39 UTC (rev 250866)
@@ -1,3 +1,100 @@
+2019-10-08  Kate Cheney  <katherine_che...@apple.com>
+
+        Implement Telemetry and Dumping Routines for SQLite backend (195088)
+        https://bugs.webkit.org/show_bug.cgi?id=195088
+        <rdar://problem/54213407>
+
+        Reviewed by John Wilander.
+
+        Implemented database telemetry calculating for ITP. Mimicked
+        ResourceLoadStatisticsMemoryStore telemetry logging behavior using
+        SQLite Queries as opposed to vector sorting/manipulation. Once fully
+        integrated, this will simplify analysis of ITP data by transitioning
+        ITP data storage from a plist to a SQLite database.
+
+        * NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp:
+        (WebKit::ResourceLoadStatisticsDatabaseStore::ResourceLoadStatisticsDatabaseStore):
+        Added SQL queries to be initialized in the constructor. These queries
+        are needed to mimic the telemetry calculations done in
+        ResourceLoadStatisticsMemoryStore.
+        
+        (WebKit::resetStatement):
+        To reduce code duplication, this function holds common code to reset
+        a SQL query.
+
+        (WebKit::ResourceLoadStatisticsDatabaseStore::prepareStatements):
+        Added SQL queries needed for telemetry calculations to be prepared.
+        
+        (WebKit::joinSubStatisticsForSorting):
+        This function returns the query string for sorting resources that is
+        shared by many queries.
+
+        (WebKit::ResourceLoadStatisticsDatabaseStore::getMedianOfPrevalentResourcesWithUserInteraction const):
+        Implemented a function to take the median days since user interaction
+        from all prevalent resources in the database with user interaction
+        (sorted by max count of subframes, subresources and unique redirects under
+        the top frame domain).
+
+        (WebKit::ResourceLoadStatisticsDatabaseStore::getNumberOfPrevalentResources const):
+        Executes a SQL query to get the number of prevalent resources to log as
+        telemetry.
+
+        (WebKit::ResourceLoadStatisticsDatabaseStore::getNumberOfPrevalentResourcesWithUI const):
+        Executes a SQL query to get the number of prevalent resources with user
+        interaction to log as telemetry.
+
+        (WebKit::ResourceLoadStatisticsDatabaseStore::getTopPrevelentResourceDaysSinceUI const):
+        Prepares and executes a SQL query to get the days since user
+        interaction from the top prevalent resource to be recorded as
+        telemetry data.
+
+        (WebKit::ResourceLoadStatisticsDatabaseStore::getMedianStatisticOfPrevalentResourceWithoutUserInteraction const):
+        Implemented a function which takes a statistic and returns the value
+        of that statistic for the median prevalent resource without user
+        interaction to be recorded as telemetry data.
+
+        (WebKit::ResourceLoadStatisticsDatabaseStore::getNumberOfPrevalentResourcesInTopResources const):
+        Returns the count of prevalent resources in the top x resources
+        sorted by sum of substatistics again to be logged as telemetry.
+
+        (WebKit::ResourceLoadStatisticsDatabaseStore::calculateTelemetryData const):
+        Function which executes all functions which populate the struct with
+        telemetry data. This struct will then be passed to
+        WebResourceLoadStatisticsTelemetry to be logged.
+
+        (WebKit::ResourceLoadStatisticsDatabaseStore::calculateAndSubmitTelemetry const):
+        Initializes the telemetry struct and calls the function to populate
+        it, then passes it to the WebResourceLoadStatisticsTelemetry object
+        to be recorded.
+
+        * NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h:
+        Describe PrevalentResourceDatabaseTelemetry Struct to be passed and
+        logged as telemetry data.
+
+        * NetworkProcess/Classifier/WebResourceLoadStatisticsTelemetry.cpp:
+        (WebKit::databaseSubmitTopLists):
+        Logging telemetry data by looping through 2D array of statistics for
+        the top 1, 3, 10, 50, and 100 prevalent resources sorted by the sum
+        of substatistics under the top frame domain. This matches the logging
+        already done in ResourceLoadStatisticsMemoryStore.
+
+        (WebKit::WebResourceLoadStatisticsTelemetry::submitTelemetry):
+        Submits data to the webPageProxy logs and plists.
+
+        * NetworkProcess/Classifier/WebResourceLoadStatisticsTelemetry.h:
+        Added new submitTopList function to accomodate database telemetry
+        logging.
+        
+        * NetworkProcess/NetworkSession.cpp:
+        (WebKit::NetworkSession::notifyPageStatisticsTelemetryFinished):
+        * NetworkProcess/NetworkSession.h:
+        * UIProcess/Network/NetworkProcessProxy.cpp:
+        (WebKit::NetworkProcessProxy::notifyResourceLoadStatisticsTelemetryFinished):
+        * UIProcess/Network/NetworkProcessProxy.h:
+        * UIProcess/Network/NetworkProcessProxy.messages.in:
+        Updated the current testing for telemetry which only tested 3
+        statistics. With this patch it now tests 10 statistics.
+
 2019-10-08  Adrian Perez de Castro  <ape...@igalia.com>
 
         [GTK][WPE] Fix non-unified builds after r250486

Modified: trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp (250865 => 250866)


--- trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp	2019-10-08 22:00:48 UTC (rev 250865)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.cpp	2019-10-08 22:13:39 UTC (rev 250866)
@@ -67,7 +67,11 @@
 constexpr auto countSubframeUnderTopFrameQuery = "SELECT COUNT(*) FROM SubframeUnderTopFrameDomains WHERE subFrameDomainID = ? AND topFrameDomainID = ?;"_s;
 constexpr auto countSubresourceUnderTopFrameQuery = "SELECT COUNT(*) FROM SubresourceUnderTopFrameDomains WHERE subresourceDomainID = ? AND topFrameDomainID = ?;"_s;
 constexpr auto countSubresourceUniqueRedirectsToQuery = "SELECT COUNT(*) FROM SubresourceUniqueRedirectsTo WHERE subresourceDomainID = ? AND toDomainID = ?;"_s;
+constexpr auto countPrevalentResourcesQuery = "SELECT COUNT(DISTINCT registrableDomain) FROM ObservedDomains WHERE isPrevalent = 1;"_s;
+constexpr auto countPrevalentResourcesWithUserInteractionQuery = "SELECT COUNT(DISTINCT registrableDomain) FROM ObservedDomains WHERE isPrevalent = 1 AND hadUserInteraction = 1;"_s;
 
+constexpr auto countPrevalentResourcesWithoutUserInteractionQuery = "SELECT COUNT(DISTINCT registrableDomain) FROM ObservedDomains WHERE isPrevalent = 1 AND hadUserInteraction = 0;"_s;
+
 // INSERT Queries
 constexpr auto insertObservedDomainQuery = "INSERT INTO ObservedDomains (registrableDomain, lastSeen, hadUserInteraction,"
     "mostRecentUserInteractionTime, grandfathered, isPrevalent, isVeryPrevalent, dataRecordsRemoved, timesAccessedAsFirstPartyDueToUserInteraction,"
@@ -186,7 +190,8 @@
 constexpr auto createUniqueIndexSubresourceUniqueRedirectsTo = "CREATE UNIQUE INDEX IF NOT EXISTS SubresourceUniqueRedirectsTo_subresourceDomainID_toDomainID on SubresourceUniqueRedirectsTo ( subresourceDomainID, toDomainID );"_s;
 constexpr auto createUniqueIndexSubresourceUniqueRedirectsFrom = "CREATE UNIQUE INDEX IF NOT EXISTS SubresourceUniqueRedirectsFrom_subresourceDomainID_fromDomainID on SubresourceUnderTopFrameDomains ( subresourceDomainID, fromDomainID );"_s;
 
-    
+const unsigned minimumPrevalentResourcesForTelemetry = 3;
+
 ResourceLoadStatisticsDatabaseStore::ResourceLoadStatisticsDatabaseStore(WebResourceLoadStatisticsStore& store, WorkQueue& workQueue, ShouldIncludeLocalhost shouldIncludeLocalhost, const String& storageDirectoryPath, PAL::SessionID sessionID)
     : ResourceLoadStatisticsStore(store, workQueue, shouldIncludeLocalhost)
     , m_storageDirectoryPath(storageDirectoryPath + "/observations.db")
@@ -210,6 +215,9 @@
     , m_updateGrandfatheredStatement(m_database, updateGrandfatheredQuery)
     , m_isGrandfatheredStatement(m_database, isGrandfatheredQuery)
     , m_findExpiredUserInteractionStatement(m_database, findExpiredUserInteractionQuery)
+    , m_countPrevalentResourcesStatement(m_database, countPrevalentResourcesQuery)
+    , m_countPrevalentResourcesWithUserInteractionStatement(m_database, countPrevalentResourcesWithUserInteractionQuery)
+    , m_countPrevalentResourcesWithoutUserInteractionStatement(m_database, countPrevalentResourcesWithoutUserInteractionQuery)
     , m_sessionID(sessionID)
 {
     ASSERT(!RunLoop::isMain());
@@ -246,6 +254,12 @@
     });
 }
 
+static void resetStatement(SQLiteStatement& statement)
+{
+    int resetResult = statement.reset();
+    ASSERT_UNUSED(resetResult, resetResult == SQLITE_OK);
+}
+
 bool ResourceLoadStatisticsDatabaseStore::isEmpty() const
 {
     ASSERT(!RunLoop::isMain());
@@ -359,7 +373,11 @@
         || m_updateGrandfatheredStatement.prepare() != SQLITE_OK
         || m_isGrandfatheredStatement.prepare() != SQLITE_OK
         || m_findExpiredUserInteractionStatement.prepare() != SQLITE_OK
-        || m_topFrameLinkDecorationsFromExists.prepare() != SQLITE_OK) {
+        || m_topFrameLinkDecorationsFromExists.prepare() != SQLITE_OK
+        || m_countPrevalentResourcesStatement.prepare() != SQLITE_OK
+        || m_countPrevalentResourcesWithUserInteractionStatement.prepare() != SQLITE_OK
+        || m_countPrevalentResourcesWithoutUserInteractionStatement.prepare() != SQLITE_OK
+        ) {
         RELEASE_LOG_ERROR(Network, "%p - ResourceLoadStatisticsDatabaseStore::prepareStatements failed to prepare, error message: %{public}s", this, m_database.lastErrorMsg());
         ASSERT_NOT_REACHED();
         return false;
@@ -602,11 +620,286 @@
         insertDomainRelationships(statistic);
 }
 
+static const StringView joinSubStatisticsForSorting()
+{
+    return R"query(
+        domainID,
+        (cnt1 + cnt2 + cnt3) as sum
+        FROM (
+        SELECT
+            domainID,
+            COUNT(DISTINCT f.topFrameDomainID) as cnt1,
+            COUNT(DISTINCT r.topFrameDomainID) as cnt2,
+            COUNT(DISTINCT toDomainID) as cnt3
+        FROM
+        ObservedDomains o
+        LEFT JOIN SubframeUnderTopFrameDomains f ON o.domainID = f.subFrameDomainID
+        LEFT JOIN SubresourceUnderTopFrameDomains r ON o.domainID = r.subresourceDomainID
+        LEFT JOIN SubresourceUniqueRedirectsTo u ON o.domainID = u.subresourceDomainID
+        WHERE isPrevalent = 1
+        and hadUserInteraction LIKE ?
+        GROUP BY domainID) ORDER BY sum DESC
+        )query";
+}
+
+static SQLiteStatement makeMedianWithUIQuery(SQLiteDatabase& database)
+{
+    return SQLiteStatement(database, makeString("SELECT mostRecentUserInteractionTime FROM ObservedDomains INNER JOIN (SELECT ", joinSubStatisticsForSorting(), ") as q ON ObservedDomains.domainID = q.domainID LIMIT 1 OFFSET ?"));
+}
+
+static std::pair<StringView, StringView> buildQueryStartAndEnd(PrevalentResourceDatabaseTelemetry::Statistic statistic)
+{
+    switch (statistic) {
+    case PrevalentResourceDatabaseTelemetry::Statistic::MedianSubFrameWithoutUI:
+        return std::make_pair("SELECT cnt1 FROM ObservedDomains o INNER JOIN(SELECT cnt1, ", ") as q ON o.domainID = q.domainID LIMIT 1 OFFSET ?");
+    case PrevalentResourceDatabaseTelemetry::Statistic::MedianSubResourceWithoutUI:
+        return std::make_pair("SELECT cnt2 FROM ObservedDomains o INNER JOIN(SELECT cnt2, ", ") as q ON o.domainID = q.domainID LIMIT 1 OFFSET ?");
+    case PrevalentResourceDatabaseTelemetry::Statistic::MedianUniqueRedirectsWithoutUI:
+        return std::make_pair("SELECT cnt3 FROM ObservedDomains o INNER JOIN(SELECT cnt3, ", ") as q ON o.domainID = q.domainID LIMIT 1 OFFSET ?");
+    case PrevalentResourceDatabaseTelemetry::Statistic::MedianDataRecordsRemovedWithoutUI:
+        return std::make_pair("SELECT dataRecordsRemoved FROM (SELECT * FROM ObservedDomains o INNER JOIN(SELECT ", ") as q ON o.domainID = q.domainID) LIMIT 1 OFFSET ?");
+    case PrevalentResourceDatabaseTelemetry::Statistic::MedianTimesAccessedDueToUserInteractionWithoutUI:
+        return std::make_pair("SELECT timesAccessedAsFirstPartyDueToUserInteraction FROM (SELECT * FROM ObservedDomains o INNER JOIN(SELECT ", ") as q ON o.domainID = q.domainID) LIMIT 1 OFFSET ?");
+    case PrevalentResourceDatabaseTelemetry::Statistic::MedianTimesAccessedDueToStorageAccessAPIWithoutUI:
+        return std::make_pair("SELECT timesAccessedAsFirstPartyDueToStorageAccessAPI FROM (SELECT * FROM ObservedDomains o INNER JOIN(SELECT ", ") as q ON o.domainID = q.domainID) LIMIT 1 OFFSET ?");
+    case PrevalentResourceDatabaseTelemetry::Statistic::NumberOfPrevalentResourcesWithUI:
+        LOG_ERROR("ResourceLoadStatisticsDatabaseStore::makeMedianWithoutUIQuery was called for an incorrect statistic, undetermined query behavior will result.");
+        RELEASE_ASSERT_NOT_REACHED();
+    }
+}
+
+static SQLiteStatement makeMedianWithoutUIQuery(SQLiteDatabase& database, PrevalentResourceDatabaseTelemetry::Statistic statistic)
+{
+    auto[queryStart, queryEnd] = buildQueryStartAndEnd(statistic);
+
+    return SQLiteStatement(database, makeString(queryStart, joinSubStatisticsForSorting(), queryEnd));
+}
+
+static unsigned getMedianOfPrevalentResourcesWithUserInteraction(SQLiteDatabase& database, unsigned prevalentResourcesWithUserInteractionCount)
+{
+    SQLiteStatement medianDaysSinceUIStatement = makeMedianWithUIQuery(database);
+
+    // Prepare
+    if (medianDaysSinceUIStatement.prepare() != SQLITE_OK) {
+        RELEASE_LOG_ERROR(Network, "ResourceLoadStatisticsDatabaseStore::getMedianOfPrevalentResourcesWithUserInteraction, error message: %{public}s", database.lastErrorMsg());
+        ASSERT_NOT_REACHED();
+        return 0;
+    }
+
+    // Bind
+    if (medianDaysSinceUIStatement.bindInt(1, 1) != SQLITE_OK || medianDaysSinceUIStatement.bindInt(2, (prevalentResourcesWithUserInteractionCount / 2) != SQLITE_OK)) {
+        RELEASE_LOG_ERROR(Network, "ResourceLoadStatisticsDatabaseStore::getMedianOfPrevalentResourcesWithUserInteraction, error message: %{public}s", database.lastErrorMsg());
+        ASSERT_NOT_REACHED();
+        return 0;
+    }
+
+    // Step
+    if (medianDaysSinceUIStatement.step() != SQLITE_ROW) {
+        RELEASE_LOG_ERROR(Network, "ResourceLoadStatisticsDatabaseStore::getMedianOfPrevalentResourcesWithUserInteraction, error message: %{public}s", database.lastErrorMsg());
+        return 0;
+    }
+
+    double rawSeconds = medianDaysSinceUIStatement.getColumnDouble(0);
+    WallTime wallTime = WallTime::fromRawSeconds(rawSeconds);
+    unsigned median = wallTime <= WallTime() ? 0 : std::floor((WallTime::now() - wallTime) / 24_h);
+
+    if (prevalentResourcesWithUserInteractionCount & 1)
+        return median;
+
+    SQLiteStatement lowerMedianDaysSinceUIStatement = makeMedianWithUIQuery(database);
+
+    // Prepare
+    if (lowerMedianDaysSinceUIStatement.prepare() != SQLITE_OK) {
+        RELEASE_LOG_ERROR(Network, "ResourceLoadStatisticsDatabaseStore::getMedianOfPrevalentResourcesWithUserInteraction, error message: %{public}s", database.lastErrorMsg());
+        ASSERT_NOT_REACHED();
+        return 0;
+    }
+
+    // Bind
+    if (lowerMedianDaysSinceUIStatement.bindInt(1, 1) != SQLITE_OK || lowerMedianDaysSinceUIStatement.bindInt(2, ((prevalentResourcesWithUserInteractionCount - 1) / 2)) != SQLITE_OK) {
+        RELEASE_LOG_ERROR(Network, "ResourceLoadStatisticsDatabaseStore::getMedianOfPrevalentResourcesWithUserInteraction, error message: %{public}s", database.lastErrorMsg());
+        ASSERT_NOT_REACHED();
+        return 0;
+    }
+
+    // Step
+    if (lowerMedianDaysSinceUIStatement.step() != SQLITE_ROW) {
+        RELEASE_LOG_ERROR(Network, "ResourceLoadStatisticsDatabaseStore::getMedianOfPrevalentResourcesWithUserInteraction, error message: %{public}s", database.lastErrorMsg());
+        return 0;
+    }
+
+    double rawSecondsLower = lowerMedianDaysSinceUIStatement.getColumnDouble(0);
+    WallTime wallTimeLower = WallTime::fromRawSeconds(rawSecondsLower);
+    return ((wallTimeLower <= WallTime() ? 0 : std::floor((WallTime::now() - wallTimeLower) / 24_h)) + median) / 2;
+}
+
+unsigned ResourceLoadStatisticsDatabaseStore::getNumberOfPrevalentResources() const
+{
+    if (m_countPrevalentResourcesStatement.step() == SQLITE_ROW) {
+        unsigned prevalentResourceCount = m_countPrevalentResourcesStatement.getColumnInt(0);
+        if (prevalentResourceCount >= minimumPrevalentResourcesForTelemetry) {
+            resetStatement(m_countPrevalentResourcesStatement);
+            return prevalentResourceCount;
+        }
+    }
+    resetStatement(m_countPrevalentResourcesStatement);
+    return 0;
+}
+
+unsigned ResourceLoadStatisticsDatabaseStore::getNumberOfPrevalentResourcesWithUI() const
+{
+    if (m_countPrevalentResourcesWithUserInteractionStatement.step() == SQLITE_ROW) {
+        int count = m_countPrevalentResourcesWithUserInteractionStatement.getColumnInt(0);
+        resetStatement(m_countPrevalentResourcesWithUserInteractionStatement);
+        return count;
+    }
+    resetStatement(m_countPrevalentResourcesWithUserInteractionStatement);
+    return 0;
+}
+
+unsigned ResourceLoadStatisticsDatabaseStore::getTopPrevelentResourceDaysSinceUI() const
+{
+    SQLiteStatement topPrevalentResourceWithUserInteractionDaysSinceUserInteractionStatement(m_database, makeString("SELECT mostRecentUserInteractionTime FROM ObservedDomains INNER JOIN (SELECT ", joinSubStatisticsForSorting(), " LIMIT 1) as q ON ObservedDomains.domainID = q.domainID;"));
+    
+    // Prepare
+    if (topPrevalentResourceWithUserInteractionDaysSinceUserInteractionStatement.prepare() != SQLITE_OK) {
+        RELEASE_LOG_ERROR(Network, "ResourceLoadStatisticsDatabaseStore::topPrevalentResourceWithUserInteractionDaysSinceUserInteractionStatement query failed to prepare, error message: %{public}s", m_database.lastErrorMsg());
+        ASSERT_NOT_REACHED();
+        return 0;
+    }
+    
+    // Bind
+    if (topPrevalentResourceWithUserInteractionDaysSinceUserInteractionStatement.bindInt(1, 1) != SQLITE_OK) {
+        RELEASE_LOG_ERROR(Network, "ResourceLoadStatisticsDatabaseStore::topPrevalentResourceWithUserInteractionDaysSinceUserInteractionStatement query failed to bind, error message: %{public}s", m_database.lastErrorMsg());
+        ASSERT_NOT_REACHED();
+        return 0;
+    }
+    
+    // Step
+    if (topPrevalentResourceWithUserInteractionDaysSinceUserInteractionStatement.step() != SQLITE_ROW) {
+        RELEASE_LOG_ERROR(Network, "ResourceLoadStatisticsDatabaseStore::topPrevalentResourceWithUserInteractionDaysSinceUserInteractionStatement query failed to step, error message: %{public}s", m_database.lastErrorMsg());
+        return 0;
+    }
+    
+    double rawSeconds = topPrevalentResourceWithUserInteractionDaysSinceUserInteractionStatement.getColumnDouble(0);
+    WallTime wallTime = WallTime::fromRawSeconds(rawSeconds);
+    
+    return wallTime <= WallTime() ? 0 : std::floor((WallTime::now() - wallTime) / 24_h);
+}
+
+static unsigned getMedianOfPrevalentResourceWithoutUserInteraction(SQLiteDatabase& database, unsigned bucketSize, PrevalentResourceDatabaseTelemetry::Statistic statistic, unsigned numberOfPrevalentResourcesWithoutUI)
+{
+    if (numberOfPrevalentResourcesWithoutUI < bucketSize)
+        return 0;
+
+    unsigned median;
+    SQLiteStatement getMedianStatistic = makeMedianWithoutUIQuery(database, statistic);
+
+    if (getMedianStatistic.prepare() == SQLITE_OK) {
+        if (getMedianStatistic.bindInt(1, 0) != SQLITE_OK
+            || getMedianStatistic.bindInt(2, (bucketSize / 2)) != SQLITE_OK) {
+            RELEASE_LOG_ERROR(Network, "ResourceLoadStatisticsDatabaseStore::makeMedianWithoutUIQuery, error message: %{public}s", database.lastErrorMsg());
+            ASSERT_NOT_REACHED();
+            return 0;
+        }
+        if (getMedianStatistic.step() == SQLITE_ROW)
+            median = getMedianStatistic.getColumnDouble(0);
+    }
+
+    if (bucketSize & 1)
+        return median;
+
+    SQLiteStatement getLowerMedianStatistic = makeMedianWithoutUIQuery(database, statistic);
+
+    if (getLowerMedianStatistic.prepare() == SQLITE_OK) {
+        if (getLowerMedianStatistic.bindInt(1, 0) != SQLITE_OK
+            || getLowerMedianStatistic.bindInt(2, ((bucketSize-1) / 2)) != SQLITE_OK) {
+            RELEASE_LOG_ERROR(Network, "ResourceLoadStatisticsDatabaseStore::makeMedianWithoutUIQuery, error message: %{public}s", database.lastErrorMsg());
+            ASSERT_NOT_REACHED();
+            return 0;
+        }
+        if (getLowerMedianStatistic.step() == SQLITE_ROW)
+            return (getLowerMedianStatistic.getColumnDouble(0) + median) / 2;
+    }
+
+    return 0;
+}
+
+static unsigned getNumberOfPrevalentResourcesInTopResources(SQLiteDatabase& database, unsigned bucketSize)
+{
+    SQLiteStatement prevalentResourceCountInTop(database, makeString("SELECT COUNT(*) FROM (SELECT * FROM ObservedDomains o INNER JOIN(SELECT ", joinSubStatisticsForSorting(), ") as q on q.domainID = o.domainID LIMIT ?) as p WHERE p.hadUserInteraction = 1;"));
+
+    if (prevalentResourceCountInTop.prepare() == SQLITE_OK) {
+        if (prevalentResourceCountInTop.bindText(1, "%") != SQLITE_OK
+            || prevalentResourceCountInTop.bindInt(2, bucketSize) != SQLITE_OK) {
+            RELEASE_LOG_ERROR(Network, "ResourceLoadStatisticsDatabaseStore::getNumberOfPrevalentResourcesInTopResources, error message: %{public}s", database.lastErrorMsg());
+            ASSERT_NOT_REACHED();
+            return 0;
+        }
+
+        if (prevalentResourceCountInTop.step() == SQLITE_ROW)
+            return prevalentResourceCountInTop.getColumnInt(0);
+    }
+
+    return 0;
+}
+
+static unsigned makeStatisticQuery(SQLiteDatabase& database, PrevalentResourceDatabaseTelemetry::Statistic statistic, int bucketSize, unsigned totalWithUI, unsigned totalWithoutUI)
+{
+    switch (statistic) {
+    case PrevalentResourceDatabaseTelemetry::Statistic::NumberOfPrevalentResourcesWithUI:
+        return getNumberOfPrevalentResourcesInTopResources(database, bucketSize);
+    case PrevalentResourceDatabaseTelemetry::Statistic::MedianSubFrameWithoutUI:
+    case PrevalentResourceDatabaseTelemetry::Statistic::MedianSubResourceWithoutUI:
+    case PrevalentResourceDatabaseTelemetry::Statistic::MedianUniqueRedirectsWithoutUI:
+    case PrevalentResourceDatabaseTelemetry::Statistic::MedianDataRecordsRemovedWithoutUI:
+    case PrevalentResourceDatabaseTelemetry::Statistic::MedianTimesAccessedDueToUserInteractionWithoutUI:
+    case PrevalentResourceDatabaseTelemetry::Statistic::MedianTimesAccessedDueToStorageAccessAPIWithoutUI:
+        return getMedianOfPrevalentResourceWithoutUserInteraction(database, bucketSize, statistic, totalWithoutUI);
+    }
+}
+
+unsigned ResourceLoadStatisticsDatabaseStore::getNumberOfPrevalentResourcesWithoutUI() const
+{
+    if (m_countPrevalentResourcesWithoutUserInteractionStatement.step() == SQLITE_ROW) {
+        int count = m_countPrevalentResourcesWithoutUserInteractionStatement.getColumnInt(0);
+        resetStatement(m_countPrevalentResourcesWithoutUserInteractionStatement);
+        return count;
+    }
+    resetStatement(m_countPrevalentResourcesWithoutUserInteractionStatement);
+    return 0;
+}
+
+void ResourceLoadStatisticsDatabaseStore::calculateTelemetryData(PrevalentResourceDatabaseTelemetry& data) const
+{
+    data.numberOfPrevalentResources = getNumberOfPrevalentResources();
+    data.numberOfPrevalentResourcesWithUserInteraction = getNumberOfPrevalentResourcesWithUI();
+    data.numberOfPrevalentResourcesWithoutUserInteraction = getNumberOfPrevalentResourcesWithoutUI();
+    data.topPrevalentResourceWithUserInteractionDaysSinceUserInteraction = getTopPrevelentResourceDaysSinceUI();
+    data.medianDaysSinceUserInteractionPrevalentResourceWithUserInteraction = getMedianOfPrevalentResourcesWithUserInteraction(m_database, data.numberOfPrevalentResourcesWithUserInteraction);
+
+    for (unsigned bucketIndex = 0; bucketIndex < bucketSizes.size(); bucketIndex++) {
+        unsigned bucketSize = bucketSizes[bucketIndex];
+
+        if (data.numberOfPrevalentResourcesWithoutUserInteraction < bucketSize)
+            return;
+
+        for (unsigned statisticIndex = 0; statisticIndex < numberOfStatistics; statisticIndex++) {
+            auto statistic = static_cast<PrevalentResourceDatabaseTelemetry::Statistic>(statisticIndex);
+            data.statistics[statisticIndex][bucketIndex] = makeStatisticQuery(m_database, statistic, bucketSize, data.numberOfPrevalentResourcesWithUserInteraction, data.numberOfPrevalentResourcesWithoutUserInteraction);
+        }
+    }
+}
+
 void ResourceLoadStatisticsDatabaseStore::calculateAndSubmitTelemetry() const
 {
     ASSERT(!RunLoop::isMain());
 
-    // FIXME(195088): Implement for Database version.
+    if (parameters().shouldSubmitTelemetry) {
+        PrevalentResourceDatabaseTelemetry prevalentResourceDatabaseTelemetry;
+        calculateTelemetryData(prevalentResourceDatabaseTelemetry);
+        WebResourceLoadStatisticsTelemetry::submitTelemetry(*this, prevalentResourceDatabaseTelemetry);
+    }
 }
 
 static String domainsToString(const HashSet<RegistrableDomain>& domains)

Modified: trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h (250865 => 250866)


--- trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h	2019-10-08 22:00:48 UTC (rev 250865)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/ResourceLoadStatisticsDatabaseStore.h	2019-10-08 22:13:39 UTC (rev 250866)
@@ -47,6 +47,32 @@
 
 namespace WebKit {
 
+static constexpr size_t numberOfBucketsPerStatistic = 5;
+static constexpr size_t numberOfStatistics = 7;
+static constexpr std::array<unsigned, numberOfBucketsPerStatistic> bucketSizes {{ 1, 3, 10, 50, 100 }};
+
+struct PrevalentResourceDatabaseTelemetry {
+    using Buckets = std::array<unsigned, numberOfBucketsPerStatistic>;
+
+    enum class Statistic {
+        NumberOfPrevalentResourcesWithUI,
+        MedianSubFrameWithoutUI,
+        MedianSubResourceWithoutUI,
+        MedianUniqueRedirectsWithoutUI,
+        MedianDataRecordsRemovedWithoutUI,
+        MedianTimesAccessedDueToUserInteractionWithoutUI,
+        MedianTimesAccessedDueToStorageAccessAPIWithoutUI
+    };
+
+    unsigned numberOfPrevalentResources;
+    unsigned numberOfPrevalentResourcesWithUserInteraction;
+    unsigned numberOfPrevalentResourcesWithoutUserInteraction;
+    unsigned topPrevalentResourceWithUserInteractionDaysSinceUserInteraction;
+    unsigned medianDaysSinceUserInteractionPrevalentResourceWithUserInteraction;
+
+    std::array<Buckets, numberOfStatistics> statistics;
+};
+
 class ResourceLoadStatisticsMemoryStore;
 
 // This is always constructed / used / destroyed on the WebResourceLoadStatisticsStore's statistics queue.
@@ -110,6 +136,13 @@
     void mergeStatistic(const ResourceLoadStatistics&);
     void merge(WebCore::SQLiteStatement&, const ResourceLoadStatistics&);
     void clearDatabaseContents();
+    unsigned getNumberOfPrevalentResources() const;
+    unsigned getNumberOfPrevalentResourcesWithUI() const;
+    unsigned getNumberOfPrevalentResourcesWithoutUI() const;
+    unsigned getTopPrevelentResourceDaysSinceUI() const;
+    void resetTelemetryPreparedStatements() const;
+    void resetTelemetryStatements() const;
+    void calculateTelemetryData(PrevalentResourceDatabaseTelemetry&) const;
     bool insertObservedDomain(const ResourceLoadStatistics&);
     void insertDomainRelationships(const ResourceLoadStatistics&);
     void insertDomainRelationshipList(const String&, const HashSet<RegistrableDomain>&, unsigned);
@@ -197,6 +230,9 @@
     WebCore::SQLiteStatement m_updateGrandfatheredStatement;
     mutable WebCore::SQLiteStatement m_isGrandfatheredStatement;
     mutable WebCore::SQLiteStatement m_findExpiredUserInteractionStatement;
+    mutable WebCore::SQLiteStatement m_countPrevalentResourcesStatement;
+    mutable WebCore::SQLiteStatement m_countPrevalentResourcesWithUserInteractionStatement;
+    mutable WebCore::SQLiteStatement m_countPrevalentResourcesWithoutUserInteractionStatement;
     PAL::SessionID m_sessionID;
 };
 

Modified: trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp (250865 => 250866)


--- trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp	2019-10-08 22:00:48 UTC (rev 250865)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp	2019-10-08 22:13:39 UTC (rev 250866)
@@ -492,9 +492,13 @@
     ASSERT(RunLoop::isMain());
 
     postTask([this, completionHandler = WTFMove(completionHandler)]() mutable  {
-        if (m_statisticsStore && is<ResourceLoadStatisticsMemoryStore>(*m_statisticsStore))
+        if (!m_statisticsStore)
+            return;
+        
+        if (is<ResourceLoadStatisticsMemoryStore>(*m_statisticsStore))
             WebResourceLoadStatisticsTelemetry::calculateAndSubmit(downcast<ResourceLoadStatisticsMemoryStore>(*m_statisticsStore));
-
+        else
+            m_statisticsStore->calculateAndSubmitTelemetry();
         postTaskReply(WTFMove(completionHandler));
     });
 }
@@ -1077,11 +1081,11 @@
         const_cast<WebResourceLoadStatisticsStore*>(this)->networkSession()->logDiagnosticMessageWithValue(message, description, value, sigDigits, shouldSample);
 }
 
-void WebResourceLoadStatisticsStore::notifyPageStatisticsTelemetryFinished(unsigned totalPrevalentResources, unsigned totalPrevalentResourcesWithUserInteraction, unsigned top3SubframeUnderTopFrameOrigins) const
+void WebResourceLoadStatisticsStore::notifyPageStatisticsTelemetryFinished(unsigned numberOfPrevalentResources, unsigned numberOfPrevalentResourcesWithUserInteraction, unsigned numberOfPrevalentResourcesWithoutUserInteraction, unsigned topPrevalentResourceWithUserInteractionDaysSinceUserInteraction, unsigned medianDaysSinceUserInteractionPrevalentResourceWithUserInteraction, unsigned top3NumberOfPrevalentResourcesWithUI, unsigned top3MedianSubFrameWithoutUI, unsigned top3MedianSubResourceWithoutUI, unsigned top3MedianUniqueRedirectsWithoutUI, unsigned top3MedianDataRecordsRemovedWithoutUI) const
 {
     ASSERT(RunLoop::isMain());
     if (m_networkSession)
-        const_cast<WebResourceLoadStatisticsStore*>(this)->networkSession()->notifyPageStatisticsTelemetryFinished(totalPrevalentResources, totalPrevalentResourcesWithUserInteraction, top3SubframeUnderTopFrameOrigins);
+        const_cast<WebResourceLoadStatisticsStore*>(this)->networkSession()->notifyPageStatisticsTelemetryFinished(numberOfPrevalentResources, numberOfPrevalentResourcesWithUserInteraction, numberOfPrevalentResourcesWithoutUserInteraction, topPrevalentResourceWithUserInteractionDaysSinceUserInteraction, medianDaysSinceUserInteractionPrevalentResourceWithUserInteraction, top3NumberOfPrevalentResourcesWithUI, top3MedianSubFrameWithoutUI, top3MedianSubResourceWithoutUI, top3MedianUniqueRedirectsWithoutUI, top3MedianDataRecordsRemovedWithoutUI);
 }
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h (250865 => 250866)


--- trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h	2019-10-08 22:00:48 UTC (rev 250865)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.h	2019-10-08 22:13:39 UTC (rev 250866)
@@ -188,7 +188,7 @@
     void invalidateAndCancel();
 
     void sendDiagnosticMessageWithValue(const String& message, const String& description, unsigned value, unsigned sigDigits, WebCore::ShouldSample) const;
-    void notifyPageStatisticsTelemetryFinished(unsigned totalPrevalentResources, unsigned totalPrevalentResourcesWithUserInteraction, unsigned top3SubframeUnderTopFrameOrigins) const;
+    void notifyPageStatisticsTelemetryFinished(unsigned numberOfPrevalentResources, unsigned numberOfPrevalentResourcesWithUserInteraction, unsigned numberOfPrevalentResourcesWithoutUserInteraction, unsigned topPrevalentResourceWithUserInteractionDaysSinceUserInteraction, unsigned medianDaysSinceUserInteractionPrevalentResourceWithUserInteraction, unsigned top3NumberOfPrevalentResourcesWithUI, unsigned top3MedianSubFrameWithoutUI, unsigned top3MedianSubResourceWithoutUI, unsigned top3MedianUniqueRedirectsWithoutUI, unsigned top3MedianDataRecordsRemovedWithoutUI) const;
 
     void resourceLoadStatisticsUpdated(Vector<WebCore::ResourceLoadStatistics>&&);
     void requestStorageAccessUnderOpener(DomainInNeedOfStorageAccess&&, WebCore::PageIdentifier openerID, OpenerDomain&&);

Modified: trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsTelemetry.cpp (250865 => 250866)


--- trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsTelemetry.cpp	2019-10-08 22:00:48 UTC (rev 250865)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsTelemetry.cpp	2019-10-08 22:13:39 UTC (rev 250866)
@@ -28,6 +28,7 @@
 
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
 
+#include "ResourceLoadStatisticsDatabaseStore.h"
 #include "ResourceLoadStatisticsMemoryStore.h"
 #include "WebPageProxy.h"
 #include "WebProcessPool.h"
@@ -199,10 +200,10 @@
 }
     
 // This function is for testing purposes.
-void static notifyPages(unsigned totalPrevalentResources, unsigned totalPrevalentResourcesWithUserInteraction, unsigned top3SubframeUnderTopFrameOrigins, const WebResourceLoadStatisticsStore& store)
+void static notifyPages(unsigned numberOfPrevalentResources, unsigned numberOfPrevalentResourcesWithUserInteraction, unsigned numberOfPrevalentResourcesWithoutUserInteraction, unsigned topPrevalentResourceWithUserInteractionDaysSinceUserInteraction, unsigned medianDaysSinceUserInteractionPrevalentResourceWithUserInteraction, unsigned top3NumberOfPrevalentResourcesWithUI, unsigned top3MedianSubFrameWithoutUI, unsigned top3MedianSubResourceWithoutUI, unsigned top3MedianUniqueRedirectsWithoutUI, unsigned top3MedianDataRecordsRemovedWithoutUI, const WebResourceLoadStatisticsStore& store)
 {
-    RunLoop::main().dispatch([totalPrevalentResources, totalPrevalentResourcesWithUserInteraction, top3SubframeUnderTopFrameOrigins, store = makeRef(store)] {
-        store->notifyPageStatisticsTelemetryFinished(totalPrevalentResources, totalPrevalentResourcesWithUserInteraction, top3SubframeUnderTopFrameOrigins);
+    RunLoop::main().dispatch([numberOfPrevalentResources, numberOfPrevalentResourcesWithUserInteraction, numberOfPrevalentResourcesWithoutUserInteraction, topPrevalentResourceWithUserInteractionDaysSinceUserInteraction, medianDaysSinceUserInteractionPrevalentResourceWithUserInteraction, top3NumberOfPrevalentResourcesWithUI, top3MedianSubFrameWithoutUI, top3MedianSubResourceWithoutUI, top3MedianUniqueRedirectsWithoutUI, top3MedianDataRecordsRemovedWithoutUI, store = makeRef(store)] {
+        store->notifyPageStatisticsTelemetryFinished(numberOfPrevalentResources, numberOfPrevalentResourcesWithUserInteraction, numberOfPrevalentResourcesWithoutUserInteraction, topPrevalentResourceWithUserInteractionDaysSinceUserInteraction, medianDaysSinceUserInteractionPrevalentResourceWithUserInteraction, top3NumberOfPrevalentResourcesWithUI, top3MedianSubFrameWithoutUI, top3MedianSubResourceWithoutUI, top3MedianUniqueRedirectsWithoutUI, top3MedianDataRecordsRemovedWithoutUI);
     });
 }
     
@@ -212,8 +213,7 @@
     WTF::Function<unsigned(const PrevalentResourceTelemetry& telemetry)> subframeUnderTopFrameOriginsGetter = [] (const PrevalentResourceTelemetry& t) {
         return t.subframeUnderTopFrameOrigins;
     };
-    
-    notifyPages(sortedPrevalentResources.size(), totalNumberOfPrevalentResourcesWithUserInteraction, median(sortedPrevalentResourcesWithoutUserInteraction, 0, 2, subframeUnderTopFrameOriginsGetter), store);
+    notifyPages(sortedPrevalentResources.size(), totalNumberOfPrevalentResourcesWithUserInteraction, 0, 0, 0, 0, median(sortedPrevalentResourcesWithoutUserInteraction, 0, 2, subframeUnderTopFrameOriginsGetter), 0, 0, 0,  store);
 }
     
 void WebResourceLoadStatisticsTelemetry::calculateAndSubmit(const ResourceLoadStatisticsMemoryStore& resourceLoadStatisticsStore)
@@ -222,7 +222,7 @@
     
     auto sortedPrevalentResources = sortedPrevalentResourceTelemetry(resourceLoadStatisticsStore);
     if (notifyPagesWhenTelemetryWasCaptured && sortedPrevalentResources.isEmpty()) {
-        notifyPages(0, 0, 0, resourceLoadStatisticsStore.store());
+        notifyPages(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, resourceLoadStatisticsStore.store());
         return;
     }
     
@@ -242,7 +242,7 @@
         auto webPageProxy = WebPageProxy::nonEphemeralWebPageProxy();
         if (!webPageProxy) {
             if (notifyPagesWhenTelemetryWasCaptured)
-                notifyPages(0, 0, 0, store);
+                notifyPages(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, store);
             return;
         }
         
@@ -263,6 +263,90 @@
         submitTopLists(sortedPrevalentResources, sortedPrevalentResourcesWithoutUserInteraction, store);
     });
 }
+
+static StringView makeDescription(PrevalentResourceDatabaseTelemetry::Statistic statistic)
+{
+    switch (statistic) {
+    case PrevalentResourceDatabaseTelemetry::Statistic::NumberOfPrevalentResourcesWithUI:
+        return "PrevalentResourcesWithUserInteraction";
+    case PrevalentResourceDatabaseTelemetry::Statistic::MedianSubFrameWithoutUI:
+        return "SubframeUnderTopFrameOrigins";
+    case PrevalentResourceDatabaseTelemetry::Statistic::MedianSubResourceWithoutUI:
+        return "SubresourceUnderTopFrameOrigins";
+    case PrevalentResourceDatabaseTelemetry::Statistic::MedianUniqueRedirectsWithoutUI:
+        return "SubresourceUniqueRedirectsTo";
+    case PrevalentResourceDatabaseTelemetry::Statistic::MedianDataRecordsRemovedWithoutUI:
+        return "NumberOfTimesDataRecordsRemoved";
+    case PrevalentResourceDatabaseTelemetry::Statistic::MedianTimesAccessedDueToUserInteractionWithoutUI:
+        return "NumberOfTimesAccessedAsFirstPartyDueToUserInteraction";
+    case PrevalentResourceDatabaseTelemetry::Statistic::MedianTimesAccessedDueToStorageAccessAPIWithoutUI:
+        return "NumberOfTimesAccessedAsFirstPartyDueToStorageAccessAPI";
+    }
+}
+
+static void databaseSubmitTopLists(const PrevalentResourceDatabaseTelemetry& telemetry, const WebResourceLoadStatisticsStore& store)
+{
+    for (unsigned bucketIndex = 0; bucketIndex < bucketSizes.size(); bucketIndex++) {
+
+        if (telemetry.numberOfPrevalentResourcesWithoutUserInteraction < bucketSizes[bucketIndex])
+            return;
+
+        String descriptionPreamble = makeString("top", bucketSizes[bucketIndex]);
+
+        for (unsigned statisticIndex = 0; statisticIndex < numberOfStatistics; statisticIndex++) {
+            auto statistic = static_cast<PrevalentResourceDatabaseTelemetry::Statistic>(statisticIndex);
+
+            store.sendDiagnosticMessageWithValue(DiagnosticLoggingKeys::resourceLoadStatisticsTelemetryKey(), descriptionPreamble + makeDescription(statistic), telemetry.statistics[statisticIndex][bucketIndex], significantFiguresForLoggedValues, ShouldSample::No);
+        }
+    }
+}
+
+void WebResourceLoadStatisticsTelemetry::submitTelemetry(const ResourceLoadStatisticsDatabaseStore& resourceLoadStatisticsStore, PrevalentResourceDatabaseTelemetry& prevalentResourceDatabaseTelemetry)
+{
+    ASSERT(!RunLoop::isMain());
+
+    if (notifyPagesWhenTelemetryWasCaptured && !prevalentResourceDatabaseTelemetry.numberOfPrevalentResources) {
+        notifyPages(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, resourceLoadStatisticsStore.store());
+        return;
+    }
+
+    // Dispatch on the main thread to make sure the WebPageProxy we're using doesn't go away.
+    RunLoop::main().dispatch([telemetry = WTFMove(prevalentResourceDatabaseTelemetry), store = makeRef(resourceLoadStatisticsStore.store())] () {
+
+        // The notify pages function is for testing so we don't need to do an actual submission.
+        if (notifyPagesWhenTelemetryWasCaptured) {
+            if (telemetry.numberOfPrevalentResourcesWithoutUserInteraction < 3) {
+                notifyPages(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, store);
+                return;
+            }
+            notifyPages(telemetry.numberOfPrevalentResources,
+                telemetry.numberOfPrevalentResourcesWithUserInteraction,
+                telemetry.numberOfPrevalentResourcesWithoutUserInteraction,
+                telemetry.topPrevalentResourceWithUserInteractionDaysSinceUserInteraction,
+                telemetry.medianDaysSinceUserInteractionPrevalentResourceWithUserInteraction,
+                telemetry.statistics[0][1], // bucket 1 -> top3.
+                telemetry.statistics[1][1],
+                telemetry.statistics[2][1],
+                telemetry.statistics[3][1],
+                telemetry.statistics[4][1],
+                store);
+            return;
+        }
+        
+        auto webPageProxy = WebPageProxy::nonEphemeralWebPageProxy();
+        if (!webPageProxy)
+            return;
+
+        webPageProxy->logDiagnosticMessageWithValue(DiagnosticLoggingKeys::resourceLoadStatisticsTelemetryKey(), "totalNumberOfPrevalentResources"_s, telemetry.numberOfPrevalentResources, significantFiguresForLoggedValues, ShouldSample::No);
+        webPageProxy->logDiagnosticMessageWithValue(DiagnosticLoggingKeys::resourceLoadStatisticsTelemetryKey(), "totalNumberOfPrevalentResourcesWithUserInteraction"_s, telemetry.numberOfPrevalentResourcesWithUserInteraction, significantFiguresForLoggedValues, ShouldSample::No);
+        if (telemetry.numberOfPrevalentResourcesWithUserInteraction > 0)
+            webPageProxy->logDiagnosticMessageWithValue(DiagnosticLoggingKeys::resourceLoadStatisticsTelemetryKey(), "topPrevalentResourceWithUserInteractionDaysSinceUserInteraction"_s, telemetry.topPrevalentResourceWithUserInteractionDaysSinceUserInteraction, significantFiguresForLoggedValues, ShouldSample::No);
+        if (telemetry.numberOfPrevalentResourcesWithUserInteraction > 1)
+            webPageProxy->logDiagnosticMessageWithValue(DiagnosticLoggingKeys::resourceLoadStatisticsTelemetryKey(), "medianPrevalentResourcesWithUserInteractionDaysSinceUserInteraction"_s, telemetry.medianDaysSinceUserInteractionPrevalentResourceWithUserInteraction, significantFiguresForLoggedValues, ShouldSample::No);
+
+        databaseSubmitTopLists(telemetry, store);
+    });
+}
     
 void WebResourceLoadStatisticsTelemetry::setNotifyPagesWhenTelemetryWasCaptured(bool always)
 {

Modified: trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsTelemetry.h (250865 => 250866)


--- trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsTelemetry.h	2019-10-08 22:00:48 UTC (rev 250865)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsTelemetry.h	2019-10-08 22:13:39 UTC (rev 250866)
@@ -32,10 +32,13 @@
 namespace WebKit {
 
 class ResourceLoadStatisticsMemoryStore;
+class ResourceLoadStatisticsDatabaseStore;
+struct PrevalentResourceDatabaseTelemetry;
 
 namespace WebResourceLoadStatisticsTelemetry {
     
 void calculateAndSubmit(const ResourceLoadStatisticsMemoryStore&);
+void submitTelemetry(const ResourceLoadStatisticsDatabaseStore&, PrevalentResourceDatabaseTelemetry&);
 void setNotifyPagesWhenTelemetryWasCaptured(bool);
     
 }

Modified: trunk/Source/WebKit/NetworkProcess/NetworkSession.cpp (250865 => 250866)


--- trunk/Source/WebKit/NetworkProcess/NetworkSession.cpp	2019-10-08 22:00:48 UTC (rev 250865)
+++ trunk/Source/WebKit/NetworkProcess/NetworkSession.cpp	2019-10-08 22:13:39 UTC (rev 250866)
@@ -193,9 +193,9 @@
     m_networkProcess->parentProcessConnection()->send(Messages::WebPageProxy::LogDiagnosticMessageWithValue(message, description, value, significantFigures, shouldSample), 0);
 }
 
-void NetworkSession::notifyPageStatisticsTelemetryFinished(unsigned totalPrevalentResources, unsigned totalPrevalentResourcesWithUserInteraction, unsigned top3SubframeUnderTopFrameOrigins)
+void NetworkSession::notifyPageStatisticsTelemetryFinished(unsigned numberOfPrevalentResources, unsigned numberOfPrevalentResourcesWithUserInteraction, unsigned numberOfPrevalentResourcesWithoutUserInteraction, unsigned topPrevalentResourceWithUserInteractionDaysSinceUserInteraction, unsigned medianDaysSinceUserInteractionPrevalentResourceWithUserInteraction, unsigned top3NumberOfPrevalentResourcesWithUI, unsigned top3MedianSubFrameWithoutUI, unsigned top3MedianSubResourceWithoutUI, unsigned top3MedianUniqueRedirectsWithoutUI, unsigned top3MedianDataRecordsRemovedWithoutUI)
 {
-    m_networkProcess->parentProcessConnection()->send(Messages::NetworkProcessProxy::NotifyResourceLoadStatisticsTelemetryFinished(totalPrevalentResources, totalPrevalentResourcesWithUserInteraction, top3SubframeUnderTopFrameOrigins), 0);
+    m_networkProcess->parentProcessConnection()->send(Messages::NetworkProcessProxy::NotifyResourceLoadStatisticsTelemetryFinished(numberOfPrevalentResources, numberOfPrevalentResourcesWithUserInteraction, numberOfPrevalentResourcesWithoutUserInteraction, topPrevalentResourceWithUserInteractionDaysSinceUserInteraction, medianDaysSinceUserInteractionPrevalentResourceWithUserInteraction, top3NumberOfPrevalentResourcesWithUI, top3MedianSubFrameWithoutUI, top3MedianSubResourceWithoutUI, top3MedianUniqueRedirectsWithoutUI, top3MedianDataRecordsRemovedWithoutUI), 0);
 }
 
 void NetworkSession::deleteWebsiteDataForRegistrableDomains(OptionSet<WebsiteDataType> dataTypes, Vector<std::pair<RegistrableDomain, WebsiteDataToRemove>>&& domains, bool shouldNotifyPage, CompletionHandler<void(const HashSet<RegistrableDomain>&)>&& completionHandler)

Modified: trunk/Source/WebKit/NetworkProcess/NetworkSession.h (250865 => 250866)


--- trunk/Source/WebKit/NetworkProcess/NetworkSession.h	2019-10-08 22:00:48 UTC (rev 250865)
+++ trunk/Source/WebKit/NetworkProcess/NetworkSession.h	2019-10-08 22:13:39 UTC (rev 250866)
@@ -90,7 +90,7 @@
     void deleteWebsiteDataForRegistrableDomains(OptionSet<WebsiteDataType>, Vector<std::pair<WebCore::RegistrableDomain, WebsiteDataToRemove>>&&, bool shouldNotifyPage, 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);
+    void notifyPageStatisticsTelemetryFinished(unsigned numberOfPrevalentResources, unsigned numberOfPrevalentResourcesWithUserInteraction, unsigned numberOfPrevalentResourcesWithoutUserInteraction, unsigned topPrevalentResourceWithUserInteractionDaysSinceUserInteraction, unsigned medianDaysSinceUserInteractionPrevalentResourceWithUserInteraction, unsigned top3NumberOfPrevalentResourcesWithUI, unsigned top3MedianSubFrameWithoutUI, unsigned top3MedianSubResourceWithoutUI, unsigned top3MedianUniqueRedirectsWithoutUI, unsigned top3MedianDataRecordsRemovedWithoutUI);
     bool enableResourceLoadStatisticsLogTestingEvent() const { return m_enableResourceLoadStatisticsLogTestingEvent; }
     void setResourceLoadStatisticsLogTestingEvent(bool log) { m_enableResourceLoadStatisticsLogTestingEvent = log; }
     bool shouldIsolateSessionsForPrevalentTopFrames() const { return m_enableResourceLoadStatisticsNSURLSessionSwitching == EnableResourceLoadStatisticsNSURLSessionSwitching::Yes; }

Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp (250865 => 250866)


--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp	2019-10-08 22:00:48 UTC (rev 250865)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp	2019-10-08 22:13:39 UTC (rev 250866)
@@ -956,12 +956,19 @@
     WebProcessProxy::notifyWebsiteDataScanForRegistrableDomainsFinished();
 }
 
-void NetworkProcessProxy::notifyResourceLoadStatisticsTelemetryFinished(unsigned totalPrevalentResources, unsigned totalPrevalentResourcesWithUserInteraction, unsigned top3SubframeUnderTopFrameOrigins)
+void NetworkProcessProxy::notifyResourceLoadStatisticsTelemetryFinished(unsigned numberOfPrevalentResources, unsigned numberOfPrevalentResourcesWithUserInteraction, unsigned numberOfPrevalentResourcesWithoutUserInteraction, unsigned topPrevalentResourceWithUserInteractionDaysSinceUserInteraction, unsigned medianDaysSinceUserInteractionPrevalentResourceWithUserInteraction, unsigned top3NumberOfPrevalentResourcesWithUI, unsigned top3MedianSubFrameWithoutUI, unsigned top3MedianSubResourceWithoutUI, unsigned top3MedianUniqueRedirectsWithoutUI, unsigned top3MedianDataRecordsRemovedWithoutUI)
 {
     API::Dictionary::MapType messageBody;
-    messageBody.set("TotalPrevalentResources"_s, API::UInt64::create(totalPrevalentResources));
-    messageBody.set("TotalPrevalentResourcesWithUserInteraction"_s, API::UInt64::create(totalPrevalentResourcesWithUserInteraction));
-    messageBody.set("Top3SubframeUnderTopFrameOrigins"_s, API::UInt64::create(top3SubframeUnderTopFrameOrigins));
+    messageBody.set("NumberOfPrevalentResources"_s, API::UInt64::create(numberOfPrevalentResources));
+    messageBody.set("NumberOfPrevalentResourcesWithUserInteraction"_s, API::UInt64::create(numberOfPrevalentResourcesWithUserInteraction));
+    messageBody.set("NumberOfPrevalentResourcesWithoutUserInteraction"_s, API::UInt64::create(numberOfPrevalentResourcesWithoutUserInteraction));
+    messageBody.set("TopPrevalentResourceWithUserInteractionDaysSinceUserInteraction"_s, API::UInt64::create(topPrevalentResourceWithUserInteractionDaysSinceUserInteraction));
+    messageBody.set("MedianDaysSinceUserInteractionPrevalentResourceWithUserInteraction"_s, API::UInt64::create(medianDaysSinceUserInteractionPrevalentResourceWithUserInteraction));
+    messageBody.set("Top3NumberOfPrevalentResourcesWithUI"_s, API::UInt64::create(top3NumberOfPrevalentResourcesWithUI));
+    messageBody.set("Top3MedianSubFrameWithoutUI"_s, API::UInt64::create(top3MedianSubFrameWithoutUI));
+    messageBody.set("Top3MedianSubResourceWithoutUI"_s, API::UInt64::create(top3MedianSubResourceWithoutUI));
+    messageBody.set("Top3MedianUniqueRedirectsWithoutUI"_s, API::UInt64::create(top3MedianUniqueRedirectsWithoutUI));
+    messageBody.set("Top3MedianDataRecordsRemovedWithoutUI"_s, API::UInt64::create(top3MedianDataRecordsRemovedWithoutUI));
 
     WebProcessProxy::notifyPageStatisticsTelemetryFinished(API::Dictionary::create(messageBody).ptr());
 }

Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h (250865 => 250866)


--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h	2019-10-08 22:00:48 UTC (rev 250865)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h	2019-10-08 22:13:39 UTC (rev 250866)
@@ -232,7 +232,7 @@
     void notifyResourceLoadStatisticsProcessed();
     void notifyWebsiteDataDeletionForRegistrableDomainsFinished();
     void notifyWebsiteDataScanForRegistrableDomainsFinished();
-    void notifyResourceLoadStatisticsTelemetryFinished(unsigned totalPrevalentResources, unsigned totalPrevalentResourcesWithUserInteraction, unsigned top3SubframeUnderTopFrameOrigins);
+    void notifyResourceLoadStatisticsTelemetryFinished(unsigned numberOfPrevalentResources, unsigned numberOfPrevalentResourcesWithUserInteraction, unsigned numberOfPrevalentResourcesWithoutUserInteraction, unsigned topPrevalentResourceWithUserInteractionDaysSinceUserInteraction, unsigned medianDaysSinceUserInteractionPrevalentResourceWithUserInteraction, unsigned top3NumberOfPrevalentResourcesWithUI, unsigned top3MedianSubFrameWithoutUI, unsigned top3MedianSubResourceWithoutUI, unsigned top3MedianUniqueRedirectsWithoutUI, unsigned top3MedianDataRecordsRemovedWithoutUI);
 #endif
     void retrieveCacheStorageParameters(PAL::SessionID);
 

Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.messages.in (250865 => 250866)


--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.messages.in	2019-10-08 22:00:48 UTC (rev 250865)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.messages.in	2019-10-08 22:13:39 UTC (rev 250866)
@@ -45,7 +45,7 @@
     NotifyResourceLoadStatisticsProcessed()
     NotifyWebsiteDataDeletionForRegistrableDomainsFinished()
     NotifyWebsiteDataScanForRegistrableDomainsFinished()
-    NotifyResourceLoadStatisticsTelemetryFinished(unsigned totalPrevalentResources, unsigned totalPrevalentResourcesWithUserInteraction, unsigned top3SubframeUnderTopFrameOrigins)
+    NotifyResourceLoadStatisticsTelemetryFinished(unsigned numberOfPrevalentResources, unsigned numberOfPrevalentResourcesWithUserInteraction, unsigned numberOfPrevalentResourcesWithoutUserInteraction, unsigned topPrevalentResourceWithUserInteractionDaysSinceUserInteraction, unsigned medianDaysSinceUserInteractionPrevalentResourceWithUserInteraction, unsigned top3NumberOfPrevalentResourcesWithUI, unsigned top3MedianSubFrameWithoutUI, unsigned top3MedianSubResourceWithoutUI, unsigned top3MedianUniqueRedirectsWithoutUI, unsigned top3MedianDataRecordsRemovedWithoutUI)
     RequestStorageAccessConfirm(WebKit::WebPageProxyIdentifier pageID, WebCore::FrameIdentifier frameID, WebCore::RegistrableDomain subFrameDomain, WebCore::RegistrableDomain topFrameDomain) -> (bool userDidGrantAccess) Async
     DeleteWebsiteDataInUIProcessForRegistrableDomains(PAL::SessionID sessionID, OptionSet<WebKit::WebsiteDataType> dataTypes, OptionSet<WebKit::WebsiteDataFetchOption> fetchOptions, Vector<WebCore::RegistrableDomain> domains) -> (HashSet<WebCore::RegistrableDomain> domainsWithMatchingDataRecords) Async
     DidCommitCrossSiteLoadWithDataTransferFromPrevalentResource(WebKit::WebPageProxyIdentifier pageID)

Modified: trunk/Tools/ChangeLog (250865 => 250866)


--- trunk/Tools/ChangeLog	2019-10-08 22:00:48 UTC (rev 250865)
+++ trunk/Tools/ChangeLog	2019-10-08 22:13:39 UTC (rev 250866)
@@ -1,3 +1,19 @@
+2019-10-08  Kate Cheney  <katherine_che...@apple.com>
+
+        Implement Telemetry and Dumping Routines for SQLite backend (195088)
+        https://bugs.webkit.org/show_bug.cgi?id=195088
+        <rdar://problem/54213407>
+
+        Reviewed by John Wilander.
+
+        Updated the current testing for telemetry which only tested 3
+        statistics. With this patch it now tests 10 statistics.
+        * WebKitTestRunner/InjectedBundle/InjectedBundle.cpp:
+        (WTR::InjectedBundle::didReceiveMessageToPage):
+        * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+        (WTR::TestRunner::statisticsDidRunTelemetryCallback):
+        * WebKitTestRunner/InjectedBundle/TestRunner.h:
+
 2019-10-08  Timothy Hatcher  <timo...@apple.com>
 
         Copying white text from dark mode WebKit apps and pasting in a light mode app results in white (invisible) text.

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp (250865 => 250866)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp	2019-10-08 22:00:48 UTC (rev 250865)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp	2019-10-08 22:13:39 UTC (rev 250866)
@@ -440,15 +440,29 @@
     if (WKStringIsEqualToUTF8CString(messageName, "ResourceLoadStatisticsTelemetryFinished")) {
         WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
 
-        WKRetainPtr<WKStringRef> totalPrevalentResourcesKey = adoptWK(WKStringCreateWithUTF8CString("TotalPrevalentResources"));
-        WKRetainPtr<WKStringRef> totalPrevalentResourcesWithUserInteractionKey = adoptWK(WKStringCreateWithUTF8CString("TotalPrevalentResourcesWithUserInteraction"));
-        WKRetainPtr<WKStringRef> top3SubframeUnderTopFrameOriginsKey = adoptWK(WKStringCreateWithUTF8CString("Top3SubframeUnderTopFrameOrigins"));
+        WKRetainPtr<WKStringRef> numberOfPrevalentResourcesKey = adoptWK(WKStringCreateWithUTF8CString("NumberOfPrevalentResources"));
+        WKRetainPtr<WKStringRef> numberOfPrevalentResourcesWithUserInteractionKey = adoptWK(WKStringCreateWithUTF8CString("NumberOfPrevalentResourcesWithUserInteraction"));
+        WKRetainPtr<WKStringRef> numberOfPrevalentResourcesWithoutUserInteractionKey = adoptWK(WKStringCreateWithUTF8CString("NumberOfPrevalentResourcesWithoutUserInteraction"));
+        WKRetainPtr<WKStringRef> topPrevalentResourceWithUserInteractionDaysSinceUserInteractionKey = adoptWK(WKStringCreateWithUTF8CString("TopPrevalentResourceWithUserInteractionDaysSinceUserInteraction"));
+        WKRetainPtr<WKStringRef> medianDaysSinceUserInteractionPrevalentResourceWithUserInteractionKey = adoptWK(WKStringCreateWithUTF8CString("MedianDaysSinceUserInteractionPrevalentResourceWithUserInteraction"));
+        WKRetainPtr<WKStringRef> top3NumberOfPrevalentResourcesWithUIKey = adoptWK(WKStringCreateWithUTF8CString("Top3NumberOfPrevalentResourcesWithUI"));
+        WKRetainPtr<WKStringRef> top3MedianSubFrameWithoutUIKey = adoptWK(WKStringCreateWithUTF8CString("Top3MedianSubFrameWithoutUI"));
+        WKRetainPtr<WKStringRef> top3MedianSubResourceWithoutUIKey = adoptWK(WKStringCreateWithUTF8CString("Top3MedianSubResourceWithoutUI"));
+        WKRetainPtr<WKStringRef> top3MedianUniqueRedirectsWithoutUIKey = adoptWK(WKStringCreateWithUTF8CString("Top3MedianUniqueRedirectsWithoutUI"));
+        WKRetainPtr<WKStringRef> top3MedianDataRecordsRemovedWithoutUIKey = adoptWK(WKStringCreateWithUTF8CString("Top3MedianDataRecordsRemovedWithoutUI"));
+        
+        unsigned numberOfPrevalentResources = (unsigned)WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, numberOfPrevalentResourcesKey.get())));
+        unsigned numberOfPrevalentResourcesWithUserInteraction = (unsigned)WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, numberOfPrevalentResourcesWithUserInteractionKey.get())));
+        unsigned numberOfPrevalentResourcesWithoutUserInteraction = (unsigned)WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, numberOfPrevalentResourcesWithoutUserInteractionKey.get())));
+        unsigned topPrevalentResourceWithUserInteractionDaysSinceUserInteraction = (unsigned)WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, topPrevalentResourceWithUserInteractionDaysSinceUserInteractionKey.get())));
+        unsigned medianDaysSinceUserInteractionPrevalentResourceWithUserInteraction = (unsigned)WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, medianDaysSinceUserInteractionPrevalentResourceWithUserInteractionKey.get())));
+        unsigned top3NumberOfPrevalentResourcesWithUI = (unsigned)WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, top3NumberOfPrevalentResourcesWithUIKey.get())));
+        unsigned top3MedianSubFrameWithoutUI = (unsigned)WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, top3MedianSubFrameWithoutUIKey.get())));
+        unsigned top3MedianSubResourceWithoutUI = (unsigned)WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, top3MedianSubResourceWithoutUIKey.get())));
+        unsigned top3MedianUniqueRedirectsWithoutUI = (unsigned)WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, top3MedianUniqueRedirectsWithoutUIKey.get())));
+        unsigned top3MedianDataRecordsRemovedWithoutUI = (unsigned)WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, top3MedianDataRecordsRemovedWithoutUIKey.get())));
 
-        unsigned totalPrevalentResources = (unsigned)WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, totalPrevalentResourcesKey.get())));
-        unsigned totalPrevalentResourcesWithUserInteraction = (unsigned)WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, totalPrevalentResourcesWithUserInteractionKey.get())));
-        unsigned top3SubframeUnderTopFrameOrigins = (unsigned)WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, top3SubframeUnderTopFrameOriginsKey.get())));
-
-        m_testRunner->statisticsDidRunTelemetryCallback(totalPrevalentResources, totalPrevalentResourcesWithUserInteraction, top3SubframeUnderTopFrameOrigins);
+        m_testRunner->statisticsDidRunTelemetryCallback(numberOfPrevalentResources, numberOfPrevalentResourcesWithUserInteraction, numberOfPrevalentResourcesWithoutUserInteraction, topPrevalentResourceWithUserInteractionDaysSinceUserInteraction, medianDaysSinceUserInteractionPrevalentResourceWithUserInteraction, top3NumberOfPrevalentResourcesWithUI, top3MedianSubFrameWithoutUI, top3MedianSubResourceWithoutUI, top3MedianUniqueRedirectsWithoutUI, top3MedianDataRecordsRemovedWithoutUI);
         return;
     }
     

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp (250865 => 250866)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp	2019-10-08 22:00:48 UTC (rev 250865)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp	2019-10-08 22:13:39 UTC (rev 250866)
@@ -2008,12 +2008,12 @@
     cacheTestRunnerCallback(StatisticsDidRunTelemetryCallbackID, callback);
 }
     
-void TestRunner::statisticsDidRunTelemetryCallback(unsigned totalPrevalentResources, unsigned totalPrevalentResourcesWithUserInteraction, unsigned top3SubframeUnderTopFrameOrigins)
+void TestRunner::statisticsDidRunTelemetryCallback(unsigned numberOfPrevalentResources, unsigned numberOfPrevalentResourcesWithUserInteraction, unsigned numberOfPrevalentResourcesWithoutUserInteraction, unsigned topPrevalentResourceWithUserInteractionDaysSinceUserInteraction, unsigned medianDaysSinceUserInteractionPrevalentResourceWithUserInteraction, unsigned top3NumberOfPrevalentResourcesWithUI, unsigned top3MedianSubFrameWithoutUI, unsigned top3MedianSubResourceWithoutUI, unsigned top3MedianUniqueRedirectsWithoutUI, unsigned top3MedianDataRecordsRemovedWithoutUI)
 {
     WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
     JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
     
-    String string = makeString("{ \"totalPrevalentResources\" : ", totalPrevalentResources, ", \"totalPrevalentResourcesWithUserInteraction\" : ", totalPrevalentResourcesWithUserInteraction, ", \"top3SubframeUnderTopFrameOrigins\" : ", top3SubframeUnderTopFrameOrigins, " }");
+    String string = makeString("{ \"numberOfPrevalentResources\" : ", numberOfPrevalentResources, ", \"numberOfPrevalentResourcesWithUserInteraction\" : ", numberOfPrevalentResourcesWithUserInteraction, ", \"numberOfPrevalentResourcesWithoutUserInteraction\" : ", numberOfPrevalentResourcesWithoutUserInteraction, ", \"topPrevalentResourceWithUserInteractionDaysSinceUserInteraction\" : ", topPrevalentResourceWithUserInteractionDaysSinceUserInteraction, ", \"medianDaysSinceUserInteractionPrevalentResourceWithUserInteraction\" : ", medianDaysSinceUserInteractionPrevalentResourceWithUserInteraction, ", \"top3NumberOfPrevalentResourcesWithUI\" : ", top3NumberOfPrevalentResourcesWithUI, ", \"top3MedianSubFrameWithoutUI\" : ", top3MedianSubFrameWithoutUI, ", \"top3MedianSubResourceWithoutUI\" : ", top3MedianSubResourceWith
 outUI, ", \"top3MedianUniqueRedirectsWithoutUI\" : ", top3MedianUniqueRedirectsWithoutUI, ", \"top3MedianDataRecordsRemovedWithoutUI\" : ", top3MedianDataRecordsRemovedWithoutUI, " }");
     
     JSValueRef result = JSValueMakeFromJSONString(context, adopt(JSStringCreateWithUTF8CString(string.utf8().data())).get());
 

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h (250865 => 250866)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h	2019-10-08 22:00:48 UTC (rev 250865)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h	2019-10-08 22:13:39 UTC (rev 250866)
@@ -384,7 +384,7 @@
     void installStatisticsDidRunTelemetryCallback(JSValueRef callback);
     void statisticsDidModifyDataRecordsCallback();
     void statisticsDidScanDataRecordsCallback();
-    void statisticsDidRunTelemetryCallback(unsigned totalPrevalentResources, unsigned totalPrevalentResourcesWithUserInteraction, unsigned top3SubframeUnderTopFrameOrigins);
+    void statisticsDidRunTelemetryCallback(unsigned numberOfPrevalentResources, unsigned numberOfPrevalentResourcesWithUserInteraction, unsigned numberOfPrevalentResourcesWithoutUserInteraction, unsigned topPrevalentResourceWithUserInteractionDaysSinceUserInteraction, unsigned medianDaysSinceUserInteractionPrevalentResourceWithUserInteraction, unsigned top3NumberOfPrevalentResourcesWithUI, unsigned top3MedianSubFrameWithoutUI, unsigned top3MedianSubResourceWithoutUI, unsigned top3MedianUniqueRedirectsWithoutUI, unsigned top3MedianDataRecordsRemovedWithoutUI);
     bool statisticsNotifyObserver();
     void statisticsProcessStatisticsAndDataRecords();
     void statisticsUpdateCookieBlocking(JSValueRef completionHandler);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to