e32f3a0c99f2562195b2c95a255ed06daebdccb7
[WebKit-https.git] / Source / WebKit2 / UIProcess / Cocoa / WebProcessPoolCocoa.mm
1 /*
2  * Copyright (C) 2010 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 "PluginProcessManager.h"
30 #import "SandboxUtilities.h"
31 #import "TextChecker.h"
32 #import "VersionChecks.h"
33 #import "WKBrowsingContextControllerInternal.h"
34 #import "WKBrowsingContextControllerInternal.h"
35 #import "WebKitSystemInterface.h"
36 #import "WebPageGroup.h"
37 #import "WebPreferencesKeys.h"
38 #import "WebProcessCreationParameters.h"
39 #import "WebProcessMessages.h"
40 #import "WindowServerConnection.h"
41 #import <WebCore/CFNetworkSPI.h>
42 #import <WebCore/Color.h>
43 #import <WebCore/FileSystem.h>
44 #import <WebCore/NotImplemented.h>
45 #import <WebCore/PlatformPasteboard.h>
46 #import <WebCore/SharedBuffer.h>
47 #import <sys/param.h>
48
49 #if ENABLE(NETWORK_PROCESS)
50 #import "NetworkProcessCreationParameters.h"
51 #import "NetworkProcessProxy.h"
52 #endif
53
54 #if PLATFORM(IOS)
55 #import "ArgumentCodersCF.h"
56 #import "WebMemoryPressureHandlerIOS.h"
57 #import <WebCore/RuntimeApplicationChecksIOS.h>
58 #else
59 #import <QuartzCore/CARemoteLayerServer.h>
60 #endif
61
62 using namespace WebCore;
63
64 NSString *WebDatabaseDirectoryDefaultsKey = @"WebDatabaseDirectory";
65 NSString *WebKitLocalCacheDefaultsKey = @"WebKitLocalCache";
66 NSString *WebStorageDirectoryDefaultsKey = @"WebKitLocalStorageDatabasePathPreferenceKey";
67 NSString *WebKitJSCJITEnabledDefaultsKey = @"WebKitJSCJITEnabledDefaultsKey";
68 NSString *WebKitJSCFTLJITEnabledDefaultsKey = @"WebKitJSCFTLJITEnabledDefaultsKey";
69 NSString *WebKitMediaKeysStorageDirectoryDefaultsKey = @"WebKitMediaKeysStorageDirectory";
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 #if ENABLE(NETWORK_PROCESS)
79 static NSString * const WebKit2HTTPProxyDefaultsKey = @"WebKit2HTTPProxy";
80 static NSString * const WebKit2HTTPSProxyDefaultsKey = @"WebKit2HTTPSProxy";
81 #endif
82
83 #if ENABLE(NETWORK_CACHE)
84 static NSString * const WebKitNetworkCacheEnabledDefaultsKey = @"WebKitNetworkCacheEnabled";
85 static NSString * const WebKitNetworkCacheEfficacyLoggingEnabledDefaultsKey = @"WebKitNetworkCacheEfficacyLoggingEnabled";
86 #endif
87
88 namespace WebKit {
89
90 NSString *SchemeForCustomProtocolRegisteredNotificationName = @"WebKitSchemeForCustomProtocolRegisteredNotification";
91 NSString *SchemeForCustomProtocolUnregisteredNotificationName = @"WebKitSchemeForCustomProtocolUnregisteredNotification";
92
93 static void registerUserDefaultsIfNeeded()
94 {
95     static bool didRegister;
96     if (didRegister)
97         return;
98
99     didRegister = true;
100     NSMutableDictionary *registrationDictionary = [NSMutableDictionary dictionary];
101     
102     [registrationDictionary setObject:[NSNumber numberWithBool:YES] forKey:WebKitJSCJITEnabledDefaultsKey];
103     [registrationDictionary setObject:[NSNumber numberWithBool:YES] forKey:WebKitJSCFTLJITEnabledDefaultsKey];
104
105 #if ENABLE(NETWORK_CACHE)
106     [registrationDictionary setObject:[NSNumber numberWithBool:YES] forKey:WebKitNetworkCacheEnabledDefaultsKey];
107     [registrationDictionary setObject:[NSNumber numberWithBool:NO] forKey:WebKitNetworkCacheEfficacyLoggingEnabledDefaultsKey];
108 #endif
109
110     [[NSUserDefaults standardUserDefaults] registerDefaults:registrationDictionary];
111 }
112
113 void WebProcessPool::updateProcessSuppressionState()
114 {
115 #if ENABLE(NETWORK_PROCESS)
116     if (usesNetworkProcess() && m_networkProcess)
117         m_networkProcess->setProcessSuppressionEnabled(processSuppressionEnabled());
118 #endif
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     WebKit::WebMemoryPressureHandler::singleton();
144 #endif
145 }
146
147 #if PLATFORM(IOS)
148 String WebProcessPool::cookieStorageDirectory() const
149 {
150     String path = pathForProcessContainer();
151     if (path.isEmpty())
152         path = NSHomeDirectory();
153
154     path = path + "/Library/Cookies";
155     path = stringByResolvingSymlinksInPath(path);
156     return path;
157 }
158 #endif
159
160 void WebProcessPool::platformInitializeWebProcess(WebProcessCreationParameters& parameters)
161 {
162     parameters.presenterApplicationPid = getpid();
163
164 #if PLATFORM(MAC)
165 #pragma clang diagnostic push
166 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
167     parameters.accessibilityEnhancedUserInterfaceEnabled = [[NSApp accessibilityAttributeValue:@"AXEnhancedUserInterface"] boolValue];
168 #pragma clang diagnostic pop
169 #else
170     parameters.accessibilityEnhancedUserInterfaceEnabled = false;
171 #endif
172
173     parameters.shouldEnableJIT = [[NSUserDefaults standardUserDefaults] boolForKey:WebKitJSCJITEnabledDefaultsKey];
174     parameters.shouldEnableFTLJIT = [[NSUserDefaults standardUserDefaults] boolForKey:WebKitJSCFTLJITEnabledDefaultsKey];
175     parameters.shouldEnableMemoryPressureReliefLogging = [[NSUserDefaults standardUserDefaults] boolForKey:@"LogMemoryJetsamDetails"];
176
177 #if HAVE(HOSTED_CORE_ANIMATION)
178 #if !PLATFORM(IOS)
179     parameters.acceleratedCompositingPort = MachSendRight::create([CARemoteLayerServer sharedServer].serverPort);
180 #endif
181 #endif
182
183     // FIXME: This should really be configurable; we shouldn't just blindly allow read access to the UI process bundle.
184     parameters.uiProcessBundleResourcePath = [[NSBundle mainBundle] resourcePath];
185     SandboxExtension::createHandle(parameters.uiProcessBundleResourcePath, SandboxExtension::ReadOnly, parameters.uiProcessBundleResourcePathExtensionHandle);
186
187     parameters.uiProcessBundleIdentifier = String([[NSBundle mainBundle] bundleIdentifier]);
188
189 #if ENABLE(NETWORK_PROCESS)
190     if (!usesNetworkProcess()) {
191 #endif
192         for (const auto& scheme : globalURLSchemesWithCustomProtocolHandlers())
193             parameters.urlSchemesRegisteredForCustomProtocols.append(scheme);
194 #if ENABLE(NETWORK_PROCESS)
195     }
196 #endif
197
198     parameters.fontWhitelist = m_fontWhitelist;
199
200     if (m_bundleParameters) {
201         auto data = adoptNS([[NSMutableData alloc] init]);
202         auto keyedArchiver = adoptNS([[NSKeyedArchiver alloc] initForWritingWithMutableData:data.get()]);
203
204         [keyedArchiver setRequiresSecureCoding:YES];
205
206         @try {
207             [keyedArchiver encodeObject:m_bundleParameters.get() forKey:@"parameters"];
208             [keyedArchiver finishEncoding];
209         } @catch (NSException *exception) {
210             LOG_ERROR("Failed to encode bundle parameters: %@", exception);
211         }
212
213         parameters.bundleParameterData = API::Data::createWithoutCopying((const unsigned char*)[data bytes], [data length], [] (unsigned char*, const void* data) {
214             [(NSData *)data release];
215         }, data.leakRef());
216     }
217 #if TARGET_OS_IPHONE || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
218     parameters.networkATSContext = adoptCF(_CFNetworkCopyATSContext());
219 #endif
220
221 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100
222     RetainPtr<CFDataRef> cookieStorageData = adoptCF(CFHTTPCookieStorageCreateIdentifyingData(kCFAllocatorDefault, [[NSHTTPCookieStorage sharedHTTPCookieStorage] _cookieStorage]));
223     ASSERT(parameters.uiProcessCookieStorageIdentifier.isEmpty());
224     parameters.uiProcessCookieStorageIdentifier.append(CFDataGetBytePtr(cookieStorageData.get()), CFDataGetLength(cookieStorageData.get()));
225 #endif
226 }
227
228 #if ENABLE(NETWORK_PROCESS)
229 void WebProcessPool::platformInitializeNetworkProcess(NetworkProcessCreationParameters& parameters)
230 {
231     NSURLCache *urlCache = [NSURLCache sharedURLCache];
232     parameters.nsURLCacheMemoryCapacity = [urlCache memoryCapacity];
233     parameters.nsURLCacheDiskCapacity = [urlCache diskCapacity];
234
235     parameters.parentProcessName = [[NSProcessInfo processInfo] processName];
236     parameters.uiProcessBundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
237
238     for (const auto& scheme : globalURLSchemesWithCustomProtocolHandlers())
239         parameters.urlSchemesRegisteredForCustomProtocols.append(scheme);
240
241     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
242
243     parameters.httpProxy = [defaults stringForKey:WebKit2HTTPProxyDefaultsKey];
244     parameters.httpsProxy = [defaults stringForKey:WebKit2HTTPSProxyDefaultsKey];
245 #if TARGET_OS_IPHONE || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
246     parameters.networkATSContext = adoptCF(_CFNetworkCopyATSContext());
247 #endif
248
249 #if ENABLE(NETWORK_CACHE)
250     parameters.shouldEnableNetworkCache = isNetworkCacheEnabled();
251     parameters.shouldEnableNetworkCacheEfficacyLogging = [defaults boolForKey:WebKitNetworkCacheEfficacyLoggingEnabledDefaultsKey];
252 #endif
253
254 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100
255     RetainPtr<CFDataRef> cookieStorageData = adoptCF(CFHTTPCookieStorageCreateIdentifyingData(kCFAllocatorDefault, [[NSHTTPCookieStorage sharedHTTPCookieStorage] _cookieStorage]));
256     ASSERT(parameters.uiProcessCookieStorageIdentifier.isEmpty());
257     parameters.uiProcessCookieStorageIdentifier.append(CFDataGetBytePtr(cookieStorageData.get()), CFDataGetLength(cookieStorageData.get()));
258 #endif
259 }
260 #endif
261
262 void WebProcessPool::platformInvalidateContext()
263 {
264     unregisterNotificationObservers();
265 }
266
267 #if PLATFORM(IOS)
268 String WebProcessPool::parentBundleDirectory() const
269 {
270     return [[[NSBundle mainBundle] bundlePath] stringByStandardizingPath];
271 }
272
273 String WebProcessPool::networkingCachesDirectory() const
274 {
275     String path = pathForProcessContainer();
276     if (path.isEmpty())
277         path = NSHomeDirectory();
278
279     path = path + "/Library/Caches/com.apple.WebKit.Networking/";
280     path = stringByResolvingSymlinksInPath(path);
281
282     NSError *error = nil;
283     NSString* nsPath = path;
284     if (![[NSFileManager defaultManager] createDirectoryAtPath:nsPath withIntermediateDirectories:YES attributes:nil error:&error]) {
285         NSLog(@"could not create \"%@\", error %@", nsPath, error);
286         return String();
287     }
288
289     return path;
290 }
291
292 String WebProcessPool::webContentCachesDirectory() const
293 {
294     String path = pathForProcessContainer();
295     if (path.isEmpty())
296         path = NSHomeDirectory();
297
298     path = path + "/Library/Caches/com.apple.WebKit.WebContent/";
299     path = stringByResolvingSymlinksInPath(path);
300
301     NSError *error = nil;
302     NSString* nsPath = path;
303     if (![[NSFileManager defaultManager] createDirectoryAtPath:nsPath withIntermediateDirectories:YES attributes:nil error:&error]) {
304         NSLog(@"could not create \"%@\", error %@", nsPath, error);
305         return String();
306     }
307
308     return path;
309 }
310
311 String WebProcessPool::containerTemporaryDirectory() const
312 {
313     String path = NSTemporaryDirectory();
314     return stringByResolvingSymlinksInPath(path);
315 }
316 #endif
317
318 String WebProcessPool::legacyPlatformDefaultWebSQLDatabaseDirectory()
319 {
320     registerUserDefaultsIfNeeded();
321
322     NSString *databasesDirectory = [[NSUserDefaults standardUserDefaults] objectForKey:WebDatabaseDirectoryDefaultsKey];
323     if (!databasesDirectory || ![databasesDirectory isKindOfClass:[NSString class]])
324         databasesDirectory = @"~/Library/WebKit/Databases";
325     return stringByResolvingSymlinksInPath([databasesDirectory stringByStandardizingPath]);
326 }
327
328 String WebProcessPool::legacyPlatformDefaultIndexedDBDatabaseDirectory()
329 {
330     // Indexed databases exist in a subdirectory of the "database directory path."
331     // Currently, the top level of that directory contains entities related to WebSQL databases.
332     // We should fix this, and move WebSQL into a subdirectory (https://bugs.webkit.org/show_bug.cgi?id=124807)
333     // In the meantime, an entity name prefixed with three underscores will not conflict with any WebSQL entities.
334     return pathByAppendingComponent(legacyPlatformDefaultWebSQLDatabaseDirectory(), "___IndexedDB");
335 }
336
337 String WebProcessPool::legacyPlatformDefaultLocalStorageDirectory()
338 {
339     registerUserDefaultsIfNeeded();
340
341     NSString *localStorageDirectory = [[NSUserDefaults standardUserDefaults] objectForKey:WebStorageDirectoryDefaultsKey];
342     if (!localStorageDirectory || ![localStorageDirectory isKindOfClass:[NSString class]])
343         localStorageDirectory = @"~/Library/WebKit/LocalStorage";
344     return stringByResolvingSymlinksInPath([localStorageDirectory stringByStandardizingPath]);
345 }
346
347 String WebProcessPool::legacyPlatformDefaultMediaKeysStorageDirectory()
348 {
349     registerUserDefaultsIfNeeded();
350
351     NSString *mediaKeysStorageDirectory = [[NSUserDefaults standardUserDefaults] objectForKey:WebKitMediaKeysStorageDirectoryDefaultsKey];
352     if (!mediaKeysStorageDirectory || ![mediaKeysStorageDirectory isKindOfClass:[NSString class]])
353         mediaKeysStorageDirectory = @"~/Library/WebKit/MediaKeys";
354     return stringByResolvingSymlinksInPath([mediaKeysStorageDirectory stringByStandardizingPath]);
355 }
356
357 String WebProcessPool::legacyPlatformDefaultApplicationCacheDirectory()
358 {
359     NSString *appName = [[NSBundle mainBundle] bundleIdentifier];
360     if (!appName)
361         appName = [[NSProcessInfo processInfo] processName];
362 #if PLATFORM(IOS)
363     // This quirk used to make these apps share application cache storage, but doesn't accomplish that any more.
364     // Preserving it avoids the need to migrate data when upgrading.
365     if (applicationIsMobileSafari() || applicationIsWebApp())
366         appName = @"com.apple.WebAppCache";
367 #endif
368
369     ASSERT(appName);
370
371 #if PLATFORM(IOS)
372     NSString *cacheDir = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Caches"];
373 #else
374     char cacheDirectory[MAXPATHLEN];
375     size_t cacheDirectoryLen = confstr(_CS_DARWIN_USER_CACHE_DIR, cacheDirectory, MAXPATHLEN);
376     if (!cacheDirectoryLen)
377         return String();
378
379     NSString *cacheDir = [[NSFileManager defaultManager] stringWithFileSystemRepresentation:cacheDirectory length:cacheDirectoryLen - 1];
380 #endif
381     NSString* cachePath = [cacheDir stringByAppendingPathComponent:appName];
382     return stringByResolvingSymlinksInPath([cachePath stringByStandardizingPath]);
383 }
384
385 String WebProcessPool::legacyPlatformDefaultNetworkCacheDirectory()
386 {
387     RetainPtr<NSString> cachePath = adoptNS((NSString *)WKCopyFoundationCacheDirectory());
388     if (!cachePath)
389         cachePath = @"~/Library/Caches/com.apple.WebKit.WebProcess";
390
391 #if ENABLE(NETWORK_CACHE)
392     if (isNetworkCacheEnabled())
393         cachePath = [cachePath stringByAppendingPathComponent:@"WebKitCache"];
394 #endif
395
396     return stringByResolvingSymlinksInPath([cachePath stringByStandardizingPath]);
397 }
398
399 bool WebProcessPool::isNetworkCacheEnabled()
400 {
401 #if ENABLE(NETWORK_CACHE)
402     registerUserDefaultsIfNeeded();
403
404     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
405
406     bool networkCacheEnabledByDefaults = [defaults boolForKey:WebKitNetworkCacheEnabledDefaultsKey];
407
408     return networkCacheEnabledByDefaults && linkedOnOrAfter(LibraryVersion::FirstWithNetworkCache);
409 #else
410     return false;
411 #endif
412 }
413
414 String WebProcessPool::platformDefaultIconDatabasePath() const
415 {
416     // FIXME: <rdar://problem/9138817> - After this "backwards compatibility" radar is removed, this code should be removed to only return an empty String.
417     NSString *databasesDirectory = [[NSUserDefaults standardUserDefaults] objectForKey:WebIconDatabaseDirectoryDefaultsKey];
418     if (!databasesDirectory || ![databasesDirectory isKindOfClass:[NSString class]])
419         databasesDirectory = @"~/Library/Icons/WebpageIcons.db";
420     return stringByResolvingSymlinksInPath([databasesDirectory stringByStandardizingPath]);
421 }
422
423 bool WebProcessPool::omitPDFSupport()
424 {
425     // Since this is a "secret default" we don't bother registering it.
426     return [[NSUserDefaults standardUserDefaults] boolForKey:@"WebKitOmitPDFSupport"];
427 }
428
429 bool WebProcessPool::processSuppressionEnabled() const
430 {
431     return !m_userObservablePageCounter.value() && !m_processSuppressionDisabledForPageCounter.value();
432 }
433
434 void WebProcessPool::registerNotificationObservers()
435 {
436 #if !PLATFORM(IOS)
437     // Listen for enhanced accessibility changes and propagate them to the WebProcess.
438     m_enhancedAccessibilityObserver = [[NSNotificationCenter defaultCenter] addObserverForName:WebKitApplicationDidChangeAccessibilityEnhancedUserInterfaceNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *note) {
439         setEnhancedAccessibility([[[note userInfo] objectForKey:@"AXEnhancedUserInterface"] boolValue]);
440     }];
441
442     m_automaticTextReplacementNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSSpellCheckerDidChangeAutomaticTextReplacementNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) {
443         TextChecker::didChangeAutomaticTextReplacementEnabled();
444         textCheckerStateChanged();
445     }];
446     
447     m_automaticSpellingCorrectionNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSSpellCheckerDidChangeAutomaticSpellingCorrectionNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) {
448         TextChecker::didChangeAutomaticSpellingCorrectionEnabled();
449         textCheckerStateChanged();
450     }];
451
452     m_automaticQuoteSubstitutionNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSSpellCheckerDidChangeAutomaticQuoteSubstitutionNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) {
453         TextChecker::didChangeAutomaticQuoteSubstitutionEnabled();
454         textCheckerStateChanged();
455     }];
456
457     m_automaticDashSubstitutionNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSSpellCheckerDidChangeAutomaticDashSubstitutionNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) {
458         TextChecker::didChangeAutomaticDashSubstitutionEnabled();
459         textCheckerStateChanged();
460     }];
461 #endif // !PLATFORM(IOS)
462 }
463
464 void WebProcessPool::unregisterNotificationObservers()
465 {
466 #if !PLATFORM(IOS)
467     [[NSNotificationCenter defaultCenter] removeObserver:m_enhancedAccessibilityObserver.get()];    
468     [[NSNotificationCenter defaultCenter] removeObserver:m_automaticTextReplacementNotificationObserver.get()];
469     [[NSNotificationCenter defaultCenter] removeObserver:m_automaticSpellingCorrectionNotificationObserver.get()];
470     [[NSNotificationCenter defaultCenter] removeObserver:m_automaticQuoteSubstitutionNotificationObserver.get()];
471     [[NSNotificationCenter defaultCenter] removeObserver:m_automaticDashSubstitutionNotificationObserver.get()];
472 #endif // !PLATFORM(IOS)
473 }
474
475 static CFURLStorageSessionRef privateBrowsingSession()
476 {
477     static CFURLStorageSessionRef session;
478     static dispatch_once_t once;
479     dispatch_once(&once, ^{
480         NSString *identifier = [NSString stringWithFormat:@"%@.PrivateBrowsing", [[NSBundle mainBundle] bundleIdentifier]];
481
482         session = WKCreatePrivateStorageSession((CFStringRef)identifier);
483     });
484
485     return session;
486 }
487
488 bool WebProcessPool::isURLKnownHSTSHost(const String& urlString, bool privateBrowsingEnabled) const
489 {
490     RetainPtr<CFURLRef> url = URL(URL(), urlString).createCFURL();
491
492     return _CFNetworkIsKnownHSTSHostWithSession(url.get(), privateBrowsingEnabled ? privateBrowsingSession() : nullptr);
493 }
494
495 void WebProcessPool::resetHSTSHosts()
496 {
497     _CFNetworkResetHSTSHostsWithSession(nullptr);
498     _CFNetworkResetHSTSHostsWithSession(privateBrowsingSession());
499 }
500
501 void WebProcessPool::resetHSTSHostsAddedAfterDate(double startDateIntervalSince1970)
502 {
503 #if PLATFORM(IOS) || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000)
504     NSDate *startDate = [NSDate dateWithTimeIntervalSince1970:startDateIntervalSince1970];
505     _CFNetworkResetHSTSHostsSinceDate(nullptr, (__bridge CFDateRef)startDate);
506 #if PLATFORM(IOS) || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
507     _CFNetworkResetHSTSHostsSinceDate(privateBrowsingSession(), (__bridge CFDateRef)startDate);
508 #endif
509 #endif
510 }
511
512 int networkProcessLatencyQOS()
513 {
514     static const int qos = [[NSUserDefaults standardUserDefaults] integerForKey:@"WebKitNetworkProcessLatencyQOS"];
515     return qos;
516 }
517
518 int networkProcessThroughputQOS()
519 {
520     static const int qos = [[NSUserDefaults standardUserDefaults] integerForKey:@"WebKitNetworkProcessThroughputQOS"];
521     return qos;
522 }
523
524 int webProcessLatencyQOS()
525 {
526     static const int qos = [[NSUserDefaults standardUserDefaults] integerForKey:@"WebKitWebProcessLatencyQOS"];
527     return qos;
528 }
529
530 int webProcessThroughputQOS()
531 {
532     static const int qos = [[NSUserDefaults standardUserDefaults] integerForKey:@"WebKitWebProcessThroughputQOS"];
533     return qos;
534 }
535
536 } // namespace WebKit