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