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