Fix entitlements and sandboxing for iphoneminimalsimulator
[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 "NetworkCache.h"
31 #import "NetworkProcessCreationParameters.h"
32 #import "NetworkResourceLoader.h"
33 #import "NetworkSessionCocoa.h"
34 #import "SandboxExtension.h"
35 #import "SessionTracker.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 <pal/spi/cf/CFNetworkSPI.h>
43 #import <wtf/BlockPtr.h>
44 #import <wtf/ProcessPrivilege.h>
45
46 namespace WebKit {
47
48 static void initializeNetworkSettings()
49 {
50     static const unsigned preferredConnectionCount = 6;
51
52     _CFNetworkHTTPConnectionCacheSetLimit(kHTTPLoadWidth, preferredConnectionCount);
53
54     Boolean keyExistsAndHasValidFormat = false;
55     Boolean prefValue = CFPreferencesGetAppBooleanValue(CFSTR("WebKitEnableHTTPPipelining"), kCFPreferencesCurrentApplication, &keyExistsAndHasValidFormat);
56     if (keyExistsAndHasValidFormat)
57         WebCore::ResourceRequest::setHTTPPipeliningEnabled(prefValue);
58
59     if (WebCore::ResourceRequest::resourcePrioritiesEnabled()) {
60         const unsigned fastLaneConnectionCount = 1;
61
62         _CFNetworkHTTPConnectionCacheSetLimit(kHTTPPriorityNumLevels, toPlatformRequestPriority(WebCore::ResourceLoadPriority::Highest));
63         _CFNetworkHTTPConnectionCacheSetLimit(kHTTPMinimumFastLanePriority, toPlatformRequestPriority(WebCore::ResourceLoadPriority::Medium));
64         _CFNetworkHTTPConnectionCacheSetLimit(kHTTPNumFastLanes, fastLaneConnectionCount);
65     }
66 }
67
68 void NetworkProcess::platformInitializeNetworkProcessCocoa(const NetworkProcessCreationParameters& parameters)
69 {
70     WebCore::setApplicationBundleIdentifier(parameters.uiProcessBundleIdentifier);
71
72 #if PLATFORM(IOS)
73     SandboxExtension::consumePermanently(parameters.cookieStorageDirectoryExtensionHandle);
74     SandboxExtension::consumePermanently(parameters.containerCachesDirectoryExtensionHandle);
75     SandboxExtension::consumePermanently(parameters.parentBundleDirectoryExtensionHandle);
76 #endif
77     m_diskCacheDirectory = parameters.diskCacheDirectory;
78
79     _CFNetworkSetATSContext(parameters.networkATSContext.get());
80
81     SessionTracker::setIdentifierBase(parameters.uiProcessBundleIdentifier);
82
83     NetworkSessionCocoa::setSourceApplicationAuditTokenData(sourceApplicationAuditData());
84     NetworkSessionCocoa::setSourceApplicationBundleIdentifier(parameters.sourceApplicationBundleIdentifier);
85     NetworkSessionCocoa::setSourceApplicationSecondaryIdentifier(parameters.sourceApplicationSecondaryIdentifier);
86     NetworkSessionCocoa::setUsesNetworkCache(parameters.shouldEnableNetworkCache);
87 #if PLATFORM(IOS)
88     NetworkSessionCocoa::setCTDataConnectionServiceType(parameters.ctDataConnectionServiceType);
89 #endif
90
91     initializeNetworkSettings();
92
93 #if PLATFORM(MAC)
94     setSharedHTTPCookieStorage(parameters.uiProcessCookieStorageIdentifier);
95 #endif
96
97     WebCore::NetworkStorageSession::setCookieStoragePartitioningEnabled(parameters.cookieStoragePartitioningEnabled);
98     WebCore::NetworkStorageSession::setStorageAccessAPIEnabled(parameters.storageAccessAPIEnabled);
99
100     // FIXME: Most of what this function does for cache size gets immediately overridden by setCacheModel().
101     // - memory cache size passed from UI process is always ignored;
102     // - disk cache size passed from UI process is effectively a minimum size.
103     // 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.
104
105     ASSERT(!m_diskCacheIsDisabledForTesting || !parameters.nsURLCacheDiskCapacity);
106
107     if (!parameters.cacheStorageDirectory.isNull()) {
108         m_cacheStorageDirectory = parameters.cacheStorageDirectory;
109         m_cacheStoragePerOriginQuota = parameters.cacheStoragePerOriginQuota;
110         SandboxExtension::consumePermanently(parameters.cacheStorageDirectoryExtensionHandle);
111     }
112
113     if (!m_diskCacheDirectory.isNull()) {
114         SandboxExtension::consumePermanently(parameters.diskCacheDirectoryExtensionHandle);
115         if (parameters.shouldEnableNetworkCache) {
116             OptionSet<NetworkCache::Cache::Option> cacheOptions { NetworkCache::Cache::Option::RegisterNotify };
117             if (parameters.shouldEnableNetworkCacheEfficacyLogging)
118                 cacheOptions |= NetworkCache::Cache::Option::EfficacyLogging;
119             if (parameters.shouldUseTestingNetworkSession)
120                 cacheOptions |= NetworkCache::Cache::Option::TestingMode;
121 #if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION)
122             if (parameters.shouldEnableNetworkCacheSpeculativeRevalidation)
123                 cacheOptions |= NetworkCache::Cache::Option::SpeculativeRevalidation;
124 #endif
125             m_cache = NetworkCache::Cache::open(m_diskCacheDirectory, cacheOptions);
126
127             if (m_cache) {
128                 // Disable NSURLCache.
129                 auto urlCache(adoptNS([[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:nil]));
130                 [NSURLCache setSharedURLCache:urlCache.get()];
131                 return;
132             }
133         }
134         String nsURLCacheDirectory = m_diskCacheDirectory;
135 #if PLATFORM(IOS)
136         // NSURLCache path is relative to network process cache directory.
137         // This puts cache files under <container>/Library/Caches/com.apple.WebKit.Networking/
138         nsURLCacheDirectory = ".";
139 #endif
140         [NSURLCache setSharedURLCache:adoptNS([[NSURLCache alloc]
141             initWithMemoryCapacity:parameters.nsURLCacheMemoryCapacity
142             diskCapacity:parameters.nsURLCacheDiskCapacity
143             diskPath:nsURLCacheDirectory]).get()];
144     }
145 }
146
147 void NetworkProcess::platformSetURLCacheSize(unsigned urlCacheMemoryCapacity, uint64_t urlCacheDiskCapacity)
148 {
149     NSURLCache *nsurlCache = [NSURLCache sharedURLCache];
150     [nsurlCache setMemoryCapacity:urlCacheMemoryCapacity];
151     if (!m_diskCacheIsDisabledForTesting)
152         [nsurlCache setDiskCapacity:std::max<uint64_t>(urlCacheDiskCapacity, [nsurlCache diskCapacity])]; // Don't shrink a big disk cache, since that would cause churn.
153 }
154
155 RetainPtr<CFDataRef> NetworkProcess::sourceApplicationAuditData() const
156 {
157 #if PLATFORM(IOS) && !ENABLE(MINIMAL_SIMULATOR)
158     audit_token_t auditToken;
159     ASSERT(parentProcessConnection());
160     if (!parentProcessConnection() || !parentProcessConnection()->getAuditToken(auditToken))
161         return nullptr;
162     return adoptCF(CFDataCreate(nullptr, (const UInt8*)&auditToken, sizeof(auditToken)));
163 #else
164     return nullptr;
165 #endif
166 }
167
168 void NetworkProcess::clearHSTSCache(WebCore::NetworkStorageSession& session, WallTime modifiedSince)
169 {
170     NSTimeInterval timeInterval = modifiedSince.secondsSinceEpoch().seconds();
171     NSDate *date = [NSDate dateWithTimeIntervalSince1970:timeInterval];
172
173     _CFNetworkResetHSTSHostsSinceDate(session.platformSession(), (__bridge CFDateRef)date);
174 }
175
176 static void clearNSURLCache(dispatch_group_t group, WallTime modifiedSince, Function<void ()>&& completionHandler)
177 {
178     dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), BlockPtr<void()>::fromCallable([modifiedSince, completionHandler = WTFMove(completionHandler)] () mutable {
179         NSURLCache *cache = [NSURLCache sharedURLCache];
180
181         NSTimeInterval timeInterval = modifiedSince.secondsSinceEpoch().seconds();
182         NSDate *date = [NSDate dateWithTimeIntervalSince1970:timeInterval];
183         [cache removeCachedResponsesSinceDate:date];
184
185         dispatch_async(dispatch_get_main_queue(), BlockPtr<void()>::fromCallable([completionHandler = WTFMove(completionHandler)] {
186             completionHandler();
187         }).get());
188     }).get());
189 }
190
191 void NetworkProcess::clearDiskCache(WallTime modifiedSince, Function<void ()>&& completionHandler)
192 {
193     if (!m_clearCacheDispatchGroup)
194         m_clearCacheDispatchGroup = dispatch_group_create();
195
196     if (auto* cache = NetworkProcess::singleton().cache()) {
197         auto group = m_clearCacheDispatchGroup;
198         dispatch_group_async(group, dispatch_get_main_queue(), BlockPtr<void()>::fromCallable([cache, group, modifiedSince, completionHandler = WTFMove(completionHandler)] () mutable {
199             cache->clear(modifiedSince, [group, modifiedSince, completionHandler = WTFMove(completionHandler)] () mutable {
200                 // FIXME: Probably not necessary.
201                 clearNSURLCache(group, modifiedSince, WTFMove(completionHandler));
202             });
203         }).get());
204         return;
205     }
206     clearNSURLCache(m_clearCacheDispatchGroup, modifiedSince, WTFMove(completionHandler));
207 }
208
209 #if PLATFORM(MAC)
210 void NetworkProcess::setSharedHTTPCookieStorage(const Vector<uint8_t>& identifier)
211 {
212     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
213     [NSHTTPCookieStorage _setSharedHTTPCookieStorage:adoptNS([[NSHTTPCookieStorage alloc] _initWithCFHTTPCookieStorage:cookieStorageFromIdentifyingData(identifier).get()]).get()];
214 }
215 #endif
216
217 void NetworkProcess::setCookieStoragePartitioningEnabled(bool enabled)
218 {
219     WebCore::NetworkStorageSession::setCookieStoragePartitioningEnabled(enabled);
220 }
221
222 void NetworkProcess::setStorageAccessAPIEnabled(bool enabled)
223 {
224     WebCore::NetworkStorageSession::setStorageAccessAPIEnabled(enabled);
225 }
226
227 void NetworkProcess::syncAllCookies()
228 {
229     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
230 #pragma clang diagnostic push
231 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
232     _CFHTTPCookieStorageFlushCookieStores();
233 #pragma clang diagnostic pop
234 }
235
236 }