Add support for fetching and remove type _WKWebsiteDataTypeHSTSCache
[WebKit-https.git] / Source / WebKit / NetworkProcess / cocoa / NetworkProcessCocoa.mm
1 /*
2  * Copyright (C) 2014-2018 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 "CookieStorageUtilsCF.h"
30 #import "Logging.h"
31 #import "NetworkCache.h"
32 #import "NetworkProcessCreationParameters.h"
33 #import "NetworkResourceLoader.h"
34 #import "NetworkSessionCocoa.h"
35 #import "SandboxExtension.h"
36 #import "SessionTracker.h"
37 #import <WebCore/NetworkStorageSession.h>
38 #import <WebCore/PublicSuffix.h>
39 #import <WebCore/ResourceRequestCFNet.h>
40 #import <WebCore/RuntimeApplicationChecks.h>
41 #import <WebCore/SecurityOrigin.h>
42 #import <WebCore/SecurityOriginData.h>
43 #import <pal/spi/cf/CFNetworkSPI.h>
44 #import <wtf/BlockPtr.h>
45 #import <wtf/CallbackAggregator.h>
46 #import <wtf/ProcessPrivilege.h>
47
48 #if USE(APPLE_INTERNAL_SDK)
49 #import <WebKitAdditions/NetworkProcessCocoaAdditions.mm>
50 #endif
51
52 namespace WebKit {
53
54 static void initializeNetworkSettings()
55 {
56     static const unsigned preferredConnectionCount = 6;
57
58     _CFNetworkHTTPConnectionCacheSetLimit(kHTTPLoadWidth, preferredConnectionCount);
59
60     Boolean keyExistsAndHasValidFormat = false;
61     Boolean prefValue = CFPreferencesGetAppBooleanValue(CFSTR("WebKitEnableHTTPPipelining"), kCFPreferencesCurrentApplication, &keyExistsAndHasValidFormat);
62     if (keyExistsAndHasValidFormat)
63         WebCore::ResourceRequest::setHTTPPipeliningEnabled(prefValue);
64
65     if (WebCore::ResourceRequest::resourcePrioritiesEnabled()) {
66         const unsigned fastLaneConnectionCount = 1;
67
68         _CFNetworkHTTPConnectionCacheSetLimit(kHTTPPriorityNumLevels, toPlatformRequestPriority(WebCore::ResourceLoadPriority::Highest));
69         _CFNetworkHTTPConnectionCacheSetLimit(kHTTPMinimumFastLanePriority, toPlatformRequestPriority(WebCore::ResourceLoadPriority::Medium));
70         _CFNetworkHTTPConnectionCacheSetLimit(kHTTPNumFastLanes, fastLaneConnectionCount);
71     }
72 }
73
74 void NetworkProcess::platformInitializeNetworkProcessCocoa(const NetworkProcessCreationParameters& parameters)
75 {
76     WebCore::setApplicationBundleIdentifier(parameters.uiProcessBundleIdentifier);
77
78 #if PLATFORM(IOS)
79     SandboxExtension::consumePermanently(parameters.cookieStorageDirectoryExtensionHandle);
80     SandboxExtension::consumePermanently(parameters.containerCachesDirectoryExtensionHandle);
81     SandboxExtension::consumePermanently(parameters.parentBundleDirectoryExtensionHandle);
82 #endif
83     m_diskCacheDirectory = parameters.diskCacheDirectory;
84
85     _CFNetworkSetATSContext(parameters.networkATSContext.get());
86
87     SessionTracker::setIdentifierBase(parameters.uiProcessBundleIdentifier);
88
89     NetworkSessionCocoa::setSourceApplicationAuditTokenData(sourceApplicationAuditData());
90     NetworkSessionCocoa::setSourceApplicationBundleIdentifier(parameters.sourceApplicationBundleIdentifier);
91     NetworkSessionCocoa::setSourceApplicationSecondaryIdentifier(parameters.sourceApplicationSecondaryIdentifier);
92 #if PLATFORM(IOS)
93     NetworkSessionCocoa::setCTDataConnectionServiceType(parameters.ctDataConnectionServiceType);
94 #endif
95
96     initializeNetworkSettings();
97
98 #if PLATFORM(COCOA)
99     setSharedHTTPCookieStorage(parameters.uiProcessCookieStorageIdentifier);
100 #endif
101
102     WebCore::NetworkStorageSession::setCookieStoragePartitioningEnabled(parameters.cookieStoragePartitioningEnabled);
103     WebCore::NetworkStorageSession::setStorageAccessAPIEnabled(parameters.storageAccessAPIEnabled);
104     m_suppressesConnectionTerminationOnSystemChange = parameters.suppressesConnectionTerminationOnSystemChange;
105
106     // FIXME: Most of what this function does for cache size gets immediately overridden by setCacheModel().
107     // - memory cache size passed from UI process is always ignored;
108     // - disk cache size passed from UI process is effectively a minimum size.
109     // 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.
110
111     ASSERT(!m_diskCacheIsDisabledForTesting);
112
113 #if ENABLE(WIFI_ASSERTIONS)
114     initializeWiFiAssertions(parameters);
115 #endif
116
117     if (m_diskCacheDirectory.isNull())
118         return;
119
120     SandboxExtension::consumePermanently(parameters.diskCacheDirectoryExtensionHandle);
121     OptionSet<NetworkCache::Cache::Option> cacheOptions { NetworkCache::Cache::Option::RegisterNotify };
122     if (parameters.shouldEnableNetworkCacheEfficacyLogging)
123         cacheOptions |= NetworkCache::Cache::Option::EfficacyLogging;
124     if (parameters.shouldUseTestingNetworkSession)
125         cacheOptions |= NetworkCache::Cache::Option::TestingMode;
126 #if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION)
127     if (parameters.shouldEnableNetworkCacheSpeculativeRevalidation)
128         cacheOptions |= NetworkCache::Cache::Option::SpeculativeRevalidation;
129 #endif
130
131     m_cache = NetworkCache::Cache::open(m_diskCacheDirectory, cacheOptions);
132     if (!m_cache)
133         RELEASE_LOG_ERROR(NetworkCache, "Failed to initialize the WebKit network disk cache");
134
135     // Disable NSURLCache.
136     auto urlCache(adoptNS([[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:nil]));
137     [NSURLCache setSharedURLCache:urlCache.get()];
138 }
139
140 RetainPtr<CFDataRef> NetworkProcess::sourceApplicationAuditData() const
141 {
142 #if PLATFORM(IOS) && !PLATFORM(IOSMAC)
143     audit_token_t auditToken;
144     ASSERT(parentProcessConnection());
145     if (!parentProcessConnection() || !parentProcessConnection()->getAuditToken(auditToken))
146         return nullptr;
147     return adoptCF(CFDataCreate(nullptr, (const UInt8*)&auditToken, sizeof(auditToken)));
148 #else
149     return nullptr;
150 #endif
151 }
152
153 static void filterPreloadHSTSEntry(const void* key, const void* value, void* context)
154 {
155     HashSet<String>* hostnames = static_cast<HashSet<String>*>(context);
156     auto val = static_cast<CFDictionaryRef>(value);
157     if (CFDictionaryGetValue(val, _kCFNetworkHSTSPreloaded) != kCFBooleanTrue)
158         hostnames->add((CFStringRef)key);
159 }
160
161 void NetworkProcess::getHostNamesWithHSTSCache(WebCore::NetworkStorageSession& session, HashSet<String>& hostNames)
162 {
163     auto HSTSPolicies = adoptCF(_CFNetworkCopyHSTSPolicies(session.platformSession()));
164     CFDictionaryApplyFunction(HSTSPolicies.get(), filterPreloadHSTSEntry, &hostNames);
165 }
166
167 void NetworkProcess::deleteHSTSCacheForHostNames(WebCore::NetworkStorageSession& session, const Vector<String>& hostNames)
168 {
169     for (auto& hostName : hostNames)
170         _CFNetworkResetHSTS(CFURLCreateWithString(kCFAllocatorDefault, hostName.createCFString().get(), NULL), session.platformSession());
171 }
172
173 void NetworkProcess::clearHSTSCache(WebCore::NetworkStorageSession& session, WallTime modifiedSince)
174 {
175     NSTimeInterval timeInterval = modifiedSince.secondsSinceEpoch().seconds();
176     NSDate *date = [NSDate dateWithTimeIntervalSince1970:timeInterval];
177
178     _CFNetworkResetHSTSHostsSinceDate(session.platformSession(), (__bridge CFDateRef)date);
179 }
180
181 void NetworkProcess::clearDiskCache(WallTime modifiedSince, Function<void ()>&& completionHandler)
182 {
183     if (!m_clearCacheDispatchGroup)
184         m_clearCacheDispatchGroup = dispatch_group_create();
185
186     if (auto* cache = NetworkProcess::singleton().cache()) {
187         auto group = m_clearCacheDispatchGroup;
188         dispatch_group_async(group, dispatch_get_main_queue(), BlockPtr<void()>::fromCallable([cache, modifiedSince, completionHandler = WTFMove(completionHandler)] () mutable {
189             cache->clear(modifiedSince, [completionHandler = WTFMove(completionHandler)] () mutable {
190             });
191         }).get());
192     }
193 }
194
195 #if PLATFORM(COCOA)
196 void NetworkProcess::setSharedHTTPCookieStorage(const Vector<uint8_t>& identifier)
197 {
198     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
199     [NSHTTPCookieStorage _setSharedHTTPCookieStorage:adoptNS([[NSHTTPCookieStorage alloc] _initWithCFHTTPCookieStorage:cookieStorageFromIdentifyingData(identifier).get()]).get()];
200 }
201 #endif
202
203 void NetworkProcess::setCookieStoragePartitioningEnabled(bool enabled)
204 {
205     WebCore::NetworkStorageSession::setCookieStoragePartitioningEnabled(enabled);
206 }
207
208 void NetworkProcess::setStorageAccessAPIEnabled(bool enabled)
209 {
210     WebCore::NetworkStorageSession::setStorageAccessAPIEnabled(enabled);
211 }
212
213 void NetworkProcess::syncAllCookies()
214 {
215     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
216 #pragma clang diagnostic push
217 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
218     
219 #if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400) || (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 120000)
220     RefPtr<CallbackAggregator> callbackAggregator = CallbackAggregator::create([this] {
221         didSyncAllCookies();
222     });
223     WebCore::NetworkStorageSession::forEach([&] (auto& networkStorageSession) {
224         [networkStorageSession.nsCookieStorage() _saveCookies:[callbackAggregator] { }];
225     });
226 #else
227     _CFHTTPCookieStorageFlushCookieStores();
228     didSyncAllCookies();
229 #endif
230
231 #pragma clang diagnostic pop
232 }
233
234 void NetworkProcess::platformPrepareToSuspend()
235 {
236 #if ENABLE(WIFI_ASSERTIONS)
237     suspendWiFiAssertions(SuspensionReason::ProcessSuspending);
238 #endif
239 }
240
241 void NetworkProcess::platformProcessDidResume()
242 {
243 #if ENABLE(WIFI_ASSERTIONS)
244     resumeWiFiAssertions(ResumptionReason::ProcessResuming);
245 #endif
246 }
247
248 void NetworkProcess::platformProcessDidTransitionToBackground()
249 {
250 #if ENABLE(WIFI_ASSERTIONS)
251     suspendWiFiAssertions(SuspensionReason::ProcessBackgrounding);
252 #endif
253 }
254     
255 void NetworkProcess::platformProcessDidTransitionToForeground()
256 {
257 #if ENABLE(WIFI_ASSERTIONS)
258     resumeWiFiAssertions(ResumptionReason::ProcessForegrounding);
259 #endif
260 }
261
262 }