https://bugs.webkit.org/show_bug.cgi?id=175232
<rdar://problem/
33709386>
Reviewed by Alex Christensen.
Source/WebCore:
Prior to Intelligent Tracking Prevention, WebKit would deny the ability to create a third party cookie if the user's
settings prohibited it. Due to the internal mechanics of cookie partitioning, we now accept the third party cookie,
but destroy it at some arbitrary moment which is difficult for websites to work with.
This patch revises WebKit so that attempts to set third party cookies without user interaction fails immediately,
which is what sites are expecting from Safari.
Tests: http/tests/loading/resourceLoadStatistics/third-party-cookie-with-and-without-user-interaction.html
* platform/network/NetworkStorageSession.h:
* platform/network/cf/NetworkStorageSessionCFNet.cpp:
(WebCore::NetworkStorageSession::shouldPartitionCookies const): Revise for new naming.
(WebCore::NetworkStorageSession::shouldAllowThirdPartyCookies const): Allow third party cookies when the
user interaction property applies.
(WebCore::NetworkStorageSession::shouldBlockCookies const): Deny cookies for origins that are not allowed by
user interaction, and that are not being partitioned.
(WebCore::NetworkStorageSession::setPrevalentDomainsWithAndWithoutInteraction): Revise for new naming, and
to track prevalent origins with and without user interaction.
(WebCore::NetworkStorageSession::setShouldPartitionCookiesForHosts): Renamed to setPrevalentDomainsWithAndWithoutInteraction.
(WebCore::NetworkStorageSession::removePrevalentDomains): New helper function for testing.
Source/WebKit:
Prior to Intelligent Tracking Prevention, WebKit would deny the ability to create a third party cookie if the user's
settings prohibited it. Due to the internal mechanics of cookie partitioning, we now accept the third party cookie,
but destroy it at some arbitrary moment which is difficult for websites to work with.
This patch revises WebKit so that attempts to set third party cookies without user interaction fails immediately,
which is what sites are expecting from Safari.
* NetworkProcess/NetworkProcess.cpp:
(WebKit::NetworkProcess::updatePrevalentDomainsWithAndWithoutInteraction):
(WebKit::NetworkProcess::updateCookiePartitioningForTopPrivatelyOwnedDomains): Renamed to updatePrevalentDomainsWithAndWithoutInteraction.
* NetworkProcess/NetworkProcess.h:
* NetworkProcess/NetworkProcess.messages.in: Renamed the UpdateCookiePartitioningForTopPrivatelyOwnedDomains message
to UpdatePrevalentDomainsWithAndWithoutInteraction.
* NetworkProcess/cocoa/NetworkDataTaskCocoa.mm:
(WebKit::NetworkDataTaskCocoa::NetworkDataTaskCocoa): Recognize cases where a network session should block cookies, and
use the stateless session so we fail immediately when attempting an invalid cookie set operation.
* UIProcess/API/Cocoa/WKWebsiteDataStore.mm:
(WebKit::WKWebsiteDataStore::_resourceLoadStatisticsSetShouldPartitionCookies): Use new helper function to clear partitioning state.
* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::WebResourceLoadStatisticsStore): Update for revised naming.
(WebKit::WebResourceLoadStatisticsStore::updateCookiePartitioning): Track domains with and without interaction so that we can recognize
domains that should be immediately blocked from setting cookies.
(WebKit::WebResourceLoadStatisticsStore::updateCookiePartitioningForDomains): Update for revised naming.
(WebKit::WebResourceLoadStatisticsStore::scheduleClearPartitioningStateForDomains): Added helper function for testing.
* UIProcess/WebResourceLoadStatisticsStore.h:
* UIProcess/WebsiteData/WebsiteDataStore.cpp:
(WebKit::WebsiteDataStore::updatePrevalentDomainsWithAndWithoutInteraction): Update for revised naming.
(WebKit::WebsiteDataStore::enableResourceLoadStatisticsAndSetTestingCallback): Ditto.
(WebKit::WebsiteDataStore::updateCookiePartitioningForTopPrivatelyOwnedDomains): Renamed to updatePrevalentDomainsWithAndWithoutInteraction.
* UIProcess/WebsiteData/WebsiteDataStore.h:
LayoutTests:
* http/tests/loading/resourceLoadStatistics/third-party-cookie-with-and-without-user-interaction-expected.txt: Added.
* http/tests/loading/resourceLoadStatistics/third-party-cookie-with-and-without-user-interaction.html: Added.
* platform/mac-highsierra-wk2/TestExpectations: Add new test expectation.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@221683
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2017-09-06 Brent Fulgham <bfulgham@apple.com>
+
+ Deny third-party cookie creation for prevalent resources without interaction
+ https://bugs.webkit.org/show_bug.cgi?id=175232
+ <rdar://problem/33709386>
+
+ Reviewed by Alex Christensen.
+
+ * http/tests/loading/resourceLoadStatistics/third-party-cookie-with-and-without-user-interaction-expected.txt: Added.
+ * http/tests/loading/resourceLoadStatistics/third-party-cookie-with-and-without-user-interaction.html: Added.
+ * platform/mac-highsierra-wk2/TestExpectations: Add new test expectation.
+
2017-09-06 Per Arne Vollan <pvollan@apple.com>
Layout Test http/tests/preload/single_download_preload.html is flaky.
--- /dev/null
+main frame - didStartProvisionalLoadForFrame
+main frame - didCommitLoadForFrame
+main frame - didReceiveTitle: Test for Partitioned Cookies With and Without User Interaction
+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/third-party-cookie-with-and-without-user-interaction.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/third-party-cookie-with-and-without-user-interaction.html#step2
+main frame - didStartProvisionalLoadForFrame
+main frame - didCancelClientRedirectForFrame
+main frame - didCommitLoadForFrame
+main frame - didReceiveTitle: Test for Partitioned Cookies With and Without User Interaction
+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 //<!--frame3-->-->" - didStartProvisionalLoadForFrame
+frame "<!--framePath //<!--frame2-->-->" - didHandleOnloadEventsForFrame
+frame "<!--framePath //<!--frame2-->-->" - didFinishLoadForFrame
+frame "<!--framePath //<!--frame3-->-->" - didCommitLoadForFrame
+frame "<!--framePath //<!--frame3-->-->" - didFinishDocumentLoadForFrame
+frame "<!--framePath //<!--frame4-->-->" - didStartProvisionalLoadForFrame
+frame "<!--framePath //<!--frame3-->-->" - didHandleOnloadEventsForFrame
+frame "<!--framePath //<!--frame3-->-->" - didFinishLoadForFrame
+frame "<!--framePath //<!--frame4-->-->" - didCommitLoadForFrame
+frame "<!--framePath //<!--frame4-->-->" - didFinishDocumentLoadForFrame
+frame "<!--framePath //<!--frame4-->-->" - didHandleOnloadEventsForFrame
+frame "<!--framePath //<!--frame4-->-->" - didFinishLoadForFrame
+main frame - didFinishLoadForFrame
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+
+--------
+Frame: '<!--framePath //<!--frame0-->-->'
+--------
+Setting third party cookie.
+
+
+--------
+Frame: '<!--framePath //<!--frame1-->-->'
+--------
+Should receive no cookies.
+Did not receive cookie named 'firstPartyCookie'.
+Did not receive cookie named 'thirdPartyCookie'.
+Client-side document.cookie: firstPartyCookie=value
+
+--------
+Frame: '<!--framePath //<!--frame2-->-->'
+--------
+Setting partitioned, third party cookie.
+
+
+--------
+Frame: '<!--framePath //<!--frame3-->-->'
+--------
+Should receive partitioned, third party cookie.
+Did not receive cookie named 'firstPartyCookie'.
+Received cookie named 'thirdPartyCookie'.
+Client-side document.cookie: thirdPartyCookie=value
+
+--------
+Frame: '<!--framePath //<!--frame4-->-->'
+--------
+After user interaction, should receive non-partitioned, first party cookie.
+Received cookie named 'firstPartyCookie'.
+Did not receive cookie named 'thirdPartyCookie'.
+Client-side document.cookie: firstPartyCookie=value
--- /dev/null
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title>Test for Partitioned Cookies With and Without User Interaction</title>
+ <script src="/js-test-resources/js-test.js"></script>
+</head>
+<body>
+<script>
+ const partitionHost = "127.0.0.1:8000";
+ const thirdPartyHostname = "localhost";
+ const thirdPartyOrigin = "http://" + thirdPartyHostname + ":8000";
+ const thirdPartyBaseUrl = thirdPartyOrigin + "/loading/resourceLoadStatistics/resources";
+ const firstPartyCookieName = "firstPartyCookie";
+ const subPathToSetFirstPartyCookie = "/set-cookie.php?name=" + firstPartyCookieName + "&value=value";
+ const thirdPartyCookieName = "thirdPartyCookie";
+ const subPathToSetThirdPartyCookie = "/set-cookie.php?name=" + thirdPartyCookieName + "&value=value";
+ const fragmentWithReturnUrl = "http://127.0.0.1:8000/loading/resourceLoadStatistics/third-party-cookie-with-and-without-user-interaction.html";
+ const subPathToGetCookies = "/get-cookies.php?name1=" + firstPartyCookieName + "&name2=" + thirdPartyCookieName;
+
+ function setEnableFeature(enable) {
+ if (!enable) {
+ testRunner.statisticsResetToConsistentState();
+ }
+ testRunner.setStatisticsNotifyPagesWhenDataRecordsWereScanned(enable);
+ internals.setResourceLoadStatisticsEnabled(enable);
+ testRunner.setCookieStoragePartitioningEnabled(enable);
+ }
+
+ function finishTest() {
+ setEnableFeature(false);
+ testRunner.notifyDone();
+ }
+
+ function openIframe(url, onLoadHandler) {
+ const element = document.createElement("iframe");
+ element.src = url;
+ if (onLoadHandler) {
+ element.onload = onLoadHandler;
+ }
+ document.body.appendChild(element);
+ }
+
+ function setUserInteractionAndContinue() {
+ testRunner.setStatisticsHasHadUserInteraction(thirdPartyOrigin, true);
+ if (!testRunner.isStatisticsHasHadUserInteraction(thirdPartyOrigin))
+ testFailed("Third party did not get logged for user interaction.");
+ runTest();
+ }
+
+ function runTest() {
+ switch (document.location.hash) {
+ case "#step1":
+ document.location.href = thirdPartyBaseUrl + subPathToSetFirstPartyCookie + "#" + fragmentWithReturnUrl + "#step2";
+ break;
+ case "#step2":
+ document.location.hash = "step3";
+ openIframe(thirdPartyBaseUrl + subPathToSetThirdPartyCookie + "&message=Setting third party cookie.", runTest);
+ break;
+ case "#step3":
+ document.location.hash = "step4";
+ openIframe(thirdPartyBaseUrl + subPathToGetCookies + "&message=Should receive no cookies.", runTest);
+ break;
+ case "#step4":
+ document.location.hash = "step5";
+ testRunner.statisticsSetShouldPartitionCookiesForHost(thirdPartyHostname, true);
+ openIframe(thirdPartyBaseUrl + subPathToSetThirdPartyCookie + "&message=Setting partitioned, third party cookie.", runTest);
+ break;
+ case "#step5":
+ document.location.hash = "step6";
+ openIframe(thirdPartyBaseUrl + subPathToGetCookies + "&message=Should receive partitioned, third party cookie.", setUserInteractionAndContinue);
+ break;
+ case "#step6":
+ openIframe(thirdPartyBaseUrl + subPathToGetCookies + "&message=After user interaction, should receive non-partitioned, first party cookie.", finishTest);
+ break;
+ }
+ }
+
+ if (document.location.host === partitionHost && document.location.hash == "" && window.testRunner && window.internals) {
+ setEnableFeature(true);
+
+ // Start test with third party as non-prevalent
+ testRunner.setStatisticsPrevalentResource(thirdPartyHostname, false);
+ testRunner.setStatisticsHasHadUserInteraction(thirdPartyOrigin, false);
+ testRunner.statisticsSetShouldPartitionCookiesForHost(thirdPartyHostname, false);
+
+ testRunner.waitUntilDone();
+ testRunner.dumpChildFramesAsText();
+ document.location.hash = "step1";
+ }
+
+ runTest();
+</script>
+</body>
+</html>
http/tests/loading/resourceLoadStatistics/clear-in-memory-and-persistent-store-one-hour.html [ Pass ]
http/tests/loading/resourceLoadStatistics/partitioned-and-unpartitioned-cookie-deletion.html [ Pass ]
http/tests/loading/resourceLoadStatistics/partitioned-and-unpartitioned-cookie-with-partitioning-timeout.html [ Pass ]
+http/tests/loading/resourceLoadStatistics/third-party-cookie-with-and-without-user-interaction.html [ Pass ]
# <rdar://problem/33555759>
http/tests/media/video-buffered-range-contains-currentTime.html [ Pass ImageOnlyFailure ]
+2017-09-06 Brent Fulgham <bfulgham@apple.com>
+
+ Deny third-party cookie creation for prevalent resources without interaction
+ https://bugs.webkit.org/show_bug.cgi?id=175232
+ <rdar://problem/33709386>
+
+ Reviewed by Alex Christensen.
+
+ Prior to Intelligent Tracking Prevention, WebKit would deny the ability to create a third party cookie if the user's
+ settings prohibited it. Due to the internal mechanics of cookie partitioning, we now accept the third party cookie,
+ but destroy it at some arbitrary moment which is difficult for websites to work with.
+
+ This patch revises WebKit so that attempts to set third party cookies without user interaction fails immediately,
+ which is what sites are expecting from Safari.
+
+ Tests: http/tests/loading/resourceLoadStatistics/third-party-cookie-with-and-without-user-interaction.html
+
+ * platform/network/NetworkStorageSession.h:
+ * platform/network/cf/NetworkStorageSessionCFNet.cpp:
+ (WebCore::NetworkStorageSession::shouldPartitionCookies const): Revise for new naming.
+ (WebCore::NetworkStorageSession::shouldAllowThirdPartyCookies const): Allow third party cookies when the
+ user interaction property applies.
+ (WebCore::NetworkStorageSession::shouldBlockCookies const): Deny cookies for origins that are not allowed by
+ user interaction, and that are not being partitioned.
+ (WebCore::NetworkStorageSession::setPrevalentDomainsWithAndWithoutInteraction): Revise for new naming, and
+ to track prevalent origins with and without user interaction.
+ (WebCore::NetworkStorageSession::setShouldPartitionCookiesForHosts): Renamed to setPrevalentDomainsWithAndWithoutInteraction.
+ (WebCore::NetworkStorageSession::removePrevalentDomains): New helper function for testing.
+
2017-09-06 Tomas Popela <tpopela@redhat.com>
Missing break in URLParser
WEBCORE_EXPORT static void setCookieStoragePartitioningEnabled(bool);
#if HAVE(CFNETWORK_STORAGE_PARTITIONING)
WEBCORE_EXPORT String cookieStoragePartition(const ResourceRequest&) const;
+ WEBCORE_EXPORT bool shouldBlockCookies(const ResourceRequest&) const;
String cookieStoragePartition(const URL& firstPartyForCookies, const URL& resource) const;
- WEBCORE_EXPORT void setShouldPartitionCookiesForHosts(const Vector<String>& domainsToRemove, const Vector<String>& domainsToAdd, bool clearFirst);
+ WEBCORE_EXPORT void setPrevalentDomainsWithAndWithoutInteraction(const Vector<String>& domainsWithInteraction, const Vector<String>& domainsWithoutInteraction, bool clearFirst);
+ WEBCORE_EXPORT void removePrevalentDomains(const Vector<String>& domains);
#endif
#elif USE(SOUP)
NetworkStorageSession(PAL::SessionID, std::unique_ptr<SoupNetworkSession>&&);
#if HAVE(CFNETWORK_STORAGE_PARTITIONING)
bool shouldPartitionCookies(const String& topPrivatelyControlledDomain) const;
- HashSet<String> m_topPrivatelyControlledDomainsForCookiePartitioning;
+ bool shouldAllowThirdPartyCookies(const String& topPrivatelyControlledDomain) const;
+ HashSet<String> m_prevalentTopPrivatelyControlledDomainsWithoutInteraction;
+ HashSet<String> m_prevalentTopPrivatelyControlledDomainsWithInteraction;
#endif
#if PLATFORM(COCOA)
if (topPrivatelyControlledDomain.isEmpty())
return false;
- return m_topPrivatelyControlledDomainsForCookiePartitioning.contains(topPrivatelyControlledDomain);
+ return m_prevalentTopPrivatelyControlledDomainsWithoutInteraction.contains(topPrivatelyControlledDomain);
}
-void NetworkStorageSession::setShouldPartitionCookiesForHosts(const Vector<String>& domainsToRemove, const Vector<String>& domainsToAdd, bool clearFirst)
+bool NetworkStorageSession::shouldAllowThirdPartyCookies(const String& topPrivatelyControlledDomain) const
{
- if (clearFirst)
- m_topPrivatelyControlledDomainsForCookiePartitioning.clear();
+ if (topPrivatelyControlledDomain.isEmpty())
+ return false;
+
+ return m_prevalentTopPrivatelyControlledDomainsWithInteraction.contains(topPrivatelyControlledDomain);
+}
+
+bool NetworkStorageSession::shouldBlockCookies(const ResourceRequest& request) const
+{
+ if (!cookieStoragePartitioningEnabled)
+ return false;
+
+ auto firstPartyDomain = getPartitioningDomain(request.firstPartyForCookies());
+ if (firstPartyDomain.isEmpty())
+ return false;
+
+ auto resourceDomain = getPartitioningDomain(request.url());
+ if (resourceDomain.isEmpty())
+ return false;
+
+ if (firstPartyDomain == resourceDomain)
+ return false;
+
+ if (shouldPartitionCookies(resourceDomain))
+ return false;
+
+ return !shouldAllowThirdPartyCookies(resourceDomain);
+}
+
+void NetworkStorageSession::setPrevalentDomainsWithAndWithoutInteraction(const Vector<String>& domainsWithInteraction, const Vector<String>& domainsWithoutInteraction, bool clearFirst)
+{
+ if (clearFirst) {
+ m_prevalentTopPrivatelyControlledDomainsWithoutInteraction.clear();
+ m_prevalentTopPrivatelyControlledDomainsWithInteraction.clear();
+ }
+
+ for (auto& domain : domainsWithInteraction) {
+ if (!clearFirst)
+ m_prevalentTopPrivatelyControlledDomainsWithoutInteraction.remove(domain);
+ m_prevalentTopPrivatelyControlledDomainsWithInteraction.add(domain);
+ }
- if (!domainsToRemove.isEmpty()) {
- for (auto& domain : domainsToRemove)
- m_topPrivatelyControlledDomainsForCookiePartitioning.remove(domain);
+ for (auto& domain : domainsWithoutInteraction) {
+ m_prevalentTopPrivatelyControlledDomainsWithoutInteraction.add(domain);
+ if (!clearFirst)
+ m_prevalentTopPrivatelyControlledDomainsWithInteraction.remove(domain);
+ }
+}
+
+void NetworkStorageSession::removePrevalentDomains(const Vector<String>& domains)
+{
+ for (auto& domain : domains) {
+ m_prevalentTopPrivatelyControlledDomainsWithoutInteraction.remove(domain);
+ m_prevalentTopPrivatelyControlledDomainsWithInteraction.remove(domain);
}
-
- if (!domainsToAdd.isEmpty())
- m_topPrivatelyControlledDomainsForCookiePartitioning.add(domainsToAdd.begin(), domainsToAdd.end());
}
#endif // HAVE(CFNETWORK_STORAGE_PARTITIONING)
+2017-09-06 Brent Fulgham <bfulgham@apple.com>
+
+ Deny third-party cookie creation for prevalent resources without interaction
+ https://bugs.webkit.org/show_bug.cgi?id=175232
+ <rdar://problem/33709386>
+
+ Reviewed by Alex Christensen.
+
+ Prior to Intelligent Tracking Prevention, WebKit would deny the ability to create a third party cookie if the user's
+ settings prohibited it. Due to the internal mechanics of cookie partitioning, we now accept the third party cookie,
+ but destroy it at some arbitrary moment which is difficult for websites to work with.
+
+ This patch revises WebKit so that attempts to set third party cookies without user interaction fails immediately,
+ which is what sites are expecting from Safari.
+
+ * NetworkProcess/NetworkProcess.cpp:
+ (WebKit::NetworkProcess::updatePrevalentDomainsWithAndWithoutInteraction):
+ (WebKit::NetworkProcess::updateCookiePartitioningForTopPrivatelyOwnedDomains): Renamed to updatePrevalentDomainsWithAndWithoutInteraction.
+ * NetworkProcess/NetworkProcess.h:
+ * NetworkProcess/NetworkProcess.messages.in: Renamed the UpdateCookiePartitioningForTopPrivatelyOwnedDomains message
+ to UpdatePrevalentDomainsWithAndWithoutInteraction.
+ * NetworkProcess/cocoa/NetworkDataTaskCocoa.mm:
+ (WebKit::NetworkDataTaskCocoa::NetworkDataTaskCocoa): Recognize cases where a network session should block cookies, and
+ use the stateless session so we fail immediately when attempting an invalid cookie set operation.
+ * UIProcess/API/Cocoa/WKWebsiteDataStore.mm:
+ (WebKit::WKWebsiteDataStore::_resourceLoadStatisticsSetShouldPartitionCookies): Use new helper function to clear partitioning state.
+ * UIProcess/WebResourceLoadStatisticsStore.cpp:
+ (WebKit::WebResourceLoadStatisticsStore::WebResourceLoadStatisticsStore): Update for revised naming.
+ (WebKit::WebResourceLoadStatisticsStore::updateCookiePartitioning): Track domains with and without interaction so that we can recognize
+ domains that should be immediately blocked from setting cookies.
+ (WebKit::WebResourceLoadStatisticsStore::updateCookiePartitioningForDomains): Update for revised naming.
+ (WebKit::WebResourceLoadStatisticsStore::scheduleClearPartitioningStateForDomains): Added helper function for testing.
+ * UIProcess/WebResourceLoadStatisticsStore.h:
+ * UIProcess/WebsiteData/WebsiteDataStore.cpp:
+ (WebKit::WebsiteDataStore::updatePrevalentDomainsWithAndWithoutInteraction): Update for revised naming.
+ (WebKit::WebsiteDataStore::enableResourceLoadStatisticsAndSetTestingCallback): Ditto.
+ (WebKit::WebsiteDataStore::updateCookiePartitioningForTopPrivatelyOwnedDomains): Renamed to updatePrevalentDomainsWithAndWithoutInteraction.
+ * UIProcess/WebsiteData/WebsiteDataStore.h:
+
2017-09-06 Adrian Perez de Castro <aperez@igalia.com>
[WPE][CMake] Fix path to the WebKitApplicationInfo.h header.
}
#if HAVE(CFNETWORK_STORAGE_PARTITIONING)
-void NetworkProcess::updateCookiePartitioningForTopPrivatelyOwnedDomains(PAL::SessionID sessionID, const Vector<String>& domainsToRemove, const Vector<String>& domainsToAdd, bool shouldClearFirst)
+void NetworkProcess::updatePrevalentDomainsWithAndWithoutInteraction(PAL::SessionID sessionID, const Vector<String>& domainsWithInteraction, const Vector<String>& domainsWithoutInteraction, bool shouldClearFirst)
{
if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
- networkStorageSession->setShouldPartitionCookiesForHosts(domainsToRemove, domainsToAdd, shouldClearFirst);
+ networkStorageSession->setPrevalentDomainsWithAndWithoutInteraction(domainsWithInteraction, domainsWithoutInteraction, shouldClearFirst);
+}
+
+void NetworkProcess::removePrevalentDomains(PAL::SessionID sessionID, const Vector<String>& domains)
+{
+ if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
+ networkStorageSession->removePrevalentDomains(domains);
}
#endif
void grantSandboxExtensionsToStorageProcessForBlobs(const Vector<String>& filenames, Function<void ()>&& completionHandler);
#if HAVE(CFNETWORK_STORAGE_PARTITIONING)
- void updateCookiePartitioningForTopPrivatelyOwnedDomains(PAL::SessionID, const Vector<String>& domainsToRemove, const Vector<String>& domainsToAdd, bool shouldClearFirst);
+ void updatePrevalentDomainsWithAndWithoutInteraction(PAL::SessionID, const Vector<String>& domainsWithInteraction, const Vector<String>& domainsWithoutInteraction, bool shouldClearFirst);
+ void removePrevalentDomains(PAL::SessionID, const Vector<String>& domains);
#endif
Seconds loadThrottleLatency() const { return m_loadThrottleLatency; }
DidGrantSandboxExtensionsToStorageProcessForBlobs(uint64_t requestID)
#if HAVE(CFNETWORK_STORAGE_PARTITIONING)
- UpdateCookiePartitioningForTopPrivatelyOwnedDomains(PAL::SessionID sessionID, Vector<String> domainsToRemove, Vector<String> domainsToAdd, bool shouldClearFirst)
+ UpdatePrevalentDomainsWithAndWithoutInteraction(PAL::SessionID sessionID, Vector<String> domainsWithInteraction, Vector<String> domainsWithoutInteraction, bool shouldClearFirst)
+ RemovePrevalentDomains(PAL::SessionID sessionID, Vector<String> domainsWithInteraction);
#endif
}
}
auto& cocoaSession = static_cast<NetworkSessionCocoa&>(m_session.get());
+ if (session.networkStorageSession().shouldBlockCookies(request)) {
+ storedCredentials = WebCore::DoNotAllowStoredCredentials;
+ m_storedCredentials = WebCore::DoNotAllowStoredCredentials;
+ }
+
if (storedCredentials == WebCore::AllowStoredCredentials) {
m_task = [cocoaSession.m_sessionWithCredentialStorage dataTaskWithRequest:nsRequest];
ASSERT(!cocoaSession.m_dataTaskMapWithCredentials.contains([m_task taskIdentifier]));
cocoaSession.m_dataTaskMapWithCredentials.add([m_task taskIdentifier], this);
+ LOG(NetworkSession, "%llu Creating stateless NetworkDataTask with URL %s", [m_task taskIdentifier], nsRequest.URL.absoluteString.UTF8String);
} else {
m_task = [cocoaSession.m_statelessSession dataTaskWithRequest:nsRequest];
ASSERT(!cocoaSession.m_dataTaskMapWithoutState.contains([m_task taskIdentifier]));
cocoaSession.m_dataTaskMapWithoutState.add([m_task taskIdentifier], this);
+ LOG(NetworkSession, "%llu Creating NetworkDataTask with URL %s", [m_task taskIdentifier], nsRequest.URL.absoluteString.UTF8String);
}
- LOG(NetworkSession, "%llu Creating NetworkDataTask with URL %s", [m_task taskIdentifier], nsRequest.URL.absoluteString.UTF8String);
#if HAVE(CFNETWORK_STORAGE_PARTITIONING)
- String storagePartition = session.networkStorageSession().cookieStoragePartition(request);
- if (!storagePartition.isEmpty()) {
- LOG(NetworkSession, "%llu Partitioning cookies for URL %s", [m_task taskIdentifier], nsRequest.URL.absoluteString.UTF8String);
- m_task.get()._storagePartitionIdentifier = storagePartition;
+ if (storedCredentials == WebCore::AllowStoredCredentials) {
+ String storagePartition = session.networkStorageSession().cookieStoragePartition(request);
+ if (!storagePartition.isEmpty()) {
+ LOG(NetworkSession, "%llu Partitioning cookies for URL %s", [m_task taskIdentifier], nsRequest.URL.absoluteString.UTF8String);
+ m_task.get()._storagePartitionIdentifier = storagePartition;
+ }
}
#endif
if (value)
store->scheduleCookiePartitioningUpdateForDomains({ }, { host }, WebKit::ShouldClearFirst::No);
else
- store->scheduleCookiePartitioningUpdateForDomains({ host }, { }, WebKit::ShouldClearFirst::No);
+ store->scheduleClearPartitioningStateForDomains({ host });
}
- (void)_resourceLoadStatisticsSubmitTelemetry
return mergedDates;
}
-WebResourceLoadStatisticsStore::WebResourceLoadStatisticsStore(const String& resourceLoadStatisticsDirectory, Function<void (const String&)>&& testingCallback, UpdateCookiePartitioningForDomainsHandler&& updateCookiePartitioningForDomainsHandler)
+WebResourceLoadStatisticsStore::WebResourceLoadStatisticsStore(const String& resourceLoadStatisticsDirectory, Function<void (const String&)>&& testingCallback, UpdatePrevalentDomainsWithAndWithoutInteractionHandler&& updatePrevalentDomainsWithAndWithoutInteractionHandler, RemovePrevalentDomainsHandler&& removeDomainsHandler)
: m_statisticsQueue(WorkQueue::create("WebResourceLoadStatisticsStore Process Data Queue", WorkQueue::Type::Serial, WorkQueue::QOS::Utility))
, m_persistentStorage(*this, resourceLoadStatisticsDirectory)
- , m_updateCookiePartitioningForDomainsHandler(WTFMove(updateCookiePartitioningForDomainsHandler))
+ , m_updatePrevalentDomainsWithAndWithoutInteractionHandler(WTFMove(updatePrevalentDomainsWithAndWithoutInteractionHandler))
+ , m_removeDomainsHandler(WTFMove(removeDomainsHandler))
, m_dailyTasksTimer(RunLoop::main(), this, &WebResourceLoadStatisticsStore::performDailyTasks)
, m_statisticsTestingCallback(WTFMove(testingCallback))
{
});
}
+void WebResourceLoadStatisticsStore::scheduleClearPartitioningStateForDomains(const Vector<String>& domains)
+{
+ // Helper function used by testing system. Should only be called from the main thread.
+ ASSERT(RunLoop::isMain());
+ m_statisticsQueue->dispatch([this, protectedThis = makeRef(*this), domains = crossThreadCopy(domains)] {
+ clearPartitioningStateForDomains(domains);
+ });
+}
+
#if HAVE(CFNETWORK_STORAGE_PARTITIONING)
void WebResourceLoadStatisticsStore::scheduleCookiePartitioningStateReset()
{
{
ASSERT(!RunLoop::isMain());
- Vector<String> domainsToRemove;
- Vector<String> domainsToAdd;
+ Vector<String> domainsWithoutInteraction;
+ Vector<String> domainsWithInteraction;
for (auto& resourceStatistic : m_resourceStatisticsMap.values()) {
bool shouldPartition = shouldPartitionCookies(resourceStatistic);
if (resourceStatistic.isMarkedForCookiePartitioning && !shouldPartition) {
resourceStatistic.isMarkedForCookiePartitioning = false;
- domainsToRemove.append(resourceStatistic.highLevelDomain);
+ domainsWithInteraction.append(resourceStatistic.highLevelDomain);
} else if (!resourceStatistic.isMarkedForCookiePartitioning && shouldPartition) {
resourceStatistic.isMarkedForCookiePartitioning = true;
- domainsToAdd.append(resourceStatistic.highLevelDomain);
+ domainsWithoutInteraction.append(resourceStatistic.highLevelDomain);
}
}
- if (domainsToRemove.isEmpty() && domainsToAdd.isEmpty())
+ if (domainsWithInteraction.isEmpty() && domainsWithoutInteraction.isEmpty())
return;
- RunLoop::main().dispatch([this, protectedThis = makeRef(*this), domainsToRemove = crossThreadCopy(domainsToRemove), domainsToAdd = crossThreadCopy(domainsToAdd)] () {
- m_updateCookiePartitioningForDomainsHandler(domainsToRemove, domainsToAdd, ShouldClearFirst::No);
+ RunLoop::main().dispatch([this, protectedThis = makeRef(*this), domainsWithInteraction = crossThreadCopy(domainsWithInteraction), domainsWithoutInteraction = crossThreadCopy(domainsWithoutInteraction)] () {
+ m_updatePrevalentDomainsWithAndWithoutInteractionHandler(domainsWithInteraction, domainsWithoutInteraction, ShouldClearFirst::No);
});
}
-void WebResourceLoadStatisticsStore::updateCookiePartitioningForDomains(const Vector<String>& domainsToRemove, const Vector<String>& domainsToAdd, ShouldClearFirst shouldClearFirst)
+void WebResourceLoadStatisticsStore::updateCookiePartitioningForDomains(const Vector<String>& domainsWithInteraction, const Vector<String>& domainsWithoutInteraction, ShouldClearFirst shouldClearFirst)
{
ASSERT(!RunLoop::isMain());
- if (domainsToRemove.isEmpty() && domainsToAdd.isEmpty())
+ if (domainsWithInteraction.isEmpty() && domainsWithoutInteraction.isEmpty())
return;
- RunLoop::main().dispatch([this, shouldClearFirst, protectedThis = makeRef(*this), domainsToRemove = crossThreadCopy(domainsToRemove), domainsToAdd = crossThreadCopy(domainsToAdd)] () {
- m_updateCookiePartitioningForDomainsHandler(domainsToRemove, domainsToAdd, shouldClearFirst);
+ RunLoop::main().dispatch([this, shouldClearFirst, protectedThis = makeRef(*this), domainsWithInteraction = crossThreadCopy(domainsWithInteraction), domainsWithoutInteraction = crossThreadCopy(domainsWithoutInteraction)] () {
+ m_updatePrevalentDomainsWithAndWithoutInteractionHandler(domainsWithInteraction, domainsWithoutInteraction, shouldClearFirst);
});
if (shouldClearFirst == ShouldClearFirst::Yes)
resetCookiePartitioningState();
else {
- for (auto& domain : domainsToRemove)
+ for (auto& domain : domainsWithInteraction)
ensureResourceStatisticsForPrimaryDomain(domain).isMarkedForCookiePartitioning = false;
}
- for (auto& domain : domainsToAdd)
+ for (auto& domain : domainsWithoutInteraction)
ensureResourceStatisticsForPrimaryDomain(domain).isMarkedForCookiePartitioning = true;
}
+void WebResourceLoadStatisticsStore::clearPartitioningStateForDomains(const Vector<String>& domains)
+{
+ ASSERT(!RunLoop::isMain());
+ if (domains.isEmpty())
+ return;
+
+ RunLoop::main().dispatch([this, protectedThis = makeRef(*this), domains = crossThreadCopy(domains)] () {
+ m_removeDomainsHandler(domains);
+ });
+
+ for (auto& domain : domains)
+ ensureResourceStatisticsForPrimaryDomain(domain).isMarkedForCookiePartitioning = false;
+}
+
void WebResourceLoadStatisticsStore::resetCookiePartitioningState()
{
ASSERT(!RunLoop::isMain());
class WebResourceLoadStatisticsStore final : public IPC::Connection::WorkQueueMessageReceiver {
public:
- using UpdateCookiePartitioningForDomainsHandler = WTF::Function<void(const Vector<String>& domainsToRemove, const Vector<String>& domainsToAdd, ShouldClearFirst)>;
- static Ref<WebResourceLoadStatisticsStore> create(const String& resourceLoadStatisticsDirectory, Function<void (const String&)>&& testingCallback, UpdateCookiePartitioningForDomainsHandler&& updateCookiePartitioningForDomainsHandler = [](const Vector<String>&, const Vector<String>&, ShouldClearFirst) { })
+ using UpdatePrevalentDomainsWithAndWithoutInteractionHandler = WTF::Function<void(const Vector<String>& domainsWithInteraction, const Vector<String>& domainsWithoutInteraction, ShouldClearFirst)>;
+ using RemovePrevalentDomainsHandler = WTF::Function<void (const Vector<String>&)>;
+ static Ref<WebResourceLoadStatisticsStore> create(const String& resourceLoadStatisticsDirectory, Function<void (const String&)>&& testingCallback, UpdatePrevalentDomainsWithAndWithoutInteractionHandler&& updateCookiePartitioningForDomainsHandler = [](const Vector<String>&, const Vector<String>&, ShouldClearFirst) { }, RemovePrevalentDomainsHandler&& removeDomainsHandler = [] (const Vector<String>&) { })
{
- return adoptRef(*new WebResourceLoadStatisticsStore(resourceLoadStatisticsDirectory, WTFMove(testingCallback), WTFMove(updateCookiePartitioningForDomainsHandler)));
+ return adoptRef(*new WebResourceLoadStatisticsStore(resourceLoadStatisticsDirectory, WTFMove(testingCallback), WTFMove(updateCookiePartitioningForDomainsHandler), WTFMove(removeDomainsHandler)));
}
~WebResourceLoadStatisticsStore();
void setSubresourceUniqueRedirectTo(const WebCore::URL& subresource, const WebCore::URL& hostNameRedirectedTo);
void scheduleCookiePartitioningUpdate();
void scheduleCookiePartitioningUpdateForDomains(const Vector<String>& domainsToRemove, const Vector<String>& domainsToAdd, ShouldClearFirst);
+ void scheduleClearPartitioningStateForDomains(const Vector<String>& domains);
void scheduleStatisticsAndDataRecordsProcessing();
void submitTelemetry();
void scheduleCookiePartitioningStateReset();
void logTestingEvent(const String&);
private:
- WebResourceLoadStatisticsStore(const String&, Function<void (const String&)>&& testingCallback, UpdateCookiePartitioningForDomainsHandler&&);
+ WebResourceLoadStatisticsStore(const String&, Function<void (const String&)>&& testingCallback, UpdatePrevalentDomainsWithAndWithoutInteractionHandler&&, RemovePrevalentDomainsHandler&&);
void removeDataRecords();
Vector<String> topPrivatelyControlledDomainsToRemoveWebsiteDataFor();
void updateCookiePartitioning();
void updateCookiePartitioningForDomains(const Vector<String>& domainsToRemove, const Vector<String>& domainsToAdd, ShouldClearFirst);
+ void clearPartitioningStateForDomains(const Vector<String>& domains);
void mergeStatistics(Vector<WebCore::ResourceLoadStatistics>&&);
WebCore::ResourceLoadStatistics& ensureResourceStatisticsForPrimaryDomain(const String&);
void processStatisticsAndDataRecords();
ResourceLoadStatisticsPersistentStorage m_persistentStorage;
Vector<OperatingDate> m_operatingDates;
- UpdateCookiePartitioningForDomainsHandler m_updateCookiePartitioningForDomainsHandler;
+ UpdatePrevalentDomainsWithAndWithoutInteractionHandler m_updatePrevalentDomainsWithAndWithoutInteractionHandler;
+ RemovePrevalentDomainsHandler m_removeDomainsHandler;
WallTime m_endOfGrandfatheringTimestamp;
RunLoop::Timer<WebResourceLoadStatisticsStore> m_dailyTasksTimer;
}
#if HAVE(CFNETWORK_STORAGE_PARTITIONING)
-void WebsiteDataStore::updateCookiePartitioningForTopPrivatelyOwnedDomains(const Vector<String>& domainsToRemove, const Vector<String>& domainsToAdd, ShouldClearFirst shouldClearFirst)
+void WebsiteDataStore::updatePrevalentDomainsWithAndWithoutInteraction(const Vector<String>& domainsWithInteraction, const Vector<String>& domainsWithoutInteraction, ShouldClearFirst shouldClearFirst)
{
for (auto& processPool : processPools())
- processPool->sendToNetworkingProcess(Messages::NetworkProcess::UpdateCookiePartitioningForTopPrivatelyOwnedDomains(m_sessionID, domainsToRemove, domainsToAdd, shouldClearFirst == ShouldClearFirst::Yes));
+ processPool->sendToNetworkingProcess(Messages::NetworkProcess::UpdatePrevalentDomainsWithAndWithoutInteraction(m_sessionID, domainsWithInteraction, domainsWithoutInteraction, shouldClearFirst == ShouldClearFirst::Yes));
+}
+
+void WebsiteDataStore::removePrevalentDomains(const Vector<String>& domains)
+{
+ for (auto& processPool : processPools())
+ processPool->sendToNetworkingProcess(Messages::NetworkProcess::RemovePrevalentDomains(m_sessionID, domains));
}
#endif
}
#if HAVE(CFNETWORK_STORAGE_PARTITIONING)
- m_resourceLoadStatistics = WebResourceLoadStatisticsStore::create(m_configuration.resourceLoadStatisticsDirectory, WTFMove(callback), [this] (const Vector<String>& domainsToRemove, const Vector<String>& domainsToAdd, ShouldClearFirst shouldClearFirst) {
- updateCookiePartitioningForTopPrivatelyOwnedDomains(domainsToRemove, domainsToAdd, shouldClearFirst);
+ m_resourceLoadStatistics = WebResourceLoadStatisticsStore::create(m_configuration.resourceLoadStatisticsDirectory, WTFMove(callback), [this] (const Vector<String>& domainsWithInteraction, const Vector<String>& domainsWithoutInteraction, ShouldClearFirst shouldClearFirst) {
+ updatePrevalentDomainsWithAndWithoutInteraction(domainsWithInteraction, domainsWithoutInteraction, shouldClearFirst);
+ }, [this] (const Vector<String>& domainsToRemove) {
+ removePrevalentDomains(domainsToRemove);
});
#else
m_resourceLoadStatistics = WebResourceLoadStatisticsStore::create(m_configuration.resourceLoadStatisticsDirectory, WTFMove(callback));
void removeDataForTopPrivatelyControlledDomains(OptionSet<WebsiteDataType>, OptionSet<WebsiteDataFetchOption>, const Vector<String>& topPrivatelyControlledDomains, Function<void(HashSet<String>&&)>&& completionHandler);
#if HAVE(CFNETWORK_STORAGE_PARTITIONING)
- void updateCookiePartitioningForTopPrivatelyOwnedDomains(const Vector<String>& domainsToRemove, const Vector<String>& domainsToAdd, ShouldClearFirst);
+ void updatePrevalentDomainsWithAndWithoutInteraction(const Vector<String>& domainsWithInteraction, const Vector<String>& domainsWithoutInteraction, ShouldClearFirst);
+ void removePrevalentDomains(const Vector<String>& domains);
#endif
void networkProcessDidCrash();
void resolveDirectoriesIfNecessary();