[Cocoa] Upstream CFNetwork-related WebKitSystemInterface functions
[WebKit-https.git] / Source / WebCore / platform / network / cocoa / NetworkStorageSessionCocoa.mm
1 /*
2  * Copyright (C) 2015-2017 Apple Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "NetworkStorageSession.h"
28
29 #import "Cookie.h"
30 #import "CookieStorageObserver.h"
31 #import "URL.h"
32 #import <pal/spi/cf/CFNetworkSPI.h>
33 #import <wtf/BlockObjCExceptions.h>
34
35 namespace WebCore {
36
37 void NetworkStorageSession::setCookie(const Cookie& cookie)
38 {
39     BEGIN_BLOCK_OBJC_EXCEPTIONS;
40     [nsCookieStorage() setCookie:(NSHTTPCookie *)cookie];
41     END_BLOCK_OBJC_EXCEPTIONS;
42 }
43
44 void NetworkStorageSession::setCookies(const Vector<Cookie>& cookies, const URL& url, const URL& mainDocumentURL)
45 {
46     RetainPtr<NSMutableArray> nsCookies = adoptNS([[NSMutableArray alloc] initWithCapacity:cookies.size()]);
47     for (const auto& cookie : cookies)
48         [nsCookies addObject:(NSHTTPCookie *)cookie];
49
50     BEGIN_BLOCK_OBJC_EXCEPTIONS;
51     [nsCookieStorage() setCookies:nsCookies.get() forURL:(NSURL *)url mainDocumentURL:(NSURL *)mainDocumentURL];
52     END_BLOCK_OBJC_EXCEPTIONS;
53 }
54
55 void NetworkStorageSession::deleteCookie(const Cookie& cookie)
56 {
57     [nsCookieStorage() deleteCookie:(NSHTTPCookie *)cookie];
58 }
59
60 static Vector<Cookie> nsCookiesToCookieVector(NSArray<NSHTTPCookie *> *nsCookies)
61 {
62     Vector<Cookie> cookies;
63     cookies.reserveInitialCapacity(nsCookies.count);
64     for (NSHTTPCookie *nsCookie in nsCookies)
65         cookies.uncheckedAppend(nsCookie);
66
67     return cookies;
68 }
69
70 Vector<Cookie> NetworkStorageSession::getAllCookies()
71 {
72     return nsCookiesToCookieVector(nsCookieStorage().cookies);
73 }
74
75 Vector<Cookie> NetworkStorageSession::getCookies(const URL& url)
76 {
77     return nsCookiesToCookieVector([nsCookieStorage() cookiesForURL:(NSURL *)url]);
78 }
79
80 void NetworkStorageSession::flushCookieStore()
81 {
82     [nsCookieStorage() _saveCookies];
83 }
84
85 NSHTTPCookieStorage *NetworkStorageSession::nsCookieStorage() const
86 {
87     auto cfCookieStorage = cookieStorage();
88     if (!cfCookieStorage || [NSHTTPCookieStorage sharedHTTPCookieStorage]._cookieStorage == cfCookieStorage)
89         return [NSHTTPCookieStorage sharedHTTPCookieStorage];
90
91     return [[[NSHTTPCookieStorage alloc] _initWithCFHTTPCookieStorage:cfCookieStorage.get()] autorelease];
92 }
93
94 CookieStorageObserver& NetworkStorageSession::cookieStorageObserver() const
95 {
96     if (!m_cookieStorageObserver)
97         m_cookieStorageObserver = CookieStorageObserver::create(nsCookieStorage());
98
99     return *m_cookieStorageObserver;
100 }
101
102 CFURLStorageSessionRef createPrivateStorageSession(CFStringRef identifier)
103 {
104     const void* sessionPropertyKeys[] = { _kCFURLStorageSessionIsPrivate };
105     const void* sessionPropertyValues[] = { kCFBooleanTrue };
106     auto sessionProperties = adoptCF(CFDictionaryCreate(kCFAllocatorDefault, sessionPropertyKeys, sessionPropertyValues, sizeof(sessionPropertyKeys) / sizeof(*sessionPropertyKeys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
107     auto storageSession = adoptCF(_CFURLStorageSessionCreate(kCFAllocatorDefault, identifier, sessionProperties.get()));
108
109     if (!storageSession)
110         return nullptr;
111
112     // The private storage session should have the same properties as the default storage session,
113     // with the exception that it should be in-memory only storage.
114
115     // FIXME 9199649: If any of the storages do not exist, do no use the storage session.
116     // This could occur if there is an issue figuring out where to place a storage on disk (e.g. the
117     // sandbox does not allow CFNetwork access).
118
119     auto cache = adoptCF(_CFURLStorageSessionCopyCache(kCFAllocatorDefault, storageSession.get()));
120     if (!cache)
121         return nullptr;
122
123     CFURLCacheSetDiskCapacity(cache.get(), 0); // Setting disk cache size should not be necessary once <rdar://problem/12656814> is fixed.
124     CFURLCacheSetMemoryCapacity(cache.get(), [[NSURLCache sharedURLCache] memoryCapacity]);
125
126     auto cookieStorage = adoptCF(_CFURLStorageSessionCopyCookieStorage(kCFAllocatorDefault, storageSession.get()));
127     if (!cookieStorage)
128         return nullptr;
129
130     // FIXME: Use _CFHTTPCookieStorageGetDefault when USE(CFNETWORK) is defined in WebKit for consistency.
131     CFHTTPCookieStorageSetCookieAcceptPolicy(cookieStorage.get(), [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookieAcceptPolicy]);
132
133     return storageSession.leakRef();
134 }
135
136 } // namespace WebCore