Title: [228416] trunk
Revision
228416
Author
wilan...@apple.com
Date
2018-02-12 22:08:18 -0800 (Mon, 12 Feb 2018)

Log Message

Resource Load Statistics: Classify resources as prevalent based on redirects to other prevalent resources
https://bugs.webkit.org/show_bug.cgi?id=182664
<rdar://problem/37372572>

Reviewed by Brent Fulgham.

Source/WebCore:

Tests: http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-subresource-redirect-collusion.html
       http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-top-frame-redirect-collusion.html
       http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-top-frame-unique-redirects-to.html

* loader/ResourceLoadObserver.cpp:
(WebCore::ResourceLoadObserver::logFrameNavigation):
    We now collect statistics on top frame navigational redirects too, both to and from.
(WebCore::ResourceLoadObserver::logSubresourceLoading):
    We now collect statistics on redirects from in addition to the existing redirects to.
* loader/ResourceLoadStatistics.cpp:
(WebCore::ResourceLoadStatistics::encode const):
(WebCore::ResourceLoadStatistics::decode):
(WebCore::ResourceLoadStatistics::toString const):
(WebCore::ResourceLoadStatistics::merge):
* loader/ResourceLoadStatistics.h:
    Three new fields:
    - topFrameUniqueRedirectsTo
    - topFrameUniqueRedirectsFrom
    - subresourceUniqueRedirectsFrom

Source/WebKit:

* Platform/classifier/ResourceLoadStatisticsClassifier.cpp:
(WebKit::ResourceLoadStatisticsClassifier::hasPrevalentResourceCharacteristics):
    Unique top frame redirects now counts toward classification as prevalent.
* Shared/WebCoreArgumentCoders.cpp:
(IPC::ArgumentCoder<ResourceLoadStatistics>::encode):
(IPC::ArgumentCoder<ResourceLoadStatistics>::decode):
* UIProcess/API/C/WKWebsiteDataStoreRef.cpp:
(WKWebsiteDataStoreSetStatisticsSubresourceUniqueRedirectFrom):
(WKWebsiteDataStoreSetStatisticsTopFrameUniqueRedirectTo):
(WKWebsiteDataStoreSetStatisticsTopFrameUniqueRedirectFrom):
    Test infrastructure.
* UIProcess/API/C/WKWebsiteDataStoreRef.h:
* UIProcess/WebResourceLoadStatisticsStore.cpp:
    Bumped the statistics model to 11 because of the added fields.
(WebKit::WebResourceLoadStatisticsStore::recursivelyGetAllDomainsThatHaveRedirectedToThisDomain):
    This function back traces redirect chains to classify domains
    that have redirected to a newly classified prevalent resource.
(WebKit::WebResourceLoadStatisticsStore::processStatisticsAndDataRecords):
    Now uses the new convenience function WebResourceLoadStatisticsStore::setPrevalentResource().
(WebKit::WebResourceLoadStatisticsStore::setPrevalentResource):
    New convenience function to make sure we always call
    WebResourceLoadStatisticsStore::recursivelyGetAllDomainsThatHaveRedirectedToThisDomain()
    and capture redirect chains backward.
(WebKit::WebResourceLoadStatisticsStore::setSubframeUnderTopFrameOrigin):
(WebKit::WebResourceLoadStatisticsStore::setSubresourceUnderTopFrameOrigin):
(WebKit::WebResourceLoadStatisticsStore::setSubresourceUniqueRedirectTo):
(WebKit::WebResourceLoadStatisticsStore::setSubresourceUniqueRedirectFrom):
(WebKit::WebResourceLoadStatisticsStore::setTopFrameUniqueRedirectTo):
(WebKit::WebResourceLoadStatisticsStore::setTopFrameUniqueRedirectFrom):
    Test infrastructure.
* UIProcess/WebResourceLoadStatisticsStore.h:

Tools:

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

LayoutTests:

* http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-subresource-redirect-collusion-expected.txt: Added.
* http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-subresource-redirect-collusion.html: Added.
* http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-top-frame-redirect-collusion-expected.txt: Added.
* http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-top-frame-redirect-collusion.html: Added.
* http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-top-frame-unique-redirects-to-expected.txt: Added.
* http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-top-frame-unique-redirects-to.html: Added.
* platform/wk2/TestExpectations:
    New tests added as [ Pass ].

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (228415 => 228416)


--- trunk/LayoutTests/ChangeLog	2018-02-13 04:44:21 UTC (rev 228415)
+++ trunk/LayoutTests/ChangeLog	2018-02-13 06:08:18 UTC (rev 228416)
@@ -1,3 +1,20 @@
+2018-02-12  John Wilander  <wilan...@apple.com>
+
+        Resource Load Statistics: Classify resources as prevalent based on redirects to other prevalent resources
+        https://bugs.webkit.org/show_bug.cgi?id=182664
+        <rdar://problem/37372572>
+
+        Reviewed by Brent Fulgham.
+
+        * http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-subresource-redirect-collusion-expected.txt: Added.
+        * http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-subresource-redirect-collusion.html: Added.
+        * http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-top-frame-redirect-collusion-expected.txt: Added.
+        * http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-top-frame-redirect-collusion.html: Added.
+        * http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-top-frame-unique-redirects-to-expected.txt: Added.
+        * http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-top-frame-unique-redirects-to.html: Added.
+        * platform/wk2/TestExpectations:
+            New tests added as [ Pass ].
+
 2018-02-12  Matt Lewis  <jlew...@apple.com>
 
         Marked multiple http/tests/resourceLoadStatistics tests as flaky and skip.

Added: trunk/LayoutTests/http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-subresource-redirect-collusion-expected.txt (0 => 228416)


--- trunk/LayoutTests/http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-subresource-redirect-collusion-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-subresource-redirect-collusion-expected.txt	2018-02-13 06:08:18 UTC (rev 228416)
@@ -0,0 +1,14 @@
+Tests for classification based on subresource redirect collusion.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Colluding host 1 got set as prevalent resource.
+PASS Colluding host 2 got set as prevalent resource.
+PASS Colluding host 3 got set as prevalent resource.
+PASS Colluding host 4 got set as prevalent resource.
+PASS Colluding localhost got set as prevalent resource after actual sub frame redirect.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-subresource-redirect-collusion.html (0 => 228416)


--- trunk/LayoutTests/http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-subresource-redirect-collusion.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-subresource-redirect-collusion.html	2018-02-13 06:08:18 UTC (rev 228416)
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <script src=""
+</head>
+<body>
+<script>
+    description("Tests for classification based on subresource redirect collusion.");
+    jsTestIsAsync = true;
+
+    const hostUnderTest = "127.0.0.1:8000";
+    const statisticsUrl = "http://" + hostUnderTest + "/temp";
+    const subresourceOrigin1 = "http://127.0.0.2:8000/temp";
+    const subresourceOrigin2 = "http://127.0.0.3:8000/temp";
+    const subresourceOrigin3 = "http://127.0.0.4:8000/temp";
+    const subresourceOrigin4 = "http://127.0.0.5:8000/temp";
+
+    function setEnableFeature(enable) {
+        if (!enable)
+            testRunner.statisticsResetToConsistentState();
+        internals.setResourceLoadStatisticsEnabled(enable);
+        testRunner.setCookieStoragePartitioningEnabled(enable);
+    }
+
+    function runTest() {
+        testRunner.statisticsNotifyObserver();
+
+        testRunner.setStatisticsSubresourceUniqueRedirectFrom(statisticsUrl, subresourceOrigin1);
+        testRunner.setStatisticsSubresourceUniqueRedirectFrom(subresourceOrigin1, subresourceOrigin2);
+        testRunner.setStatisticsSubresourceUniqueRedirectFrom(subresourceOrigin2, subresourceOrigin3);
+        testRunner.setStatisticsSubresourceUniqueRedirectFrom(subresourceOrigin3, subresourceOrigin4);
+
+        testRunner.setStatisticsPrevalentResource(statisticsUrl, true);
+        if (!testRunner.isStatisticsPrevalentResource(statisticsUrl))
+            testFailed("Host explicity set did not get set as prevalent resource.");
+        if (testRunner.isStatisticsPrevalentResource(subresourceOrigin1))
+            testPassed("Colluding host 1 got set as prevalent resource.");
+        if (testRunner.isStatisticsPrevalentResource(subresourceOrigin2))
+            testPassed("Colluding host 2 got set as prevalent resource.");
+        if (testRunner.isStatisticsPrevalentResource(subresourceOrigin3))
+            testPassed("Colluding host 3 got set as prevalent resource.");
+        if (testRunner.isStatisticsPrevalentResource(subresourceOrigin4))
+            testPassed("Colluding host 4 got set as prevalent resource.");
+        if (testRunner.isStatisticsPrevalentResource("http://localhost:8000"))
+            testPassed("Colluding localhost got set as prevalent resource after actual sub frame redirect.");
+
+        setEnableFeature(false);
+        finishJSTest();
+    }
+
+    if (document.location.host === hostUnderTest && window.testRunner && window.internals) {
+        setEnableFeature(true);
+
+        testRunner.setStatisticsPrevalentResource(statisticsUrl, false);
+        if (testRunner.isStatisticsPrevalentResource(statisticsUrl))
+            testFailed("Host did not get set as non-prevalent resource.");
+    }
+</script>
+<iframe _onload_="runTest()" src=""
+</body>
+</html>

Added: trunk/LayoutTests/http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-top-frame-redirect-collusion-expected.txt (0 => 228416)


--- trunk/LayoutTests/http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-top-frame-redirect-collusion-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-top-frame-redirect-collusion-expected.txt	2018-02-13 06:08:18 UTC (rev 228416)
@@ -0,0 +1,14 @@
+Tests for classification based on top frame redirect collusion.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Colluding host 1 got set as prevalent resource.
+PASS Colluding host 2 got set as prevalent resource.
+PASS Colluding host 3 got set as prevalent resource.
+PASS Colluding host 4 got set as prevalent resource.
+PASS Colluding localhost got set as prevalent resource after actual navigational redirect.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-top-frame-redirect-collusion.html (0 => 228416)


--- trunk/LayoutTests/http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-top-frame-redirect-collusion.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-top-frame-redirect-collusion.html	2018-02-13 06:08:18 UTC (rev 228416)
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <script src=""
+</head>
+<body>
+<script>
+    description("Tests for classification based on top frame redirect collusion.");
+    jsTestIsAsync = true;
+
+    const hostUnderTest = "127.0.0.1:8000";
+    const statisticsUrl = "http://" + hostUnderTest + "/temp";
+    const topFrameOrigin1 = "http://127.0.0.2:8000/temp";
+    const topFrameOrigin2 = "http://127.0.0.3:8000/temp";
+    const topFrameOrigin3 = "http://127.0.0.4:8000/temp";
+    const topFrameOrigin4 = "http://127.0.0.5:8000/temp";
+    const topFrameOrigin5 = "http://localhost:8000/";
+
+    function setEnableFeature(enable) {
+        if (!enable)
+            testRunner.statisticsResetToConsistentState();
+        internals.setResourceLoadStatisticsEnabled(enable);
+        testRunner.setCookieStoragePartitioningEnabled(enable);
+    }
+
+    function runTest() {
+        testRunner.setStatisticsTopFrameUniqueRedirectFrom(statisticsUrl, topFrameOrigin1);
+        testRunner.setStatisticsTopFrameUniqueRedirectFrom(topFrameOrigin1, topFrameOrigin2);
+        testRunner.setStatisticsTopFrameUniqueRedirectFrom(topFrameOrigin2, topFrameOrigin3);
+        testRunner.setStatisticsTopFrameUniqueRedirectFrom(topFrameOrigin3, topFrameOrigin4);
+
+        testRunner.setStatisticsPrevalentResource(statisticsUrl, true);
+        if (!testRunner.isStatisticsPrevalentResource(statisticsUrl))
+            testFailed("Host explicity set did not get set as prevalent resource.");
+        if (testRunner.isStatisticsPrevalentResource(topFrameOrigin1))
+            testPassed("Colluding host 1 got set as prevalent resource.");
+        if (testRunner.isStatisticsPrevalentResource(topFrameOrigin2))
+            testPassed("Colluding host 2 got set as prevalent resource.");
+        if (testRunner.isStatisticsPrevalentResource(topFrameOrigin3))
+            testPassed("Colluding host 3 got set as prevalent resource.");
+        if (testRunner.isStatisticsPrevalentResource(topFrameOrigin4))
+            testPassed("Colluding host 4 got set as prevalent resource.");
+        if (testRunner.isStatisticsPrevalentResource(topFrameOrigin5))
+            testPassed("Colluding localhost got set as prevalent resource after actual navigational redirect.");
+
+        setEnableFeature(false);
+        finishJSTest();
+    }
+
+    if (document.location.hash === "" && window.testRunner && window.internals) {
+        setEnableFeature(true);
+
+        testRunner.setStatisticsPrevalentResource(statisticsUrl, false);
+        if (testRunner.isStatisticsPrevalentResource(statisticsUrl))
+            testFailed("Host did not get set as non-prevalent resource.");
+
+        document.location.href = "" + "resourceLoadStatistics/resources/redirect.php?redirectTo=http://127.0.0.1:8000/resourceLoadStatistics/classify-as-prevalent-based-on-top-frame-redirect-collusion.html#continue";
+    } else {
+        testRunner.statisticsNotifyObserver();
+        runTest();
+    }
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-top-frame-unique-redirects-to-expected.txt (0 => 228416)


--- trunk/LayoutTests/http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-top-frame-unique-redirects-to-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-top-frame-unique-redirects-to-expected.txt	2018-02-13 06:08:18 UTC (rev 228416)
@@ -0,0 +1,10 @@
+Tests for classification based on top frame unique redirects to.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Host classified as prevalent resource.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-top-frame-unique-redirects-to.html (0 => 228416)


--- trunk/LayoutTests/http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-top-frame-unique-redirects-to.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-top-frame-unique-redirects-to.html	2018-02-13 06:08:18 UTC (rev 228416)
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <script src=""
+</head>
+<body>
+<script>
+    description("Tests for classification based on top frame unique redirects to.");
+    jsTestIsAsync = true;
+
+    const hostUnderTest = "127.0.0.1:8000";
+    const statisticsUrl = "http://" + hostUnderTest + "/temp";
+    const topFrameOrigin1 = "http://127.0.0.2:8000/temp";
+    const topFrameOrigin2 = "http://127.0.0.3:8000/temp";
+    const topFrameOrigin3 = "http://127.0.0.4:8000/temp";
+    const topFrameOrigin4 = "http://127.0.0.5:8000/temp";
+
+    function setEnableFeature(enable) {
+        if (!enable)
+            testRunner.statisticsResetToConsistentState();
+        internals.setResourceLoadStatisticsEnabled(enable);
+        testRunner.setCookieStoragePartitioningEnabled(enable);
+    }
+
+    function completeTest() {
+        if (!testRunner.isStatisticsPrevalentResource(statisticsUrl))
+            testFailed("Host did not get classified as prevalent resource.");
+        else
+            testPassed("Host classified as prevalent resource.");
+
+        setEnableFeature(false);
+        finishJSTest();
+    }
+
+    function runTest() {
+        testRunner.setStatisticsTopFrameUniqueRedirectTo(statisticsUrl, topFrameOrigin1);
+        testRunner.setStatisticsTopFrameUniqueRedirectTo(statisticsUrl, topFrameOrigin2);
+        testRunner.setStatisticsTopFrameUniqueRedirectTo(statisticsUrl, topFrameOrigin3);
+        testRunner.setStatisticsTopFrameUniqueRedirectTo(statisticsUrl, topFrameOrigin4);
+
+        testRunner.installStatisticsDidScanDataRecordsCallback(completeTest);
+
+        testRunner.statisticsProcessStatisticsAndDataRecords();
+    }
+
+    if (document.location.host === hostUnderTest && window.testRunner && window.internals) {
+        setEnableFeature(true);
+        testRunner.setStatisticsNotifyPagesWhenDataRecordsWereScanned(true);
+
+        testRunner.setStatisticsPrevalentResource(statisticsUrl, false);
+        if (testRunner.isStatisticsPrevalentResource(statisticsUrl))
+            testFailed("Host did not get set as non-prevalent resource.");
+        runTest();
+    }
+</script>
+</body>
+</html>

Modified: trunk/LayoutTests/platform/wk2/TestExpectations (228415 => 228416)


--- trunk/LayoutTests/platform/wk2/TestExpectations	2018-02-13 04:44:21 UTC (rev 228415)
+++ trunk/LayoutTests/platform/wk2/TestExpectations	2018-02-13 06:08:18 UTC (rev 228416)
@@ -689,6 +689,9 @@
 http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-sub-frame-under-top-frame-origins.html [ Pass ]
 http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-subresource-under-top-frame-origins.html [ Pass ]
 http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-subresource-unique-redirects-to.html [ Pass ]
+http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-subresource-redirect-collusion.html [ Pass ]
+http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-top-frame-redirect-collusion.html [ Pass ]
+http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-top-frame-unique-redirects-to.html [ Pass ]
 webkit.org/b/181223 http/tests/resourceLoadStatistics/clear-in-memory-and-persistent-store.html [ Skip ]
 http/tests/resourceLoadStatistics/grandfathering.html [ Pass ]
 webkit.org/b/180703 http/tests/resourceLoadStatistics/telemetry-generation.html [ Pass Failure ]

Modified: trunk/Source/WebCore/ChangeLog (228415 => 228416)


--- trunk/Source/WebCore/ChangeLog	2018-02-13 04:44:21 UTC (rev 228415)
+++ trunk/Source/WebCore/ChangeLog	2018-02-13 06:08:18 UTC (rev 228416)
@@ -1,3 +1,31 @@
+2018-02-12  John Wilander  <wilan...@apple.com>
+
+        Resource Load Statistics: Classify resources as prevalent based on redirects to other prevalent resources
+        https://bugs.webkit.org/show_bug.cgi?id=182664
+        <rdar://problem/37372572>
+
+        Reviewed by Brent Fulgham.
+
+        Tests: http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-subresource-redirect-collusion.html
+               http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-top-frame-redirect-collusion.html
+               http/tests/resourceLoadStatistics/classify-as-prevalent-based-on-top-frame-unique-redirects-to.html
+
+        * loader/ResourceLoadObserver.cpp:
+        (WebCore::ResourceLoadObserver::logFrameNavigation):
+            We now collect statistics on top frame navigational redirects too, both to and from.
+        (WebCore::ResourceLoadObserver::logSubresourceLoading):
+            We now collect statistics on redirects from in addition to the existing redirects to.
+        * loader/ResourceLoadStatistics.cpp:
+        (WebCore::ResourceLoadStatistics::encode const):
+        (WebCore::ResourceLoadStatistics::decode):
+        (WebCore::ResourceLoadStatistics::toString const):
+        (WebCore::ResourceLoadStatistics::merge):
+        * loader/ResourceLoadStatistics.h:
+            Three new fields:
+            - topFrameUniqueRedirectsTo
+            - topFrameUniqueRedirectsFrom
+            - subresourceUniqueRedirectsFrom
+
 2018-02-12  Zalan Bujtas  <za...@apple.com>
 
         [RenderTreeBuilder] Move RenderMenuList::takeChild() to RenderTreeBuilder

Modified: trunk/Source/WebCore/loader/ResourceLoadObserver.cpp (228415 => 228416)


--- trunk/Source/WebCore/loader/ResourceLoadObserver.cpp	2018-02-13 04:44:21 UTC (rev 228415)
+++ trunk/Source/WebCore/loader/ResourceLoadObserver.cpp	2018-02-13 06:08:18 UTC (rev 228416)
@@ -138,9 +138,6 @@
     ASSERT(topFrame.document());
     ASSERT(topFrame.page());
 
-    if (frame.isMainFrame())
-        return;
-    
     auto* page = topFrame.page();
     if (!shouldLog(page))
         return;
@@ -177,8 +174,21 @@
 
     if (isRedirect
         && !areDomainsAssociated(page, sourcePrimaryDomain, targetPrimaryDomain)) {
-        auto& redirectingOriginStatistics = ensureResourceStatisticsForPrimaryDomain(sourcePrimaryDomain);
-        if (redirectingOriginStatistics.subresourceUniqueRedirectsTo.add(targetPrimaryDomain).isNewEntry)
+        bool isNewRedirectToEntry = false;
+        bool isNewRedirectFromEntry = false;
+        if (frame.isMainFrame()) {
+            auto& redirectingOriginStatistics = ensureResourceStatisticsForPrimaryDomain(sourcePrimaryDomain);
+            isNewRedirectToEntry = redirectingOriginStatistics.topFrameUniqueRedirectsTo.add(targetPrimaryDomain).isNewEntry;
+            auto& targetStatistics = ensureResourceStatisticsForPrimaryDomain(targetPrimaryDomain);
+            isNewRedirectFromEntry = targetStatistics.topFrameUniqueRedirectsFrom.add(sourcePrimaryDomain).isNewEntry;
+        } else {
+            auto& redirectingOriginStatistics = ensureResourceStatisticsForPrimaryDomain(sourcePrimaryDomain);
+            isNewRedirectToEntry = redirectingOriginStatistics.subresourceUniqueRedirectsTo.add(targetPrimaryDomain).isNewEntry;
+            auto& targetStatistics = ensureResourceStatisticsForPrimaryDomain(targetPrimaryDomain);
+            isNewRedirectFromEntry = targetStatistics.subresourceUniqueRedirectsFrom.add(sourcePrimaryDomain).isNewEntry;
+        }
+
+        if (isNewRedirectToEntry || isNewRedirectFromEntry)
             shouldCallNotificationCallback = true;
     }
 
@@ -234,7 +244,11 @@
 
     if (isRedirect) {
         auto& redirectingOriginStatistics = ensureResourceStatisticsForPrimaryDomain(sourcePrimaryDomain);
-        if (redirectingOriginStatistics.subresourceUniqueRedirectsTo.add(targetPrimaryDomain).isNewEntry)
+        bool isNewRedirectToEntry = redirectingOriginStatistics.subresourceUniqueRedirectsTo.add(targetPrimaryDomain).isNewEntry;
+        auto& targetStatistics = ensureResourceStatisticsForPrimaryDomain(targetPrimaryDomain);
+        bool isNewRedirectFromEntry = targetStatistics.subresourceUniqueRedirectsFrom.add(sourcePrimaryDomain).isNewEntry;
+
+        if (isNewRedirectToEntry || isNewRedirectFromEntry)
             shouldCallNotificationCallback = true;
     }
 

Modified: trunk/Source/WebCore/loader/ResourceLoadStatistics.cpp (228415 => 228416)


--- trunk/Source/WebCore/loader/ResourceLoadStatistics.cpp	2018-02-13 04:44:21 UTC (rev 228415)
+++ trunk/Source/WebCore/loader/ResourceLoadStatistics.cpp	2018-02-13 06:08:18 UTC (rev 228416)
@@ -70,6 +70,10 @@
     // Storage access
     encodeHashSet(encoder, "storageAccessUnderTopFrameOrigins", storageAccessUnderTopFrameOrigins);
 
+    // Top frame stats
+    encodeHashCountedSet(encoder, "topFrameUniqueRedirectsTo", topFrameUniqueRedirectsTo);
+    encodeHashCountedSet(encoder, "topFrameUniqueRedirectsFrom", topFrameUniqueRedirectsFrom);
+
     // Subframe stats
     encodeHashCountedSet(encoder, "subframeUnderTopFrameOrigins", subframeUnderTopFrameOrigins);
     
@@ -76,7 +80,8 @@
     // Subresource stats
     encodeHashCountedSet(encoder, "subresourceUnderTopFrameOrigins", subresourceUnderTopFrameOrigins);
     encodeHashCountedSet(encoder, "subresourceUniqueRedirectsTo", subresourceUniqueRedirectsTo);
-    
+    encodeHashCountedSet(encoder, "subresourceUniqueRedirectsFrom", subresourceUniqueRedirectsFrom);
+
     // Prevalent Resource
     encoder.encodeBool("isPrevalentResource", isPrevalentResource);
     encoder.encodeUInt32("dataRecordsRemoved", dataRecordsRemoved);
@@ -125,6 +130,10 @@
     // Storage access
     decodeHashSet(decoder, "storageAccessUnderTopFrameOrigins", storageAccessUnderTopFrameOrigins);
 
+    // Top frame stats
+    decodeHashCountedSet(decoder, "topFrameUniqueRedirectsTo", topFrameUniqueRedirectsTo);
+    decodeHashCountedSet(decoder, "topFrameUniqueRedirectsFrom", topFrameUniqueRedirectsFrom);
+
     // Subframe stats
     decodeHashCountedSet(decoder, "subframeUnderTopFrameOrigins", subframeUnderTopFrameOrigins);
     
@@ -131,7 +140,8 @@
     // Subresource stats
     decodeHashCountedSet(decoder, "subresourceUnderTopFrameOrigins", subresourceUnderTopFrameOrigins);
     decodeHashCountedSet(decoder, "subresourceUniqueRedirectsTo", subresourceUniqueRedirectsTo);
-    
+    decodeHashCountedSet(decoder, "subresourceUniqueRedirectsFrom", subresourceUniqueRedirectsFrom);
+
     // Prevalent Resource
     if (!decoder.decodeBool("isPrevalentResource", isPrevalentResource))
         return false;
@@ -222,6 +232,10 @@
     // Storage access
     appendHashSet(builder, "storageAccessUnderTopFrameOrigins", storageAccessUnderTopFrameOrigins);
 
+    // Top frame stats
+    appendHashCountedSet(builder, "topFrameUniqueRedirectsTo", topFrameUniqueRedirectsTo);
+    appendHashCountedSet(builder, "topFrameUniqueRedirectsFrom", topFrameUniqueRedirectsFrom);
+
     // Subframe stats
     appendHashCountedSet(builder, "subframeUnderTopFrameOrigins", subframeUnderTopFrameOrigins);
     
@@ -228,7 +242,8 @@
     // Subresource stats
     appendHashCountedSet(builder, "subresourceUnderTopFrameOrigins", subresourceUnderTopFrameOrigins);
     appendHashCountedSet(builder, "subresourceUniqueRedirectsTo", subresourceUniqueRedirectsTo);
-    
+    appendHashCountedSet(builder, "subresourceUniqueRedirectsFrom", subresourceUniqueRedirectsFrom);
+
     // Prevalent Resource
     appendBoolean(builder, "isPrevalentResource", isPrevalentResource);
     builder.appendLiteral("    dataRecordsRemoved: ");
@@ -283,6 +298,10 @@
     // Storage access
     mergeHashSet(storageAccessUnderTopFrameOrigins, other.storageAccessUnderTopFrameOrigins);
 
+    // Top frame stats
+    mergeHashCountedSet(topFrameUniqueRedirectsTo, other.topFrameUniqueRedirectsTo);
+    mergeHashCountedSet(topFrameUniqueRedirectsFrom, other.topFrameUniqueRedirectsFrom);
+
     // Subframe stats
     mergeHashCountedSet(subframeUnderTopFrameOrigins, other.subframeUnderTopFrameOrigins);
     
@@ -289,7 +308,8 @@
     // Subresource stats
     mergeHashCountedSet(subresourceUnderTopFrameOrigins, other.subresourceUnderTopFrameOrigins);
     mergeHashCountedSet(subresourceUniqueRedirectsTo, other.subresourceUniqueRedirectsTo);
-    
+    mergeHashCountedSet(subresourceUniqueRedirectsFrom, other.subresourceUniqueRedirectsFrom);
+
     // Prevalent resource stats
     isPrevalentResource |= other.isPrevalentResource;
     dataRecordsRemoved = std::max(dataRecordsRemoved, other.dataRecordsRemoved);

Modified: trunk/Source/WebCore/loader/ResourceLoadStatistics.h (228415 => 228416)


--- trunk/Source/WebCore/loader/ResourceLoadStatistics.h	2018-02-13 04:44:21 UTC (rev 228415)
+++ trunk/Source/WebCore/loader/ResourceLoadStatistics.h	2018-02-13 06:08:18 UTC (rev 228416)
@@ -73,6 +73,10 @@
     // Storage access
     HashSet<String> storageAccessUnderTopFrameOrigins;
 
+    // Top frame stats
+    HashCountedSet<String> topFrameUniqueRedirectsTo;
+    HashCountedSet<String> topFrameUniqueRedirectsFrom;
+
     // Subframe stats
     HashCountedSet<String> subframeUnderTopFrameOrigins;
     
@@ -79,7 +83,8 @@
     // Subresource stats
     HashCountedSet<String> subresourceUnderTopFrameOrigins;
     HashCountedSet<String> subresourceUniqueRedirectsTo;
-    
+    HashCountedSet<String> subresourceUniqueRedirectsFrom;
+
     // Prevalent resource stats
     bool isPrevalentResource { false };
     unsigned dataRecordsRemoved { 0 };

Modified: trunk/Source/WebKit/ChangeLog (228415 => 228416)


--- trunk/Source/WebKit/ChangeLog	2018-02-13 04:44:21 UTC (rev 228415)
+++ trunk/Source/WebKit/ChangeLog	2018-02-13 06:08:18 UTC (rev 228416)
@@ -1,3 +1,43 @@
+2018-02-12  John Wilander  <wilan...@apple.com>
+
+        Resource Load Statistics: Classify resources as prevalent based on redirects to other prevalent resources
+        https://bugs.webkit.org/show_bug.cgi?id=182664
+        <rdar://problem/37372572>
+
+        Reviewed by Brent Fulgham.
+
+        * Platform/classifier/ResourceLoadStatisticsClassifier.cpp:
+        (WebKit::ResourceLoadStatisticsClassifier::hasPrevalentResourceCharacteristics):
+            Unique top frame redirects now counts toward classification as prevalent.
+        * Shared/WebCoreArgumentCoders.cpp:
+        (IPC::ArgumentCoder<ResourceLoadStatistics>::encode):
+        (IPC::ArgumentCoder<ResourceLoadStatistics>::decode):
+        * UIProcess/API/C/WKWebsiteDataStoreRef.cpp:
+        (WKWebsiteDataStoreSetStatisticsSubresourceUniqueRedirectFrom):
+        (WKWebsiteDataStoreSetStatisticsTopFrameUniqueRedirectTo):
+        (WKWebsiteDataStoreSetStatisticsTopFrameUniqueRedirectFrom):
+            Test infrastructure.
+        * UIProcess/API/C/WKWebsiteDataStoreRef.h:
+        * UIProcess/WebResourceLoadStatisticsStore.cpp:
+            Bumped the statistics model to 11 because of the added fields.
+        (WebKit::WebResourceLoadStatisticsStore::recursivelyGetAllDomainsThatHaveRedirectedToThisDomain):
+            This function back traces redirect chains to classify domains
+            that have redirected to a newly classified prevalent resource.
+        (WebKit::WebResourceLoadStatisticsStore::processStatisticsAndDataRecords):
+            Now uses the new convenience function WebResourceLoadStatisticsStore::setPrevalentResource().
+        (WebKit::WebResourceLoadStatisticsStore::setPrevalentResource):
+            New convenience function to make sure we always call
+            WebResourceLoadStatisticsStore::recursivelyGetAllDomainsThatHaveRedirectedToThisDomain()
+            and capture redirect chains backward.
+        (WebKit::WebResourceLoadStatisticsStore::setSubframeUnderTopFrameOrigin):
+        (WebKit::WebResourceLoadStatisticsStore::setSubresourceUnderTopFrameOrigin):
+        (WebKit::WebResourceLoadStatisticsStore::setSubresourceUniqueRedirectTo):
+        (WebKit::WebResourceLoadStatisticsStore::setSubresourceUniqueRedirectFrom):
+        (WebKit::WebResourceLoadStatisticsStore::setTopFrameUniqueRedirectTo):
+        (WebKit::WebResourceLoadStatisticsStore::setTopFrameUniqueRedirectFrom):
+            Test infrastructure.
+        * UIProcess/WebResourceLoadStatisticsStore.h:
+
 2018-02-12  Antti Koivisto  <an...@apple.com>
 
         Update NetworkCache::Storage::lastStableVersion after r226349

Modified: trunk/Source/WebKit/Platform/classifier/ResourceLoadStatisticsClassifier.cpp (228415 => 228416)


--- trunk/Source/WebKit/Platform/classifier/ResourceLoadStatisticsClassifier.cpp	2018-02-13 04:44:21 UTC (rev 228415)
+++ trunk/Source/WebKit/Platform/classifier/ResourceLoadStatisticsClassifier.cpp	2018-02-13 06:08:18 UTC (rev 228416)
@@ -38,15 +38,18 @@
     auto subresourceUnderTopFrameOriginsCount = resourceStatistic.subresourceUnderTopFrameOrigins.size();
     auto subresourceUniqueRedirectsToCount = resourceStatistic.subresourceUniqueRedirectsTo.size();
     auto subframeUnderTopFrameOriginsCount = resourceStatistic.subframeUnderTopFrameOrigins.size();
+    auto topFrameUniqueRedirectsToCount = resourceStatistic.topFrameUniqueRedirectsTo.size();
     
     if (!subresourceUnderTopFrameOriginsCount
         && !subresourceUniqueRedirectsToCount
-        && !subframeUnderTopFrameOriginsCount)
+        && !subframeUnderTopFrameOriginsCount
+        && !topFrameUniqueRedirectsToCount)
         return false;
     
     if (subresourceUnderTopFrameOriginsCount > featureVectorLengthThreshold
         || subresourceUniqueRedirectsToCount > featureVectorLengthThreshold
-        || subframeUnderTopFrameOriginsCount > featureVectorLengthThreshold)
+        || subframeUnderTopFrameOriginsCount > featureVectorLengthThreshold
+        || topFrameUniqueRedirectsToCount > featureVectorLengthThreshold)
         return true;
 
     return classify(subresourceUnderTopFrameOriginsCount, subresourceUniqueRedirectsToCount, subframeUnderTopFrameOriginsCount);

Modified: trunk/Source/WebKit/Shared/WebCoreArgumentCoders.cpp (228415 => 228416)


--- trunk/Source/WebKit/Shared/WebCoreArgumentCoders.cpp	2018-02-13 04:44:21 UTC (rev 228415)
+++ trunk/Source/WebKit/Shared/WebCoreArgumentCoders.cpp	2018-02-13 06:08:18 UTC (rev 228416)
@@ -2538,6 +2538,10 @@
     // Storage access
     encoder << statistics.storageAccessUnderTopFrameOrigins;
 
+    // Top frame stats
+    encoder << statistics.topFrameUniqueRedirectsTo;
+    encoder << statistics.topFrameUniqueRedirectsFrom;
+
     // Subframe stats
     encoder << statistics.subframeUnderTopFrameOrigins;
     
@@ -2544,7 +2548,8 @@
     // Subresource stats
     encoder << statistics.subresourceUnderTopFrameOrigins;
     encoder << statistics.subresourceUniqueRedirectsTo;
-    
+    encoder << statistics.subresourceUniqueRedirectsFrom;
+
     // Prevalent Resource
     encoder << statistics.isPrevalentResource;
     encoder << statistics.dataRecordsRemoved;
@@ -2577,6 +2582,13 @@
     if (!decoder.decode(statistics.storageAccessUnderTopFrameOrigins))
         return std::nullopt;
 
+    // Top frame stats
+    if (!decoder.decode(statistics.topFrameUniqueRedirectsTo))
+        return std::nullopt;    
+
+    if (!decoder.decode(statistics.topFrameUniqueRedirectsFrom))
+        return std::nullopt;
+
     // Subframe stats
     if (!decoder.decode(statistics.subframeUnderTopFrameOrigins))
         return std::nullopt;
@@ -2588,6 +2600,9 @@
     if (!decoder.decode(statistics.subresourceUniqueRedirectsTo))
         return std::nullopt;
     
+    if (!decoder.decode(statistics.subresourceUniqueRedirectsFrom))
+        return std::nullopt;
+    
     // Prevalent Resource
     if (!decoder.decode(statistics.isPrevalentResource))
         return std::nullopt;

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


--- trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp	2018-02-13 04:44:21 UTC (rev 228415)
+++ trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp	2018-02-13 06:08:18 UTC (rev 228416)
@@ -211,6 +211,33 @@
     store->setSubresourceUniqueRedirectTo(WebCore::URL(WebCore::URL(), WebKit::toImpl(host)->string()), WebCore::URL(WebCore::URL(), WebKit::toImpl(hostRedirectedTo)->string()));
 }
 
+void WKWebsiteDataStoreSetStatisticsSubresourceUniqueRedirectFrom(WKWebsiteDataStoreRef dataStoreRef, WKStringRef host, WKStringRef hostRedirectedFrom)
+{
+    auto* store = WebKit::toImpl(dataStoreRef)->websiteDataStore().resourceLoadStatistics();
+    if (!store)
+        return;
+    
+    store->setSubresourceUniqueRedirectFrom(WebCore::URL(WebCore::URL(), WebKit::toImpl(host)->string()), WebCore::URL(WebCore::URL(), WebKit::toImpl(hostRedirectedFrom)->string()));
+}
+
+void WKWebsiteDataStoreSetStatisticsTopFrameUniqueRedirectTo(WKWebsiteDataStoreRef dataStoreRef, WKStringRef host, WKStringRef hostRedirectedTo)
+{
+    auto* store = WebKit::toImpl(dataStoreRef)->websiteDataStore().resourceLoadStatistics();
+    if (!store)
+        return;
+    
+    store->setTopFrameUniqueRedirectTo(WebCore::URL(WebCore::URL(), WebKit::toImpl(host)->string()), WebCore::URL(WebCore::URL(), WebKit::toImpl(hostRedirectedTo)->string()));
+}
+
+void WKWebsiteDataStoreSetStatisticsTopFrameUniqueRedirectFrom(WKWebsiteDataStoreRef dataStoreRef, WKStringRef host, WKStringRef hostRedirectedFrom)
+{
+    auto* store = WebKit::toImpl(dataStoreRef)->websiteDataStore().resourceLoadStatistics();
+    if (!store)
+        return;
+    
+    store->setTopFrameUniqueRedirectFrom(WebCore::URL(WebCore::URL(), WebKit::toImpl(host)->string()), WebCore::URL(WebCore::URL(), WebKit::toImpl(hostRedirectedFrom)->string()));
+}
+
 void WKWebsiteDataStoreSetStatisticsTimeToLiveUserInteraction(WKWebsiteDataStoreRef dataStoreRef, double seconds)
 {
     auto* store = WebKit::toImpl(dataStoreRef)->websiteDataStore().resourceLoadStatistics();

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


--- trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.h	2018-02-13 04:44:21 UTC (rev 228415)
+++ trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.h	2018-02-13 06:08:18 UTC (rev 228416)
@@ -58,6 +58,9 @@
 WK_EXPORT void WKWebsiteDataStoreSetStatisticsSubframeUnderTopFrameOrigin(WKWebsiteDataStoreRef dataStoreRef, WKStringRef host, WKStringRef topFrameHost);
 WK_EXPORT void WKWebsiteDataStoreSetStatisticsSubresourceUnderTopFrameOrigin(WKWebsiteDataStoreRef dataStoreRef, WKStringRef host, WKStringRef topFrameHost);
 WK_EXPORT void WKWebsiteDataStoreSetStatisticsSubresourceUniqueRedirectTo(WKWebsiteDataStoreRef dataStoreRef, WKStringRef host, WKStringRef hostRedirectedTo);
+WK_EXPORT void WKWebsiteDataStoreSetStatisticsSubresourceUniqueRedirectFrom(WKWebsiteDataStoreRef dataStoreRef, WKStringRef host, WKStringRef hostRedirectedFrom);
+WK_EXPORT void WKWebsiteDataStoreSetStatisticsTopFrameUniqueRedirectTo(WKWebsiteDataStoreRef dataStoreRef, WKStringRef host, WKStringRef hostRedirectedTo);
+WK_EXPORT void WKWebsiteDataStoreSetStatisticsTopFrameUniqueRedirectFrom(WKWebsiteDataStoreRef dataStoreRef, WKStringRef host, WKStringRef hostRedirectedFrom);
 WK_EXPORT void WKWebsiteDataStoreSetStatisticsTimeToLiveUserInteraction(WKWebsiteDataStoreRef dataStoreRef, double seconds);
 WK_EXPORT void WKWebsiteDataStoreSetStatisticsTimeToLiveCookiePartitionFree(WKWebsiteDataStoreRef dataStoreRef, double seconds);
 WK_EXPORT void WKWebsiteDataStoreStatisticsProcessStatisticsAndDataRecords(WKWebsiteDataStoreRef dataStoreRef);

Modified: trunk/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.cpp (228415 => 228416)


--- trunk/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.cpp	2018-02-13 04:44:21 UTC (rev 228415)
+++ trunk/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.cpp	2018-02-13 06:08:18 UTC (rev 228416)
@@ -46,8 +46,9 @@
 using namespace WebCore;
 
 constexpr unsigned operatingDatesWindow { 30 };
-constexpr unsigned statisticsModelVersion { 10 };
+constexpr unsigned statisticsModelVersion { 11 };
 constexpr unsigned maxImportance { 3 };
+constexpr unsigned maxNumberOfRecursiveCallsInRedirectTraceBack { 50 };
 
 template<typename T> static inline String isolatedPrimaryDomain(const T& value)
 {
@@ -224,6 +225,35 @@
     });
 }
 
+
+unsigned WebResourceLoadStatisticsStore::recursivelyGetAllDomainsThatHaveRedirectedToThisDomain(const WebCore::ResourceLoadStatistics& resourceStatistic, HashSet<String>& domainsThatHaveRedirectedTo, unsigned numberOfRecursiveCalls)
+{
+    if (numberOfRecursiveCalls >= maxNumberOfRecursiveCallsInRedirectTraceBack) {
+        ASSERT_NOT_REACHED();
+        WTFLogAlways("Hit %u recursive calls in redirect backtrace. Returning early.", maxNumberOfRecursiveCallsInRedirectTraceBack);
+        return numberOfRecursiveCalls;
+    }
+
+    numberOfRecursiveCalls++;
+    
+    for (auto& subresourceUniqueRedirectFromDomain : resourceStatistic.subresourceUniqueRedirectsFrom.values()) {
+        auto mapEntry = m_resourceStatisticsMap.find(subresourceUniqueRedirectFromDomain);
+        if (mapEntry == m_resourceStatisticsMap.end() || mapEntry->value.isPrevalentResource)
+            continue;
+        if (domainsThatHaveRedirectedTo.add(mapEntry->value.highLevelDomain).isNewEntry)
+            numberOfRecursiveCalls = recursivelyGetAllDomainsThatHaveRedirectedToThisDomain(mapEntry->value, domainsThatHaveRedirectedTo, numberOfRecursiveCalls);
+    }
+    for (auto& topFrameUniqueRedirectFromDomain : resourceStatistic.topFrameUniqueRedirectsFrom.values()) {
+        auto mapEntry = m_resourceStatisticsMap.find(topFrameUniqueRedirectFromDomain);
+        if (mapEntry == m_resourceStatisticsMap.end() || mapEntry->value.isPrevalentResource)
+            continue;
+        if (domainsThatHaveRedirectedTo.add(mapEntry->value.highLevelDomain).isNewEntry)
+            numberOfRecursiveCalls = recursivelyGetAllDomainsThatHaveRedirectedToThisDomain(mapEntry->value, domainsThatHaveRedirectedTo, numberOfRecursiveCalls);
+    }
+    
+    return numberOfRecursiveCalls;
+}
+
 void WebResourceLoadStatisticsStore::processStatisticsAndDataRecords()
 {
     ASSERT(!RunLoop::isMain());
@@ -231,7 +261,7 @@
     if (m_parameters.shouldClassifyResourcesBeforeDataRecordsRemoval) {
         for (auto& resourceStatistic : m_resourceStatisticsMap.values()) {
             if (!resourceStatistic.isPrevalentResource && m_resourceLoadStatisticsClassifier.hasPrevalentResourceCharacteristics(resourceStatistic))
-                resourceStatistic.isPrevalentResource = true;
+                setPrevalentResource(resourceStatistic);
         }
     }
     removeDataRecords();
@@ -448,11 +478,26 @@
         return;
 
     m_statisticsQueue->dispatch([this, protectedThis = makeRef(*this), primaryDomain = isolatedPrimaryDomain(url)] {
-        auto& statistics = ensureResourceStatisticsForPrimaryDomain(primaryDomain);
-        statistics.isPrevalentResource = true;
+        auto& resourceStatistic = ensureResourceStatisticsForPrimaryDomain(primaryDomain);
+        setPrevalentResource(resourceStatistic);
     });
 }
 
+void WebResourceLoadStatisticsStore::setPrevalentResource(WebCore::ResourceLoadStatistics& resourceStatistic)
+{
+    ASSERT(!RunLoop::isMain());
+    resourceStatistic.isPrevalentResource = true;
+    HashSet<String> domainsThatHaveRedirectedTo;
+    recursivelyGetAllDomainsThatHaveRedirectedToThisDomain(resourceStatistic, domainsThatHaveRedirectedTo, 0);
+    for (auto& domain : domainsThatHaveRedirectedTo) {
+        auto mapEntry = m_resourceStatisticsMap.find(domain);
+        if (mapEntry == m_resourceStatisticsMap.end())
+            continue;
+        ASSERT(!mapEntry->value.isPrevalentResource);
+        mapEntry->value.isPrevalentResource = true;
+    }
+}
+
 void WebResourceLoadStatisticsStore::isPrevalentResource(const URL& url, WTF::Function<void (bool)>&& completionHandler)
 {
     if (url.isBlankURL() || url.isEmpty()) {
@@ -537,6 +582,8 @@
     m_statisticsQueue->dispatch([this, protectedThis = makeRef(*this), primaryTopFrameDomain = isolatedPrimaryDomain(topFrame), primarySubFrameDomain = isolatedPrimaryDomain(subframe)] {
         auto& statistics = ensureResourceStatisticsForPrimaryDomain(primarySubFrameDomain);
         statistics.subframeUnderTopFrameOrigins.add(primaryTopFrameDomain);
+        // For consistency, make sure we also have a statistics entry for the top frame domain.
+        ensureResourceStatisticsForPrimaryDomain(primaryTopFrameDomain);
     });
 }
 
@@ -548,6 +595,8 @@
     m_statisticsQueue->dispatch([this, protectedThis = makeRef(*this), primaryTopFrameDomain = isolatedPrimaryDomain(topFrame), primarySubresourceDomain = isolatedPrimaryDomain(subresource)] {
         auto& statistics = ensureResourceStatisticsForPrimaryDomain(primarySubresourceDomain);
         statistics.subresourceUnderTopFrameOrigins.add(primaryTopFrameDomain);
+        // For consistency, make sure we also have a statistics entry for the top frame domain.
+        ensureResourceStatisticsForPrimaryDomain(primaryTopFrameDomain);
     });
 }
 
@@ -559,9 +608,50 @@
     m_statisticsQueue->dispatch([this, protectedThis = makeRef(*this), primaryRedirectDomain = isolatedPrimaryDomain(hostNameRedirectedTo), primarySubresourceDomain = isolatedPrimaryDomain(subresource)] {
         auto& statistics = ensureResourceStatisticsForPrimaryDomain(primarySubresourceDomain);
         statistics.subresourceUniqueRedirectsTo.add(primaryRedirectDomain);
+        // For consistency, make sure we also have a statistics entry for the redirect domain.
+        ensureResourceStatisticsForPrimaryDomain(primaryRedirectDomain);
     });
 }
 
+void WebResourceLoadStatisticsStore::setSubresourceUniqueRedirectFrom(const URL& subresource, const URL& hostNameRedirectedFrom)
+{
+    if (subresource.isBlankURL() || subresource.isEmpty() || hostNameRedirectedFrom.isBlankURL() || hostNameRedirectedFrom.isEmpty())
+        return;
+    
+    m_statisticsQueue->dispatch([this, protectedThis = makeRef(*this), primaryRedirectDomain = isolatedPrimaryDomain(hostNameRedirectedFrom), primarySubresourceDomain = isolatedPrimaryDomain(subresource)] {
+        auto& statistics = ensureResourceStatisticsForPrimaryDomain(primarySubresourceDomain);
+        statistics.subresourceUniqueRedirectsFrom.add(primaryRedirectDomain);
+        // For consistency, make sure we also have a statistics entry for the redirect domain.
+        ensureResourceStatisticsForPrimaryDomain(primaryRedirectDomain);
+    });
+}
+
+void WebResourceLoadStatisticsStore::setTopFrameUniqueRedirectTo(const URL& topFrameHostName, const URL& hostNameRedirectedTo)
+{
+    if (topFrameHostName.isBlankURL() || topFrameHostName.isEmpty() || hostNameRedirectedTo.isBlankURL() || hostNameRedirectedTo.isEmpty())
+        return;
+    
+    m_statisticsQueue->dispatch([this, protectedThis = makeRef(*this), primaryRedirectDomain = isolatedPrimaryDomain(hostNameRedirectedTo), topFramePrimaryDomain = isolatedPrimaryDomain(topFrameHostName)] {
+        auto& statistics = ensureResourceStatisticsForPrimaryDomain(topFramePrimaryDomain);
+        statistics.topFrameUniqueRedirectsTo.add(primaryRedirectDomain);
+        // For consistency, make sure we also have a statistics entry for the redirect domain.
+        ensureResourceStatisticsForPrimaryDomain(primaryRedirectDomain);
+    });
+}
+
+void WebResourceLoadStatisticsStore::setTopFrameUniqueRedirectFrom(const URL& topFrameHostName, const URL& hostNameRedirectedFrom)
+{
+    if (topFrameHostName.isBlankURL() || topFrameHostName.isEmpty() || hostNameRedirectedFrom.isBlankURL() || hostNameRedirectedFrom.isEmpty())
+        return;
+    
+    m_statisticsQueue->dispatch([this, protectedThis = makeRef(*this), primaryRedirectDomain = isolatedPrimaryDomain(hostNameRedirectedFrom), topFramePrimaryDomain = isolatedPrimaryDomain(topFrameHostName)] {
+        auto& statistics = ensureResourceStatisticsForPrimaryDomain(topFramePrimaryDomain);
+        statistics.topFrameUniqueRedirectsFrom.add(primaryRedirectDomain);
+        // For consistency, make sure we also have a statistics entry for the redirect domain.
+        ensureResourceStatisticsForPrimaryDomain(primaryRedirectDomain);
+    });
+}
+
 void WebResourceLoadStatisticsStore::scheduleCookiePartitioningUpdate(CompletionHandler<void()>&& callback)
 {
     // Helper function used by testing system. Should only be called from the main thread.

Modified: trunk/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.h (228415 => 228416)


--- trunk/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.h	2018-02-13 04:44:21 UTC (rev 228415)
+++ trunk/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.h	2018-02-13 06:08:18 UTC (rev 228416)
@@ -106,6 +106,9 @@
     void setSubframeUnderTopFrameOrigin(const WebCore::URL& subframe, const WebCore::URL& topFrame);
     void setSubresourceUnderTopFrameOrigin(const WebCore::URL& subresource, const WebCore::URL& topFrame);
     void setSubresourceUniqueRedirectTo(const WebCore::URL& subresource, const WebCore::URL& hostNameRedirectedTo);
+    void setSubresourceUniqueRedirectFrom(const WebCore::URL& subresource, const WebCore::URL& hostNameRedirectedFrom);
+    void setTopFrameUniqueRedirectTo(const WebCore::URL& topFrameHostName, const WebCore::URL& hostNameRedirectedTo);
+    void setTopFrameUniqueRedirectFrom(const WebCore::URL& topFrameHostName, const WebCore::URL& hostNameRedirectedFrom);
     void scheduleCookiePartitioningUpdate(CompletionHandler<void()>&&);
     void scheduleCookiePartitioningUpdateForDomains(const Vector<String>& domainsToPartition, const Vector<String>& domainsToBlock, const Vector<String>& domainsToNeitherPartitionNorBlock, ShouldClearFirst, CompletionHandler<void()>&&);
     void scheduleClearPartitioningStateForDomains(const Vector<String>& domains, CompletionHandler<void()>&&);
@@ -167,6 +170,8 @@
     void clearPartitioningStateForDomains(const Vector<String>& domains, CompletionHandler<void()>&&);
     void mergeStatistics(Vector<WebCore::ResourceLoadStatistics>&&);
     WebCore::ResourceLoadStatistics& ensureResourceStatisticsForPrimaryDomain(const String&);
+    unsigned recursivelyGetAllDomainsThatHaveRedirectedToThisDomain(const WebCore::ResourceLoadStatistics&, HashSet<String>& domainsThatHaveRedirectedTo, unsigned numberOfRecursiveCalls);
+    void setPrevalentResource(WebCore::ResourceLoadStatistics&);
     void processStatisticsAndDataRecords();
 
     void resetCookiePartitioningState();

Modified: trunk/Tools/ChangeLog (228415 => 228416)


--- trunk/Tools/ChangeLog	2018-02-13 04:44:21 UTC (rev 228415)
+++ trunk/Tools/ChangeLog	2018-02-13 06:08:18 UTC (rev 228416)
@@ -1,3 +1,25 @@
+2018-02-12  John Wilander  <wilan...@apple.com>
+
+        Resource Load Statistics: Classify resources as prevalent based on redirects to other prevalent resources
+        https://bugs.webkit.org/show_bug.cgi?id=182664
+        <rdar://problem/37372572>
+
+        Reviewed by Brent Fulgham.
+
+        * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
+        * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+        (WTR::TestRunner::setStatisticsSubresourceUniqueRedirectFrom):
+        (WTR::TestRunner::setStatisticsTopFrameUniqueRedirectTo):
+        (WTR::TestRunner::setStatisticsTopFrameUniqueRedirectFrom):
+        * WebKitTestRunner/InjectedBundle/TestRunner.h:
+        * WebKitTestRunner/TestController.cpp:
+        (WTR::TestController::setStatisticsSubresourceUniqueRedirectFrom):
+        (WTR::TestController::setStatisticsTopFrameUniqueRedirectTo):
+        (WTR::TestController::setStatisticsTopFrameUniqueRedirectFrom):
+        * WebKitTestRunner/TestController.h:
+        * WebKitTestRunner/TestInvocation.cpp:
+        (WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):
+
 2018-02-12  Ross Kirsling  <ross.kirsl...@sony.com>
 
         download-latest-github-release .py should not use "browser download URL".

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl (228415 => 228416)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl	2018-02-13 04:44:21 UTC (rev 228415)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl	2018-02-13 06:08:18 UTC (rev 228416)
@@ -278,6 +278,9 @@
     void setStatisticsSubframeUnderTopFrameOrigin(DOMString hostName, DOMString topFrameHostName);
     void setStatisticsSubresourceUnderTopFrameOrigin(DOMString hostName, DOMString topFrameHostName);
     void setStatisticsSubresourceUniqueRedirectTo(DOMString hostName, DOMString hostNameRedirectedTo);
+    void setStatisticsSubresourceUniqueRedirectFrom(DOMString hostName, DOMString hostNameRedirectedTo);
+    void setStatisticsTopFrameUniqueRedirectTo(DOMString hostName, DOMString hostNameRedirectedTo);
+    void setStatisticsTopFrameUniqueRedirectFrom(DOMString hostName, DOMString hostNameRedirectedTo);
     void setStatisticsTimeToLiveUserInteraction(double seconds);
     void setStatisticsTimeToLiveCookiePartitionFree(double seconds);
     void statisticsNotifyObserver();

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp (228415 => 228416)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp	2018-02-13 04:44:21 UTC (rev 228415)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp	2018-02-13 06:08:18 UTC (rev 228416)
@@ -1477,6 +1477,80 @@
     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
 }
 
+
+void TestRunner::setStatisticsSubresourceUniqueRedirectFrom(JSStringRef hostName, JSStringRef hostNameRedirectedFrom)
+{
+    Vector<WKRetainPtr<WKStringRef>> keys;
+    Vector<WKRetainPtr<WKTypeRef>> values;
+    
+    keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
+    values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
+    
+    keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostNameRedirectedFrom") });
+    values.append({ AdoptWK, WKStringCreateWithJSString(hostNameRedirectedFrom) });
+    
+    Vector<WKStringRef> rawKeys(keys.size());
+    Vector<WKTypeRef> rawValues(values.size());
+    
+    for (size_t i = 0; i < keys.size(); ++i) {
+        rawKeys[i] = keys[i].get();
+        rawValues[i] = values[i].get();
+    }
+    
+    WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsSubresourceUniqueRedirectFrom"));
+    WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
+    WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
+}
+
+void TestRunner::setStatisticsTopFrameUniqueRedirectTo(JSStringRef hostName, JSStringRef hostNameRedirectedTo)
+{
+    Vector<WKRetainPtr<WKStringRef>> keys;
+    Vector<WKRetainPtr<WKTypeRef>> values;
+    
+    keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
+    values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
+    
+    keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostNameRedirectedTo") });
+    values.append({ AdoptWK, WKStringCreateWithJSString(hostNameRedirectedTo) });
+    
+    Vector<WKStringRef> rawKeys(keys.size());
+    Vector<WKTypeRef> rawValues(values.size());
+    
+    for (size_t i = 0; i < keys.size(); ++i) {
+        rawKeys[i] = keys[i].get();
+        rawValues[i] = values[i].get();
+    }
+    
+    WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsTopFrameUniqueRedirectTo"));
+    WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
+    WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
+}
+
+void TestRunner::setStatisticsTopFrameUniqueRedirectFrom(JSStringRef hostName, JSStringRef hostNameRedirectedFrom)
+{
+    Vector<WKRetainPtr<WKStringRef>> keys;
+    Vector<WKRetainPtr<WKTypeRef>> values;
+    
+    keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") });
+    values.append({ AdoptWK, WKStringCreateWithJSString(hostName) });
+    
+    keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostNameRedirectedFrom") });
+    values.append({ AdoptWK, WKStringCreateWithJSString(hostNameRedirectedFrom) });
+    
+    Vector<WKStringRef> rawKeys(keys.size());
+    Vector<WKTypeRef> rawValues(values.size());
+    
+    for (size_t i = 0; i < keys.size(); ++i) {
+        rawKeys[i] = keys[i].get();
+        rawValues[i] = values[i].get();
+    }
+    
+    WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsTopFrameUniqueRedirectFrom"));
+    WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size()));
+    WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
+}
+
+
 void TestRunner::setStatisticsTimeToLiveUserInteraction(double seconds)
 {
     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsTimeToLiveUserInteraction"));

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h (228415 => 228416)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h	2018-02-13 04:44:21 UTC (rev 228415)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h	2018-02-13 06:08:18 UTC (rev 228416)
@@ -383,6 +383,9 @@
     void setStatisticsSubframeUnderTopFrameOrigin(JSStringRef hostName, JSStringRef topFrameHostName);
     void setStatisticsSubresourceUnderTopFrameOrigin(JSStringRef hostName, JSStringRef topFrameHostName);
     void setStatisticsSubresourceUniqueRedirectTo(JSStringRef hostName, JSStringRef hostNameRedirectedTo);
+    void setStatisticsSubresourceUniqueRedirectFrom(JSStringRef hostName, JSStringRef hostNameRedirectedFrom);
+    void setStatisticsTopFrameUniqueRedirectTo(JSStringRef hostName, JSStringRef hostNameRedirectedTo);
+    void setStatisticsTopFrameUniqueRedirectFrom(JSStringRef hostName, JSStringRef hostNameRedirectedFrom);
     void setStatisticsTimeToLiveUserInteraction(double seconds);
     void setStatisticsTimeToLiveCookiePartitionFree(double seconds);
     void setStatisticsNotifyPagesWhenDataRecordsWereScanned(bool);

Modified: trunk/Tools/WebKitTestRunner/TestController.cpp (228415 => 228416)


--- trunk/Tools/WebKitTestRunner/TestController.cpp	2018-02-13 04:44:21 UTC (rev 228415)
+++ trunk/Tools/WebKitTestRunner/TestController.cpp	2018-02-13 06:08:18 UTC (rev 228416)
@@ -2596,6 +2596,24 @@
     WKWebsiteDataStoreSetStatisticsSubresourceUniqueRedirectTo(dataStore, host, hostRedirectedTo);
 }
 
+void TestController::setStatisticsSubresourceUniqueRedirectFrom(WKStringRef host, WKStringRef hostRedirectedFrom)
+{
+    auto* dataStore = WKContextGetWebsiteDataStore(platformContext());
+    WKWebsiteDataStoreSetStatisticsSubresourceUniqueRedirectFrom(dataStore, host, hostRedirectedFrom);
+}
+
+void TestController::setStatisticsTopFrameUniqueRedirectTo(WKStringRef host, WKStringRef hostRedirectedTo)
+{
+    auto* dataStore = WKContextGetWebsiteDataStore(platformContext());
+    WKWebsiteDataStoreSetStatisticsTopFrameUniqueRedirectTo(dataStore, host, hostRedirectedTo);
+}
+
+void TestController::setStatisticsTopFrameUniqueRedirectFrom(WKStringRef host, WKStringRef hostRedirectedFrom)
+{
+    auto* dataStore = WKContextGetWebsiteDataStore(platformContext());
+    WKWebsiteDataStoreSetStatisticsTopFrameUniqueRedirectFrom(dataStore, host, hostRedirectedFrom);
+}
+
 void TestController::setStatisticsTimeToLiveUserInteraction(double seconds)
 {
     auto* dataStore = WKContextGetWebsiteDataStore(platformContext());

Modified: trunk/Tools/WebKitTestRunner/TestController.h (228415 => 228416)


--- trunk/Tools/WebKitTestRunner/TestController.h	2018-02-13 04:44:21 UTC (rev 228415)
+++ trunk/Tools/WebKitTestRunner/TestController.h	2018-02-13 06:08:18 UTC (rev 228416)
@@ -166,6 +166,9 @@
     void setStatisticsSubframeUnderTopFrameOrigin(WKStringRef hostName, WKStringRef topFrameHostName);
     void setStatisticsSubresourceUnderTopFrameOrigin(WKStringRef hostName, WKStringRef topFrameHostName);
     void setStatisticsSubresourceUniqueRedirectTo(WKStringRef hostName, WKStringRef hostNameRedirectedTo);
+    void setStatisticsSubresourceUniqueRedirectFrom(WKStringRef host, WKStringRef hostRedirectedFrom);
+    void setStatisticsTopFrameUniqueRedirectTo(WKStringRef host, WKStringRef hostRedirectedTo);
+    void setStatisticsTopFrameUniqueRedirectFrom(WKStringRef host, WKStringRef hostRedirectedFrom);
     void setStatisticsTimeToLiveUserInteraction(double seconds);
     void setStatisticsTimeToLiveCookiePartitionFree(double seconds);
     void statisticsProcessStatisticsAndDataRecords();

Modified: trunk/Tools/WebKitTestRunner/TestInvocation.cpp (228415 => 228416)


--- trunk/Tools/WebKitTestRunner/TestInvocation.cpp	2018-02-13 04:44:21 UTC (rev 228415)
+++ trunk/Tools/WebKitTestRunner/TestInvocation.cpp	2018-02-13 06:08:18 UTC (rev 228416)
@@ -1107,6 +1107,48 @@
         return nullptr;
     }
 
+    if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsSubresourceUniqueRedirectFrom")) {
+        ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
+        
+        WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
+        WKRetainPtr<WKStringRef> hostNameKey(AdoptWK, WKStringCreateWithUTF8CString("HostName"));
+        WKRetainPtr<WKStringRef> hostNameRedirectedFromKey(AdoptWK, WKStringCreateWithUTF8CString("HostNameRedirectedFrom"));
+        
+        WKStringRef hostName = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, hostNameKey.get()));
+        WKStringRef hostNameRedirectedFrom = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, hostNameRedirectedFromKey.get()));
+        
+        TestController::singleton().setStatisticsSubresourceUniqueRedirectFrom(hostName, hostNameRedirectedFrom);
+        return nullptr;
+    }
+    
+    if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsTopFrameUniqueRedirectTo")) {
+        ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
+        
+        WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
+        WKRetainPtr<WKStringRef> hostNameKey(AdoptWK, WKStringCreateWithUTF8CString("HostName"));
+        WKRetainPtr<WKStringRef> hostNameRedirectedToKey(AdoptWK, WKStringCreateWithUTF8CString("HostNameRedirectedTo"));
+        
+        WKStringRef hostName = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, hostNameKey.get()));
+        WKStringRef hostNameRedirectedTo = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, hostNameRedirectedToKey.get()));
+        
+        TestController::singleton().setStatisticsTopFrameUniqueRedirectTo(hostName, hostNameRedirectedTo);
+        return nullptr;
+    }
+    
+    if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsTopFrameUniqueRedirectFrom")) {
+        ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
+        
+        WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
+        WKRetainPtr<WKStringRef> hostNameKey(AdoptWK, WKStringCreateWithUTF8CString("HostName"));
+        WKRetainPtr<WKStringRef> hostNameRedirectedFromKey(AdoptWK, WKStringCreateWithUTF8CString("HostNameRedirectedFrom"));
+        
+        WKStringRef hostName = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, hostNameKey.get()));
+        WKStringRef hostNameRedirectedFrom = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, hostNameRedirectedFromKey.get()));
+        
+        TestController::singleton().setStatisticsTopFrameUniqueRedirectFrom(hostName, hostNameRedirectedFrom);
+        return nullptr;
+    }
+    
     if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsTimeToLiveUserInteraction")) {
         ASSERT(WKGetTypeID(messageBody) == WKDoubleGetTypeID());
         WKDoubleRef seconds = static_cast<WKDoubleRef>(messageBody);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to