Interacting with WKHTTPCookieStores before creating WKWebViews and WKProcessPools...
authorachristensen@apple.com <achristensen@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 17 May 2017 16:51:46 +0000 (16:51 +0000)
committerachristensen@apple.com <achristensen@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 17 May 2017 16:51:46 +0000 (16:51 +0000)
https://bugs.webkit.org/show_bug.cgi?id=171987

Reviewed by Brady Eidson.

Source/WebCore:

Covered by new API tests.

* CMakeLists.txt:
* platform/Cookie.h:
(WebCore::Cookie::Cookie):
(WebCore::Cookie::isNull):
(WebCore::CookieHash::hash):
(WebCore::CookieHash::equal):
(WTF::HashTraits<WebCore::Cookie>::emptyValue):
(WTF::HashTraits<WebCore::Cookie>::constructDeletedValue):
(WTF::HashTraits<WebCore::Cookie>::isDeletedValue):
* platform/network/Cookie.cpp: Added.
(WebCore::Cookie::operator==):
(WebCore::Cookie::hash):
* platform/network/cocoa/CookieCocoa.mm:
(WebCore::Cookie::operator NSHTTPCookie *):
(WebCore::Cookie::operator==):
(WebCore::Cookie::hash):
* platform/network/cocoa/NetworkStorageSessionCocoa.mm:
(WebCore::NetworkStorageSession::setCookies):
Use NSHTTPCookie's hash and equality comparison to more closely match the NSHTTPCookie behavior.

Source/WebKit2:

When putting cookies in a WKHTTPCookieStore that hasn't been associated with a WKProcessPool yet, there is no
NetworkProcess into which to put the cookies.  In such a case, we should store these cookies in the WebsiteDataStore
until there is a NetworkProcess.

* NetworkProcess/NetworkConnectionToWebProcess.cpp:
(WebKit::NetworkConnectionToWebProcess::ensureLegacyPrivateBrowsingSession):
* NetworkProcess/NetworkProcess.cpp:
(WebKit::NetworkProcess::initializeNetworkProcess):
(WebKit::NetworkProcess::ensurePrivateBrowsingSession):
* NetworkProcess/NetworkProcess.h:
* NetworkProcess/NetworkProcess.messages.in:
* NetworkProcess/RemoteNetworkingContext.h:
* NetworkProcess/mac/RemoteNetworkingContext.mm:
(WebKit::RemoteNetworkingContext::ensurePrivateBrowsingSession):
(WebKit::RemoteNetworkingContext::ensureWebsiteDataStoreSession):
* Shared/WebsiteDataStoreParameters.cpp:
(WebKit::WebsiteDataStoreParameters::~WebsiteDataStoreParameters):
(WebKit::WebsiteDataStoreParameters::encode):
(WebKit::WebsiteDataStoreParameters::decode):
(WebKit::WebsiteDataStoreParameters::WebsiteDataStoreParameters): Deleted.
* Shared/WebsiteDataStoreParameters.h:
* UIProcess/API/APIHTTPCookieStore.cpp:
(API::HTTPCookieStore::cookies):
(API::HTTPCookieStore::setCookie):
(API::HTTPCookieStore::deleteCookie):
* UIProcess/API/APIHTTPCookieStore.h:
* UIProcess/WebProcessPool.cpp:
(WebKit::WebProcessPool::setAnyPageGroupMightHavePrivateBrowsingEnabled):
(WebKit::WebProcessPool::pageAddedToProcess):
* UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm:
(WebKit::WebsiteDataStore::parameters):
* UIProcess/WebsiteData/WebsiteDataStore.cpp:
(WebKit::WebsiteDataStore::pendingCookies):
(WebKit::WebsiteDataStore::addPendingCookie):
(WebKit::WebsiteDataStore::removePendingCookie):
* UIProcess/WebsiteData/WebsiteDataStore.h:

Tools:

* TestWebKitAPI/Tests/WebKit2Cocoa/WKHTTPCookieStore.mm:
(-[CookieUIDelegate webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:]):
(TEST):

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

24 files changed:
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/platform/Cookie.h
Source/WebCore/platform/network/Cookie.cpp [new file with mode: 0644]
Source/WebCore/platform/network/cocoa/CookieCocoa.mm
Source/WebCore/platform/network/cocoa/NetworkStorageSessionCocoa.mm
Source/WebKit2/ChangeLog
Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.cpp
Source/WebKit2/NetworkProcess/NetworkProcess.cpp
Source/WebKit2/NetworkProcess/NetworkProcess.h
Source/WebKit2/NetworkProcess/NetworkProcess.messages.in
Source/WebKit2/NetworkProcess/RemoteNetworkingContext.h
Source/WebKit2/NetworkProcess/mac/RemoteNetworkingContext.mm
Source/WebKit2/NetworkProcess/soup/RemoteNetworkingContextSoup.cpp
Source/WebKit2/Shared/WebsiteDataStoreParameters.cpp
Source/WebKit2/Shared/WebsiteDataStoreParameters.h
Source/WebKit2/UIProcess/API/APIHTTPCookieStore.cpp
Source/WebKit2/UIProcess/API/APIHTTPCookieStore.h
Source/WebKit2/UIProcess/WebProcessPool.cpp
Source/WebKit2/UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm
Source/WebKit2/UIProcess/WebsiteData/WebsiteDataStore.cpp
Source/WebKit2/UIProcess/WebsiteData/WebsiteDataStore.h
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WKHTTPCookieStore.mm

index 2fb3788..2c8fdf8 100644 (file)
@@ -2411,6 +2411,7 @@ set(WebCore_SOURCES
     platform/network/BlobRegistryImpl.cpp
     platform/network/BlobResourceHandle.cpp
     platform/network/CacheValidation.cpp
+    platform/network/Cookie.cpp
     platform/network/CredentialBase.cpp
     platform/network/CredentialStorage.cpp
     platform/network/DNSResolveQueue.cpp
index 408c6a8..1e6cedf 100644 (file)
@@ -1,3 +1,32 @@
+2017-05-17  Alex Christensen  <achristensen@webkit.org>
+
+        Interacting with WKHTTPCookieStores before creating WKWebViews and WKProcessPools should affect cookies used
+        https://bugs.webkit.org/show_bug.cgi?id=171987
+
+        Reviewed by Brady Eidson.
+
+        Covered by new API tests.
+
+        * CMakeLists.txt:
+        * platform/Cookie.h:
+        (WebCore::Cookie::Cookie):
+        (WebCore::Cookie::isNull):
+        (WebCore::CookieHash::hash):
+        (WebCore::CookieHash::equal):
+        (WTF::HashTraits<WebCore::Cookie>::emptyValue):
+        (WTF::HashTraits<WebCore::Cookie>::constructDeletedValue):
+        (WTF::HashTraits<WebCore::Cookie>::isDeletedValue):
+        * platform/network/Cookie.cpp: Added.
+        (WebCore::Cookie::operator==):
+        (WebCore::Cookie::hash):
+        * platform/network/cocoa/CookieCocoa.mm:
+        (WebCore::Cookie::operator NSHTTPCookie *):
+        (WebCore::Cookie::operator==):
+        (WebCore::Cookie::hash):
+        * platform/network/cocoa/NetworkStorageSessionCocoa.mm:
+        (WebCore::NetworkStorageSession::setCookies):
+        Use NSHTTPCookie's hash and equality comparison to more closely match the NSHTTPCookie behavior.
+
 2017-05-17  Emilio Cobos Álvarez  <ecobos@igalia.com>
 
         Add a RuntimeEnabledFeature for display: contents, defaulted to false.
index 5ddb935..99c9a7d 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2009 Joseph Pecoraro. All rights reserved.
+ * Copyright (C) 2017 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 +38,10 @@ namespace WebCore {
 
 struct Cookie {
     Cookie() { }
+    
+    Cookie(WTF::HashTableDeletedValueType)
+        : name(WTF::HashTableDeletedValue)
+    { }
 
     Cookie(const String& name, const String& value, const String& domain, const String& path, double expires, bool httpOnly, bool secure, bool session, const String& comment, const URL& commentURL, const Vector<uint16_t> ports)
         : name(name)
@@ -56,36 +61,53 @@ struct Cookie {
     template<class Encoder> void encode(Encoder&) const;
     template<class Decoder> static bool decode(Decoder&, Cookie&);
 
+    WEBCORE_EXPORT bool operator==(const Cookie&) const;
+    WEBCORE_EXPORT unsigned hash() const;
+
 #ifdef __OBJC__
     WEBCORE_EXPORT Cookie(NSHTTPCookie *);
     WEBCORE_EXPORT operator NSHTTPCookie *() const;
 #endif
 
+    bool isNull() const
+    {
+        return name.isNull()
+        && value.isNull()
+        && domain.isNull()
+        && path.isNull()
+        && expires == 0
+        && !httpOnly
+        && !secure
+        && !session
+        && comment.isNull()
+        && commentURL.isNull();
+    }
+    
     String name;
     String value;
     String domain;
     String path;
     // Expiration date, expressed as milliseconds since the UNIX epoch.
-    double expires;
-    bool httpOnly;
-    bool secure;
-    bool session;
+    double expires { 0 };
+    bool httpOnly { false };
+    bool secure { false };
+    bool session { false };
     String comment;
     URL commentURL;
     Vector<uint16_t> ports;
-
 };
 
 struct CookieHash {
     static unsigned hash(const Cookie& key)
-    { 
-        return StringHash::hash(key.name) + StringHash::hash(key.domain) + StringHash::hash(key.path) + key.secure;
+    {
+        return key.hash();
     }
 
     static bool equal(const Cookie& a, const Cookie& b)
     {
-        return a.name == b.name && a.domain == b.domain && a.path == b.path && a.secure == b.secure;
+        return a == b;
     }
+    static const bool safeToCompareToEmptyOrDeleted = false;
 };
 
 template<class Encoder>
@@ -130,4 +152,9 @@ namespace WTF {
     template<> struct DefaultHash<WebCore::Cookie> {
         typedef WebCore::CookieHash Hash;
     };
+    template<> struct HashTraits<WebCore::Cookie> : GenericHashTraits<WebCore::Cookie> {
+        static WebCore::Cookie emptyValue() { return { }; }
+        static void constructDeletedValue(WebCore::Cookie& slot) { slot = WebCore::Cookie(WTF::HashTableDeletedValue); }
+        static bool isDeletedValue(const WebCore::Cookie& slot) { return slot.name.isHashTableDeletedValue(); }
+    };
 }
diff --git a/Source/WebCore/platform/network/Cookie.cpp b/Source/WebCore/platform/network/Cookie.cpp
new file mode 100644 (file)
index 0000000..cefcf5a
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2017 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. ``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
+ * 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 "Cookie.h"
+
+namespace WebCore {
+    
+#if !PLATFORM(COCOA)
+bool Cookie::operator==(const Cookie& other) const
+{
+    return name == other.name
+        && domain == other.domain
+        && path == other.path
+        && secure == other.secure;
+}
+    
+unsigned Cookie::hash() const
+{
+    return StringHash::hash(name) + StringHash::hash(domain) + StringHash::hash(path) + secure;
+}
+#endif
+    
+} // namespace WebCore
+
index 3609661..4458fcc 100644 (file)
@@ -64,6 +64,9 @@ Cookie::Cookie(NSHTTPCookie *cookie)
 
 Cookie::operator NSHTTPCookie *() const
 {
+    if (isNull())
+        return nil;
+
     // FIXME: existing APIs do not provide a way to set httpOnly without parsing headers from scratch.
 
     NSMutableDictionary *properties = [NSMutableDictionary dictionaryWithCapacity:11];
@@ -105,5 +108,25 @@ Cookie::operator NSHTTPCookie *() const
 
     return [NSHTTPCookie cookieWithProperties:properties];
 }
+    
+bool Cookie::operator==(const Cookie& other) const
+{
+    ASSERT(!name.isHashTableDeletedValue());
+    bool thisNull = isNull();
+    bool otherNull = other.isNull();
+    if (thisNull || otherNull)
+        return thisNull == otherNull;
+    
+    NSHTTPCookie *nsCookie(*this);
+    return [nsCookie isEqual:other];
+}
+    
+unsigned Cookie::hash() const
+{
+    ASSERT(!name.isHashTableDeletedValue());
+    ASSERT(!isNull());
+    NSHTTPCookie *nsCookie(*this);
+    return nsCookie.hash;
+}
 
 } // namespace WebCore
index 957dcc8..c88c9f6 100644 (file)
@@ -43,7 +43,7 @@ void NetworkStorageSession::setCookie(const Cookie& cookie)
 void NetworkStorageSession::setCookies(const Vector<Cookie>& cookies, const URL& url, const URL& mainDocumentURL)
 {
     RetainPtr<NSMutableArray> nsCookies = adoptNS([[NSMutableArray alloc] initWithCapacity:cookies.size()]);
-    for (auto cookie : cookies)
+    for (const auto& cookie : cookies)
         [nsCookies addObject:(NSHTTPCookie *)cookie];
 
     BEGIN_BLOCK_OBJC_EXCEPTIONS;
index 1023a90..7008a35 100644 (file)
@@ -1,3 +1,47 @@
+2017-05-17  Alex Christensen  <achristensen@webkit.org>
+
+        Interacting with WKHTTPCookieStores before creating WKWebViews and WKProcessPools should affect cookies used
+        https://bugs.webkit.org/show_bug.cgi?id=171987
+
+        Reviewed by Brady Eidson.
+
+        When putting cookies in a WKHTTPCookieStore that hasn't been associated with a WKProcessPool yet, there is no
+        NetworkProcess into which to put the cookies.  In such a case, we should store these cookies in the WebsiteDataStore
+        until there is a NetworkProcess.
+
+        * NetworkProcess/NetworkConnectionToWebProcess.cpp:
+        (WebKit::NetworkConnectionToWebProcess::ensureLegacyPrivateBrowsingSession):
+        * NetworkProcess/NetworkProcess.cpp:
+        (WebKit::NetworkProcess::initializeNetworkProcess):
+        (WebKit::NetworkProcess::ensurePrivateBrowsingSession):
+        * NetworkProcess/NetworkProcess.h:
+        * NetworkProcess/NetworkProcess.messages.in:
+        * NetworkProcess/RemoteNetworkingContext.h:
+        * NetworkProcess/mac/RemoteNetworkingContext.mm:
+        (WebKit::RemoteNetworkingContext::ensurePrivateBrowsingSession):
+        (WebKit::RemoteNetworkingContext::ensureWebsiteDataStoreSession):
+        * Shared/WebsiteDataStoreParameters.cpp:
+        (WebKit::WebsiteDataStoreParameters::~WebsiteDataStoreParameters):
+        (WebKit::WebsiteDataStoreParameters::encode):
+        (WebKit::WebsiteDataStoreParameters::decode):
+        (WebKit::WebsiteDataStoreParameters::WebsiteDataStoreParameters): Deleted.
+        * Shared/WebsiteDataStoreParameters.h:
+        * UIProcess/API/APIHTTPCookieStore.cpp:
+        (API::HTTPCookieStore::cookies):
+        (API::HTTPCookieStore::setCookie):
+        (API::HTTPCookieStore::deleteCookie):
+        * UIProcess/API/APIHTTPCookieStore.h:
+        * UIProcess/WebProcessPool.cpp:
+        (WebKit::WebProcessPool::setAnyPageGroupMightHavePrivateBrowsingEnabled):
+        (WebKit::WebProcessPool::pageAddedToProcess):
+        * UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm:
+        (WebKit::WebsiteDataStore::parameters):
+        * UIProcess/WebsiteData/WebsiteDataStore.cpp:
+        (WebKit::WebsiteDataStore::pendingCookies):
+        (WebKit::WebsiteDataStore::addPendingCookie):
+        (WebKit::WebsiteDataStore::removePendingCookie):
+        * UIProcess/WebsiteData/WebsiteDataStore.h:
+
 2017-05-17  Emilio Cobos Álvarez  <ecobos@igalia.com>
 
         Add a RuntimeEnabledFeature for display: contents, defaulted to false.
index 1dfa437..0181cec 100644 (file)
@@ -45,6 +45,7 @@
 #include "RemoteNetworkingContext.h"
 #include "SessionTracker.h"
 #include "WebCoreArgumentCoders.h"
+#include "WebsiteDataStoreParameters.h"
 #include <WebCore/NetworkStorageSession.h>
 #include <WebCore/PingHandle.h>
 #include <WebCore/PlatformCookieJar.h>
@@ -399,7 +400,7 @@ void NetworkConnectionToWebProcess::setCaptureExtraNetworkLoadMetricsEnabled(boo
 
 void NetworkConnectionToWebProcess::ensureLegacyPrivateBrowsingSession()
 {
-    NetworkProcess::singleton().ensurePrivateBrowsingSession(SessionID::legacyPrivateSessionID());
+    NetworkProcess::singleton().ensurePrivateBrowsingSession({SessionID::legacyPrivateSessionID(), { }, { }, { }});
 }
 
 } // namespace WebKit
index ae8fe3d..317460e 100644 (file)
@@ -49,6 +49,7 @@
 #include "WebProcessPoolMessages.h"
 #include "WebsiteData.h"
 #include "WebsiteDataFetchOption.h"
+#include "WebsiteDataStoreParameters.h"
 #include "WebsiteDataType.h"
 #include <WebCore/DNS.h>
 #include <WebCore/DiagnosticLoggingClient.h>
@@ -236,7 +237,7 @@ void NetworkProcess::initializeNetworkProcess(NetworkProcessCreationParameters&&
 
     // FIXME: instead of handling this here, a message should be sent later (scales to multiple sessions)
     if (parameters.privateBrowsingEnabled)
-        RemoteNetworkingContext::ensurePrivateBrowsingSession(SessionID::legacyPrivateSessionID());
+        RemoteNetworkingContext::ensurePrivateBrowsingSession({SessionID::legacyPrivateSessionID(), { }, { }, { }});
 
     if (parameters.shouldUseTestingNetworkSession)
         NetworkStorageSession::switchToNewTestingSession();
@@ -287,9 +288,9 @@ void NetworkProcess::clearCachedCredentials()
 #endif
 }
 
-void NetworkProcess::ensurePrivateBrowsingSession(SessionID sessionID)
+void NetworkProcess::ensurePrivateBrowsingSession(WebsiteDataStoreParameters&& parameters)
 {
-    RemoteNetworkingContext::ensurePrivateBrowsingSession(sessionID);
+    RemoteNetworkingContext::ensurePrivateBrowsingSession(WTFMove(parameters));
 }
 
 void NetworkProcess::addWebsiteDataStore(WebsiteDataStoreParameters&& parameters)
index eac9c08..f050037 100644 (file)
@@ -113,7 +113,7 @@ public:
 
     void prefetchDNS(const String&);
 
-    void ensurePrivateBrowsingSession(WebCore::SessionID);
+    void ensurePrivateBrowsingSession(WebsiteDataStoreParameters&&);
 
     void grantSandboxExtensionsToDatabaseProcessForBlobs(const Vector<String>& filenames, Function<void ()>&& completionHandler);
 
index 8094400..a2bcd2f 100644 (file)
@@ -35,7 +35,7 @@ messages -> NetworkProcess LegacyReceiver {
 
     ClearCachedCredentials()
 
-    EnsurePrivateBrowsingSession(WebCore::SessionID sessionID)
+    EnsurePrivateBrowsingSession(struct WebKit::WebsiteDataStoreParameters websiteDataStoreParameters)
     AddWebsiteDataStore(struct WebKit::WebsiteDataStoreParameters websiteDataStoreParameters);
     DestroySession(WebCore::SessionID sessionID)
 
index 376e966..ab3efbb 100644 (file)
@@ -43,7 +43,7 @@ public:
     virtual ~RemoteNetworkingContext();
 
     // FIXME: Remove platform-specific code and use SessionTracker.
-    static void ensurePrivateBrowsingSession(WebCore::SessionID);
+    static void ensurePrivateBrowsingSession(WebsiteDataStoreParameters&&);
     static void ensureWebsiteDataStoreSession(WebsiteDataStoreParameters&&);
 
     bool shouldClearReferrerOnHTTPSToHTTPRedirect() const override { return m_shouldClearReferrerOnHTTPSToHTTPRedirect; }
index f33da28..f44cdea 100644 (file)
@@ -80,11 +80,11 @@ ResourceError RemoteNetworkingContext::blockedError(const ResourceRequest& reque
     return WebKit::blockedError(request);
 }
 
-void RemoteNetworkingContext::ensurePrivateBrowsingSession(SessionID sessionID)
+void RemoteNetworkingContext::ensurePrivateBrowsingSession(WebsiteDataStoreParameters&& parameters)
 {
-    ASSERT(sessionID.isEphemeral());
+    ASSERT(parameters.sessionID.isEphemeral());
 
-    if (NetworkStorageSession::storageSession(sessionID))
+    if (NetworkStorageSession::storageSession(parameters.sessionID))
         return;
 
     String base;
@@ -93,11 +93,15 @@ void RemoteNetworkingContext::ensurePrivateBrowsingSession(SessionID sessionID)
     else
         base = SessionTracker::getIdentifierBase();
 
-    NetworkStorageSession::ensurePrivateBrowsingSession(sessionID, base + '.' + String::number(sessionID.sessionID()));
+    NetworkStorageSession::ensurePrivateBrowsingSession(parameters.sessionID, base + '.' + String::number(parameters.sessionID.sessionID()));
+
+    auto* session = NetworkStorageSession::storageSession(parameters.sessionID);
+    for (const auto& cookie : parameters.pendingCookies)
+        session->setCookie(cookie);
 
 #if USE(NETWORK_SESSION)
-    auto networkSession = NetworkSession::create(sessionID, NetworkProcess::singleton().supplement<LegacyCustomProtocolManager>());
-    SessionTracker::setSession(sessionID, WTFMove(networkSession));
+    auto networkSession = NetworkSession::create(parameters.sessionID, NetworkProcess::singleton().supplement<LegacyCustomProtocolManager>());
+    SessionTracker::setSession(parameters.sessionID, WTFMove(networkSession));
 #endif
 }
 
@@ -122,6 +126,10 @@ void RemoteNetworkingContext::ensureWebsiteDataStoreSession(WebsiteDataStorePara
 
     NetworkStorageSession::ensureSession(parameters.sessionID, base + '.' + String::number(parameters.sessionID.sessionID()), WTFMove(uiProcessCookieStorage));
 
+    auto* session = NetworkStorageSession::storageSession(parameters.sessionID);
+    for (const auto& cookie : parameters.pendingCookies)
+        session->setCookie(cookie);
+
 #if USE(NETWORK_SESSION)
     auto networkSession = NetworkSession::create(parameters.sessionID, NetworkProcess::singleton().supplement<LegacyCustomProtocolManager>());
     SessionTracker::setSession(parameters.sessionID, WTFMove(networkSession));
index 0ea8070..f76d6df 100644 (file)
@@ -48,15 +48,15 @@ bool RemoteNetworkingContext::isValid() const
     return true;
 }
 
-void RemoteNetworkingContext::ensurePrivateBrowsingSession(SessionID sessionID)
+void RemoteNetworkingContext::ensurePrivateBrowsingSession(WebsiteDataStoreParameters&& parameters)
 {
-    ASSERT(sessionID.isEphemeral());
+    ASSERT(parameters.sessionID.isEphemeral());
 
-    if (NetworkStorageSession::storageSession(sessionID))
+    if (NetworkStorageSession::storageSession(parameters.sessionID))
         return;
 
-    NetworkStorageSession::ensurePrivateBrowsingSession(sessionID, String::number(sessionID.sessionID()));
-    SessionTracker::setSession(sessionID, NetworkSession::create(sessionID));
+    NetworkStorageSession::ensurePrivateBrowsingSession(parameters.sessionID, String::number(parameters.sessionID.sessionID()));
+    SessionTracker::setSession(parameters.sessionID, NetworkSession::create(parameters.sessionID));
 }
 
 void RemoteNetworkingContext::ensureWebsiteDataStoreSession(WebsiteDataStoreParameters&&)
index 807608f..93ef1c9 100644 (file)
@@ -30,8 +30,7 @@
 
 namespace WebKit {
 
-
-WebsiteDataStoreParameters::WebsiteDataStoreParameters()
+WebsiteDataStoreParameters::~WebsiteDataStoreParameters()
 {
 }
 
@@ -40,6 +39,7 @@ void WebsiteDataStoreParameters::encode(IPC::Encoder& encoder) const
     encoder << sessionID;
     encoder << uiProcessCookieStorageIdentifier;
     encoder << cookieStoragePathExtensionHandle;
+    encoder << pendingCookies;
 }
 
 bool WebsiteDataStoreParameters::decode(IPC::Decoder& decoder, WebsiteDataStoreParameters& parameters)
@@ -53,6 +53,9 @@ bool WebsiteDataStoreParameters::decode(IPC::Decoder& decoder, WebsiteDataStoreP
     if (!decoder.decode(parameters.cookieStoragePathExtensionHandle))
         return false;
 
+    if (!decoder.decode(parameters.pendingCookies))
+        return false;
+
     return true;
 }
 
index 8b750e4..e92c07f 100644 (file)
@@ -26,6 +26,7 @@
 #pragma once
 
 #include "SandboxExtension.h"
+#include <WebCore/Cookie.h>
 #include <WebCore/SessionID.h>
 #include <wtf/Vector.h>
 #include <wtf/text/WTFString.h>
@@ -38,14 +39,17 @@ class Encoder;
 namespace WebKit {
 
 struct WebsiteDataStoreParameters {
-    WebsiteDataStoreParameters();
-
+    WebsiteDataStoreParameters() = default;
+    WebsiteDataStoreParameters(WebsiteDataStoreParameters&&) = default;
+    ~WebsiteDataStoreParameters();
+    
     void encode(IPC::Encoder&) const;
     static bool decode(IPC::Decoder&, WebsiteDataStoreParameters&);
 
     WebCore::SessionID sessionID;
     Vector<uint8_t> uiProcessCookieStorageIdentifier;
     SandboxExtension::Handle cookieStoragePathExtensionHandle;
+    Vector<WebCore::Cookie> pendingCookies;
 };
 
 } // namespace WebKit
index b9f40b3..5a91593 100644 (file)
@@ -57,13 +57,9 @@ void HTTPCookieStore::cookies(Function<void (const Vector<WebCore::Cookie>&)>&&
     auto& dataStore = m_owningDataStore.websiteDataStore();
     auto* pool = dataStore.processPoolForCookieStorageOperations();
     if (!pool) {
-        // FIXME: This is not necessarily the right storage session, but it's currently
-        // the best we can do in the absence of a process pool.
-        auto allCookies = WebCore::NetworkStorageSession::defaultStorageSession().getAllCookies();
-        callOnMainThread([completionHandler = WTFMove(completionHandler), allCookies = WTFMove(allCookies)]() {
+        callOnMainThread([completionHandler = WTFMove(completionHandler), allCookies = dataStore.pendingCookies()]() {
             completionHandler(allCookies);
         });
-
         return;
     }
 
@@ -78,13 +74,10 @@ void HTTPCookieStore::setCookie(const WebCore::Cookie& cookie, Function<void ()>
     auto& dataStore = m_owningDataStore.websiteDataStore();
     auto* pool = dataStore.processPoolForCookieStorageOperations();
     if (!pool) {
-        // FIXME: This is not necessarily the right storage session, but it's currently
-        // the best we can do in the absence of a process pool.
-        WebCore::NetworkStorageSession::defaultStorageSession().setCookie(cookie);
+        dataStore.addPendingCookie(cookie);
         callOnMainThread([completionHandler = WTFMove(completionHandler)]() {
             completionHandler();
         });
-
         return;
     }
 
@@ -99,13 +92,10 @@ void HTTPCookieStore::deleteCookie(const WebCore::Cookie& cookie, Function<void
     auto& dataStore = m_owningDataStore.websiteDataStore();
     auto* pool = dataStore.processPoolForCookieStorageOperations();
     if (!pool) {
-        // FIXME: This is not necessarily the right storage session, but it's currently
-        // the best we can do in the absence of a process pool.
-        WebCore::NetworkStorageSession::defaultStorageSession().deleteCookie(cookie);
+        dataStore.removePendingCookie(cookie);
         callOnMainThread([completionHandler = WTFMove(completionHandler)]() {
             completionHandler();
         });
-
         return;
     }
 
index dfc056f..45fde85 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "APIObject.h"
 #include "HTTPCookieAcceptPolicy.h"
+#include <WebCore/Cookie.h>
 #include <wtf/Function.h>
 #include <wtf/HashSet.h>
 #include <wtf/Vector.h>
index ebaa96f..12b1178 100644 (file)
@@ -578,7 +578,7 @@ void WebProcessPool::setAnyPageGroupMightHavePrivateBrowsingEnabled(bool private
 
     if (networkProcess()) {
         if (privateBrowsingEnabled)
-            networkProcess()->send(Messages::NetworkProcess::EnsurePrivateBrowsingSession(SessionID::legacyPrivateSessionID()), 0);
+            networkProcess()->send(Messages::NetworkProcess::EnsurePrivateBrowsingSession({SessionID::legacyPrivateSessionID(), { }, { }, { }}), 0);
         else
             networkProcess()->send(Messages::NetworkProcess::DestroySession(SessionID::legacyPrivateSessionID()), 0);
     }
@@ -945,7 +945,9 @@ void WebProcessPool::pageAddedToProcess(WebPageProxy& page)
 
     auto sessionID = page.sessionID();
     if (sessionID.isEphemeral()) {
-        sendToNetworkingProcess(Messages::NetworkProcess::EnsurePrivateBrowsingSession(sessionID));
+        // FIXME: Merge NetworkProcess::EnsurePrivateBrowsingSession and NetworkProcess::AddWebsiteDataStore into one message type.
+        // They do basically the same thing.
+        sendToNetworkingProcess(Messages::NetworkProcess::EnsurePrivateBrowsingSession(page.websiteDataStore().parameters()));
         page.process().send(Messages::WebProcess::EnsurePrivateBrowsingSession(sessionID), 0);
     } else if (sessionID != SessionID::defaultSessionID()) {
         sendToNetworkingProcess(Messages::NetworkProcess::AddWebsiteDataStore(page.websiteDataStore().parameters()));
index e1d28a3..624a2f1 100644 (file)
@@ -70,6 +70,8 @@ WebsiteDataStoreParameters WebsiteDataStore::parameters()
     parameters.uiProcessCookieStorageIdentifier = m_uiProcessCookieStorageIdentifier;
 #endif
 
+    copyToVector(m_pendingCookies, parameters.pendingCookies);
+
     if (!cookieFile.isEmpty())
         SandboxExtension::createHandleForReadWriteDirectory(WebCore::directoryName(cookieFile), parameters.cookieStoragePathExtensionHandle);
 
index b6eaeef..13a7ad9 100644 (file)
@@ -1265,6 +1265,23 @@ DatabaseProcessCreationParameters WebsiteDataStore::databaseProcessParameters()
     return parameters;
 }
 
+Vector<WebCore::Cookie> WebsiteDataStore::pendingCookies() const
+{
+    Vector<WebCore::Cookie> cookies;
+    copyToVector(m_pendingCookies, cookies);
+    return cookies;
+}
+
+void WebsiteDataStore::addPendingCookie(const WebCore::Cookie& cookie)
+{
+    m_pendingCookies.add(cookie);
+}
+
+void WebsiteDataStore::removePendingCookie(const WebCore::Cookie& cookie)
+{
+    m_pendingCookies.remove(cookie);
+}
+
 #if !PLATFORM(COCOA)
 WebsiteDataStoreParameters WebsiteDataStore::parameters()
 {
index f89d4ee..7be6435 100644 (file)
@@ -26,6 +26,7 @@
 #pragma once
 
 #include "WebProcessLifetimeObserver.h"
+#include <WebCore/Cookie.h>
 #include <WebCore/SecurityOriginData.h>
 #include <WebCore/SecurityOriginHash.h>
 #include <WebCore/SessionID.h>
@@ -118,6 +119,10 @@ public:
     WebsiteDataStoreParameters parameters();
     DatabaseProcessCreationParameters databaseProcessParameters();
 
+    Vector<WebCore::Cookie> pendingCookies() const;
+    void addPendingCookie(const WebCore::Cookie&);
+    void removePendingCookie(const WebCore::Cookie&);
+
 private:
     explicit WebsiteDataStore(WebCore::SessionID);
     explicit WebsiteDataStore(Configuration, WebCore::SessionID);
@@ -160,6 +165,7 @@ private:
     Vector<uint8_t> m_uiProcessCookieStorageIdentifier;
     RetainPtr<CFHTTPCookieStorageRef> m_cfCookieStorage;
 #endif
+    HashSet<WebCore::Cookie> m_pendingCookies;
 };
 
 }
index 4f7a09e..549e22d 100644 (file)
@@ -1,3 +1,14 @@
+2017-05-17  Alex Christensen  <achristensen@webkit.org>
+
+        Interacting with WKHTTPCookieStores before creating WKWebViews and WKProcessPools should affect cookies used
+        https://bugs.webkit.org/show_bug.cgi?id=171987
+
+        Reviewed by Brady Eidson.
+
+        * TestWebKitAPI/Tests/WebKit2Cocoa/WKHTTPCookieStore.mm:
+        (-[CookieUIDelegate webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:]):
+        (TEST):
+
 2017-05-17  Emilio Cobos Álvarez  <ecobos@igalia.com>
 
         Add a RuntimeEnabledFeature for display: contents, defaulted to false.
index 15b679f..23ebd2b 100644 (file)
@@ -167,4 +167,64 @@ TEST(WebKit2, WKHTTPCookieStore)
     [globalCookieStore removeObserver:observer2.get()];
 }
 
+static bool finished;
+
+@interface CookieUIDelegate : NSObject <WKUIDelegate>
+@end
+
+@implementation CookieUIDelegate
+- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
+{
+    EXPECT_STREQ("cookie:cookiename=cookievalue", message.UTF8String);
+    finished = true;
+    completionHandler();
+}
+@end
+
+TEST(WebKit2, WKHTTPCookieStoreWithoutProcessPool)
+{
+    NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:[NSDictionary dictionaryWithObjectsAndKeys:@"127.0.0.1", NSHTTPCookieDomain, @"/", NSHTTPCookiePath, @"cookiename", NSHTTPCookieName, @"cookievalue", NSHTTPCookieValue, [NSDate distantFuture], NSHTTPCookieExpires, nil]];
+    NSString *alertCookieHTML = @"<script>alert('cookie:'+document.cookie);</script>";
+    
+    finished = false;
+    WKWebsiteDataStore *ephemeralStoreWithCookies = [WKWebsiteDataStore nonPersistentDataStore];
+    [ephemeralStoreWithCookies.httpCookieStore setCookie:cookie completionHandler:^ {
+        WKWebsiteDataStore *ephemeralStoreWithIndependentCookieStorage = [WKWebsiteDataStore nonPersistentDataStore];
+        [ephemeralStoreWithIndependentCookieStorage.httpCookieStore getAllCookies:^(NSArray<NSHTTPCookie *> *cookies) {
+            ASSERT_EQ(cookies.count, 0u);
+            
+            WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
+            configuration.websiteDataStore = ephemeralStoreWithCookies;
+            WKWebView *view = [[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration];
+            view.UIDelegate = [[CookieUIDelegate alloc] init];
+
+            [view loadHTMLString:alertCookieHTML baseURL:[NSURL URLWithString:@"http://127.0.0.1/"]];
+        }];
+    }];
+    TestWebKitAPI::Util::run(&finished);
+    
+    finished = false;
+    WKWebsiteDataStore *defaultStore = [WKWebsiteDataStore defaultDataStore];
+    [defaultStore.httpCookieStore setCookie:cookie completionHandler:^ {
+        [defaultStore.httpCookieStore getAllCookies:^(NSArray<NSHTTPCookie *> *cookies) {
+            ASSERT_EQ(cookies.count, 1u);
+            
+            WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
+            configuration.websiteDataStore = defaultStore;
+            WKWebView *view = [[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration];
+            view.UIDelegate = [[CookieUIDelegate alloc] init];
+            
+            [view loadHTMLString:alertCookieHTML baseURL:[NSURL URLWithString:@"http://127.0.0.1/"]];
+        }];
+    }];
+    TestWebKitAPI::Util::run(&finished);
+    
+    [defaultStore.httpCookieStore deleteCookie:cookie completionHandler:^ {
+        [defaultStore.httpCookieStore getAllCookies:^(NSArray<NSHTTPCookie *> *cookies) {
+            ASSERT_EQ(cookies.count, 0u);
+            finished = true;
+        }];
+    }];
+    TestWebKitAPI::Util::run(&finished);
+}
 #endif