Title: [197518] trunk/Source
Revision
197518
Author
[email protected]
Date
2016-03-03 13:46:07 -0800 (Thu, 03 Mar 2016)

Log Message

Adopt CFNetwork storage partitioning SPI
https://bugs.webkit.org/show_bug.cgi?id=154957
rdar://problem/23614620

Reviewed by Darin Adler.

Source/WebCore:

Adopt CFNetwork SPI for creating storage partitions. If Settings::cookieStoragePartitioningEnabled() is true,
create cookie storage partitions for third-party contexts. This feature is disabled by default.

No new tests. Test support is tracked by <https://webkit.org/b/154958>.

* page/Settings.cpp:
(WebCore::Settings::setCookieStoragePartitioningEnabled): Controls whether storage partitioning for cookies is enabled.
* page/Settings.h:
(WebCore::Settings::cookieStoragePartitioningEnabled):
* platform/network/NetworkStorageSession.h:
* platform/network/cf/NetworkStorageSessionCFNet.cpp:
(WebCore::cookieStoragePartition): Computes a storage partition identifier by determining the top
privately-controlled domain of the cookie's first-party (main frame document) URL, then determining whether the
cookie's document hostname is a subdomain of it. If is is not, the first-party top domain is the partition name.
Otherwise, there is no partition name.
* platform/network/mac/CookieJarMac.mm:
(WebCore::applyPartitionToCookies): Returns a deep copy of the given cookie array after adding a storage
partition property to each copied cookie.
(WebCore::cookiesInPartitionForURL): Returns cookies for the partition computed by the given URLs. If no
partition can be determined, nil is returned.
(WebCore::cookiesForURL): Returns cookiesInPartitionForURL() if non-nil, otherwise returns wkHTTPCookiesForURL().
(WebCore::cookiesForSession): Started calling cookiesForURL().
(WebCore::setCookiesFromDOM): Called applyPartitionToCookies() if a partition can be computed from the given URLs.
(WebCore::getRawCookies): Started calling cookiesForURL().
* platform/network/mac/ResourceHandleMac.mm:
(WebCore::ResourceHandle::createNSURLConnection): Computed the storage partition identifier for the new request.
If non-empty, set it as a property on the NSURLRequest where CFNetwork knows to find it.
* platform/spi/cf/CFNetworkSPI.h: Declare new SPI for building with the public SDK.

Source/WebKit2:

* NetworkProcess/cocoa/NetworkDataTaskCocoa.mm:
(WebKit::NetworkDataTask::NetworkDataTask): Computed the storage partition identifier for the new session task.
If non-empty, set it using a NSURLSessionTask SPI.

Source/WTF:

* wtf/Platform.h: Defined HAVE_CFNETWORK_STORAGE_PARTITIONING.

Modified Paths

Diff

Modified: trunk/Source/WTF/ChangeLog (197517 => 197518)


--- trunk/Source/WTF/ChangeLog	2016-03-03 21:43:47 UTC (rev 197517)
+++ trunk/Source/WTF/ChangeLog	2016-03-03 21:46:07 UTC (rev 197518)
@@ -1,3 +1,13 @@
+2016-03-03  Andy Estes  <[email protected]>
+
+        Adopt CFNetwork storage partitioning SPI
+        https://bugs.webkit.org/show_bug.cgi?id=154957
+        rdar://problem/23614620
+
+        Reviewed by Darin Adler.
+
+        * wtf/Platform.h: Defined HAVE_CFNETWORK_STORAGE_PARTITIONING.
+
 2016-03-02  Konstantin Tokarev  <[email protected]>
 
         [cmake] Moved PRE/POST_BUILD_COMMAND to WEBKIT_FRAMEWORK.

Modified: trunk/Source/WTF/wtf/Platform.h (197517 => 197518)


--- trunk/Source/WTF/wtf/Platform.h	2016-03-03 21:43:47 UTC (rev 197517)
+++ trunk/Source/WTF/wtf/Platform.h	2016-03-03 21:46:07 UTC (rev 197518)
@@ -665,6 +665,10 @@
 #define HAVE_VIRTUALALLOC 1
 #endif
 
+#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) || (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000)
+#define HAVE_CFNETWORK_STORAGE_PARTITIONING 1
+#endif
+
 /* ENABLE macro defaults */
 
 /* FIXME: move out all ENABLE() defines from here to FeatureDefines.h */

Modified: trunk/Source/WebCore/ChangeLog (197517 => 197518)


--- trunk/Source/WebCore/ChangeLog	2016-03-03 21:43:47 UTC (rev 197517)
+++ trunk/Source/WebCore/ChangeLog	2016-03-03 21:46:07 UTC (rev 197518)
@@ -1,3 +1,40 @@
+2016-03-03  Andy Estes  <[email protected]>
+
+        Adopt CFNetwork storage partitioning SPI
+        https://bugs.webkit.org/show_bug.cgi?id=154957
+        rdar://problem/23614620
+
+        Reviewed by Darin Adler.
+
+        Adopt CFNetwork SPI for creating storage partitions. If Settings::cookieStoragePartitioningEnabled() is true,
+        create cookie storage partitions for third-party contexts. This feature is disabled by default.
+
+        No new tests. Test support is tracked by <https://webkit.org/b/154958>.
+
+        * page/Settings.cpp:
+        (WebCore::Settings::setCookieStoragePartitioningEnabled): Controls whether storage partitioning for cookies is enabled.
+        * page/Settings.h:
+        (WebCore::Settings::cookieStoragePartitioningEnabled):
+        * platform/network/NetworkStorageSession.h:
+        * platform/network/cf/NetworkStorageSessionCFNet.cpp:
+        (WebCore::cookieStoragePartition): Computes a storage partition identifier by determining the top
+        privately-controlled domain of the cookie's first-party (main frame document) URL, then determining whether the
+        cookie's document hostname is a subdomain of it. If is is not, the first-party top domain is the partition name.
+        Otherwise, there is no partition name.
+        * platform/network/mac/CookieJarMac.mm:
+        (WebCore::applyPartitionToCookies): Returns a deep copy of the given cookie array after adding a storage
+        partition property to each copied cookie.
+        (WebCore::cookiesInPartitionForURL): Returns cookies for the partition computed by the given URLs. If no
+        partition can be determined, nil is returned.
+        (WebCore::cookiesForURL): Returns cookiesInPartitionForURL() if non-nil, otherwise returns wkHTTPCookiesForURL().
+        (WebCore::cookiesForSession): Started calling cookiesForURL().
+        (WebCore::setCookiesFromDOM): Called applyPartitionToCookies() if a partition can be computed from the given URLs.
+        (WebCore::getRawCookies): Started calling cookiesForURL().
+        * platform/network/mac/ResourceHandleMac.mm:
+        (WebCore::ResourceHandle::createNSURLConnection): Computed the storage partition identifier for the new request.
+        If non-empty, set it as a property on the NSURLRequest where CFNetwork knows to find it.
+        * platform/spi/cf/CFNetworkSPI.h: Declare new SPI for building with the public SDK.
+
 2016-03-03  Manuel Rego Casasnovas  <[email protected]>
 
         [css-grid] Fix order of grid shorthands in CSSPropertyNames.in

Modified: trunk/Source/WebCore/page/Settings.cpp (197517 => 197518)


--- trunk/Source/WebCore/page/Settings.cpp	2016-03-03 21:43:47 UTC (rev 197517)
+++ trunk/Source/WebCore/page/Settings.cpp	2016-03-03 21:46:07 UTC (rev 197518)
@@ -82,6 +82,7 @@
 
 #if PLATFORM(COCOA)
 bool Settings::gQTKitEnabled = false;
+bool Settings::gCookieStoragePartitioningEnabled = false;
 #endif
 
 bool Settings::gMockScrollbarsEnabled = false;
@@ -598,6 +599,11 @@
     gQTKitEnabled = enabled;
     HTMLMediaElement::resetMediaEngines();
 }
+    
+void Settings::setCookieStoragePartitioningEnabled(bool enabled)
+{
+    gCookieStoragePartitioningEnabled = enabled;
+}
 #endif
 
 #if ENABLE(MEDIA_STREAM)

Modified: trunk/Source/WebCore/page/Settings.h (197517 => 197518)


--- trunk/Source/WebCore/page/Settings.h	2016-03-03 21:43:47 UTC (rev 197517)
+++ trunk/Source/WebCore/page/Settings.h	2016-03-03 21:46:07 UTC (rev 197518)
@@ -198,6 +198,9 @@
 #if PLATFORM(COCOA)
     WEBCORE_EXPORT static void setQTKitEnabled(bool flag);
     static bool isQTKitEnabled() { return gQTKitEnabled; }
+
+    WEBCORE_EXPORT static void setCookieStoragePartitioningEnabled(bool flag);
+    static bool cookieStoragePartitioningEnabled() { return gCookieStoragePartitioningEnabled; }
 #else
     static bool isQTKitEnabled() { return false; }
 #endif
@@ -352,6 +355,7 @@
 
 #if PLATFORM(COCOA)
     WEBCORE_EXPORT static bool gQTKitEnabled;
+    static bool gCookieStoragePartitioningEnabled;
 #endif
 
     static bool gMockScrollbarsEnabled;

Modified: trunk/Source/WebCore/platform/network/NetworkStorageSession.h (197517 => 197518)


--- trunk/Source/WebCore/platform/network/NetworkStorageSession.h	2016-03-03 21:43:47 UTC (rev 197517)
+++ trunk/Source/WebCore/platform/network/NetworkStorageSession.h	2016-03-03 21:46:07 UTC (rev 197518)
@@ -38,6 +38,7 @@
 namespace WebCore {
 
 class NetworkingContext;
+class ResourceRequest;
 class SoupNetworkSession;
 
 class NetworkStorageSession {
@@ -79,6 +80,9 @@
     CredentialStorage m_credentialStorage;
 };
 
+WEBCORE_EXPORT String cookieStoragePartition(const ResourceRequest&);
+String cookieStoragePartition(const URL& firstPartyForCookies, const URL& resource);
+
 }
 
 #endif // NetworkStorageSession_h

Modified: trunk/Source/WebCore/platform/network/cf/NetworkStorageSessionCFNet.cpp (197517 => 197518)


--- trunk/Source/WebCore/platform/network/cf/NetworkStorageSessionCFNet.cpp	2016-03-03 21:43:47 UTC (rev 197517)
+++ trunk/Source/WebCore/platform/network/cf/NetworkStorageSessionCFNet.cpp	2016-03-03 21:46:07 UTC (rev 197518)
@@ -31,6 +31,9 @@
 #include <wtf/ProcessID.h>
 
 #if PLATFORM(COCOA)
+#include "PublicSuffix.h"
+#include "ResourceRequest.h"
+#include "Settings.h"
 #include "WebCoreSystemInterface.h"
 #else
 #include <WebKitSystemInterface/WebKitSystemInterface.h>
@@ -94,4 +97,36 @@
 #endif
 }
 
+#if PLATFORM(COCOA)
+
+String cookieStoragePartition(const ResourceRequest& request)
+{
+    return cookieStoragePartition(request.firstPartyForCookies(), request.url());
 }
+
+static inline bool hostIsInDomain(StringView host, StringView domain)
+{
+    if (!host.endsWithIgnoringASCIICase(domain))
+        return false;
+
+    ASSERT(host.length() >= domain.length());
+    unsigned suffixOffset = host.length() - domain.length();
+    return suffixOffset == 0 || host[suffixOffset - 1] == '.';
+}
+
+String cookieStoragePartition(const URL& firstPartyForCookies, const URL& resource)
+{
+    if (!Settings::cookieStoragePartitioningEnabled())
+        return emptyString();
+
+    String firstPartyDomain = firstPartyForCookies.host();
+#if ENABLE(PUBLIC_SUFFIX_LIST)
+    firstPartyDomain = topPrivatelyControlledDomain(firstPartyDomain);
+#endif
+    
+    return hostIsInDomain(resource.host(), firstPartyDomain) ? emptyString() : firstPartyDomain;
+}
+
+#endif
+
+}

Modified: trunk/Source/WebCore/platform/network/mac/CookieJarMac.mm (197517 => 197518)


--- trunk/Source/WebCore/platform/network/mac/CookieJarMac.mm	2016-03-03 21:43:47 UTC (rev 197517)
+++ trunk/Source/WebCore/platform/network/mac/CookieJarMac.mm	2016-03-03 21:46:07 UTC (rev 197518)
@@ -36,6 +36,7 @@
 #import "Cookie.h"
 #import "CookieStorage.h"
 #import "URL.h"
+#import <wtf/Optional.h>
 #import <wtf/text/StringBuilder.h>
 
 namespace WebCore {
@@ -64,12 +65,64 @@
     return filteredCookies;
 }
 
+#if HAVE(CFNETWORK_STORAGE_PARTITIONING)
+
+static NSArray *applyPartitionToCookies(NSString *partition, NSArray *cookies)
+{
+    // FIXME 24747739: CFNetwork should expose this key as SPI
+    static NSString * const partitionKey = @"StoragePartition";
+
+    NSMutableArray *partitionedCookies = [NSMutableArray arrayWithCapacity:cookies.count];
+    for (NSHTTPCookie *cookie in cookies) {
+        RetainPtr<NSMutableDictionary> properties = adoptNS([cookie.properties mutableCopy]);
+        [properties setObject:partition forKey:partitionKey];
+        [partitionedCookies addObject:[NSHTTPCookie cookieWithProperties:properties.get()]];
+    }
+
+    return partitionedCookies;
+}
+
+static NSArray *cookiesInPartitionForURL(const NetworkStorageSession& session, const URL& firstParty, const URL& url)
+{
+    String partition = cookieStoragePartition(firstParty, url);
+    if (partition.isEmpty())
+        return nil;
+
+    // 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> cookieStorage;
+    if (auto storage = session.cookieStorage())
+        cookieStorage = adoptNS([[NSHTTPCookieStorage alloc] _initWithCFHTTPCookieStorage:storage.get()]);
+    else
+        cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
+
+    // The _getCookiesForURL: method calls the completionHandler synchronously.
+    Optional<RetainPtr<NSArray *>> cookiesPtr;
+    [cookieStorage _getCookiesForURL:url mainDocumentURL:firstParty partition:partition completionHandler:[&cookiesPtr](NSArray *cookies) {
+        cookiesPtr = retainPtr(cookies);
+    }];
+    ASSERT(!!cookiesPtr);
+
+    return cookiesPtr->autorelease();
+}
+
+#endif // HAVE(CFNETWORK_STORAGE_PARTITIONING)
+    
+static NSArray *cookiesForURL(const NetworkStorageSession& session, const URL& firstParty, const URL& url)
+{
+#if HAVE(CFNETWORK_STORAGE_PARTITIONING)
+    if (NSArray *cookies = cookiesInPartitionForURL(session, firstParty, url))
+        return cookies;
+#endif
+    return wkHTTPCookiesForURL(session.cookieStorage().get(), firstParty, url);
+}
+
 enum IncludeHTTPOnlyOrNot { DoNotIncludeHTTPOnly, IncludeHTTPOnly };
 static String cookiesForSession(const NetworkStorageSession& session, const URL& firstParty, const URL& url, IncludeHTTPOnlyOrNot includeHTTPOnly)
 {
     BEGIN_BLOCK_OBJC_EXCEPTIONS;
 
-    NSArray *cookies = wkHTTPCookiesForURL(session.cookieStorage().get(), firstParty, url);
+    NSArray *cookies = cookiesForURL(session, firstParty, url);
     if (![cookies count])
         return String(); // Return a null string, not an empty one that StringBuilder would create below.
 
@@ -129,6 +182,12 @@
     RetainPtr<NSArray> filteredCookies = filterCookies(unfilteredCookies);
     ASSERT([filteredCookies.get() count] <= 1);
 
+#if HAVE(CFNETWORK_STORAGE_PARTITIONING)
+    String partition = cookieStoragePartition(firstParty, url);
+    if (!partition.isEmpty())
+        filteredCookies = applyPartitionToCookies(partition, filteredCookies.get());
+#endif
+
     wkSetHTTPCookiesForURL(session.cookieStorage().get(), filteredCookies.get(), cookieURL, firstParty);
 
     END_BLOCK_OBJC_EXCEPTIONS;
@@ -150,7 +209,7 @@
     rawCookies.clear();
     BEGIN_BLOCK_OBJC_EXCEPTIONS;
 
-    NSArray *cookies = wkHTTPCookiesForURL(session.cookieStorage().get(), firstParty, url);
+    NSArray *cookies = cookiesForURL(session, firstParty, url);
     NSUInteger count = [cookies count];
     rawCookies.reserveCapacity(count);
     for (NSUInteger i = 0; i < count; ++i) {

Modified: trunk/Source/WebCore/platform/network/mac/ResourceHandleMac.mm (197517 => 197518)


--- trunk/Source/WebCore/platform/network/mac/ResourceHandleMac.mm	2016-03-03 21:43:47 UTC (rev 197517)
+++ trunk/Source/WebCore/platform/network/mac/ResourceHandleMac.mm	2016-03-03 21:46:07 UTC (rev 197518)
@@ -40,6 +40,7 @@
 #import "Logging.h"
 #import "MIMETypeRegistry.h"
 #import "NSURLConnectionSPI.h"
+#import "NetworkStorageSession.h"
 #import "NetworkingContext.h"
 #import "Page.h"
 #import "ResourceError.h"
@@ -172,6 +173,15 @@
         nsRequest = mutableRequest;
     }
 
+#if HAVE(CFNETWORK_STORAGE_PARTITIONING)
+    String storagePartition = cookieStoragePartition(firstRequest());
+    if (!storagePartition.isEmpty()) {
+        NSMutableURLRequest *mutableRequest = [[nsRequest mutableCopy] autorelease];
+        [mutableRequest _setProperty:storagePartition forKey:@"__STORAGE_PARTITION_IDENTIFIER"];
+        nsRequest = mutableRequest;
+    }
+#endif
+
     if (d->m_storageSession)
         nsRequest = [wkCopyRequestWithStorageSession(d->m_storageSession.get(), nsRequest) autorelease];
 

Modified: trunk/Source/WebCore/platform/spi/cf/CFNetworkSPI.h (197517 => 197518)


--- trunk/Source/WebCore/platform/spi/cf/CFNetworkSPI.h	2016-03-03 21:43:47 UTC (rev 197517)
+++ trunk/Source/WebCore/platform/spi/cf/CFNetworkSPI.h	2016-03-03 21:46:07 UTC (rev 197518)
@@ -41,7 +41,7 @@
 #include <CFNetwork/CFURLResponsePriv.h>
 #include <CFNetwork/CFURLStorageSession.h>
 
-// FIXME: Remove the defined(__OBJC__)-guard onnce we fix <rdar://problem/19033610>.
+// FIXME: Remove the defined(__OBJC__)-guard once we fix <rdar://problem/19033610>.
 #if defined(__OBJC__) && PLATFORM(COCOA)
 // FIXME: As a workaround for <rdar://problem/18337182>, we conditionally enclose the header
 // in an extern "C" linkage block to make it suitable for C++ use.
@@ -103,8 +103,22 @@
 @end
 #endif
 
+#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) || (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000)
+@interface NSHTTPCookie ()
+@property (nullable, readonly, copy) NSString *_storagePartition;
+@end
+
+@interface NSHTTPCookieStorage ()
+- (void)_getCookiesForURL:(NSURL *)url mainDocumentURL:(NSURL *)mainDocumentURL partition:(NSString *)partition completionHandler:(void (^)(NSArray *))completionHandler;
+@end
+
+@interface NSURLSessionTask ()
+@property (copy) NSString *_storagePartitionIdentifier;
+@end
 #endif
 
+#endif // defined(__OBJC__)
+
 #endif // PLATFORM(WIN) || USE(APPLE_INTERNAL_SDK)
 
 EXTERN_C void CFURLRequestSetShouldStartSynchronously(CFURLRequestRef, Boolean);

Modified: trunk/Source/WebKit2/ChangeLog (197517 => 197518)


--- trunk/Source/WebKit2/ChangeLog	2016-03-03 21:43:47 UTC (rev 197517)
+++ trunk/Source/WebKit2/ChangeLog	2016-03-03 21:46:07 UTC (rev 197518)
@@ -1,3 +1,15 @@
+2016-03-03  Andy Estes  <[email protected]>
+
+        Adopt CFNetwork storage partitioning SPI
+        https://bugs.webkit.org/show_bug.cgi?id=154957
+        rdar://problem/23614620
+
+        Reviewed by Darin Adler.
+
+        * NetworkProcess/cocoa/NetworkDataTaskCocoa.mm:
+        (WebKit::NetworkDataTask::NetworkDataTask): Computed the storage partition identifier for the new session task.
+        If non-empty, set it using a NSURLSessionTask SPI.
+
 2016-03-03  Alex Christensen  <[email protected]>
 
         [WK2] testRunner.setPrivateBrowsingEnabled doesn't work with NetworkProcess

Modified: trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm (197517 => 197518)


--- trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm	2016-03-03 21:43:47 UTC (rev 197517)
+++ trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm	2016-03-03 21:46:07 UTC (rev 197518)
@@ -34,6 +34,7 @@
 #import "WebCoreArgumentCoders.h"
 #import <WebCore/AuthenticationChallenge.h>
 #import <WebCore/CFNetworkSPI.h>
+#import <WebCore/NetworkStorageSession.h>
 #import <WebCore/ResourceRequest.h>
 #import <wtf/MainThread.h>
 
@@ -85,6 +86,12 @@
         ASSERT(!m_session.m_dataTaskMapWithoutCredentials.contains([m_task taskIdentifier]));
         m_session.m_dataTaskMapWithoutCredentials.add([m_task taskIdentifier], this);
     }
+
+#if HAVE(CFNETWORK_STORAGE_PARTITIONING)
+    String storagePartition = WebCore::cookieStoragePartition(request);
+    if (!storagePartition.isEmpty())
+        m_task.get()._storagePartitionIdentifier = storagePartition;
+#endif
 }
 
 NetworkDataTask::~NetworkDataTask()
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to