Use WTF::Function instead of std::function in NetworkProcess code
[WebKit-https.git] / Source / WebKit2 / NetworkProcess / cocoa / NetworkProcessCocoa.mm
1 /*
2  * Copyright (C) 2014-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. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "NetworkProcess.h"
28
29 #import "NetworkCache.h"
30 #import "NetworkProcessCreationParameters.h"
31 #import "NetworkResourceLoader.h"
32 #import "NetworkSessionCocoa.h"
33 #import "SandboxExtension.h"
34 #import "SessionTracker.h"
35 #import <WebCore/CFNetworkSPI.h>
36 #import <WebCore/NetworkStorageSession.h>
37 #import <WebCore/PublicSuffix.h>
38 #import <WebCore/ResourceRequestCFNet.h>
39 #import <WebCore/RuntimeApplicationChecks.h>
40 #import <WebCore/SecurityOrigin.h>
41 #import <WebCore/SecurityOriginData.h>
42 #import <WebKitSystemInterface.h>
43 #import <wtf/BlockPtr.h>
44
45 namespace WebKit {
46
47 static void initializeNetworkSettings()
48 {
49     static const unsigned preferredConnectionCount = 6;
50
51     _CFNetworkHTTPConnectionCacheSetLimit(kHTTPLoadWidth, preferredConnectionCount);
52
53     Boolean keyExistsAndHasValidFormat = false;
54     Boolean prefValue = CFPreferencesGetAppBooleanValue(CFSTR("WebKitEnableHTTPPipelining"), kCFPreferencesCurrentApplication, &keyExistsAndHasValidFormat);
55     if (keyExistsAndHasValidFormat)
56         WebCore::ResourceRequest::setHTTPPipeliningEnabled(prefValue);
57
58     if (WebCore::ResourceRequest::resourcePrioritiesEnabled()) {
59         const unsigned fastLaneConnectionCount = 1;
60
61         _CFNetworkHTTPConnectionCacheSetLimit(kHTTPPriorityNumLevels, toPlatformRequestPriority(WebCore::ResourceLoadPriority::Highest));
62         _CFNetworkHTTPConnectionCacheSetLimit(kHTTPMinimumFastLanePriority, toPlatformRequestPriority(WebCore::ResourceLoadPriority::Medium));
63         _CFNetworkHTTPConnectionCacheSetLimit(kHTTPNumFastLanes, fastLaneConnectionCount);
64     }
65 }
66
67 void NetworkProcess::platformInitializeNetworkProcessCocoa(const NetworkProcessCreationParameters& parameters)
68 {
69     WebCore::setApplicationBundleIdentifier(parameters.uiProcessBundleIdentifier);
70
71 #if PLATFORM(IOS)
72     SandboxExtension::consumePermanently(parameters.cookieStorageDirectoryExtensionHandle);
73     SandboxExtension::consumePermanently(parameters.containerCachesDirectoryExtensionHandle);
74     SandboxExtension::consumePermanently(parameters.parentBundleDirectoryExtensionHandle);
75 #endif
76     m_diskCacheDirectory = parameters.diskCacheDirectory;
77
78 #if PLATFORM(IOS) || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
79     _CFNetworkSetATSContext(parameters.networkATSContext.get());
80 #endif
81
82     SessionTracker::setIdentifierBase(parameters.uiProcessBundleIdentifier);
83
84 #if USE(NETWORK_SESSION)
85     NetworkSessionCocoa::setSourceApplicationAuditTokenData(sourceApplicationAuditData());
86     NetworkSessionCocoa::setSourceApplicationBundleIdentifier(parameters.sourceApplicationBundleIdentifier);
87     NetworkSessionCocoa::setSourceApplicationSecondaryIdentifier(parameters.sourceApplicationSecondaryIdentifier);
88     NetworkSessionCocoa::setAllowsCellularAccess(parameters.allowsCellularAccess);
89 #if PLATFORM(IOS)
90     NetworkSessionCocoa::setCTDataConnectionServiceType(parameters.ctDataConnectionServiceType);
91 #endif
92 #endif
93
94     initializeNetworkSettings();
95
96 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100
97     setSharedHTTPCookieStorage(parameters.uiProcessCookieStorageIdentifier);
98 #endif
99
100     WebCore::NetworkStorageSession::setCookieStoragePartitioningEnabled(parameters.cookieStoragePartitioningEnabled);
101
102     // FIXME: Most of what this function does for cache size gets immediately overridden by setCacheModel().
103     // - memory cache size passed from UI process is always ignored;
104     // - disk cache size passed from UI process is effectively a minimum size.
105     // One non-obvious constraint is that we need to use -setSharedURLCache: even in testing mode, to prevent creating a default one on disk later, when some other code touches the cache.
106
107     ASSERT(!m_diskCacheIsDisabledForTesting || !parameters.nsURLCacheDiskCapacity);
108
109     if (!m_diskCacheDirectory.isNull()) {
110         SandboxExtension::consumePermanently(parameters.diskCacheDirectoryExtensionHandle);
111 #if ENABLE(NETWORK_CACHE)
112         if (parameters.shouldEnableNetworkCache) {
113             OptionSet<NetworkCache::Cache::Option> cacheOptions;
114             if (parameters.shouldEnableNetworkCacheEfficacyLogging)
115                 cacheOptions |= NetworkCache::Cache::Option::EfficacyLogging;
116             if (parameters.shouldUseTestingNetworkSession)
117                 cacheOptions |= NetworkCache::Cache::Option::TestingMode;
118 #if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION)
119             if (parameters.shouldEnableNetworkCacheSpeculativeRevalidation)
120                 cacheOptions |= NetworkCache::Cache::Option::SpeculativeRevalidation;
121 #endif
122             if (NetworkCache::singleton().initialize(m_diskCacheDirectory, cacheOptions)) {
123                 auto urlCache(adoptNS([[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:nil]));
124                 [NSURLCache setSharedURLCache:urlCache.get()];
125                 return;
126             }
127         }
128 #endif
129         String nsURLCacheDirectory = m_diskCacheDirectory;
130 #if PLATFORM(IOS)
131         // NSURLCache path is relative to network process cache directory.
132         // This puts cache files under <container>/Library/Caches/com.apple.WebKit.Networking/
133         nsURLCacheDirectory = ".";
134 #endif
135         [NSURLCache setSharedURLCache:adoptNS([[NSURLCache alloc]
136             initWithMemoryCapacity:parameters.nsURLCacheMemoryCapacity
137             diskCapacity:parameters.nsURLCacheDiskCapacity
138             diskPath:nsURLCacheDirectory]).get()];
139     }
140 }
141
142 void NetworkProcess::platformSetURLCacheSize(unsigned urlCacheMemoryCapacity, uint64_t urlCacheDiskCapacity)
143 {
144     NSURLCache *nsurlCache = [NSURLCache sharedURLCache];
145     [nsurlCache setMemoryCapacity:urlCacheMemoryCapacity];
146     if (!m_diskCacheIsDisabledForTesting)
147         [nsurlCache setDiskCapacity:std::max<uint64_t>(urlCacheDiskCapacity, [nsurlCache diskCapacity])]; // Don't shrink a big disk cache, since that would cause churn.
148 }
149
150 RetainPtr<CFDataRef> NetworkProcess::sourceApplicationAuditData() const
151 {
152 #if PLATFORM(IOS)
153     audit_token_t auditToken;
154     ASSERT(parentProcessConnection());
155     if (!parentProcessConnection() || !parentProcessConnection()->getAuditToken(auditToken))
156         return nullptr;
157     return adoptCF(CFDataCreate(nullptr, (const UInt8*)&auditToken, sizeof(auditToken)));
158 #else
159     return nullptr;
160 #endif
161 }
162
163 void NetworkProcess::clearHSTSCache(WebCore::NetworkStorageSession& session, std::chrono::system_clock::time_point modifiedSince)
164 {
165     NSTimeInterval timeInterval = std::chrono::duration_cast<std::chrono::duration<double>>(modifiedSince.time_since_epoch()).count();
166     NSDate *date = [NSDate dateWithTimeIntervalSince1970:timeInterval];
167
168     _CFNetworkResetHSTSHostsSinceDate(session.platformSession(), (__bridge CFDateRef)date);
169 }
170
171 static void clearNSURLCache(dispatch_group_t group, std::chrono::system_clock::time_point modifiedSince, Function<void ()>&& completionHandler)
172 {
173     dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), BlockPtr<void()>::fromCallable([modifiedSince, completionHandler = WTFMove(completionHandler)] () mutable {
174         NSURLCache *cache = [NSURLCache sharedURLCache];
175
176         NSTimeInterval timeInterval = std::chrono::duration_cast<std::chrono::duration<double>>(modifiedSince.time_since_epoch()).count();
177         NSDate *date = [NSDate dateWithTimeIntervalSince1970:timeInterval];
178         [cache removeCachedResponsesSinceDate:date];
179
180         dispatch_async(dispatch_get_main_queue(), BlockPtr<void()>::fromCallable([completionHandler = WTFMove(completionHandler)] {
181             completionHandler();
182         }).get());
183     }).get());
184 }
185
186 void NetworkProcess::clearDiskCache(std::chrono::system_clock::time_point modifiedSince, Function<void ()>&& completionHandler)
187 {
188     if (!m_clearCacheDispatchGroup)
189         m_clearCacheDispatchGroup = dispatch_group_create();
190
191 #if ENABLE(NETWORK_CACHE)
192     auto group = m_clearCacheDispatchGroup;
193     dispatch_group_async(group, dispatch_get_main_queue(), BlockPtr<void()>::fromCallable([group, modifiedSince, completionHandler = WTFMove(completionHandler)] () mutable {
194         NetworkCache::singleton().clear(modifiedSince, [group, modifiedSince, completionHandler = WTFMove(completionHandler)] () mutable {
195             // FIXME: Probably not necessary.
196             clearNSURLCache(group, modifiedSince, WTFMove(completionHandler));
197         });
198     }).get());
199 #else
200     clearNSURLCache(m_clearCacheDispatchGroup, modifiedSince, WTFMove(completionHandler));
201 #endif
202 }
203
204 void NetworkProcess::setCookieStoragePartitioningEnabled(bool enabled)
205 {
206     WebCore::NetworkStorageSession::setCookieStoragePartitioningEnabled(enabled);
207 }
208
209 void NetworkProcess::syncAllCookies()
210 {
211 #pragma clang diagnostic push
212 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
213     _CFHTTPCookieStorageFlushCookieStores();
214 #pragma clang diagnostic pop
215 }
216
217 }