Remove ENABLE_NETWORK_CACHE
[WebKit-https.git] / Source / WebKit / UIProcess / Cocoa / WebProcessPoolCocoa.mm
1 /*
2  * Copyright (C) 2010-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 "WebProcessPool.h"
28
29 #import "CookieStorageUtilsCF.h"
30 #import "LegacyCustomProtocolManagerClient.h"
31 #import "NetworkProcessCreationParameters.h"
32 #import "NetworkProcessMessages.h"
33 #import "NetworkProcessProxy.h"
34 #import "PluginProcessManager.h"
35 #import "SandboxUtilities.h"
36 #import "TextChecker.h"
37 #import "VersionChecks.h"
38 #import "WKBrowsingContextControllerInternal.h"
39 #import "WebPageGroup.h"
40 #import "WebPreferencesKeys.h"
41 #import "WebProcessCreationParameters.h"
42 #import "WebProcessMessages.h"
43 #import "WindowServerConnection.h"
44 #import <WebCore/Color.h>
45 #import <WebCore/FileSystem.h>
46 #import <WebCore/NetworkStorageSession.h>
47 #import <WebCore/NotImplemented.h>
48 #import <WebCore/PlatformPasteboard.h>
49 #import <WebCore/RuntimeApplicationChecks.h>
50 #import <WebCore/SharedBuffer.h>
51 #import <pal/spi/cf/CFNetworkSPI.h>
52 #import <sys/param.h>
53
54 #if PLATFORM(IOS)
55 #import "ArgumentCodersCF.h"
56 #import "WebMemoryPressureHandlerIOS.h"
57 #else
58 #import <QuartzCore/CARemoteLayerServer.h>
59 #endif
60
61 using namespace WebCore;
62
63 NSString *WebDatabaseDirectoryDefaultsKey = @"WebDatabaseDirectory";
64 NSString *WebKitLocalCacheDefaultsKey = @"WebKitLocalCache";
65 NSString *WebStorageDirectoryDefaultsKey = @"WebKitLocalStorageDatabasePathPreferenceKey";
66 NSString *WebKitJSCJITEnabledDefaultsKey = @"WebKitJSCJITEnabledDefaultsKey";
67 NSString *WebKitJSCFTLJITEnabledDefaultsKey = @"WebKitJSCFTLJITEnabledDefaultsKey";
68 NSString *WebKitMediaKeysStorageDirectoryDefaultsKey = @"WebKitMediaKeysStorageDirectory";
69 NSString *WebKitMediaCacheDirectoryDefaultsKey = @"WebKitMediaCacheDirectory";
70
71 #if !PLATFORM(IOS)
72 static NSString *WebKitApplicationDidChangeAccessibilityEnhancedUserInterfaceNotification = @"NSApplicationDidChangeAccessibilityEnhancedUserInterfaceNotification";
73 #endif
74
75 // FIXME: <rdar://problem/9138817> - After this "backwards compatibility" radar is removed, this code should be removed to only return an empty String.
76 NSString *WebIconDatabaseDirectoryDefaultsKey = @"WebIconDatabaseDirectoryDefaultsKey";
77
78 static NSString * const WebKit2HTTPProxyDefaultsKey = @"WebKit2HTTPProxy";
79 static NSString * const WebKit2HTTPSProxyDefaultsKey = @"WebKit2HTTPSProxy";
80
81 static NSString * const WebKitNetworkCacheEnabledDefaultsKey = @"WebKitNetworkCacheEnabled";
82 static NSString * const WebKitNetworkCacheEfficacyLoggingEnabledDefaultsKey = @"WebKitNetworkCacheEfficacyLoggingEnabled";
83
84 static NSString * const WebKitSuppressMemoryPressureHandlerDefaultsKey = @"WebKitSuppressMemoryPressureHandler";
85 static NSString * const WebKitNetworkLoadThrottleLatencyMillisecondsDefaultsKey = @"WebKitNetworkLoadThrottleLatencyMilliseconds";
86
87 #if ENABLE(NETWORK_CAPTURE)
88 static NSString * const WebKitRecordReplayModeDefaultsKey = @"WebKitRecordReplayMode";
89 static NSString * const WebKitRecordReplayCacheLocationDefaultsKey = @"WebKitRecordReplayCacheLocation";
90 #endif
91
92 namespace WebKit {
93
94 NSString *SchemeForCustomProtocolRegisteredNotificationName = @"WebKitSchemeForCustomProtocolRegisteredNotification";
95 NSString *SchemeForCustomProtocolUnregisteredNotificationName = @"WebKitSchemeForCustomProtocolUnregisteredNotification";
96
97 static void registerUserDefaultsIfNeeded()
98 {
99     static bool didRegister;
100     if (didRegister)
101         return;
102
103     didRegister = true;
104     NSMutableDictionary *registrationDictionary = [NSMutableDictionary dictionary];
105     
106     [registrationDictionary setObject:@YES forKey:WebKitJSCJITEnabledDefaultsKey];
107     [registrationDictionary setObject:@YES forKey:WebKitJSCFTLJITEnabledDefaultsKey];
108
109     [registrationDictionary setObject:@YES forKey:WebKitNetworkCacheEnabledDefaultsKey];
110     [registrationDictionary setObject:@NO forKey:WebKitNetworkCacheEfficacyLoggingEnabledDefaultsKey];
111
112     [[NSUserDefaults standardUserDefaults] registerDefaults:registrationDictionary];
113 }
114
115 void WebProcessPool::updateProcessSuppressionState()
116 {
117     if (m_networkProcess)
118         m_networkProcess->setProcessSuppressionEnabled(processSuppressionEnabled());
119
120 #if ENABLE(NETSCAPE_PLUGIN_API)
121     if (!m_processSuppressionDisabledForPageCounter.value())
122         m_pluginProcessManagerProcessSuppressionDisabledToken = nullptr;
123     else if (!m_pluginProcessManagerProcessSuppressionDisabledToken)
124         m_pluginProcessManagerProcessSuppressionDisabledToken = PluginProcessManager::singleton().processSuppressionDisabledToken();
125 #endif
126 }
127
128 NSMutableDictionary *WebProcessPool::ensureBundleParameters()
129 {
130     if (!m_bundleParameters)
131         m_bundleParameters = adoptNS([[NSMutableDictionary alloc] init]);
132
133     return m_bundleParameters.get();
134 }
135
136 void WebProcessPool::platformInitialize()
137 {
138     registerUserDefaultsIfNeeded();
139     registerNotificationObservers();
140
141 #if PLATFORM(IOS)
142     IPC::setAllowsDecodingSecKeyRef(true);
143     installMemoryPressureHandler();
144 #endif
145
146     setLegacyCustomProtocolManagerClient(std::make_unique<LegacyCustomProtocolManagerClient>());
147 }
148
149 #if PLATFORM(IOS)
150 String WebProcessPool::cookieStorageDirectory() const
151 {
152     String path = pathForProcessContainer();
153     if (path.isEmpty())
154         path = NSHomeDirectory();
155
156     path = path + "/Library/Cookies";
157     path = stringByResolvingSymlinksInPath(path);
158     return path;
159 }
160 #endif
161
162 void WebProcessPool::platformResolvePathsForSandboxExtensions()
163 {
164     m_resolvedPaths.uiProcessBundleResourcePath = resolvePathForSandboxExtension([[NSBundle mainBundle] resourcePath]);
165
166 #if PLATFORM(IOS)
167     m_resolvedPaths.cookieStorageDirectory = resolveAndCreateReadWriteDirectoryForSandboxExtension(cookieStorageDirectory());
168     m_resolvedPaths.containerCachesDirectory = resolveAndCreateReadWriteDirectoryForSandboxExtension(webContentCachesDirectory());
169     m_resolvedPaths.containerTemporaryDirectory = resolveAndCreateReadWriteDirectoryForSandboxExtension(containerTemporaryDirectory());
170 #endif
171 }
172
173 void WebProcessPool::platformInitializeWebProcess(WebProcessCreationParameters& parameters)
174 {
175 #if PLATFORM(MAC)
176 #pragma clang diagnostic push
177 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
178     parameters.accessibilityEnhancedUserInterfaceEnabled = [[NSApp accessibilityAttributeValue:@"AXEnhancedUserInterface"] boolValue];
179 #pragma clang diagnostic pop
180 #else
181     parameters.accessibilityEnhancedUserInterfaceEnabled = false;
182 #endif
183
184     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
185
186     parameters.shouldEnableJIT = [defaults boolForKey:WebKitJSCJITEnabledDefaultsKey];
187     parameters.shouldEnableFTLJIT = [defaults boolForKey:WebKitJSCFTLJITEnabledDefaultsKey];
188     parameters.shouldEnableMemoryPressureReliefLogging = [defaults boolForKey:@"LogMemoryJetsamDetails"];
189     parameters.shouldSuppressMemoryPressureHandler = [defaults boolForKey:WebKitSuppressMemoryPressureHandlerDefaultsKey];
190
191 #if HAVE(HOSTED_CORE_ANIMATION)
192 #if !PLATFORM(IOS)
193     parameters.acceleratedCompositingPort = MachSendRight::create([CARemoteLayerServer sharedServer].serverPort);
194 #endif
195 #endif
196
197     // FIXME: This should really be configurable; we shouldn't just blindly allow read access to the UI process bundle.
198     parameters.uiProcessBundleResourcePath = m_resolvedPaths.uiProcessBundleResourcePath;
199     SandboxExtension::createHandleWithoutResolvingPath(parameters.uiProcessBundleResourcePath, SandboxExtension::Type::ReadOnly, parameters.uiProcessBundleResourcePathExtensionHandle);
200
201     parameters.uiProcessBundleIdentifier = String([[NSBundle mainBundle] bundleIdentifier]);
202
203 #if PLATFORM(IOS)
204     if (!m_resolvedPaths.cookieStorageDirectory.isEmpty())
205         SandboxExtension::createHandleWithoutResolvingPath(m_resolvedPaths.cookieStorageDirectory, SandboxExtension::Type::ReadWrite, parameters.cookieStorageDirectoryExtensionHandle);
206
207     if (!m_resolvedPaths.containerCachesDirectory.isEmpty())
208         SandboxExtension::createHandleWithoutResolvingPath(m_resolvedPaths.containerCachesDirectory, SandboxExtension::Type::ReadWrite, parameters.containerCachesDirectoryExtensionHandle);
209
210     if (!m_resolvedPaths.containerTemporaryDirectory.isEmpty())
211         SandboxExtension::createHandleWithoutResolvingPath(m_resolvedPaths.containerTemporaryDirectory, SandboxExtension::Type::ReadWrite, parameters.containerTemporaryDirectoryExtensionHandle);
212 #endif
213
214     parameters.fontWhitelist = m_fontWhitelist;
215
216     if (m_bundleParameters) {
217         auto data = adoptNS([[NSMutableData alloc] init]);
218         auto keyedArchiver = adoptNS([[NSKeyedArchiver alloc] initForWritingWithMutableData:data.get()]);
219
220         [keyedArchiver setRequiresSecureCoding:YES];
221
222         @try {
223             [keyedArchiver encodeObject:m_bundleParameters.get() forKey:@"parameters"];
224             [keyedArchiver finishEncoding];
225         } @catch (NSException *exception) {
226             LOG_ERROR("Failed to encode bundle parameters: %@", exception);
227         }
228
229         parameters.bundleParameterData = API::Data::createWithoutCopying((const unsigned char*)[data bytes], [data length], [] (unsigned char*, const void* data) {
230             [(NSData *)data release];
231         }, data.leakRef());
232     }
233     parameters.networkATSContext = adoptCF(_CFNetworkCopyATSContext());
234
235 #if PLATFORM(MAC)
236     ASSERT(parameters.uiProcessCookieStorageIdentifier.isEmpty());
237     parameters.uiProcessCookieStorageIdentifier = identifyingDataFromCookieStorage([[NSHTTPCookieStorage sharedHTTPCookieStorage] _cookieStorage]);
238 #endif
239 #if ENABLE(MEDIA_STREAM)
240     // Allow microphone access if either preference is set because WebRTC requires microphone access.
241     bool mediaDevicesEnabled = m_defaultPageGroup->preferences().mediaDevicesEnabled();
242     bool webRTCEnabled = m_defaultPageGroup->preferences().peerConnectionEnabled();
243     if ([defaults objectForKey:@"ExperimentalPeerConnectionEnabled"])
244         webRTCEnabled = [defaults boolForKey:@"ExperimentalPeerConnectionEnabled"];
245
246     bool isSafari = false;
247 #if PLATFORM(IOS)
248     if (WebCore::IOSApplication::isMobileSafari())
249         isSafari = true;
250 #elif PLATFORM(MAC)
251     if (WebCore::MacApplication::isSafari())
252         isSafari = true;
253 #endif
254
255 #if !LOG_DISABLED || !RELEASE_LOG_DISABLED
256     parameters.webCoreLoggingChannels = [[NSUserDefaults standardUserDefaults] stringForKey:@"WebCoreLogging"];
257 #endif
258
259     // FIXME: Remove this and related parameter when <rdar://problem/29448368> is fixed.
260     if (isSafari && !parameters.shouldCaptureAudioInUIProcess && mediaDevicesEnabled)
261         SandboxExtension::createHandleForGenericExtension("com.apple.webkit.microphone", parameters.audioCaptureExtensionHandle);
262 #endif
263 }
264
265 void WebProcessPool::platformInitializeNetworkProcess(NetworkProcessCreationParameters& parameters)
266 {
267     NSURLCache *urlCache = [NSURLCache sharedURLCache];
268     parameters.nsURLCacheMemoryCapacity = [urlCache memoryCapacity];
269     parameters.nsURLCacheDiskCapacity = [urlCache diskCapacity];
270
271     parameters.parentProcessName = [[NSProcessInfo processInfo] processName];
272     parameters.uiProcessBundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
273
274     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
275
276     parameters.httpProxy = [defaults stringForKey:WebKit2HTTPProxyDefaultsKey];
277     parameters.httpsProxy = [defaults stringForKey:WebKit2HTTPSProxyDefaultsKey];
278     parameters.networkATSContext = adoptCF(_CFNetworkCopyATSContext());
279
280     parameters.shouldEnableNetworkCache = isNetworkCacheEnabled();
281     parameters.shouldEnableNetworkCacheEfficacyLogging = [defaults boolForKey:WebKitNetworkCacheEfficacyLoggingEnabledDefaultsKey];
282
283     parameters.sourceApplicationBundleIdentifier = m_configuration->sourceApplicationBundleIdentifier();
284     parameters.sourceApplicationSecondaryIdentifier = m_configuration->sourceApplicationSecondaryIdentifier();
285 #if PLATFORM(IOS)
286     parameters.ctDataConnectionServiceType = m_configuration->ctDataConnectionServiceType();
287 #endif
288
289     parameters.shouldSuppressMemoryPressureHandler = [defaults boolForKey:WebKitSuppressMemoryPressureHandlerDefaultsKey];
290     parameters.loadThrottleLatency = Seconds { [defaults integerForKey:WebKitNetworkLoadThrottleLatencyMillisecondsDefaultsKey] / 1000. };
291
292 #if PLATFORM(MAC)
293     ASSERT(parameters.uiProcessCookieStorageIdentifier.isEmpty());
294     parameters.uiProcessCookieStorageIdentifier = identifyingDataFromCookieStorage([[NSHTTPCookieStorage sharedHTTPCookieStorage] _cookieStorage]);
295 #endif
296
297     parameters.cookieStoragePartitioningEnabled = cookieStoragePartitioningEnabled();
298
299 #if ENABLE(NETWORK_CAPTURE)
300     parameters.recordReplayMode = [defaults stringForKey:WebKitRecordReplayModeDefaultsKey];
301     parameters.recordReplayCacheLocation = [defaults stringForKey:WebKitRecordReplayCacheLocationDefaultsKey];
302     if (parameters.recordReplayCacheLocation.isEmpty())
303         parameters.recordReplayCacheLocation = parameters.diskCacheDirectory;
304 #endif
305 }
306
307 void WebProcessPool::platformInvalidateContext()
308 {
309     unregisterNotificationObservers();
310 }
311
312 #if PLATFORM(IOS)
313 String WebProcessPool::parentBundleDirectory() const
314 {
315     return [[[NSBundle mainBundle] bundlePath] stringByStandardizingPath];
316 }
317
318 String WebProcessPool::networkingCachesDirectory() const
319 {
320     String path = pathForProcessContainer();
321     if (path.isEmpty())
322         path = NSHomeDirectory();
323
324     path = path + "/Library/Caches/com.apple.WebKit.Networking/";
325     path = stringByResolvingSymlinksInPath(path);
326
327     NSError *error = nil;
328     NSString* nsPath = path;
329     if (![[NSFileManager defaultManager] createDirectoryAtPath:nsPath withIntermediateDirectories:YES attributes:nil error:&error]) {
330         NSLog(@"could not create networking caches directory \"%@\", error %@", nsPath, error);
331         return String();
332     }
333
334     return path;
335 }
336
337 String WebProcessPool::webContentCachesDirectory() const
338 {
339     String path = pathForProcessContainer();
340     if (path.isEmpty())
341         path = NSHomeDirectory();
342
343     path = path + "/Library/Caches/com.apple.WebKit.WebContent/";
344     path = stringByResolvingSymlinksInPath(path);
345
346     NSError *error = nil;
347     NSString* nsPath = path;
348     if (![[NSFileManager defaultManager] createDirectoryAtPath:nsPath withIntermediateDirectories:YES attributes:nil error:&error]) {
349         NSLog(@"could not create web content caches directory \"%@\", error %@", nsPath, error);
350         return String();
351     }
352
353     return path;
354 }
355
356 String WebProcessPool::containerTemporaryDirectory() const
357 {
358     String path = NSTemporaryDirectory();
359     return stringByResolvingSymlinksInPath(path);
360 }
361 #endif
362
363 String WebProcessPool::legacyPlatformDefaultWebSQLDatabaseDirectory()
364 {
365     registerUserDefaultsIfNeeded();
366
367     NSString *databasesDirectory = [[NSUserDefaults standardUserDefaults] objectForKey:WebDatabaseDirectoryDefaultsKey];
368     if (!databasesDirectory || ![databasesDirectory isKindOfClass:[NSString class]])
369         databasesDirectory = @"~/Library/WebKit/Databases";
370     return stringByResolvingSymlinksInPath([databasesDirectory stringByStandardizingPath]);
371 }
372
373 String WebProcessPool::legacyPlatformDefaultIndexedDBDatabaseDirectory()
374 {
375     // Indexed databases exist in a subdirectory of the "database directory path."
376     // Currently, the top level of that directory contains entities related to WebSQL databases.
377     // We should fix this, and move WebSQL into a subdirectory (https://bugs.webkit.org/show_bug.cgi?id=124807)
378     // In the meantime, an entity name prefixed with three underscores will not conflict with any WebSQL entities.
379     return pathByAppendingComponent(legacyPlatformDefaultWebSQLDatabaseDirectory(), "___IndexedDB");
380 }
381
382 String WebProcessPool::legacyPlatformDefaultLocalStorageDirectory()
383 {
384     registerUserDefaultsIfNeeded();
385
386     NSString *localStorageDirectory = [[NSUserDefaults standardUserDefaults] objectForKey:WebStorageDirectoryDefaultsKey];
387     if (!localStorageDirectory || ![localStorageDirectory isKindOfClass:[NSString class]])
388         localStorageDirectory = @"~/Library/WebKit/LocalStorage";
389     return stringByResolvingSymlinksInPath([localStorageDirectory stringByStandardizingPath]);
390 }
391
392 String WebProcessPool::legacyPlatformDefaultMediaCacheDirectory()
393 {
394     registerUserDefaultsIfNeeded();
395     
396     NSString *mediaKeysCacheDirectory = [[NSUserDefaults standardUserDefaults] objectForKey:WebKitMediaCacheDirectoryDefaultsKey];
397     if (!mediaKeysCacheDirectory || ![mediaKeysCacheDirectory isKindOfClass:[NSString class]]) {
398         mediaKeysCacheDirectory = NSTemporaryDirectory();
399         
400         if (!WebKit::processHasContainer()) {
401             NSString *bundleIdentifier = [NSBundle mainBundle].bundleIdentifier;
402             if (!bundleIdentifier)
403                 bundleIdentifier = [NSProcessInfo processInfo].processName;
404             mediaKeysCacheDirectory = [mediaKeysCacheDirectory stringByAppendingPathComponent:bundleIdentifier];
405         }
406         mediaKeysCacheDirectory = [mediaKeysCacheDirectory stringByAppendingPathComponent:@"WebKit/MediaCache"];
407     }
408     return stringByResolvingSymlinksInPath([mediaKeysCacheDirectory stringByStandardizingPath]);
409 }
410
411 String WebProcessPool::legacyPlatformDefaultMediaKeysStorageDirectory()
412 {
413     registerUserDefaultsIfNeeded();
414
415     NSString *mediaKeysStorageDirectory = [[NSUserDefaults standardUserDefaults] objectForKey:WebKitMediaKeysStorageDirectoryDefaultsKey];
416     if (!mediaKeysStorageDirectory || ![mediaKeysStorageDirectory isKindOfClass:[NSString class]])
417         mediaKeysStorageDirectory = @"~/Library/WebKit/MediaKeys";
418     return stringByResolvingSymlinksInPath([mediaKeysStorageDirectory stringByStandardizingPath]);
419 }
420
421 String WebProcessPool::legacyPlatformDefaultApplicationCacheDirectory()
422 {
423     NSString *appName = [[NSBundle mainBundle] bundleIdentifier];
424     if (!appName)
425         appName = [[NSProcessInfo processInfo] processName];
426 #if PLATFORM(IOS)
427     // This quirk used to make these apps share application cache storage, but doesn't accomplish that any more.
428     // Preserving it avoids the need to migrate data when upgrading.
429     if (IOSApplication::isMobileSafari() || IOSApplication::isWebApp())
430         appName = @"com.apple.WebAppCache";
431 #endif
432
433     ASSERT(appName);
434
435 #if PLATFORM(IOS)
436     NSString *cacheDir = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Caches"];
437 #else
438     char cacheDirectory[MAXPATHLEN];
439     size_t cacheDirectoryLen = confstr(_CS_DARWIN_USER_CACHE_DIR, cacheDirectory, MAXPATHLEN);
440     if (!cacheDirectoryLen)
441         return String();
442
443     NSString *cacheDir = [[NSFileManager defaultManager] stringWithFileSystemRepresentation:cacheDirectory length:cacheDirectoryLen - 1];
444 #endif
445     NSString* cachePath = [cacheDir stringByAppendingPathComponent:appName];
446     return stringByResolvingSymlinksInPath([cachePath stringByStandardizingPath]);
447 }
448
449 String WebProcessPool::legacyPlatformDefaultCacheStorageDirectory()
450 {
451     RetainPtr<NSString> cacheStoragePath = adoptNS((NSString *)_CFURLCacheCopyCacheDirectory([[NSURLCache sharedURLCache] _CFURLCache]));
452     if (!cacheStoragePath)
453         cacheStoragePath = @"~/Library/WebKit/CacheStorage";
454
455     return stringByResolvingSymlinksInPath([cacheStoragePath stringByStandardizingPath]);
456 }
457
458 String WebProcessPool::legacyPlatformDefaultNetworkCacheDirectory()
459 {
460     RetainPtr<NSString> cachePath = adoptNS((NSString *)_CFURLCacheCopyCacheDirectory([[NSURLCache sharedURLCache] _CFURLCache]));
461     if (!cachePath)
462         cachePath = @"~/Library/Caches/com.apple.WebKit.WebProcess";
463
464     if (isNetworkCacheEnabled())
465         cachePath = [cachePath stringByAppendingPathComponent:@"WebKitCache"];
466
467     return stringByResolvingSymlinksInPath([cachePath stringByStandardizingPath]);
468 }
469
470 String WebProcessPool::legacyPlatformDefaultJavaScriptConfigurationDirectory()
471 {
472 #if PLATFORM(IOS)
473     String path = pathForProcessContainer();
474     if (path.isEmpty())
475         path = NSHomeDirectory();
476     
477     path = path + "/Library/WebKit/JavaScriptCoreDebug";
478     path = stringByResolvingSymlinksInPath(path);
479
480     return path;
481 #else
482     RetainPtr<NSString> javaScriptConfigPath = @"~/Library/WebKit/JavaScriptCoreDebug";
483     
484     return stringByResolvingSymlinksInPath([javaScriptConfigPath stringByStandardizingPath]);
485 #endif
486 }
487
488 #if PLATFORM(IOS)
489 void WebProcessPool::setJavaScriptConfigurationFileEnabledFromDefaults()
490 {
491     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
492
493     setJavaScriptConfigurationFileEnabled([defaults boolForKey:@"WebKitJavaScriptCoreUseConfigFile"]);
494 }
495 #endif
496
497 bool WebProcessPool::isNetworkCacheEnabled()
498 {
499     registerUserDefaultsIfNeeded();
500
501     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
502
503     bool networkCacheEnabledByDefaults = [defaults boolForKey:WebKitNetworkCacheEnabledDefaultsKey];
504
505     return networkCacheEnabledByDefaults && linkedOnOrAfter(SDKVersion::FirstWithNetworkCache);
506 }
507
508 bool WebProcessPool::omitPDFSupport()
509 {
510     // Since this is a "secret default" we don't bother registering it.
511     return [[NSUserDefaults standardUserDefaults] boolForKey:@"WebKitOmitPDFSupport"];
512 }
513
514 bool WebProcessPool::processSuppressionEnabled() const
515 {
516     return !m_userObservablePageCounter.value() && !m_processSuppressionDisabledForPageCounter.value();
517 }
518
519 void WebProcessPool::registerNotificationObservers()
520 {
521 #if !PLATFORM(IOS)
522     // Listen for enhanced accessibility changes and propagate them to the WebProcess.
523     m_enhancedAccessibilityObserver = [[NSNotificationCenter defaultCenter] addObserverForName:WebKitApplicationDidChangeAccessibilityEnhancedUserInterfaceNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *note) {
524         setEnhancedAccessibility([[[note userInfo] objectForKey:@"AXEnhancedUserInterface"] boolValue]);
525     }];
526
527     m_automaticTextReplacementNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSSpellCheckerDidChangeAutomaticTextReplacementNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) {
528         TextChecker::didChangeAutomaticTextReplacementEnabled();
529         textCheckerStateChanged();
530     }];
531     
532     m_automaticSpellingCorrectionNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSSpellCheckerDidChangeAutomaticSpellingCorrectionNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) {
533         TextChecker::didChangeAutomaticSpellingCorrectionEnabled();
534         textCheckerStateChanged();
535     }];
536
537     m_automaticQuoteSubstitutionNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSSpellCheckerDidChangeAutomaticQuoteSubstitutionNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) {
538         TextChecker::didChangeAutomaticQuoteSubstitutionEnabled();
539         textCheckerStateChanged();
540     }];
541
542     m_automaticDashSubstitutionNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSSpellCheckerDidChangeAutomaticDashSubstitutionNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) {
543         TextChecker::didChangeAutomaticDashSubstitutionEnabled();
544         textCheckerStateChanged();
545     }];
546 #endif // !PLATFORM(IOS)
547 }
548
549 void WebProcessPool::unregisterNotificationObservers()
550 {
551 #if !PLATFORM(IOS)
552     [[NSNotificationCenter defaultCenter] removeObserver:m_enhancedAccessibilityObserver.get()];    
553     [[NSNotificationCenter defaultCenter] removeObserver:m_automaticTextReplacementNotificationObserver.get()];
554     [[NSNotificationCenter defaultCenter] removeObserver:m_automaticSpellingCorrectionNotificationObserver.get()];
555     [[NSNotificationCenter defaultCenter] removeObserver:m_automaticQuoteSubstitutionNotificationObserver.get()];
556     [[NSNotificationCenter defaultCenter] removeObserver:m_automaticDashSubstitutionNotificationObserver.get()];
557 #endif // !PLATFORM(IOS)
558 }
559
560 static CFURLStorageSessionRef privateBrowsingSession()
561 {
562     static CFURLStorageSessionRef session;
563     static dispatch_once_t once;
564     dispatch_once(&once, ^{
565         NSString *identifier = [NSString stringWithFormat:@"%@.PrivateBrowsing", [[NSBundle mainBundle] bundleIdentifier]];
566
567         session = createPrivateStorageSession((CFStringRef)identifier);
568     });
569
570     return session;
571 }
572
573 bool WebProcessPool::isURLKnownHSTSHost(const String& urlString, bool privateBrowsingEnabled) const
574 {
575     RetainPtr<CFURLRef> url = URL(URL(), urlString).createCFURL();
576
577     return _CFNetworkIsKnownHSTSHostWithSession(url.get(), privateBrowsingEnabled ? privateBrowsingSession() : nullptr);
578 }
579
580 void WebProcessPool::resetHSTSHosts()
581 {
582     _CFNetworkResetHSTSHostsWithSession(nullptr);
583     _CFNetworkResetHSTSHostsWithSession(privateBrowsingSession());
584 }
585
586 void WebProcessPool::resetHSTSHostsAddedAfterDate(double startDateIntervalSince1970)
587 {
588     NSDate *startDate = [NSDate dateWithTimeIntervalSince1970:startDateIntervalSince1970];
589     _CFNetworkResetHSTSHostsSinceDate(nullptr, (__bridge CFDateRef)startDate);
590     _CFNetworkResetHSTSHostsSinceDate(privateBrowsingSession(), (__bridge CFDateRef)startDate);
591 }
592
593 void WebProcessPool::setCookieStoragePartitioningEnabled(bool enabled)
594 {
595     m_cookieStoragePartitioningEnabled = enabled;
596     sendToNetworkingProcess(Messages::NetworkProcess::SetCookieStoragePartitioningEnabled(enabled));
597 }
598
599 int networkProcessLatencyQOS()
600 {
601     static const int qos = [[NSUserDefaults standardUserDefaults] integerForKey:@"WebKitNetworkProcessLatencyQOS"];
602     return qos;
603 }
604
605 int networkProcessThroughputQOS()
606 {
607     static const int qos = [[NSUserDefaults standardUserDefaults] integerForKey:@"WebKitNetworkProcessThroughputQOS"];
608     return qos;
609 }
610
611 int webProcessLatencyQOS()
612 {
613     static const int qos = [[NSUserDefaults standardUserDefaults] integerForKey:@"WebKitWebProcessLatencyQOS"];
614     return qos;
615 }
616
617 int webProcessThroughputQOS()
618 {
619     static const int qos = [[NSUserDefaults standardUserDefaults] integerForKey:@"WebKitWebProcessThroughputQOS"];
620     return qos;
621 }
622
623 } // namespace WebKit