Diff
Modified: trunk/LayoutTests/ChangeLog (256819 => 256820)
--- trunk/LayoutTests/ChangeLog 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/LayoutTests/ChangeLog 2020-02-18 06:32:42 UTC (rev 256820)
@@ -1,3 +1,21 @@
+2020-02-17 Chris Dumez <[email protected]>
+
+ [WK2][Cocoa] Implement in-WebProcess cookie cache to avoid sync IPC for document.cookie in most cases
+ https://bugs.webkit.org/show_bug.cgi?id=207593
+ <rdar://problem/56027027>
+
+ Reviewed by Antti Koivisto.
+
+ Add layout test coverage.
+
+ * http/tests/cookies/document-cookie-after-showModalDialog-expected.txt: Added.
+ * http/tests/cookies/document-cookie-after-showModalDialog.html: Added.
+ * http/tests/cookies/document-cookie-during-iframe-parsing-expected.txt: Added.
+ * http/tests/cookies/document-cookie-during-iframe-parsing.html: Added.
+ * http/tests/cookies/resources/close-modal-dialog.html: Added.
+ * http/tests/cookies/resources/document-cookie-during-iframe-parsing-iframe.html: Added.
+ * http/tests/cookies/resources/set-cookie-and-serve.php: Added.
+
2020-02-17 Ryan Haddad <[email protected]>
Changed results due to ANGLE use
Added: trunk/LayoutTests/http/tests/cookies/document-cookie-after-showModalDialog-expected.txt (0 => 256820)
--- trunk/LayoutTests/http/tests/cookies/document-cookie-after-showModalDialog-expected.txt (rev 0)
+++ trunk/LayoutTests/http/tests/cookies/document-cookie-after-showModalDialog-expected.txt 2020-02-18 06:32:42 UTC (rev 256820)
@@ -0,0 +1,11 @@
+Tests that document.cookie returns the right value after a showModalDialog() call
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS normalizeCookie(document.cookie) is "testKey=testValue"
+PASS normalizeCookie(document.cookie) is "foo=bar; testKey=testValue"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/http/tests/cookies/document-cookie-after-showModalDialog.html (0 => 256820)
--- trunk/LayoutTests/http/tests/cookies/document-cookie-after-showModalDialog.html (rev 0)
+++ trunk/LayoutTests/http/tests/cookies/document-cookie-after-showModalDialog.html 2020-02-18 06:32:42 UTC (rev 256820)
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=''></script>
+<script src=""
+</head>
+<body>
+<input id="testButton" type="button" value="Click me"></input>
+<script>
+description('Tests that document.cookie returns the right value after a showModalDialog() call');
+jsTestIsAsync = true;
+
+if (window.testRunner)
+ testRunner.setCanOpenWindows();
+
+testButton._onclick_ = () => {
+ document.cookie = "testKey=testValue";
+ shouldBeEqualToString('normalizeCookie(document.cookie)', 'testKey=testValue');
+
+ showModalDialog("resources/set-cookie-and-serve.php?cookie-name=foo&cookie-value=bar&destination=close-modal-dialog.html");
+
+ // This is so the cookie gets removed at the end of the test.
+ registerCookieForCleanup('foo=bar; path=/');
+ shouldBeEqualToString('normalizeCookie(document.cookie)', 'foo=bar; testKey=testValue');
+
+ finishJSTest();
+}
+
+_onload_ = () => {
+ internals.withUserGesture(() => {
+ testButton.click();
+ });
+};
+</script>
+<script src=''></script>
+</body>
+</html>
Added: trunk/LayoutTests/http/tests/cookies/document-cookie-during-iframe-parsing-expected.txt (0 => 256820)
--- trunk/LayoutTests/http/tests/cookies/document-cookie-during-iframe-parsing-expected.txt (rev 0)
+++ trunk/LayoutTests/http/tests/cookies/document-cookie-during-iframe-parsing-expected.txt 2020-02-18 06:32:42 UTC (rev 256820)
@@ -0,0 +1,12 @@
+Tests that document.cookie returns the right value after a showModalDialog() call
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS normalizeCookie(document.cookie) is "testKey=testValue"
+PASS normalizeCookie(cookiesInFrame) is "foo=bar; testKey=testValue"
+PASS normalizeCookie(document.cookie) is "foo=bar; testKey=testValue"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/http/tests/cookies/document-cookie-during-iframe-parsing.html (0 => 256820)
--- trunk/LayoutTests/http/tests/cookies/document-cookie-during-iframe-parsing.html (rev 0)
+++ trunk/LayoutTests/http/tests/cookies/document-cookie-during-iframe-parsing.html 2020-02-18 06:32:42 UTC (rev 256820)
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=''></script>
+<script src=""
+</head>
+<body>
+<script>
+description('Tests that document.cookie returns the right value after a showModalDialog() call');
+jsTestIsAsync = true;
+
+function validateCookiesDuringChildFrameParsing(_cookiesInFrame)
+{
+ cookiesInFrame = _cookiesInFrame;
+ shouldBeEqualToString('normalizeCookie(cookiesInFrame)', 'foo=bar; testKey=testValue');
+ shouldBeEqualToString('normalizeCookie(document.cookie)', 'foo=bar; testKey=testValue');
+ finishJSTest();
+}
+
+_onload_ = () => {
+ document.cookie = "testKey=testValue";
+ shouldBeEqualToString('normalizeCookie(document.cookie)', 'testKey=testValue');
+
+ // This is so the cookie gets removed at the end of the test.
+ registerCookieForCleanup('foo=bar; path=/');
+
+ let iframe = document.createElement("iframe");
+ iframe.src = ""
+ document.body.appendChild(iframe);
+};
+</script>
+<script src=''></script>
+</body>
+</html>
Added: trunk/LayoutTests/http/tests/cookies/resources/close-modal-dialog.html (0 => 256820)
--- trunk/LayoutTests/http/tests/cookies/resources/close-modal-dialog.html (rev 0)
+++ trunk/LayoutTests/http/tests/cookies/resources/close-modal-dialog.html 2020-02-18 06:32:42 UTC (rev 256820)
@@ -0,0 +1,7 @@
+<script>
+_onload_ = () => {
+ close();
+ if (window.testRunner)
+ testRunner.abortModal();
+};
+</script>
Added: trunk/LayoutTests/http/tests/cookies/resources/document-cookie-during-iframe-parsing-iframe.html (0 => 256820)
--- trunk/LayoutTests/http/tests/cookies/resources/document-cookie-during-iframe-parsing-iframe.html (rev 0)
+++ trunk/LayoutTests/http/tests/cookies/resources/document-cookie-during-iframe-parsing-iframe.html 2020-02-18 06:32:42 UTC (rev 256820)
@@ -0,0 +1,3 @@
+<script>
+top.validateCookiesDuringChildFrameParsing(document.cookie);
+</script>
Added: trunk/LayoutTests/http/tests/cookies/resources/set-cookie-and-serve.php (0 => 256820)
--- trunk/LayoutTests/http/tests/cookies/resources/set-cookie-and-serve.php (rev 0)
+++ trunk/LayoutTests/http/tests/cookies/resources/set-cookie-and-serve.php 2020-02-18 06:32:42 UTC (rev 256820)
@@ -0,0 +1,13 @@
+<?php
+$cookieName = $_GET['cookie-name'];
+$cookieValue = $_GET['cookie-value'];
+$destination = $_GET['destination'];
+header("Content-Type: text/html");
+header("Cache-Control: no-store");
+header("Set-Cookie: ${cookieName}=${cookieValue}; path=/");
+$fp = fopen($destination, 'rb');
+header("Content-Length: " . filesize($destination));
+
+fpassthru($fp);
+exit;
+?>
Property changes on: trunk/LayoutTests/http/tests/cookies/resources/set-cookie-and-serve.php
___________________________________________________________________
Added: svn:executable
+*
\ No newline at end of property
Modified: trunk/Source/WTF/ChangeLog (256819 => 256820)
--- trunk/Source/WTF/ChangeLog 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WTF/ChangeLog 2020-02-18 06:32:42 UTC (rev 256820)
@@ -1,3 +1,16 @@
+2020-02-17 Chris Dumez <[email protected]>
+
+ [WK2][Cocoa] Implement in-WebProcess cookie cache to avoid sync IPC for document.cookie in most cases
+ https://bugs.webkit.org/show_bug.cgi?id=207593
+ <rdar://problem/56027027>
+
+ Reviewed by Antti Koivisto.
+
+ Add build time flags for new feature.
+
+ * wtf/PlatformEnable.h:
+ * wtf/PlatformHave.h:
+
2020-02-17 Tim Horton <[email protected]>
Add and adopt HAVE(LOOKUP_GESTURE_RECOGNIZER)
Modified: trunk/Source/WTF/wtf/HashSet.h (256819 => 256820)
--- trunk/Source/WTF/wtf/HashSet.h 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WTF/wtf/HashSet.h 2020-02-18 06:32:42 UTC (rev 256820)
@@ -112,6 +112,8 @@
// them are new to the set. Returns false if the set is unchanged.
template<typename IteratorType>
bool add(IteratorType begin, IteratorType end);
+ template<typename IteratorType>
+ bool remove(IteratorType begin, IteratorType end);
bool remove(const ValueType&);
bool remove(iterator);
@@ -271,6 +273,16 @@
}
template<typename T, typename U, typename V>
+template<typename IteratorType>
+inline bool HashSet<T, U, V>::remove(IteratorType begin, IteratorType end)
+{
+ bool changed = false;
+ for (IteratorType iter = begin; iter != end; ++iter)
+ changed |= remove(*iter);
+ return changed;
+}
+
+template<typename T, typename U, typename V>
inline bool HashSet<T, U, V>::remove(iterator it)
{
if (it.m_impl == m_impl.end())
Modified: trunk/Source/WTF/wtf/PlatformHave.h (256819 => 256820)
--- trunk/Source/WTF/wtf/PlatformHave.h 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WTF/wtf/PlatformHave.h 2020-02-18 06:32:42 UTC (rev 256820)
@@ -561,6 +561,10 @@
#define HAVE_DEVICE_IDENTITY 1
#endif
+#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101600) || (PLATFORM(IOS_FAMILY) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 140000)
+#define HAVE_COOKIE_CHANGE_LISTENER_API 1
+#endif
+
#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500) || PLATFORM(IOS_FAMILY)
#define HAVE_DATA_PROTECTION_KEYCHAIN 1
#endif
Modified: trunk/Source/WebCore/ChangeLog (256819 => 256820)
--- trunk/Source/WebCore/ChangeLog 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebCore/ChangeLog 2020-02-18 06:32:42 UTC (rev 256820)
@@ -1,5 +1,87 @@
2020-02-17 Chris Dumez <[email protected]>
+ [WK2][Cocoa] Implement in-WebProcess cookie cache to avoid sync IPC for document.cookie in most cases
+ https://bugs.webkit.org/show_bug.cgi?id=207593
+ <rdar://problem/56027027>
+
+ Reviewed by Antti Koivisto.
+
+ Implement in-WebProcess DOM cookie cache for serving `document.cookie` requests from _javascript_.
+
+ The first time document.cookie is called for a given host, the WebProcess will pull in all the
+ non-HTTPOnly cookies for that host from the NetworkProcess (still via sync IPC) and store them
+ in an in-memory cookie store. Later document.cookie calls for this host from this WebProcess
+ will then leverage the in-memory cookie store and avoid doing a sync IPC to the NetworkProcess
+ entirely.
+
+ To maintain the in-process cookie store up-to-date, the WebProcess subscribe for cookie-change
+ notifications from the NetworkProcess, only for the hosts it is interested in.
+
+ If the page's _javascript_ sets a cookie by setting document.cookie, we will not invalidate the
+ cache for performance reasons. Instead, we set the cookie in our in-memory cookie before
+ sending the new cookie to the NetworkProcess.
+
+ For compatibility reasons, any sync IPC to a given host will currently invalidate the cookie
+ cache for this host. This is because this synchronous load may cause cookies to get set
+ synchronously and the page could access document.cookie right after the sync XHR. This behavior
+ is covered by the following existing test:
+ - http/tests/cookies/sync-xhr-set-cookie-invalidates-cache.html
+
+ Another limitation of the current implementation of the cookie cache is that it is currently
+ only leveraged for first party content. This is suboptimal and could be improved in a later
+ iteration. However, the default behavior in Safari is that third-party iframes do not have
+ cookie access unless they request it using the storage access API. We also currently have
+ a limit of 5 hosts with cached cookies per WebProcess.
+
+ Tests: http/tests/cookies/document-cookie-after-showModalDialog.html
+ http/tests/cookies/document-cookie-during-iframe-parsing.html
+
+ * dom/Document.cpp:
+ (WebCore::Document::didLoadResourceSynchronously):
+ * dom/Document.h:
+ * dom/ScriptExecutionContext.cpp:
+ (WebCore::ScriptExecutionContext::didLoadResourceSynchronously):
+ * dom/ScriptExecutionContext.h:
+ * loader/CookieJar.h:
+ * loader/ThreadableLoader.cpp:
+ (WebCore::ThreadableLoader::loadResourceSynchronously):
+ * page/MemoryRelease.cpp:
+ (WebCore::releaseCriticalMemory):
+ * page/Settings.yaml:
+ * platform/network/NetworkStorageSession.h:
+ (WebCore::CookieChangeObserver::~CookieChangeObserver):
+ * platform/network/cf/NetworkStorageSessionCFNet.cpp:
+ (WebCore::NetworkStorageSession::NetworkStorageSession):
+ (WebCore::NetworkStorageSession::cookieStorage const):
+ * platform/network/cocoa/NetworkStorageSessionCocoa.mm:
+ (WebCore::NetworkStorageSession::~NetworkStorageSession):
+ (WebCore::NetworkStorageSession::setCookie):
+ (WebCore::NetworkStorageSession::setCookies):
+ (WebCore::NetworkStorageSession::deleteCookie):
+ (WebCore::nsCookiesToCookieVector):
+ (WebCore::NetworkStorageSession::nsCookieStorage const):
+ (WebCore::createPrivateStorageSession):
+ (WebCore::NetworkStorageSession::httpCookies const):
+ (WebCore::NetworkStorageSession::deleteHTTPCookie const):
+ (WebCore::NetworkStorageSession::setHTTPCookiesForURL const):
+ (WebCore::NetworkStorageSession::httpCookiesForURL const):
+ (WebCore::filterCookies):
+ (WebCore::NetworkStorageSession::cookiesForURL const):
+ (WebCore::NetworkStorageSession::cookiesForSession const):
+ (WebCore::NetworkStorageSession::cookiesForDOM const):
+ (WebCore::NetworkStorageSession::cookieRequestHeaderFieldValue const):
+ (WebCore::NetworkStorageSession::setCookiesFromDOM const):
+ (WebCore::NetworkStorageSession::getRawCookies const):
+ (WebCore::NetworkStorageSession::deleteCookiesForHostnames):
+ (WebCore::NetworkStorageSession::registerCookieChangeListenersIfNecessary):
+ (WebCore::NetworkStorageSession::unregisterCookieChangeListenersIfNecessary):
+ (WebCore::NetworkStorageSession::startListeningForCookieChangeNotifications):
+ (WebCore::NetworkStorageSession::stopListeningForCookieChangeNotifications):
+ (WebCore::NetworkStorageSession::domCookiesForHost):
+ (WebCore::NetworkStorageSession::supportsCookieChangeListenerAPI const):
+
+2020-02-17 Chris Dumez <[email protected]>
+
Defer execution of async scripts until until the document is loaded
https://bugs.webkit.org/show_bug.cgi?id=207698
<rdar://problem/57625747>
Modified: trunk/Source/WebCore/PAL/ChangeLog (256819 => 256820)
--- trunk/Source/WebCore/PAL/ChangeLog 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebCore/PAL/ChangeLog 2020-02-18 06:32:42 UTC (rev 256820)
@@ -1,3 +1,15 @@
+2020-02-17 Chris Dumez <[email protected]>
+
+ [WK2][Cocoa] Implement in-WebProcess cookie cache to avoid sync IPC for document.cookie in most cases
+ https://bugs.webkit.org/show_bug.cgi?id=207593
+ <rdar://problem/56027027>
+
+ Reviewed by Antti Koivisto.
+
+ Add new CFNetwork SPI to CFNetworkSPI.h for open source builds and for using respondsToSelector.
+
+ * pal/spi/cf/CFNetworkSPI.h:
+
2020-02-17 Peng Liu <[email protected]>
Fix check-webkit-style errors related to AVFoundationSPI.h
Modified: trunk/Source/WebCore/PAL/pal/spi/cf/CFNetworkSPI.h (256819 => 256820)
--- trunk/Source/WebCore/PAL/pal/spi/cf/CFNetworkSPI.h 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebCore/PAL/pal/spi/cf/CFNetworkSPI.h 2020-02-18 06:32:42 UTC (rev 256820)
@@ -391,6 +391,10 @@
@interface NSHTTPCookieStorage ()
+ (void)_setSharedHTTPCookieStorage:(NSHTTPCookieStorage *)storage;
+- (void)_setSubscribedDomainsForCookieChanges:(NSSet<NSString*>* __nullable)domainList;
+- (void)_setCookiesAddedHandler:(void(^__nullable)(NSArray<NSHTTPCookie*>* addedCookies, NSURL* __nullable urlForAddedCookies))cookiesAddedHandler onQueue:(dispatch_queue_t __nullable)queue;
+- (void)_setCookiesDeletedHandler:(void(^__nullable)(NSArray<NSHTTPCookie*>* __nullable deletedCookies, bool deletedAllCookies))cookiesDeletedHandler onQueue:(dispatch_queue_t __nullable)queue;
+- (NSArray* __nullable)_getCookiesForDomain:(NSString*)domain;
@end
@interface NSURLResponse ()
Modified: trunk/Source/WebCore/dom/Document.cpp (256819 => 256820)
--- trunk/Source/WebCore/dom/Document.cpp 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebCore/dom/Document.cpp 2020-02-18 06:32:42 UTC (rev 256820)
@@ -7203,11 +7203,14 @@
m_cachedDOMCookies = String();
}
-void Document::didLoadResourceSynchronously()
+void Document::didLoadResourceSynchronously(const URL& url)
{
// Synchronous resources loading can set cookies so we invalidate the cookies cache
// in this case, to be safe.
invalidateDOMCookieCache();
+
+ if (auto* page = this->page())
+ page->cookieJar().clearCacheForHost(url.host().toString());
}
void Document::ensurePlugInsInjectedScript(DOMWrapperWorld& world)
Modified: trunk/Source/WebCore/dom/Document.h (256819 => 256820)
--- trunk/Source/WebCore/dom/Document.h 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebCore/dom/Document.h 2020-02-18 06:32:42 UTC (rev 256820)
@@ -1641,7 +1641,7 @@
void setCachedDOMCookies(const String&);
bool isDOMCookieCacheValid() const { return m_cookieCacheExpiryTimer.isActive(); }
void invalidateDOMCookieCache();
- void didLoadResourceSynchronously() final;
+ void didLoadResourceSynchronously(const URL&) final;
bool canNavigateInternal(Frame& targetFrame);
bool isNavigationBlockedByThirdPartyIFrameRedirectBlocking(Frame& targetFrame, const URL& destinationURL);
Modified: trunk/Source/WebCore/dom/ScriptExecutionContext.cpp (256819 => 256820)
--- trunk/Source/WebCore/dom/ScriptExecutionContext.cpp 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebCore/dom/ScriptExecutionContext.cpp 2020-02-18 06:32:42 UTC (rev 256820)
@@ -218,7 +218,7 @@
m_messagePorts.remove(&messagePort);
}
-void ScriptExecutionContext::didLoadResourceSynchronously()
+void ScriptExecutionContext::didLoadResourceSynchronously(const URL&)
{
}
Modified: trunk/Source/WebCore/dom/ScriptExecutionContext.h (256819 => 256820)
--- trunk/Source/WebCore/dom/ScriptExecutionContext.h 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebCore/dom/ScriptExecutionContext.h 2020-02-18 06:32:42 UTC (rev 256820)
@@ -152,7 +152,7 @@
void createdMessagePort(MessagePort&);
void destroyedMessagePort(MessagePort&);
- virtual void didLoadResourceSynchronously();
+ virtual void didLoadResourceSynchronously(const URL&);
void ref() { refScriptExecutionContext(); }
void deref() { derefScriptExecutionContext(); }
Modified: trunk/Source/WebCore/loader/CookieJar.h (256819 => 256820)
--- trunk/Source/WebCore/loader/CookieJar.h 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebCore/loader/CookieJar.h 2020-02-18 06:32:42 UTC (rev 256820)
@@ -60,6 +60,10 @@
virtual bool getRawCookies(const Document&, const URL&, Vector<Cookie>&) const;
virtual void deleteCookie(const Document&, const URL&, const String& cookieName);
+ // Cookie Cache.
+ virtual void clearCache() { }
+ virtual void clearCacheForHost(const String&) { }
+
virtual ~CookieJar();
protected:
static SameSiteInfo sameSiteInfo(const Document&);
Modified: trunk/Source/WebCore/loader/ThreadableLoader.cpp (256819 => 256820)
--- trunk/Source/WebCore/loader/ThreadableLoader.cpp 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebCore/loader/ThreadableLoader.cpp 2020-02-18 06:32:42 UTC (rev 256820)
@@ -110,11 +110,12 @@
void ThreadableLoader::loadResourceSynchronously(ScriptExecutionContext& context, ResourceRequest&& request, ThreadableLoaderClient& client, const ThreadableLoaderOptions& options)
{
+ auto resourceURL = request.url();
if (is<WorkerGlobalScope>(context))
WorkerThreadableLoader::loadResourceSynchronously(downcast<WorkerGlobalScope>(context), WTFMove(request), client, options);
else
DocumentThreadableLoader::loadResourceSynchronously(downcast<Document>(context), WTFMove(request), client, options);
- context.didLoadResourceSynchronously();
+ context.didLoadResourceSynchronously(resourceURL);
}
void ThreadableLoader::logError(ScriptExecutionContext& context, const ResourceError& error, const String& initiator)
Modified: trunk/Source/WebCore/page/MemoryRelease.cpp (256819 => 256820)
--- trunk/Source/WebCore/page/MemoryRelease.cpp 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebCore/page/MemoryRelease.cpp 2020-02-18 06:32:42 UTC (rev 256820)
@@ -33,6 +33,7 @@
#include "Chrome.h"
#include "ChromeClient.h"
#include "CommonVM.h"
+#include "CookieJar.h"
#include "Document.h"
#include "FontCache.h"
#include "Frame.h"
@@ -99,6 +100,10 @@
CSSValuePool::singleton().drain();
+ Page::forEachPage([](auto& page) {
+ page.cookieJar().clearCache();
+ });
+
for (auto& document : copyToVectorOf<RefPtr<Document>>(Document::allDocuments())) {
document->styleScope().releaseMemory();
document->fontSelector().emptyCaches();
Modified: trunk/Source/WebCore/page/Settings.yaml (256819 => 256820)
--- trunk/Source/WebCore/page/Settings.yaml 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebCore/page/Settings.yaml 2020-02-18 06:32:42 UTC (rev 256820)
@@ -361,6 +361,9 @@
HTTPSUpgradeEnabled:
initial: false
+inProcessCookieCacheEnabled:
+ initial: false
+
thirdPartyIframeRedirectBlockingEnabled:
initial: true
Modified: trunk/Source/WebCore/platform/network/NetworkStorageSession.cpp (256819 => 256820)
--- trunk/Source/WebCore/platform/network/NetworkStorageSession.cpp 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebCore/platform/network/NetworkStorageSession.cpp 2020-02-18 06:32:42 UTC (rev 256820)
@@ -26,6 +26,7 @@
#include "config.h"
#include "NetworkStorageSession.h"
+#include "Cookie.h"
#include "HTTPCookieAcceptPolicy.h"
#include "RuntimeApplicationChecks.h"
#include <wtf/NeverDestroyed.h>
@@ -56,6 +57,14 @@
removeProcessPrivilege(ProcessPrivilege::CanAccessRawCookies);
}
+#if !PLATFORM(COCOA)
+Vector<Cookie> NetworkStorageSession::domCookiesForHost(const String&)
+{
+ ASSERT_NOT_IMPLEMENTED_YET();
+ return { };
+}
+#endif // !PLATFORM(COCOA)
+
#if ENABLE(RESOURCE_LOAD_STATISTICS)
bool NetworkStorageSession::shouldBlockThirdPartyCookies(const RegistrableDomain& registrableDomain) const
Modified: trunk/Source/WebCore/platform/network/NetworkStorageSession.h (256819 => 256820)
--- trunk/Source/WebCore/platform/network/NetworkStorageSession.h 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebCore/platform/network/NetworkStorageSession.h 2020-02-18 06:32:42 UTC (rev 256820)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2020 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -60,6 +60,9 @@
#if PLATFORM(COCOA)
#include "CookieStorageObserver.h"
+OBJC_CLASS NSArray;
+OBJC_CLASS NSHTTPCookie;
+OBJC_CLASS NSMutableSet;
#endif
namespace WebCore {
@@ -79,6 +82,15 @@
enum class FirstPartyWebsiteDataRemovalMode : uint8_t { AllButCookies, None, AllButCookiesLiveOnTestingTimeout, AllButCookiesReproTestingTimeout };
enum class ShouldAskITP : bool { No, Yes };
+#if HAVE(COOKIE_CHANGE_LISTENER_API)
+class CookieChangeObserver {
+public:
+ virtual ~CookieChangeObserver() { }
+ virtual void cookiesAdded(const String& host, const Vector<WebCore::Cookie>&) = 0;
+ virtual void cookiesDeleted() = 0;
+};
+#endif
+
class NetworkStorageSession {
WTF_MAKE_NONCOPYABLE(NetworkStorageSession); WTF_MAKE_FAST_ALLOCATED;
public:
@@ -92,9 +104,14 @@
WEBCORE_EXPORT NSHTTPCookieStorage *nsCookieStorage() const;
#endif
+#if PLATFORM(COCOA)
+ WEBCORE_EXPORT ~NetworkStorageSession();
+#endif
+
#if PLATFORM(COCOA) || USE(CFURLCONNECTION)
WEBCORE_EXPORT static RetainPtr<CFURLStorageSessionRef> createCFStorageSessionForIdentifier(CFStringRef identifier);
- WEBCORE_EXPORT NetworkStorageSession(PAL::SessionID, RetainPtr<CFURLStorageSessionRef>&&, RetainPtr<CFHTTPCookieStorageRef>&&);
+ enum class IsInMemoryCookieStore : bool { No, Yes };
+ WEBCORE_EXPORT NetworkStorageSession(PAL::SessionID, RetainPtr<CFURLStorageSessionRef>&&, RetainPtr<CFHTTPCookieStorageRef>&&, IsInMemoryCookieStore = IsInMemoryCookieStore::No);
WEBCORE_EXPORT explicit NetworkStorageSession(PAL::SessionID);
// May be null, in which case a Foundation default should be used.
@@ -146,6 +163,14 @@
WEBCORE_EXPORT std::pair<String, bool> cookieRequestHeaderFieldValue(const URL& firstParty, const SameSiteInfo&, const URL&, Optional<FrameIdentifier>, Optional<PageIdentifier>, IncludeSecureCookies, ShouldAskITP) const;
WEBCORE_EXPORT std::pair<String, bool> cookieRequestHeaderFieldValue(const CookieRequestHeaderFieldProxy&) const;
+ WEBCORE_EXPORT Vector<Cookie> domCookiesForHost(const String& host);
+
+#if HAVE(COOKIE_CHANGE_LISTENER_API)
+ WEBCORE_EXPORT void startListeningForCookieChangeNotifications(CookieChangeObserver&, const String& host);
+ WEBCORE_EXPORT void stopListeningForCookieChangeNotifications(CookieChangeObserver&, const HashSet<String>& hosts);
+ WEBCORE_EXPORT bool supportsCookieChangeListenerAPI() const;
+#endif
+
#if ENABLE(RESOURCE_LOAD_STATISTICS)
void setResourceLoadStatisticsEnabled(bool enabled) { m_isResourceLoadStatisticsEnabled = enabled; }
WEBCORE_EXPORT bool shouldBlockCookies(const ResourceRequest&, Optional<FrameIdentifier>, Optional<PageIdentifier>) const;
@@ -173,11 +198,27 @@
#endif
private:
+#if PLATFORM(COCOA)
+ enum IncludeHTTPOnlyOrNot { DoNotIncludeHTTPOnly, IncludeHTTPOnly };
+ std::pair<String, bool> cookiesForSession(const URL& firstParty, const SameSiteInfo&, const URL&, Optional<FrameIdentifier>, Optional<PageIdentifier>, IncludeHTTPOnlyOrNot, IncludeSecureCookies, ShouldAskITP = ShouldAskITP::Yes) const;
+ NSArray *httpCookies(CFHTTPCookieStorageRef) const;
+ NSArray *httpCookiesForURL(CFHTTPCookieStorageRef, NSURL *firstParty, const Optional<SameSiteInfo>&, NSURL *) const;
+ NSArray *cookiesForURL(const URL& firstParty, const SameSiteInfo&, const URL&, Optional<FrameIdentifier>, Optional<PageIdentifier>, ShouldAskITP) const;
+ void setHTTPCookiesForURL(CFHTTPCookieStorageRef, NSArray *cookies, NSURL *, NSURL *mainDocumentURL, const SameSiteInfo&) const;
+ void deleteHTTPCookie(CFHTTPCookieStorageRef, NSHTTPCookie *) const;
+#endif
+
+#if HAVE(COOKIE_CHANGE_LISTENER_API)
+ void registerCookieChangeListenersIfNecessary();
+ void unregisterCookieChangeListenersIfNecessary();
+#endif
+
PAL::SessionID m_sessionID;
#if PLATFORM(COCOA) || USE(CFURLCONNECTION)
RetainPtr<CFURLStorageSessionRef> m_platformSession;
RetainPtr<CFHTTPCookieStorageRef> m_platformCookieStorage;
+ bool m_isInMemoryCookieStore { false };
#elif USE(SOUP)
static void cookiesDidChange(NetworkStorageSession*);
@@ -190,6 +231,12 @@
RefPtr<NetworkingContext> m_context;
#endif
+#if HAVE(COOKIE_CHANGE_LISTENER_API)
+ bool m_didRegisterCookieListeners { false };
+ RetainPtr<NSMutableSet> m_subscribedDomainsForCookieChanges;
+ HashMap<String, HashSet<CookieChangeObserver*>> m_cookieChangeObservers;
+#endif
+
CredentialStorage m_credentialStorage;
#if ENABLE(RESOURCE_LOAD_STATISTICS)
Modified: trunk/Source/WebCore/platform/network/cf/NetworkStorageSessionCFNet.cpp (256819 => 256820)
--- trunk/Source/WebCore/platform/network/cf/NetworkStorageSessionCFNet.cpp 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebCore/platform/network/cf/NetworkStorageSessionCFNet.cpp 2020-02-18 06:32:42 UTC (rev 256820)
@@ -73,11 +73,12 @@
return storageSession;
}
-NetworkStorageSession::NetworkStorageSession(PAL::SessionID sessionID, RetainPtr<CFURLStorageSessionRef>&& platformSession, RetainPtr<CFHTTPCookieStorageRef>&& platformCookieStorage)
+NetworkStorageSession::NetworkStorageSession(PAL::SessionID sessionID, RetainPtr<CFURLStorageSessionRef>&& platformSession, RetainPtr<CFHTTPCookieStorageRef>&& platformCookieStorage, IsInMemoryCookieStore isInMemoryCookieStore)
: m_sessionID(sessionID)
, m_platformSession(WTFMove(platformSession))
+ , m_isInMemoryCookieStore(isInMemoryCookieStore == IsInMemoryCookieStore::Yes)
{
- ASSERT(processMayUseCookieAPI() || !platformCookieStorage);
+ ASSERT(processMayUseCookieAPI() || !platformCookieStorage || m_isInMemoryCookieStore);
m_platformCookieStorage = platformCookieStorage ? WTFMove(platformCookieStorage) : cookieStorage();
}
@@ -88,10 +89,10 @@
RetainPtr<CFHTTPCookieStorageRef> NetworkStorageSession::cookieStorage() const
{
- if (!processMayUseCookieAPI())
+ if (!processMayUseCookieAPI() && !m_isInMemoryCookieStore)
return nullptr;
- ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
+ ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies) || m_isInMemoryCookieStore);
if (m_platformCookieStorage)
return m_platformCookieStorage;
Modified: trunk/Source/WebCore/platform/network/cocoa/NetworkStorageSessionCocoa.mm (256819 => 256820)
--- trunk/Source/WebCore/platform/network/cocoa/NetworkStorageSessionCocoa.mm 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebCore/platform/network/cocoa/NetworkStorageSessionCocoa.mm 2020-02-18 06:32:42 UTC (rev 256820)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2020 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -44,9 +44,16 @@
namespace WebCore {
+NetworkStorageSession::~NetworkStorageSession()
+{
+#if HAVE(COOKIE_CHANGE_LISTENER_API)
+ unregisterCookieChangeListenersIfNecessary();
+#endif
+}
+
void NetworkStorageSession::setCookie(const Cookie& cookie)
{
- ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
+ ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies) || m_isInMemoryCookieStore);
BEGIN_BLOCK_OBJC_EXCEPTIONS;
[nsCookieStorage() setCookie:(NSHTTPCookie *)cookie];
@@ -55,7 +62,7 @@
void NetworkStorageSession::setCookies(const Vector<Cookie>& cookies, const URL& url, const URL& mainDocumentURL)
{
- ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
+ ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies) || m_isInMemoryCookieStore);
RetainPtr<NSMutableArray> nsCookies = adoptNS([[NSMutableArray alloc] initWithCapacity:cookies.size()]);
for (const auto& cookie : cookies)
@@ -68,19 +75,18 @@
void NetworkStorageSession::deleteCookie(const Cookie& cookie)
{
- ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
+ ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies) || m_isInMemoryCookieStore);
[nsCookieStorage() deleteCookie:(NSHTTPCookie *)cookie];
}
-static Vector<Cookie> nsCookiesToCookieVector(NSArray<NSHTTPCookie *> *nsCookies)
+static Vector<Cookie> nsCookiesToCookieVector(NSArray<NSHTTPCookie *> *nsCookies, const Function<bool(NSHTTPCookie *)>& filter = { })
{
- ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
-
Vector<Cookie> cookies;
cookies.reserveInitialCapacity(nsCookies.count);
- for (NSHTTPCookie *nsCookie in nsCookies)
- cookies.uncheckedAppend(nsCookie);
-
+ for (NSHTTPCookie *nsCookie in nsCookies) {
+ if (!filter || filter(nsCookie))
+ cookies.uncheckedAppend(nsCookie);
+ }
return cookies;
}
@@ -118,7 +124,7 @@
NSHTTPCookieStorage *NetworkStorageSession::nsCookieStorage() const
{
- ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
+ ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies) || m_isInMemoryCookieStore);
auto cfCookieStorage = cookieStorage();
if (!cfCookieStorage || [NSHTTPCookieStorage sharedHTTPCookieStorage]._cookieStorage == cfCookieStorage)
return [NSHTTPCookieStorage sharedHTTPCookieStorage];
@@ -158,11 +164,6 @@
CFURLCacheSetDiskCapacity(cache.get(), 0); // Setting disk cache size should not be necessary once <rdar://problem/12656814> is fixed.
CFURLCacheSetMemoryCapacity(cache.get(), [[NSURLCache sharedURLCache] memoryCapacity]);
- if (!NetworkStorageSession::processMayUseCookieAPI())
- return storageSession.leakRef();
-
- ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
-
auto cookieStorage = adoptCF(_CFURLStorageSessionCopyCookieStorage(kCFAllocatorDefault, storageSession.get()));
if (!cookieStorage)
return nullptr;
@@ -173,20 +174,23 @@
return storageSession.leakRef();
}
-static NSArray *httpCookies(CFHTTPCookieStorageRef cookieStorage)
+NSArray *NetworkStorageSession::httpCookies(CFHTTPCookieStorageRef cookieStorage) const
{
- ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
- if (!cookieStorage)
+ ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies) || m_isInMemoryCookieStore);
+ if (!cookieStorage) {
+ RELEASE_ASSERT(!m_isInMemoryCookieStore);
return [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
+ }
auto cookies = adoptCF(CFHTTPCookieStorageCopyCookies(cookieStorage));
return [NSHTTPCookie _cf2nsCookies:cookies.get()];
}
-static void deleteHTTPCookie(CFHTTPCookieStorageRef cookieStorage, NSHTTPCookie *cookie)
+void NetworkStorageSession::deleteHTTPCookie(CFHTTPCookieStorageRef cookieStorage, NSHTTPCookie *cookie) const
{
- ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
+ ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies) || m_isInMemoryCookieStore);
if (!cookieStorage) {
+ RELEASE_ASSERT(!m_isInMemoryCookieStore);
[[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie:cookie];
return;
}
@@ -226,9 +230,9 @@
return cookiesPtr->autorelease();
}
-static void setHTTPCookiesForURL(CFHTTPCookieStorageRef cookieStorage, NSArray *cookies, NSURL *url, NSURL *mainDocumentURL, const SameSiteInfo& sameSiteInfo)
+void NetworkStorageSession::setHTTPCookiesForURL(CFHTTPCookieStorageRef cookieStorage, NSArray *cookies, NSURL *url, NSURL *mainDocumentURL, const SameSiteInfo& sameSiteInfo) const
{
- ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
+ ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies) || m_isInMemoryCookieStore);
if (!cookieStorage) {
#if !(PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101400) && !PLATFORM(WATCHOS) && !PLATFORM(APPLETV)
if ([NSHTTPCookieStorage instancesRespondToSelector:@selector(_setCookies:forURL:mainDocumentURL:policyProperties:)])
@@ -255,21 +259,22 @@
#endif
}
-static NSArray *httpCookiesForURL(CFHTTPCookieStorageRef cookieStorage, NSURL *firstParty, const Optional<SameSiteInfo>& sameSiteInfo, NSURL *url)
+NSArray *NetworkStorageSession::httpCookiesForURL(CFHTTPCookieStorageRef cookieStorage, NSURL *firstParty, const Optional<SameSiteInfo>& sameSiteInfo, NSURL *url) const
{
- ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
- if (!cookieStorage)
+ ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies) || m_isInMemoryCookieStore);
+ if (!cookieStorage) {
+ RELEASE_ASSERT(!m_isInMemoryCookieStore);
cookieStorage = _CFHTTPCookieStorageGetDefault(kCFAllocatorDefault);
+ }
// FIXME: Stop creating a new NSHTTPCookieStorage object each time we want to query the cookie jar.
// NetworkStorageSession could instead keep a NSHTTPCookieStorage object for us.
RetainPtr<NSHTTPCookieStorage> nsCookieStorage = adoptNS([[NSHTTPCookieStorage alloc] _initWithCFHTTPCookieStorage:cookieStorage]);
- return cookiesForURL(nsCookieStorage.get(), url, firstParty, sameSiteInfo);
+ return WebCore::cookiesForURL(nsCookieStorage.get(), url, firstParty, sameSiteInfo);
}
static RetainPtr<NSArray> filterCookies(NSArray *unfilteredCookies, Optional<Seconds> cappedLifetime)
{
- ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
NSUInteger count = [unfilteredCookies count];
RetainPtr<NSMutableArray> filteredCookies = adoptNS([[NSMutableArray alloc] initWithCapacity:count]);
@@ -302,10 +307,10 @@
return filteredCookies;
}
-static NSArray *cookiesForURL(const NetworkStorageSession& session, const URL& firstParty, const SameSiteInfo& sameSiteInfo, const URL& url, Optional<FrameIdentifier> frameID, Optional<PageIdentifier> pageID, ShouldAskITP shouldAskITP)
+NSArray *NetworkStorageSession::cookiesForURL(const URL& firstParty, const SameSiteInfo& sameSiteInfo, const URL& url, Optional<FrameIdentifier> frameID, Optional<PageIdentifier> pageID, ShouldAskITP shouldAskITP) const
{
#if ENABLE(RESOURCE_LOAD_STATISTICS)
- if (shouldAskITP == ShouldAskITP::Yes && session.shouldBlockCookies(firstParty, url, frameID, pageID))
+ if (shouldAskITP == ShouldAskITP::Yes && shouldBlockCookies(firstParty, url, frameID, pageID))
return nil;
#else
UNUSED_PARAM(frameID);
@@ -312,17 +317,16 @@
UNUSED_PARAM(pageID);
UNUSED_PARAM(shouldAskITP);
#endif
- return httpCookiesForURL(session.cookieStorage().get(), firstParty, sameSiteInfo, url);
+ return httpCookiesForURL(cookieStorage().get(), firstParty, sameSiteInfo, url);
}
-enum IncludeHTTPOnlyOrNot { DoNotIncludeHTTPOnly, IncludeHTTPOnly };
-static std::pair<String, bool> cookiesForSession(const NetworkStorageSession& session, const URL& firstParty, const SameSiteInfo& sameSiteInfo, const URL& url, Optional<FrameIdentifier> frameID, Optional<PageIdentifier> pageID, IncludeHTTPOnlyOrNot includeHTTPOnly, IncludeSecureCookies includeSecureCookies, ShouldAskITP shouldAskITP = ShouldAskITP::Yes)
+std::pair<String, bool> NetworkStorageSession::cookiesForSession(const URL& firstParty, const SameSiteInfo& sameSiteInfo, const URL& url, Optional<FrameIdentifier> frameID, Optional<PageIdentifier> pageID, IncludeHTTPOnlyOrNot includeHTTPOnly, IncludeSecureCookies includeSecureCookies, ShouldAskITP shouldAskITP) const
{
- ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
+ ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies) || m_isInMemoryCookieStore);
BEGIN_BLOCK_OBJC_EXCEPTIONS;
- NSArray *cookies = cookiesForURL(session, firstParty, sameSiteInfo, url, frameID, pageID, shouldAskITP);
+ NSArray *cookies = cookiesForURL(firstParty, sameSiteInfo, url, frameID, pageID, shouldAskITP);
if (![cookies count])
return { String(), false }; // Return a null string, not an empty one that StringBuilder would create below.
@@ -374,22 +378,22 @@
std::pair<String, bool> NetworkStorageSession::cookiesForDOM(const URL& firstParty, const SameSiteInfo& sameSiteInfo, const URL& url, Optional<FrameIdentifier> frameID, Optional<PageIdentifier> pageID, IncludeSecureCookies includeSecureCookies, ShouldAskITP shouldAskITP) const
{
- return cookiesForSession(*this, firstParty, sameSiteInfo, url, frameID, pageID, DoNotIncludeHTTPOnly, includeSecureCookies, shouldAskITP);
+ return cookiesForSession(firstParty, sameSiteInfo, url, frameID, pageID, DoNotIncludeHTTPOnly, includeSecureCookies, shouldAskITP);
}
std::pair<String, bool> NetworkStorageSession::cookieRequestHeaderFieldValue(const URL& firstParty, const SameSiteInfo& sameSiteInfo, const URL& url, Optional<FrameIdentifier> frameID, Optional<PageIdentifier> pageID, IncludeSecureCookies includeSecureCookies, ShouldAskITP shouldAskITP) const
{
- return cookiesForSession(*this, firstParty, sameSiteInfo, url, frameID, pageID, IncludeHTTPOnly, includeSecureCookies, shouldAskITP);
+ return cookiesForSession(firstParty, sameSiteInfo, url, frameID, pageID, IncludeHTTPOnly, includeSecureCookies, shouldAskITP);
}
std::pair<String, bool> NetworkStorageSession::cookieRequestHeaderFieldValue(const CookieRequestHeaderFieldProxy& headerFieldProxy) const
{
- return cookiesForSession(*this, headerFieldProxy.firstParty, headerFieldProxy.sameSiteInfo, headerFieldProxy.url, headerFieldProxy.frameID, headerFieldProxy.pageID, IncludeHTTPOnly, headerFieldProxy.includeSecureCookies);
+ return cookiesForSession(headerFieldProxy.firstParty, headerFieldProxy.sameSiteInfo, headerFieldProxy.url, headerFieldProxy.frameID, headerFieldProxy.pageID, IncludeHTTPOnly, headerFieldProxy.includeSecureCookies);
}
void NetworkStorageSession::setCookiesFromDOM(const URL& firstParty, const SameSiteInfo& sameSiteInfo, const URL& url, Optional<FrameIdentifier> frameID, Optional<PageIdentifier> pageID, ShouldAskITP shouldAskITP, const String& cookieStr) const
{
- ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
+ ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies) || m_isInMemoryCookieStore);
BEGIN_BLOCK_OBJC_EXCEPTIONS;
@@ -457,7 +461,7 @@
rawCookies.clear();
BEGIN_BLOCK_OBJC_EXCEPTIONS;
- NSArray *cookies = cookiesForURL(*this, firstParty, sameSiteInfo, url, frameID, pageID, shouldAskITP);
+ NSArray *cookies = cookiesForURL(firstParty, sameSiteInfo, url, frameID, pageID, shouldAskITP);
NSUInteger count = [cookies count];
rawCookies.reserveCapacity(count);
for (NSUInteger i = 0; i < count; ++i) {
@@ -518,7 +522,7 @@
void NetworkStorageSession::deleteCookiesForHostnames(const Vector<String>& hostnames, IncludeHttpOnlyCookies includeHttpOnlyCookies)
{
- ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
+ ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies) || m_isInMemoryCookieStore);
BEGIN_BLOCK_OBJC_EXCEPTIONS;
@@ -566,4 +570,98 @@
[storage _saveCookies];
}
+Vector<Cookie> NetworkStorageSession::domCookiesForHost(const String& host)
+{
+ NSArray *nsCookies = [nsCookieStorage() _getCookiesForDomain:(NSString *)host];
+ return nsCookiesToCookieVector(nsCookies, [](NSHTTPCookie *cookie) { return !cookie.HTTPOnly; });
+}
+
+#if HAVE(COOKIE_CHANGE_LISTENER_API)
+
+void NetworkStorageSession::registerCookieChangeListenersIfNecessary()
+{
+ if (m_didRegisterCookieListeners)
+ return;
+
+ m_didRegisterCookieListeners = true;
+ [nsCookieStorage() _setCookiesAddedHandler:^(NSArray<NSHTTPCookie *> * nsCookies, NSURL *urlForAddedCookies) {
+ Vector<Cookie> cookies = nsCookiesToCookieVector(nsCookies);
+ auto host = URL(urlForAddedCookies).host().toString();
+ RELEASE_ASSERT(!host.isNull());
+ auto it = m_cookieChangeObservers.find(host);
+ if (it == m_cookieChangeObservers.end())
+ return;
+ for (auto* observer : it->value)
+ observer->cookiesAdded(host, cookies);
+ } onQueue:dispatch_get_main_queue()];
+ [nsCookieStorage() _setCookiesDeletedHandler:^(NSArray<NSHTTPCookie *> *, bool /*deletedAllCookies*/) {
+ for (auto& observers : m_cookieChangeObservers.values()) {
+ for (auto* observer : observers)
+ observer->cookiesDeleted();
+ }
+ } onQueue:dispatch_get_main_queue()];
+}
+
+void NetworkStorageSession::unregisterCookieChangeListenersIfNecessary()
+{
+ if (!m_didRegisterCookieListeners)
+ return;
+
+ [nsCookieStorage() _setCookiesAddedHandler:nil onQueue:nil];
+ [nsCookieStorage() _setCookiesDeletedHandler:nil onQueue:nil];
+ [nsCookieStorage() _setSubscribedDomainsForCookieChanges:nil];
+ m_didRegisterCookieListeners = false;
+}
+
+void NetworkStorageSession::startListeningForCookieChangeNotifications(CookieChangeObserver& observer, const String& host)
+{
+ registerCookieChangeListenersIfNecessary();
+
+ auto& observers = m_cookieChangeObservers.ensure(host, [] {
+ return HashSet<CookieChangeObserver*> { };
+ }).iterator->value;
+ ASSERT(!observers.contains(&observer));
+ observers.add(&observer);
+
+ if (!m_subscribedDomainsForCookieChanges)
+ m_subscribedDomainsForCookieChanges = adoptNS([[NSMutableSet alloc] init]);
+ else if ([m_subscribedDomainsForCookieChanges containsObject:(NSString *)host])
+ return;
+
+ [m_subscribedDomainsForCookieChanges addObject:(NSString *)host];
+ [nsCookieStorage() _setSubscribedDomainsForCookieChanges:m_subscribedDomainsForCookieChanges.get()];
+}
+
+void NetworkStorageSession::stopListeningForCookieChangeNotifications(CookieChangeObserver& observer, const HashSet<String>& hosts)
+{
+ bool subscribedURLsChanged = false;
+ for (auto& host : hosts) {
+ auto it = m_cookieChangeObservers.find(host);
+ ASSERT(it != m_cookieChangeObservers.end());
+ if (it == m_cookieChangeObservers.end())
+ continue;
+
+ auto& observers = it->value;
+ ASSERT(observers.contains(&observer));
+ observers.remove(&observer);
+ if (observers.isEmpty()) {
+ m_cookieChangeObservers.remove(it);
+ ASSERT([m_subscribedDomainsForCookieChanges containsObject:(NSString *)host]);
+ [m_subscribedDomainsForCookieChanges removeObject:(NSString *)host];
+ subscribedURLsChanged = true;
+ }
+ }
+ if (subscribedURLsChanged)
+ [nsCookieStorage() _setSubscribedDomainsForCookieChanges:m_subscribedDomainsForCookieChanges.get()];
+}
+
+// FIXME: This can eventually go away, this is merely to ensure a smooth transition to the new API.
+bool NetworkStorageSession::supportsCookieChangeListenerAPI() const
+{
+ static const bool supportsAPI = [nsCookieStorage() respondsToSelector:@selector(_setSubscribedDomainsForCookieChanges:)];
+ return supportsAPI;
+}
+
+#endif // HAVE(COOKIE_CHANGE_LISTENER_API)
+
} // namespace WebCore
Modified: trunk/Source/WebKit/ChangeLog (256819 => 256820)
--- trunk/Source/WebKit/ChangeLog 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebKit/ChangeLog 2020-02-18 06:32:42 UTC (rev 256820)
@@ -1,5 +1,61 @@
2020-02-17 Chris Dumez <[email protected]>
+ [WK2][Cocoa] Implement in-WebProcess cookie cache to avoid sync IPC for document.cookie in most cases
+ https://bugs.webkit.org/show_bug.cgi?id=207593
+ <rdar://problem/56027027>
+
+ Reviewed by Antti Koivisto.
+
+ See WebCore ChangeLog.
+
+ * NetworkProcess/NetworkConnectionToWebProcess.cpp:
+ (WebKit::NetworkConnectionToWebProcess::~NetworkConnectionToWebProcess):
+ (WebKit::NetworkConnectionToWebProcess::domCookiesForHost):
+ (WebKit::NetworkConnectionToWebProcess::unsubscribeFromCookieChangeNotifications):
+ (WebKit::NetworkConnectionToWebProcess::cookiesAdded):
+ (WebKit::NetworkConnectionToWebProcess::cookiesDeleted):
+ * NetworkProcess/NetworkConnectionToWebProcess.h:
+ * NetworkProcess/NetworkConnectionToWebProcess.messages.in:
+ * Scripts/webkit/messages.py:
+ * Shared/WebPreferences.yaml:
+ * Sources.txt:
+ * SourcesCocoa.txt:
+ * WebKit.xcodeproj/project.pbxproj:
+ * WebProcess/Network/NetworkProcessConnection.cpp:
+ (WebKit::NetworkProcessConnection::cookiesAdded):
+ (WebKit::NetworkProcessConnection::cookiesDeleted):
+ * WebProcess/Network/NetworkProcessConnection.h:
+ * WebProcess/Network/NetworkProcessConnection.messages.in:
+ * WebProcess/WebPage/Cocoa/WebCookieCacheCocoa.mm: Copied from Source/WebKit/WebProcess/WebPage/WebCookieJar.h.
+ (WebKit::WebCookieCache::inMemoryStorageSession):
+ * WebProcess/WebPage/WebCookieCache.cpp: Added.
+ (WebKit::WebCookieCache::isFunctional):
+ (WebKit::WebCookieCache::cookiesForDOM):
+ (WebKit::WebCookieCache::setCookiesFromDOM):
+ (WebKit::WebCookieCache::cookiesAdded):
+ (WebKit::WebCookieCache::cookiesDeleted):
+ (WebKit::WebCookieCache::clear):
+ (WebKit::WebCookieCache::clearForHost):
+ (WebKit::WebCookieCache::pruneCacheIfNecessary):
+ * WebProcess/WebPage/WebCookieCache.h: Copied from Source/WebKit/WebProcess/WebPage/WebCookieJar.h.
+ * WebProcess/WebPage/WebCookieJar.cpp:
+ (WebKit::WebCookieJar::isEligibleForCache const):
+ (WebKit::WebCookieJar::cookies const):
+ (WebKit::WebCookieJar::setCookies):
+ (WebKit::WebCookieJar::cookiesAdded):
+ (WebKit::WebCookieJar::cookiesDeleted):
+ (WebKit::WebCookieJar::clearCache):
+ (WebKit::WebCookieJar::clearCacheForHost):
+ * WebProcess/WebPage/WebCookieJar.h:
+ * WebProcess/WebPage/WebPage.cpp:
+ (WebKit::m_overriddenMediaType):
+ * WebProcess/WebProcess.cpp:
+ (WebKit::WebProcess::WebProcess):
+ * WebProcess/WebProcess.h:
+ (WebKit::WebProcess::cookieJar):
+
+2020-02-17 Chris Dumez <[email protected]>
+
Defer execution of async scripts until until the document is loaded
https://bugs.webkit.org/show_bug.cgi?id=207698
<rdar://problem/57625747>
Modified: trunk/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp (256819 => 256820)
--- trunk/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp 2020-02-18 06:32:42 UTC (rev 256820)
@@ -124,6 +124,11 @@
for (auto& port : m_processEntangledPorts)
networkProcess().messagePortChannelRegistry().didCloseMessagePort(port);
+#if HAVE(COOKIE_CHANGE_LISTENER_API)
+ if (auto* networkStorageSession = storageSession())
+ networkStorageSession->stopListeningForCookieChangeNotifications(*this, m_hostsWithCookieListeners);
+#endif
+
#if USE(LIBWEBRTC)
if (m_rtcProvider)
m_rtcProvider->close();
@@ -633,6 +638,48 @@
networkStorageSession->deleteCookie(url, cookieName);
}
+void NetworkConnectionToWebProcess::domCookiesForHost(const String& host, bool subscribeToCookieChangeNotifications, CompletionHandler<void(const Vector<WebCore::Cookie>&)>&& completionHandler)
+{
+ auto* networkStorageSession = storageSession();
+ if (!networkStorageSession)
+ return completionHandler({ });
+
+#if HAVE(COOKIE_CHANGE_LISTENER_API)
+ if (subscribeToCookieChangeNotifications) {
+ ASSERT(!m_hostsWithCookieListeners.contains(host));
+ m_hostsWithCookieListeners.add(host);
+ networkStorageSession->startListeningForCookieChangeNotifications(*this, host);
+ }
+#else
+ UNUSED_PARAM(subscribeToCookieChangeNotifications);
+#endif
+
+ completionHandler(networkStorageSession->domCookiesForHost(host));
+}
+
+#if HAVE(COOKIE_CHANGE_LISTENER_API)
+
+void NetworkConnectionToWebProcess::unsubscribeFromCookieChangeNotifications(const HashSet<String>& hosts)
+{
+ bool removed = m_hostsWithCookieListeners.remove(hosts.begin(), hosts.end());
+ ASSERT_UNUSED(removed, removed);
+
+ if (auto* networkStorageSession = storageSession())
+ networkStorageSession->stopListeningForCookieChangeNotifications(*this, hosts);
+}
+
+void NetworkConnectionToWebProcess::cookiesAdded(const String& host, const Vector<WebCore::Cookie>& cookies)
+{
+ connection().send(Messages::NetworkProcessConnection::CookiesAdded(host, cookies), 0);
+}
+
+void NetworkConnectionToWebProcess::cookiesDeleted()
+{
+ connection().send(Messages::NetworkProcessConnection::CookiesDeleted(), 0);
+}
+
+#endif
+
void NetworkConnectionToWebProcess::registerFileBlobURL(const URL& url, const String& path, SandboxExtension::Handle&& extensionHandle, const String& contentType)
{
auto* session = networkSession();
Modified: trunk/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h (256819 => 256820)
--- trunk/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h 2020-02-18 06:32:42 UTC (rev 256820)
@@ -42,6 +42,7 @@
#include <WebCore/MessagePortChannelProvider.h>
#include <WebCore/MessagePortIdentifier.h>
#include <WebCore/NetworkLoadInformation.h>
+#include <WebCore/NetworkStorageSession.h>
#include <WebCore/PageIdentifier.h>
#include <WebCore/ProcessIdentifier.h>
#include <WebCore/RegistrableDomain.h>
@@ -88,6 +89,9 @@
#if ENABLE(APPLE_PAY_REMOTE_UI)
, public WebPaymentCoordinatorProxy::Client
#endif
+#if HAVE(COOKIE_CHANGE_LISTENER_API)
+ , public WebCore::CookieChangeObserver
+#endif
, IPC::Connection::Client {
public:
using RegistrableDomain = WebCore::RegistrableDomain;
@@ -267,6 +271,16 @@
uint64_t nextMessageBatchIdentifier(Function<void()>&&);
+ void domCookiesForHost(const String& host, bool subscribeToCookieChangeNotifications, CompletionHandler<void(const Vector<WebCore::Cookie>&)>&&);
+
+#if HAVE(COOKIE_CHANGE_LISTENER_API)
+ void unsubscribeFromCookieChangeNotifications(const HashSet<String>& hosts);
+
+ // WebCore::CookieChangeObserver.
+ void cookiesAdded(const String& host, const Vector<WebCore::Cookie>&) final;
+ void cookiesDeleted() final;
+#endif
+
struct ResourceNetworkActivityTracker {
ResourceNetworkActivityTracker() = default;
ResourceNetworkActivityTracker(const ResourceNetworkActivityTracker&) = default;
@@ -330,6 +344,9 @@
#if ENABLE(WEB_RTC)
NetworkMDNSRegister m_mdnsRegister;
#endif
+#if HAVE(COOKIE_CHANGE_LISTENER_API)
+ HashSet<String> m_hostsWithCookieListeners;
+#endif
bool m_captureExtraNetworkLoadMetricsEnabled { false };
Modified: trunk/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in (256819 => 256820)
--- trunk/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in 2020-02-18 06:32:42 UTC (rev 256820)
@@ -39,6 +39,10 @@
CookieRequestHeaderFieldValue(URL firstParty, struct WebCore::SameSiteInfo sameSiteInfo, URL url, Optional<WebCore::FrameIdentifier> frameID, Optional<WebCore::PageIdentifier> pageID, enum:bool WebCore::IncludeSecureCookies includeSecureCookies, enum:bool WebCore::ShouldAskITP shouldAskITP) -> (String cookieString, bool didAccessSecureCookies) Synchronous
GetRawCookies(URL firstParty, struct WebCore::SameSiteInfo sameSiteInfo, URL url, Optional<WebCore::FrameIdentifier> frameID, Optional<WebCore::PageIdentifier> pageID, enum:bool WebCore::ShouldAskITP shouldAskITP) -> (Vector<WebCore::Cookie> cookies) Synchronous
DeleteCookie(URL url, String cookieName)
+ DomCookiesForHost(String host, bool subscribeToCookieChangeNotifications) -> (Vector<WebCore::Cookie> cookies) Synchronous
+#if HAVE(COOKIE_CHANGE_LISTENER_API)
+ UnsubscribeFromCookieChangeNotifications(HashSet<String> hosts)
+#endif
RegisterFileBlobURL(URL url, String path, WebKit::SandboxExtension::Handle extensionHandle, String contentType)
RegisterBlobURL(URL url, Vector<WebCore::BlobPart> blobParts, String contentType)
Modified: trunk/Source/WebKit/Scripts/webkit/messages.py (256819 => 256820)
--- trunk/Source/WebKit/Scripts/webkit/messages.py 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebKit/Scripts/webkit/messages.py 2020-02-18 06:32:42 UTC (rev 256820)
@@ -625,6 +625,7 @@
'WebKit::WebWheelEvent': ['"WebEvent.h"'],
'WebCore::MediaEngineSupportParameters': ['<WebCore/MediaPlayer.h>'],
'WebCore::ISOWebVTTCue': ['<WebCore/ISOVTTCue.h>'],
+ 'struct WebCore::Cookie': ['<WebCore/Cookie.h>'],
'struct WebCore::ElementContext': ['<WebCore/ElementContext.h>'],
'struct WebKit::WebUserScriptData': ['"WebUserContentControllerDataTypes.h"'],
'struct WebKit::WebUserStyleSheetData': ['"WebUserContentControllerDataTypes.h"'],
Modified: trunk/Source/WebKit/Shared/WebPreferences.yaml (256819 => 256820)
--- trunk/Source/WebKit/Shared/WebPreferences.yaml 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebKit/Shared/WebPreferences.yaml 2020-02-18 06:32:42 UTC (rev 256820)
@@ -55,6 +55,13 @@
humanReadableDescription: "Automatic HTTPS upgrade for known supported sites"
category: experimental
+InProcessCookieCacheEnabled:
+ type: bool
+ defaultValue: true
+ humanReadableName: "In-Process Cookie Cache"
+ humanReadableDescription: "In-Process DOM Cookie Cache"
+ category: experimental
+
ThirdPartyIframeRedirectBlockingEnabled:
type: bool
defaultValue: true
Modified: trunk/Source/WebKit/Sources.txt (256819 => 256820)
--- trunk/Source/WebKit/Sources.txt 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebKit/Sources.txt 2020-02-18 06:32:42 UTC (rev 256820)
@@ -624,6 +624,7 @@
WebProcess/WebPage/VisitedLinkTableController.cpp
WebProcess/WebPage/WebBackForwardListProxy.cpp
WebProcess/WebPage/WebContextMenu.cpp
+WebProcess/WebPage/WebCookieCache.cpp
WebProcess/WebPage/WebCookieJar.cpp
WebProcess/WebPage/WebDocumentLoader.cpp
WebProcess/WebPage/WebFrame.cpp
Modified: trunk/Source/WebKit/SourcesCocoa.txt (256819 => 256820)
--- trunk/Source/WebKit/SourcesCocoa.txt 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebKit/SourcesCocoa.txt 2020-02-18 06:32:42 UTC (rev 256820)
@@ -613,6 +613,7 @@
WebProcess/WebPage/WKAccessibilityWebPageObjectIOS.mm
WebProcess/WebPage/Cocoa/TextCheckingControllerProxy.mm
+WebProcess/WebPage/Cocoa/WebCookieCacheCocoa.mm
WebProcess/WebPage/Cocoa/WebPageCocoa.mm
WebProcess/WebPage/Cocoa/WebRemoteObjectRegistry.cpp
Modified: trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj (256819 => 256820)
--- trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj 2020-02-18 06:32:42 UTC (rev 256820)
@@ -943,6 +943,7 @@
466BC03C1FA266DA002FA9C1 /* WebSWContextManagerConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 466BC0391FA266C9002FA9C1 /* WebSWContextManagerConnection.h */; };
4671FF1F23217EFF001B64C7 /* WebResourceLoadObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = 4671FF1D23217EFF001B64C7 /* WebResourceLoadObserver.h */; };
467E43E82243FF7D00B13924 /* WebProcessDataStoreParameters.h in Headers */ = {isa = PBXBuildFile; fileRef = 467E43E72243FF6D00B13924 /* WebProcessDataStoreParameters.h */; };
+ 46809A7C23D9225E00C297D0 /* WebCookieCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 46809A7A23D9225300C297D0 /* WebCookieCache.h */; };
46A2B6091E5676A600C3DEDA /* BackgroundProcessResponsivenessTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = 46A2B6071E5675A200C3DEDA /* BackgroundProcessResponsivenessTimer.h */; };
46B0524722668D8500265B97 /* WebDeviceOrientationAndMotionAccessController.h in Headers */ = {isa = PBXBuildFile; fileRef = 46B0524422668D2300265B97 /* WebDeviceOrientationAndMotionAccessController.h */; };
46BEB6D722FB9BD700269867 /* StorageArea.h in Headers */ = {isa = PBXBuildFile; fileRef = 46BEB6D522FB9BD600269867 /* StorageArea.h */; };
@@ -3486,6 +3487,8 @@
4671FF1D23217EFF001B64C7 /* WebResourceLoadObserver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebResourceLoadObserver.h; sourceTree = "<group>"; };
4671FF1E23217EFF001B64C7 /* WebResourceLoadObserver.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WebResourceLoadObserver.cpp; sourceTree = "<group>"; };
467E43E72243FF6D00B13924 /* WebProcessDataStoreParameters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebProcessDataStoreParameters.h; sourceTree = "<group>"; };
+ 46809A7A23D9225300C297D0 /* WebCookieCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebCookieCache.h; sourceTree = "<group>"; };
+ 46809A7B23D9225300C297D0 /* WebCookieCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebCookieCache.cpp; sourceTree = "<group>"; };
4683569A21E81CC7006E27A3 /* ProvisionalPageProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProvisionalPageProxy.h; sourceTree = "<group>"; };
4683569B21E81CC7006E27A3 /* ProvisionalPageProxy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProvisionalPageProxy.cpp; sourceTree = "<group>"; };
46A2B6061E5675A200C3DEDA /* BackgroundProcessResponsivenessTimer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BackgroundProcessResponsivenessTimer.cpp; sourceTree = "<group>"; };
@@ -8428,6 +8431,8 @@
BC72B9F911E6476B001EB4EA /* WebBackForwardListProxy.h */,
51871B59127CB89D00F76232 /* WebContextMenu.cpp */,
51871B5A127CB89D00F76232 /* WebContextMenu.h */,
+ 46809A7B23D9225300C297D0 /* WebCookieCache.cpp */,
+ 46809A7A23D9225300C297D0 /* WebCookieCache.h */,
5C7FB46E21E97C0B009E3241 /* WebCookieJar.cpp */,
5C7FB46F21E97C0C009E3241 /* WebCookieJar.h */,
1A5B1C5218987EDF004FCF9B /* WebDocumentLoader.cpp */,
@@ -10668,6 +10673,7 @@
51ACBB82127A8BAD00D203B9 /* WebContextMenuProxy.h in Headers */,
51ACBBA0127A8F2C00D203B9 /* WebContextMenuProxyMac.h in Headers */,
BCF4DE25168FA44800C94AFC /* WebContextSupplement.h in Headers */,
+ 46809A7C23D9225E00C297D0 /* WebCookieCache.h in Headers */,
5C7FB47021E97DC5009E3241 /* WebCookieJar.h in Headers */,
330934501315B94D0097A7BC /* WebCookieManager.h in Headers */,
330934481315B9220097A7BC /* WebCookieManagerMessages.h in Headers */,
Modified: trunk/Source/WebKit/WebProcess/Network/NetworkProcessConnection.cpp (256819 => 256820)
--- trunk/Source/WebKit/WebProcess/Network/NetworkProcessConnection.cpp 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebKit/WebProcess/Network/NetworkProcessConnection.cpp 2020-02-18 06:32:42 UTC (rev 256820)
@@ -32,6 +32,7 @@
#include "StorageAreaMap.h"
#include "StorageAreaMapMessages.h"
#include "WebCacheStorageProvider.h"
+#include "WebCookieJar.h"
#include "WebCoreArgumentCoders.h"
#include "WebIDBConnectionToServer.h"
#include "WebIDBConnectionToServerMessages.h"
@@ -234,6 +235,18 @@
m_cookieAcceptPolicy = newPolicy;
}
+#if HAVE(COOKIE_CHANGE_LISTENER_API)
+void NetworkProcessConnection::cookiesAdded(const String& host, const Vector<WebCore::Cookie>& cookies)
+{
+ WebProcess::singleton().cookieJar().cookiesAdded(host, cookies);
+}
+
+void NetworkProcessConnection::cookiesDeleted()
+{
+ WebProcess::singleton().cookieJar().cookiesDeleted();
+}
+#endif
+
#if ENABLE(SHAREABLE_RESOURCE)
void NetworkProcessConnection::didCacheResource(const ResourceRequest& request, const ShareableResource::Handle& handle)
{
Modified: trunk/Source/WebKit/WebProcess/Network/NetworkProcessConnection.h (256819 => 256820)
--- trunk/Source/WebKit/WebProcess/Network/NetworkProcessConnection.h 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebKit/WebProcess/Network/NetworkProcessConnection.h 2020-02-18 06:32:42 UTC (rev 256820)
@@ -41,6 +41,7 @@
class ResourceError;
class ResourceRequest;
class ResourceResponse;
+struct Cookie;
struct MessagePortIdentifier;
struct MessageWithMessagePorts;
enum class HTTPCookieAcceptPolicy : uint8_t;
@@ -83,6 +84,11 @@
bool cookiesEnabled() const;
+#if HAVE(COOKIE_CHANGE_LISTENER_API)
+ void cookiesAdded(const String& host, const Vector<WebCore::Cookie>&);
+ void cookiesDeleted();
+#endif
+
private:
NetworkProcessConnection(IPC::Connection::Identifier, WebCore::HTTPCookieAcceptPolicy);
Modified: trunk/Source/WebKit/WebProcess/Network/NetworkProcessConnection.messages.in (256819 => 256820)
--- trunk/Source/WebKit/WebProcess/Network/NetworkProcessConnection.messages.in 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebKit/WebProcess/Network/NetworkProcessConnection.messages.in 2020-02-18 06:32:42 UTC (rev 256820)
@@ -31,6 +31,11 @@
SetOnLineState(bool isOnLine);
CookieAcceptPolicyChanged(enum:uint8_t WebCore::HTTPCookieAcceptPolicy policy);
+#if HAVE(COOKIE_CHANGE_LISTENER_API)
+ CookiesAdded(String host, Vector<struct WebCore::Cookie> cookies);
+ CookiesDeleted();
+#endif
+
CheckProcessLocalPortForActivity(struct WebCore::MessagePortIdentifier port) -> (WebCore::MessagePortChannelProvider::HasActivity hasActivity) Async
MessagesAvailableForPort(struct WebCore::MessagePortIdentifier port)
}
Copied: trunk/Source/WebKit/WebProcess/WebPage/Cocoa/WebCookieCacheCocoa.mm (from rev 256808, trunk/Source/WebKit/WebProcess/WebPage/WebCookieJar.h) (0 => 256820)
--- trunk/Source/WebKit/WebProcess/WebPage/Cocoa/WebCookieCacheCocoa.mm (rev 0)
+++ trunk/Source/WebKit/WebProcess/WebPage/Cocoa/WebCookieCacheCocoa.mm 2020-02-18 06:32:42 UTC (rev 256820)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "WebCookieCache.h"
+
+#import "WebProcess.h"
+#import <WebCore/NetworkStorageSession.h>
+
+namespace WebKit {
+
+using namespace WebCore;
+
+NetworkStorageSession& WebCookieCache::inMemoryStorageSession()
+{
+ if (!m_inMemoryStorageSession) {
+ String sessionName = makeString("WebKitInProcessStorage-", getCurrentProcessID());
+ auto storageSession = adoptCF(WebCore::createPrivateStorageSession(sessionName.createCFString().get()));
+ auto cookieStorage = adoptCF(_CFURLStorageSessionCopyCookieStorage(kCFAllocatorDefault, storageSession.get()));
+ m_inMemoryStorageSession = makeUnique<NetworkStorageSession>(WebProcess::singleton().sessionID(), WTFMove(storageSession), WTFMove(cookieStorage), NetworkStorageSession::IsInMemoryCookieStore::Yes);
+ }
+ return *m_inMemoryStorageSession;
+}
+
+} // namespace WebKit
Added: trunk/Source/WebKit/WebProcess/WebPage/WebCookieCache.cpp (0 => 256820)
--- trunk/Source/WebKit/WebProcess/WebPage/WebCookieCache.cpp (rev 0)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebCookieCache.cpp 2020-02-18 06:32:42 UTC (rev 256820)
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WebCookieCache.h"
+
+#include "NetworkConnectionToWebProcessMessages.h"
+#include "NetworkProcessConnection.h"
+#include "WebProcess.h"
+
+namespace WebKit {
+
+using namespace WebCore;
+
+bool WebCookieCache::isSupported()
+{
+#if HAVE(COOKIE_CHANGE_LISTENER_API)
+ // FIXME: This can eventually be removed, this is merely to ensure a smooth transition to the new API.
+ return inMemoryStorageSession().supportsCookieChangeListenerAPI();
+#else
+ return false;
+#endif
+}
+
+String WebCookieCache::cookiesForDOM(const URL& firstParty, const SameSiteInfo& sameSiteInfo, const URL& url, FrameIdentifier frameID, PageIdentifier pageID, IncludeSecureCookies includeSecureCookies)
+{
+ String host = url.host().toString();
+ if (!m_hostsWithInMemoryStorage.contains(host)) {
+ Vector<Cookie> cookies;
+ bool subscribeToCookieChangeNotifications = true;
+ if (!WebProcess::singleton().ensureNetworkProcessConnection().connection().sendSync(Messages::NetworkConnectionToWebProcess::DomCookiesForHost(url.host().toString(), subscribeToCookieChangeNotifications), Messages::NetworkConnectionToWebProcess::DomCookiesForHost::Reply(cookies), 0))
+ return { };
+ pruneCacheIfNecessary();
+ m_hostsWithInMemoryStorage.add(host);
+ for (auto& cookie : cookies)
+ inMemoryStorageSession().setCookie(cookie);
+ }
+ return inMemoryStorageSession().cookiesForDOM(firstParty, sameSiteInfo, url, frameID, pageID, includeSecureCookies, ShouldAskITP::No).first;
+}
+
+void WebCookieCache::setCookiesFromDOM(const URL& firstParty, const SameSiteInfo& sameSiteInfo, const URL& url, FrameIdentifier frameID, PageIdentifier pageID, const String& cookieString)
+{
+ String host = url.host().toString();
+ if (m_hostsWithInMemoryStorage.contains(host))
+ inMemoryStorageSession().setCookiesFromDOM(firstParty, sameSiteInfo, url, frameID, pageID, ShouldAskITP::No, cookieString);
+}
+
+void WebCookieCache::cookiesAdded(const String& host, const Vector<Cookie>& cookies)
+{
+ if (!m_hostsWithInMemoryStorage.contains(host))
+ return;
+
+ for (auto& cookie : cookies)
+ inMemoryStorageSession().setCookie(cookie);
+}
+
+void WebCookieCache::cookiesDeleted()
+{
+ clear();
+}
+
+void WebCookieCache::clear()
+{
+#if HAVE(COOKIE_CHANGE_LISTENER_API)
+ if (!m_hostsWithInMemoryStorage.isEmpty())
+ WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::UnsubscribeFromCookieChangeNotifications(m_hostsWithInMemoryStorage), 0);
+#endif
+ m_hostsWithInMemoryStorage.clear();
+ m_inMemoryStorageSession = nullptr;
+}
+
+void WebCookieCache::clearForHost(const String& host)
+{
+ auto it = m_hostsWithInMemoryStorage.find(host);
+ if (it == m_hostsWithInMemoryStorage.end())
+ return;
+
+ m_hostsWithInMemoryStorage.remove(it);
+ inMemoryStorageSession().deleteCookiesForHostnames(Vector<String> { host });
+#if HAVE(COOKIE_CHANGE_LISTENER_API)
+ WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::UnsubscribeFromCookieChangeNotifications(HashSet<String> { host }), 0);
+#endif
+}
+
+void WebCookieCache::pruneCacheIfNecessary()
+{
+ // We may want to raise this limit if we start using the cache for third-party iframes.
+ static const unsigned maxCachedHosts = 5;
+
+ while (m_hostsWithInMemoryStorage.size() >= maxCachedHosts)
+ clearForHost(*m_hostsWithInMemoryStorage.random());
+}
+
+#if !PLATFORM(COCOA)
+NetworkStorageSession& WebCookieCache::inMemoryStorageSession()
+{
+ ASSERT_NOT_IMPLEMENTED_YET();
+ return *m_inMemoryStorageSession;
+}
+#endif
+
+} // namespace WebKit
Copied: trunk/Source/WebKit/WebProcess/WebPage/WebCookieCache.h (from rev 256808, trunk/Source/WebKit/WebProcess/WebPage/WebCookieJar.h) (0 => 256820)
--- trunk/Source/WebKit/WebProcess/WebPage/WebCookieCache.h (rev 0)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebCookieCache.h 2020-02-18 06:32:42 UTC (rev 256820)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <WebCore/CookieJar.h>
+#include <WebCore/SameSiteInfo.h>
+#include <wtf/HashSet.h>
+
+namespace WebCore {
+class NetworkStorageSession;
+}
+
+namespace WebKit {
+
+class WebCookieCache {
+public:
+ WebCookieCache() = default;
+
+ bool isSupported();
+
+ String cookiesForDOM(const URL& firstParty, const WebCore::SameSiteInfo&, const URL&, WebCore::FrameIdentifier, WebCore::PageIdentifier, WebCore::IncludeSecureCookies);
+ void setCookiesFromDOM(const URL& firstParty, const WebCore::SameSiteInfo&, const URL&, WebCore::FrameIdentifier, WebCore::PageIdentifier, const String& cookieString);
+
+ void cookiesAdded(const String& host, const Vector<WebCore::Cookie>&);
+ void cookiesDeleted();
+
+ void clear();
+ void clearForHost(const String&);
+
+private:
+ WebCore::NetworkStorageSession& inMemoryStorageSession();
+ void pruneCacheIfNecessary();
+
+ HashSet<String> m_hostsWithInMemoryStorage;
+ std::unique_ptr<WebCore::NetworkStorageSession> m_inMemoryStorageSession;
+};
+
+} // namespace WebKit
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebCookieJar.cpp (256819 => 256820)
--- trunk/Source/WebKit/WebProcess/WebPage/WebCookieJar.cpp 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebCookieJar.cpp 2020-02-18 06:32:42 UTC (rev 256820)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2019-2020 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,6 +37,7 @@
#include <WebCore/Frame.h>
#include <WebCore/FrameLoader.h>
#include <WebCore/FrameLoaderClient.h>
+#include <WebCore/Settings.h>
#include <WebCore/StorageSessionProvider.h>
namespace WebKit {
@@ -88,6 +89,23 @@
}
#endif
+bool WebCookieJar::isEligibleForCache(WebFrame& frame, const URL& firstPartyForCookies, const URL& resourceURL) const
+{
+ auto* page = frame.page() ? frame.page()->corePage() : nullptr;
+ if (!page || !page->settings().inProcessCookieCacheEnabled())
+ return false;
+
+ if (!m_cache.isSupported())
+ return false;
+
+ // For now, we only cache cookies for first-party content. Third-party cookie caching is a bit more complicated due to partitioning and storage access.
+ RegistrableDomain resourceDomain { resourceURL };
+ if (resourceDomain.isEmpty())
+ return false;
+
+ return frame.isMainFrame() || RegistrableDomain { firstPartyForCookies } == resourceDomain;
+}
+
String WebCookieJar::cookies(WebCore::Document& document, const URL& url) const
{
auto* webFrame = document.frame() ? WebFrame::fromCoreFrame(*document.frame()) : nullptr;
@@ -100,12 +118,17 @@
return { };
#endif
+ auto sameSiteInfo = CookieJar::sameSiteInfo(document);
+ auto includeSecureCookies = CookieJar::shouldIncludeSecureCookies(document, url);
auto frameID = webFrame->frameID();
auto pageID = webFrame->page()->identifier();
+ if (isEligibleForCache(*webFrame, document.firstPartyForCookies(), url))
+ return m_cache.cookiesForDOM(document.firstPartyForCookies(), sameSiteInfo, url, frameID, pageID, includeSecureCookies);
+
String cookieString;
bool secureCookiesAccessed = false;
- if (!WebProcess::singleton().ensureNetworkProcessConnection().connection().sendSync(Messages::NetworkConnectionToWebProcess::CookiesForDOM(document.firstPartyForCookies(), sameSiteInfo(document), url, frameID, pageID, shouldIncludeSecureCookies(document, url), shouldAskITPInNetworkProcess), Messages::NetworkConnectionToWebProcess::CookiesForDOM::Reply(cookieString, secureCookiesAccessed), 0))
+ if (!WebProcess::singleton().ensureNetworkProcessConnection().connection().sendSync(Messages::NetworkConnectionToWebProcess::CookiesForDOM(document.firstPartyForCookies(), sameSiteInfo, url, frameID, pageID, includeSecureCookies, shouldAskITPInNetworkProcess), Messages::NetworkConnectionToWebProcess::CookiesForDOM::Reply(cookieString, secureCookiesAccessed), 0))
return { };
return cookieString;
@@ -123,12 +146,36 @@
return;
#endif
+ auto sameSiteInfo = CookieJar::sameSiteInfo(document);
auto frameID = webFrame->frameID();
auto pageID = webFrame->page()->identifier();
- WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::SetCookiesFromDOM(document.firstPartyForCookies(), sameSiteInfo(document), url, frameID, pageID, shouldAskITPInNetworkProcess, cookieString), 0);
+ if (isEligibleForCache(*webFrame, document.firstPartyForCookies(), url))
+ m_cache.setCookiesFromDOM(document.firstPartyForCookies(), sameSiteInfo, url, frameID, pageID, cookieString);
+
+ WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::SetCookiesFromDOM(document.firstPartyForCookies(), sameSiteInfo, url, frameID, pageID, shouldAskITPInNetworkProcess, cookieString), 0);
}
+void WebCookieJar::cookiesAdded(const String& host, const Vector<WebCore::Cookie>& cookies)
+{
+ m_cache.cookiesAdded(host, cookies);
+}
+
+void WebCookieJar::cookiesDeleted()
+{
+ m_cache.cookiesDeleted();
+}
+
+void WebCookieJar::clearCache()
+{
+ m_cache.clear();
+}
+
+void WebCookieJar::clearCacheForHost(const String& host)
+{
+ m_cache.clearForHost(host);
+}
+
bool WebCookieJar::cookiesEnabled(const Document& document) const
{
auto* webFrame = document.frame() ? WebFrame::fromCoreFrame(*document.frame()) : nullptr;
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebCookieJar.h (256819 => 256820)
--- trunk/Source/WebKit/WebProcess/WebPage/WebCookieJar.h 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebCookieJar.h 2020-02-18 06:32:42 UTC (rev 256820)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2019-2020 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -25,10 +25,17 @@
#pragma once
+#include "WebCookieCache.h"
#include <WebCore/CookieJar.h>
+namespace WebCore {
+struct Cookie;
+}
+
namespace WebKit {
+class WebFrame;
+
class WebCookieJar final : public WebCore::CookieJar {
public:
static Ref<WebCookieJar> create() { return adoptRef(*new WebCookieJar); }
@@ -39,8 +46,18 @@
std::pair<String, WebCore::SecureCookiesAccessed> cookieRequestHeaderFieldValue(const URL& firstParty, const WebCore::SameSiteInfo&, const URL&, Optional<WebCore::FrameIdentifier>, Optional<WebCore::PageIdentifier>, WebCore::IncludeSecureCookies) const final;
bool getRawCookies(const WebCore::Document&, const URL&, Vector<WebCore::Cookie>&) const final;
void deleteCookie(const WebCore::Document&, const URL&, const String& cookieName) final;
+
+ void cookiesAdded(const String& host, const Vector<WebCore::Cookie>&);
+ void cookiesDeleted();
+
private:
WebCookieJar();
+
+ void clearCache() final;
+ void clearCacheForHost(const String&) final;
+ bool isEligibleForCache(WebFrame&, const URL& firstPartyForCookies, const URL& resourceURL) const;
+
+ mutable WebCookieCache m_cache;
};
} // namespace WebKit
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (256819 => 256820)
--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp 2020-02-18 06:32:42 UTC (rev 256820)
@@ -466,7 +466,7 @@
makeUniqueRef<WebKit::LibWebRTCProvider>(),
WebProcess::singleton().cacheStorageProvider(),
WebBackForwardListProxy::create(*this),
- WebCookieJar::create(),
+ WebProcess::singleton().cookieJar(),
makeUniqueRef<WebProgressTrackerClient>(*this),
makeUniqueRef<MediaRecorderProvider>()
);
Modified: trunk/Source/WebKit/WebProcess/WebProcess.cpp (256819 => 256820)
--- trunk/Source/WebKit/WebProcess/WebProcess.cpp 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebKit/WebProcess/WebProcess.cpp 2020-02-18 06:32:42 UTC (rev 256820)
@@ -48,6 +48,7 @@
#include "WebAutomationSessionProxy.h"
#include "WebCacheStorageProvider.h"
#include "WebConnectionToUIProcess.h"
+#include "WebCookieJar.h"
#include "WebCoreArgumentCoders.h"
#include "WebFrame.h"
#include "WebFrameNetworkingContext.h"
@@ -205,6 +206,7 @@
, m_webInspectorInterruptDispatcher(WebInspectorInterruptDispatcher::create())
, m_webLoaderStrategy(*new WebLoaderStrategy)
, m_cacheStorageProvider(WebCacheStorageProvider::create())
+ , m_cookieJar(WebCookieJar::create())
, m_dnsPrefetchHystereris([this](PAL::HysteresisState state) { if (state == PAL::HysteresisState::Stopped) m_dnsPrefetchedHosts.clear(); })
#if ENABLE(NETSCAPE_PLUGIN_API)
, m_pluginProcessConnectionManager(PluginProcessConnectionManager::create())
Modified: trunk/Source/WebKit/WebProcess/WebProcess.h (256819 => 256820)
--- trunk/Source/WebKit/WebProcess/WebProcess.h 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Source/WebKit/WebProcess/WebProcess.h 2020-02-18 06:32:42 UTC (rev 256820)
@@ -120,6 +120,7 @@
class WaylandCompositorDisplay;
class WebAutomationSessionProxy;
class WebCacheStorageProvider;
+class WebCookieJar;
class WebCompiledContentRuleListData;
class WebConnectionToUIProcess;
class WebFrame;
@@ -293,6 +294,7 @@
WebAutomationSessionProxy* automationSessionProxy() { return m_automationSessionProxy.get(); }
WebCacheStorageProvider& cacheStorageProvider() { return m_cacheStorageProvider.get(); }
+ WebCookieJar& cookieJar() { return m_cookieJar.get(); }
WebSocketChannelManager& webSocketChannelManager() { return m_webSocketChannelManager; }
#if PLATFORM(IOS_FAMILY)
@@ -558,6 +560,7 @@
#endif
Ref<WebCacheStorageProvider> m_cacheStorageProvider;
+ Ref<WebCookieJar> m_cookieJar;
WebSocketChannelManager m_webSocketChannelManager;
std::unique_ptr<LibWebRTCNetwork> m_libWebRTCNetwork;
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/CookieAcceptPolicy.mm (256819 => 256820)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/CookieAcceptPolicy.mm 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/CookieAcceptPolicy.mm 2020-02-18 06:32:42 UTC (rev 256820)
@@ -33,6 +33,10 @@
#import <pal/spi/cf/CFNetworkSPI.h>
#import <wtf/RetainPtr.h>
+// FIXME: This test is causing flakiness in API tests. It sets the cookie accept policy to 'Never'
+// and following tests often are unable to set cookies.
+#if !PLATFORM(IOS_FAMILY)
+
static bool receivedScriptMessage = false;
static RetainPtr<WKScriptMessage> lastScriptMessage;
@@ -72,3 +76,5 @@
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookieAcceptPolicy:originalCookieAcceptPolicy];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] _saveCookies];
}
+
+#endif // !PLATFORM(IOS_FAMILY)
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/CookiePrivateBrowsing.mm (256819 => 256820)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/CookiePrivateBrowsing.mm 2020-02-18 06:10:16 UTC (rev 256819)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/CookiePrivateBrowsing.mm 2020-02-18 06:32:42 UTC (rev 256820)
@@ -26,11 +26,14 @@
#include "config.h"
#import "PlatformUtilities.h"
+#import "Test.h"
+#import "TestWKWebView.h"
#import <WebKit/WKProcessPool.h>
#import <WebKit/WKProcessPoolPrivate.h>
#import <WebKit/WKWebView.h>
#import <WebKit/WKWebViewConfiguration.h>
#import <wtf/RetainPtr.h>
+#import <wtf/text/WTFString.h>
static bool receivedAlert;
@@ -68,3 +71,60 @@
[view2 loadHTMLString:alertOldCookie baseURL:[NSURL URLWithString:@"http://example.com/"]];
TestWebKitAPI::Util::run(&receivedAlert);
}
+
+TEST(WebKit, CookieCacheSyncAcrossProcess)
+{
+ auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+ [configuration setWebsiteDataStore:[WKWebsiteDataStore nonPersistentDataStore]];
+ auto view1 = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+ auto view2 = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+ [view1 synchronouslyLoadHTMLString:@"foo" baseURL:[NSURL URLWithString:@"http://example.com/"]];
+ [view2 synchronouslyLoadHTMLString:@"bar" baseURL:[NSURL URLWithString:@"http://example.com/"]];
+
+ // Cache DOM cookies in first WebView.
+ __block bool doneEvaluatingJavaScript = false;
+ [view1 evaluateJavaScript:@"document.cookie;" completionHandler:^(id _Nullable cookie, NSError * _Nullable error) {
+ EXPECT_NULL(error);
+ EXPECT_TRUE([cookie isKindOfClass:[NSString class]]);
+ EXPECT_WK_STREQ("", (NSString *)cookie);
+ doneEvaluatingJavaScript = true;
+ }];
+ TestWebKitAPI::Util::run(&doneEvaluatingJavaScript);
+
+ // Cache DOM cookies in second WebView.
+ doneEvaluatingJavaScript = false;
+ [view2 evaluateJavaScript:@"document.cookie;" completionHandler:^(id _Nullable cookie, NSError * _Nullable error) {
+ EXPECT_NULL(error);
+ EXPECT_TRUE([cookie isKindOfClass:[NSString class]]);
+ EXPECT_WK_STREQ("", (NSString *)cookie);
+ doneEvaluatingJavaScript = true;
+ }];
+ TestWebKitAPI::Util::run(&doneEvaluatingJavaScript);
+
+ // Setting cookie in first Webview / process.
+ doneEvaluatingJavaScript = false;
+ [view1 evaluateJavaScript:@"document.cookie = 'foo=bar'; document.cookie;" completionHandler:^(id _Nullable cookie, NSError * _Nullable error) {
+ EXPECT_NULL(error);
+ EXPECT_TRUE([cookie isKindOfClass:[NSString class]]);
+ EXPECT_WK_STREQ("foo=bar", (NSString *)cookie);
+ doneEvaluatingJavaScript = true;
+ }];
+ TestWebKitAPI::Util::run(&doneEvaluatingJavaScript);
+
+ // Making sure new cookie gets sync'd to second WebView process.
+ int timeout = 0;
+ __block String cookieString;
+ do {
+ TestWebKitAPI::Util::sleep(0.1);
+ doneEvaluatingJavaScript = false;
+ [view2 evaluateJavaScript:@"document.cookie;" completionHandler:^(id _Nullable cookie, NSError * _Nullable error) {
+ EXPECT_NULL(error);
+ EXPECT_TRUE([cookie isKindOfClass:[NSString class]]);
+ cookieString = (NSString *)cookie;
+ doneEvaluatingJavaScript = true;
+ }];
+ TestWebKitAPI::Util::run(&doneEvaluatingJavaScript);
+ ++timeout;
+ } while (cookieString != "" && timeout < 50);
+ EXPECT_WK_STREQ("foo=bar", cookieString);
+}