Reset cookie partitioning state after network process crashes
authorbfulgham@apple.com <bfulgham@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 11 Jul 2017 18:57:20 +0000 (18:57 +0000)
committerbfulgham@apple.com <bfulgham@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 11 Jul 2017 18:57:20 +0000 (18:57 +0000)
https://bugs.webkit.org/show_bug.cgi?id=174306
<rdar://problem/33171605>

Reviewed by Chris Dumez.

Source/WebKit2:

* UIProcess/Storage/ResourceLoadStatisticsStore.cpp:
(WebKit::ResourceLoadStatisticsStore::fireShouldPartitionCookiesHandler): Move cookie
partioning state code to helper function.
(WebKit::ResourceLoadStatisticsStore::resetPartitionCookiesState): Added.
* UIProcess/Storage/ResourceLoadStatisticsStore.h:
* UIProcess/WebProcessPool.cpp:
(WebKit::WebProcessPool::ensureNetworkProcess): Inform the statistics store that
the network process crashed.
(WebKit::WebProcessPool::terminateNetworkProcess): Mark network process as crashed.
* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::networkProcessDidCrash): Reset the cookie
partitioning state after a crash.
* UIProcess/WebResourceLoadStatisticsStore.h:
* UIProcess/WebsiteData/WebsiteDataStore.cpp:
(WebKit::WebsiteDataStore::notifyResourceLoadStatisticsNetworkProcessDidCrash): Relay
information to the statistics store.
* UIProcess/WebsiteData/WebsiteDataStore.h:

LayoutTests:

* http/tests/loading/resourceLoadStatistics/partitioned-and-unpartitioned-cookie-with-network-process-crash-expected.txt: Added.
* http/tests/loading/resourceLoadStatistics/partitioned-and-unpartitioned-cookie-with-network-process-crash.html: Added.
* http/tests/loading/resourceLoadStatistics/resources/get-cookies.php:
* http/tests/loading/resourceLoadStatistics/resources/set-cookie.php:

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

LayoutTests/ChangeLog
LayoutTests/http/tests/loading/resourceLoadStatistics/partitioned-and-unpartitioned-cookie-with-network-process-crash-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/loading/resourceLoadStatistics/partitioned-and-unpartitioned-cookie-with-network-process-crash.html [new file with mode: 0644]
LayoutTests/http/tests/loading/resourceLoadStatistics/resources/get-cookies.php
LayoutTests/http/tests/loading/resourceLoadStatistics/resources/set-cookie.php
Source/WebKit2/ChangeLog
Source/WebKit2/UIProcess/WebProcessPool.cpp
Source/WebKit2/UIProcess/WebResourceLoadStatisticsStore.cpp
Source/WebKit2/UIProcess/WebResourceLoadStatisticsStore.h
Source/WebKit2/UIProcess/WebsiteData/WebsiteDataStore.cpp
Source/WebKit2/UIProcess/WebsiteData/WebsiteDataStore.h

index 9a13c86..5c79b48 100644 (file)
@@ -1,3 +1,16 @@
+2017-07-11  Brent Fulgham  <bfulgham@apple.com>
+
+        Reset cookie partitioning state after network process crashes
+        https://bugs.webkit.org/show_bug.cgi?id=174306
+        <rdar://problem/33171605>
+
+        Reviewed by Chris Dumez.
+
+        * http/tests/loading/resourceLoadStatistics/partitioned-and-unpartitioned-cookie-with-network-process-crash-expected.txt: Added.
+        * http/tests/loading/resourceLoadStatistics/partitioned-and-unpartitioned-cookie-with-network-process-crash.html: Added.
+        * http/tests/loading/resourceLoadStatistics/resources/get-cookies.php:
+        * http/tests/loading/resourceLoadStatistics/resources/set-cookie.php:
+
 2017-07-11  Charlie Turner  <cturner@igalia.com>
 
         REGRESSION(r219298): [GTK] imported/w3c/IndexedDB-private-browsing/idbfactory_open.html is crashing occassionaly
diff --git a/LayoutTests/http/tests/loading/resourceLoadStatistics/partitioned-and-unpartitioned-cookie-with-network-process-crash-expected.txt b/LayoutTests/http/tests/loading/resourceLoadStatistics/partitioned-and-unpartitioned-cookie-with-network-process-crash-expected.txt
new file mode 100644 (file)
index 0000000..ea64528
--- /dev/null
@@ -0,0 +1,83 @@
+main frame - didStartProvisionalLoadForFrame
+main frame - didCommitLoadForFrame
+main frame - didReceiveTitle: Test for Partitioned and Unpartitioned Cookie Deletion
+main frame - didChangeLocationWithinPageForFrame
+main frame - willPerformClientRedirectToURL: http://localhost:8000/loading/resourceLoadStatistics/resources/set-cookie.php?name=firstPartyCookie&value=value#http://127.0.0.1:8000/loading/resourceLoadStatistics/partitioned-and-unpartitioned-cookie-with-network-process-crash.html#step2 
+main frame - didFinishDocumentLoadForFrame
+main frame - didFinishLoadForFrame
+main frame - didStartProvisionalLoadForFrame
+main frame - didCancelClientRedirectForFrame
+main frame - didCommitLoadForFrame
+main frame - didFinishDocumentLoadForFrame
+main frame - didHandleOnloadEventsForFrame
+main frame - didFinishLoadForFrame
+main frame - willPerformClientRedirectToURL: http://127.0.0.1:8000/loading/resourceLoadStatistics/partitioned-and-unpartitioned-cookie-with-network-process-crash.html#step2 
+main frame - didStartProvisionalLoadForFrame
+main frame - didCancelClientRedirectForFrame
+main frame - didCommitLoadForFrame
+main frame - didReceiveTitle: Test for Partitioned and Unpartitioned Cookie Deletion
+main frame - didChangeLocationWithinPageForFrame
+frame "<!--framePath //<!--frame0-->-->" - didStartProvisionalLoadForFrame
+main frame - didFinishDocumentLoadForFrame
+frame "<!--framePath //<!--frame0-->-->" - didCommitLoadForFrame
+frame "<!--framePath //<!--frame0-->-->" - didFinishDocumentLoadForFrame
+main frame - didHandleOnloadEventsForFrame
+main frame - didChangeLocationWithinPageForFrame
+frame "<!--framePath //<!--frame1-->-->" - didStartProvisionalLoadForFrame
+frame "<!--framePath //<!--frame0-->-->" - didHandleOnloadEventsForFrame
+frame "<!--framePath //<!--frame0-->-->" - didFinishLoadForFrame
+frame "<!--framePath //<!--frame1-->-->" - didCommitLoadForFrame
+frame "<!--framePath //<!--frame1-->-->" - didFinishDocumentLoadForFrame
+main frame - didChangeLocationWithinPageForFrame
+frame "<!--framePath //<!--frame2-->-->" - didStartProvisionalLoadForFrame
+frame "<!--framePath //<!--frame1-->-->" - didHandleOnloadEventsForFrame
+frame "<!--framePath //<!--frame1-->-->" - didFinishLoadForFrame
+frame "<!--framePath //<!--frame2-->-->" - didCommitLoadForFrame
+frame "<!--framePath //<!--frame2-->-->" - didFinishDocumentLoadForFrame
+main frame - didChangeLocationWithinPageForFrame
+frame "<!--framePath //<!--frame2-->-->" - didHandleOnloadEventsForFrame
+frame "<!--framePath //<!--frame2-->-->" - didFinishLoadForFrame
+main frame - didFinishLoadForFrame
+main frame - didChangeLocationWithinPageForFrame
+main frame - willPerformClientRedirectToURL: http://localhost:8000/loading/resourceLoadStatistics/resources/set-cookie.php?name=firstPartyCookie&value=value#http://127.0.0.1:8000/loading/resourceLoadStatistics/partitioned-and-unpartitioned-cookie-with-network-process-crash.html#step8 
+main frame - didStartProvisionalLoadForFrame
+main frame - didCancelClientRedirectForFrame
+main frame - didCommitLoadForFrame
+main frame - didFinishDocumentLoadForFrame
+main frame - didHandleOnloadEventsForFrame
+main frame - didFinishLoadForFrame
+main frame - willPerformClientRedirectToURL: http://127.0.0.1:8000/loading/resourceLoadStatistics/partitioned-and-unpartitioned-cookie-with-network-process-crash.html#step8 
+main frame - didStartProvisionalLoadForFrame
+main frame - didCancelClientRedirectForFrame
+main frame - didCommitLoadForFrame
+main frame - didReceiveTitle: Test for Partitioned and Unpartitioned Cookie Deletion
+main frame - didChangeLocationWithinPageForFrame
+frame "<!--framePath //<!--frame0-->-->" - didStartProvisionalLoadForFrame
+main frame - didFinishDocumentLoadForFrame
+frame "<!--framePath //<!--frame0-->-->" - didCommitLoadForFrame
+frame "<!--framePath //<!--frame0-->-->" - didFinishDocumentLoadForFrame
+frame "<!--framePath //<!--frame1-->-->" - didStartProvisionalLoadForFrame
+frame "<!--framePath //<!--frame0-->-->" - didHandleOnloadEventsForFrame
+frame "<!--framePath //<!--frame0-->-->" - didFinishLoadForFrame
+frame "<!--framePath //<!--frame1-->-->" - didCommitLoadForFrame
+frame "<!--framePath //<!--frame1-->-->" - didFinishDocumentLoadForFrame
+frame "<!--framePath //<!--frame1-->-->" - didHandleOnloadEventsForFrame
+main frame - didHandleOnloadEventsForFrame
+frame "<!--framePath //<!--frame1-->-->" - didFinishLoadForFrame
+main frame - didFinishLoadForFrame
+  
+
+--------
+Frame: '<!--framePath //<!--frame0-->-->'
+--------
+Setting second partitioned, third party cookie.
+
+
+--------
+Frame: '<!--framePath //<!--frame1-->-->'
+--------
+After network process crash, should only receive second partitioned, third party cookie.
+Received cookie named 'firstPartyCookie'.
+Did not receive cookie named 'firstThirdPartyCookie'.
+Received cookie named 'secondThirdPartyCookie'.
+Client-side document.cookie: firstPartyCookie=value; secondThirdPartyCookie=value
diff --git a/LayoutTests/http/tests/loading/resourceLoadStatistics/partitioned-and-unpartitioned-cookie-with-network-process-crash.html b/LayoutTests/http/tests/loading/resourceLoadStatistics/partitioned-and-unpartitioned-cookie-with-network-process-crash.html
new file mode 100644 (file)
index 0000000..13b8332
--- /dev/null
@@ -0,0 +1,115 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Test for Partitioned and Unpartitioned Cookie Deletion</title>
+    <script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script>
+    const partitionHost = "127.0.0.1:8000";
+    const thirdPartyOrigin = "http://localhost:8000";
+    const thirdPartyBaseUrl = thirdPartyOrigin + "/loading/resourceLoadStatistics/resources";
+    const firstPartyCookieName = "firstPartyCookie";
+    const subPathToSetFirstPartyCookie = "/set-cookie.php?name=" + firstPartyCookieName + "&value=value";
+    const firstThirdPartyCookieName = "firstThirdPartyCookie";
+    const secondThirdPartyCookieName = "secondThirdPartyCookie";
+    const subPathToSetFirstThirdPartyCookie = "/set-cookie.php?name=" + firstThirdPartyCookieName + "&value=value";
+    const subPathToSetSecondThirdPartyCookie = "/set-cookie.php?name=" + secondThirdPartyCookieName + "&value=value";
+    const fragmentWithReturnUrl = "http://" + partitionHost + "/loading/resourceLoadStatistics/partitioned-and-unpartitioned-cookie-with-network-process-crash.html";
+    const subPathToGetCookies = "/get-cookies.php?name1=" + firstPartyCookieName + "&name2=" + firstThirdPartyCookieName + "&name3=" + secondThirdPartyCookieName;
+
+    function finishTest() {
+        testRunner.notifyDone();
+    }
+
+    function openIframe(url, onLoadHandler) {
+        const element = document.createElement("iframe");
+        element.src = url;
+        if (onLoadHandler) {
+            element.onload = onLoadHandler;
+        }
+        document.body.appendChild(element);
+    }
+
+    function terminateNetworkProcessAndContinue() {
+        if (window.testRunner && window.testRunner.terminateNetworkProcess) {
+            testRunner.terminateNetworkProcess();
+            setTimeout(runTest, 1000);
+        } else {
+            testFailed("Could not terminate network process.");
+            finishTest();
+        }
+    }
+
+    function runTest() {
+        switch (document.location.hash) {
+            case "#step1":
+                // Set first-party cookie for prevalent resource.
+                document.location.href = thirdPartyBaseUrl + subPathToSetFirstPartyCookie + "#" + fragmentWithReturnUrl + "#step2";
+                break;
+            case "#step2":
+                // No cookie should be sent under partition.
+                document.location.hash = "step3";
+                openIframe(thirdPartyBaseUrl + subPathToGetCookies + "&message=Should receive no cookies.", runTest);
+                break;
+            case "#step3":
+                // Set first cookie under partition.
+                document.location.hash = "step4";
+                openIframe(thirdPartyBaseUrl + subPathToSetFirstThirdPartyCookie + "&message=Setting first partitioned, third party cookie.", runTest);
+                break;
+            case "#step4":
+                // Only first partitioned cookie should be sent under partition.
+                document.location.hash = "step5";
+                openIframe(thirdPartyBaseUrl + subPathToGetCookies + "&message=Should only receive first partitioned, third party cookie.", runTest);
+                break;
+            case "#step5":
+                // Crash (terminate) network process.
+                document.location.hash = "step6";
+                terminateNetworkProcessAndContinue();
+                break;
+            case "#step6":
+                // Fire data modification handler to again propagate partitioning info to the network process.
+                document.location.hash = "step7";
+                testRunner.setStatisticsNotifyPagesWhenDataRecordsWereScanned(true);
+                testRunner.installStatisticsDidScanDataRecordsCallback(function() {
+                    runTest();
+                });
+                if (!testRunner.isStatisticsPrevalentResource("http://localhost"))
+                    testFailed("Host was no longer prevalent resource.");
+                testRunner.statisticsFireDataModificationHandler();
+                break;
+            case "#step7":
+                // Set first-party cookie for prevalent resource.
+                document.location.href = thirdPartyBaseUrl + subPathToSetFirstPartyCookie + "#" + fragmentWithReturnUrl + "#step8";
+                break;
+            case "#step8":
+                // Set second cookie under partition.
+                document.location.hash = "step9";
+                openIframe(thirdPartyBaseUrl + subPathToSetSecondThirdPartyCookie + "&message=Setting second partitioned, third party cookie.", runTest);
+                break;
+            case "#step9":
+                // Only second partitioned cookie should be sent under partition.
+                openIframe(thirdPartyBaseUrl + subPathToGetCookies + "&message=After network process crash, should only receive second partitioned, third party cookie.", finishTest);
+                break;
+        }
+    }
+
+    if (document.location.host === partitionHost && document.location.hash === "" && window.testRunner && window.internals) {
+
+        testRunner.statisticsFireShouldPartitionCookiesHandlerForOneDomain("localhost", true);
+        testRunner.setStatisticsPrevalentResource("http://localhost", true);
+        if (!testRunner.isStatisticsPrevalentResource("http://localhost"))
+            testFailed("Host did not get set as prevalent resource.");
+
+        testRunner.setStatisticsShouldClassifyResourcesBeforeDataRecordsRemoval(false);
+
+        testRunner.waitUntilDone();
+        testRunner.dumpChildFramesAsText();
+        document.location.hash = "step1";
+    }
+
+    runTest();
+</script>
+</body>
+</html>
\ No newline at end of file
index 1845889..dad8b5a 100644 (file)
@@ -10,6 +10,13 @@ if(!isset($_COOKIE[$_GET["name2"]])) {
 } else {
     echo "Received cookie named '" . $_GET["name2"] . "'.<br>";
 }
+if(!empty($_GET["name3"])) {
+    if(!isset($_COOKIE[$_GET["name3"]])) {
+        echo "Did not receive cookie named '" . $_GET["name3"] . "'.<br>";
+    } else {
+        echo "Received cookie named '" . $_GET["name3"] . "'.<br>";
+    }
+}
 ?>
 <p id="output"></p>
 <script>
index 0a2d892..3339e9b 100644 (file)
@@ -1,5 +1,5 @@
 <?php
-setcookie($_GET["name"], $_GET["value"], 0, "/");
+setcookie($_GET["name"], $_GET["value"], (time()+60*60*24*30), "/");
 echo $_GET["message"] . "<br>";
 ?>
 <script>
index 58f425d..a544ecb 100644 (file)
@@ -1,3 +1,29 @@
+2017-07-11  Brent Fulgham  <bfulgham@apple.com>
+
+        Reset cookie partitioning state after network process crashes
+        https://bugs.webkit.org/show_bug.cgi?id=174306
+        <rdar://problem/33171605>
+
+        Reviewed by Chris Dumez.
+
+        * UIProcess/Storage/ResourceLoadStatisticsStore.cpp:
+        (WebKit::ResourceLoadStatisticsStore::fireShouldPartitionCookiesHandler): Move cookie
+        partioning state code to helper function.
+        (WebKit::ResourceLoadStatisticsStore::resetPartitionCookiesState): Added.
+        * UIProcess/Storage/ResourceLoadStatisticsStore.h:
+        * UIProcess/WebProcessPool.cpp:
+        (WebKit::WebProcessPool::ensureNetworkProcess): Inform the statistics store that
+        the network process crashed.
+        (WebKit::WebProcessPool::terminateNetworkProcess): Mark network process as crashed.
+        * UIProcess/WebResourceLoadStatisticsStore.cpp:
+        (WebKit::WebResourceLoadStatisticsStore::networkProcessDidCrash): Reset the cookie
+        partitioning state after a crash.
+        * UIProcess/WebResourceLoadStatisticsStore.h:
+        * UIProcess/WebsiteData/WebsiteDataStore.cpp:
+        (WebKit::WebsiteDataStore::notifyResourceLoadStatisticsNetworkProcessDidCrash): Relay
+        information to the statistics store.
+        * UIProcess/WebsiteData/WebsiteDataStore.h:
+
 2017-07-11  Timothy Hatcher  <timothy@hatcher.name>
 
         Fix broken build when !ENABLE(INDEXED_DATABASE)
index 6fb1ce1..ce83605 100644 (file)
@@ -482,6 +482,7 @@ NetworkProcessProxy& WebProcessPool::ensureNetworkProcess(WebsiteDataStore* with
         m_didNetworkProcessCrash = false;
         for (auto& process : m_processes)
             process->reinstateNetworkProcessAssertionState(*m_networkProcess);
+        websiteDataStore().websiteDataStore().networkProcessDidCrash();
     }
 
     if (withWebsiteDataStore)
@@ -1357,6 +1358,7 @@ void WebProcessPool::terminateNetworkProcess()
     
     m_networkProcess->terminate();
     m_networkProcess = nullptr;
+    m_didNetworkProcessCrash = true;
 }
 
 void WebProcessPool::syncNetworkProcessCookies()
index 0a953a8..e20a8be 100644 (file)
@@ -631,6 +631,15 @@ void WebResourceLoadStatisticsStore::scheduleCookiePartitioningUpdateForDomains(
     });
 }
 
+#if HAVE(CFNETWORK_STORAGE_PARTITIONING)
+void WebResourceLoadStatisticsStore::scheduleCookiePartitioningStateReset()
+{
+    m_statisticsQueue->dispatch([this, protectedThis = makeRef(*this)] {
+        resetCookiePartitioningState();
+    });
+}
+#endif
+
 void WebResourceLoadStatisticsStore::scheduleClearInMemory()
 {
     ASSERT(RunLoop::isMain());
@@ -836,10 +845,9 @@ void WebResourceLoadStatisticsStore::updateCookiePartitioningForDomains(const Ve
         m_updateCookiePartitioningForDomainsHandler(domainsToRemove, domainsToAdd, shouldClearFirst);
     });
 
-    if (shouldClearFirst == ShouldClearFirst::Yes) {
-        for (auto& resourceStatistic : m_resourceStatisticsMap.values())
-            resourceStatistic.isMarkedForCookiePartitioning = false;
-    } else {
+    if (shouldClearFirst == ShouldClearFirst::Yes)
+        resetCookiePartitioningState();
+    else {
         for (auto& domain : domainsToRemove)
             ensureResourceStatisticsForPrimaryDomain(domain).isMarkedForCookiePartitioning = false;
     }
@@ -847,7 +855,14 @@ void WebResourceLoadStatisticsStore::updateCookiePartitioningForDomains(const Ve
     for (auto& domain : domainsToAdd)
         ensureResourceStatisticsForPrimaryDomain(domain).isMarkedForCookiePartitioning = true;
 }
-    
+
+void WebResourceLoadStatisticsStore::resetCookiePartitioningState()
+{
+    ASSERT(!RunLoop::isMain());
+    for (auto& resourceStatistic : m_resourceStatisticsMap.values())
+        resourceStatistic.isMarkedForCookiePartitioning = false;
+}
+
 void WebResourceLoadStatisticsStore::processStatistics(const WTF::Function<void (const ResourceLoadStatistics&)>& processFunction) const
 {
     ASSERT(!RunLoop::isMain());
index 58a1ce5..0f2613c 100644 (file)
@@ -92,6 +92,7 @@ public:
     void scheduleCookiePartitioningUpdateForDomains(const Vector<String>& domainsToRemove, const Vector<String>& domainsToAdd, ShouldClearFirst);
     void processStatisticsAndDataRecords();
     void submitTelemetry();
+    void scheduleCookiePartitioningStateReset();
 
     void scheduleClearInMemory();
     void scheduleClearInMemoryAndPersistent();
@@ -150,6 +151,8 @@ private:
     void populateFromDecoder(WebCore::KeyedDecoder&);
     void clearInMemory();
 
+    void resetCookiePartitioningState();
+
 #if PLATFORM(COCOA)
     void registerUserDefaultsIfNeeded();
 #endif
index 36fa30c..c99a20e 100644 (file)
@@ -1106,6 +1106,14 @@ void WebsiteDataStore::updateCookiePartitioningForTopPrivatelyOwnedDomains(const
 }
 #endif
 
+void WebsiteDataStore::networkProcessDidCrash()
+{
+#if HAVE(CFNETWORK_STORAGE_PARTITIONING)
+    if (m_resourceLoadStatistics)
+        m_resourceLoadStatistics->scheduleCookiePartitioningStateReset();
+#endif
+}
+
 void WebsiteDataStore::webPageWasAdded(WebPageProxy& webPageProxy)
 {
     if (m_storageManager)
index 1ac5fce..2869b9d 100644 (file)
@@ -105,6 +105,7 @@ public:
 #if HAVE(CFNETWORK_STORAGE_PARTITIONING)
     void updateCookiePartitioningForTopPrivatelyOwnedDomains(const Vector<String>& domainsToRemove, const Vector<String>& domainsToAdd, ShouldClearFirst);
 #endif
+    void networkProcessDidCrash();
     void resolveDirectoriesIfNecessary();
     const String& resolvedApplicationCacheDirectory() const { return m_resolvedConfiguration.applicationCacheDirectory; }
     const String& resolvedMediaCacheDirectory() const { return m_resolvedConfiguration.mediaCacheDirectory; }