[PSON] Introduce a WebContent Process cache
[WebKit-https.git] / Source / WebKit / UIProcess / Cocoa / WebProcessPoolCocoa.mm
1 /*
2  * Copyright (C) 2010-2019 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 "WebMemoryPressureHandler.h"
40 #import "WebPageGroup.h"
41 #import "WebPreferencesKeys.h"
42 #import "WebProcessCreationParameters.h"
43 #import "WebProcessMessages.h"
44 #import "WindowServerConnection.h"
45 #import <WebCore/Color.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/FileSystem.h>
55 #import <wtf/ProcessPrivilege.h>
56 #import <wtf/cocoa/Entitlements.h>
57 #import <wtf/spi/darwin/dyldSPI.h>
58
59 #if PLATFORM(MAC)
60 #import <QuartzCore/CARemoteLayerServer.h>
61 #endif
62
63 NSString *WebServiceWorkerRegistrationDirectoryDefaultsKey = @"WebServiceWorkerRegistrationDirectory";
64 NSString *WebKitLocalCacheDefaultsKey = @"WebKitLocalCache";
65 NSString *WebKitJSCJITEnabledDefaultsKey = @"WebKitJSCJITEnabledDefaultsKey";
66 NSString *WebKitJSCFTLJITEnabledDefaultsKey = @"WebKitJSCFTLJITEnabledDefaultsKey";
67
68 #if !PLATFORM(IOS_FAMILY)
69 static NSString *WebKitApplicationDidChangeAccessibilityEnhancedUserInterfaceNotification = @"NSApplicationDidChangeAccessibilityEnhancedUserInterfaceNotification";
70 #endif
71
72 static NSString * const WebKitNetworkCacheEfficacyLoggingEnabledDefaultsKey = @"WebKitNetworkCacheEfficacyLoggingEnabled";
73
74 static NSString * const WebKitSuppressMemoryPressureHandlerDefaultsKey = @"WebKitSuppressMemoryPressureHandler";
75
76 #if ENABLE(RESOURCE_LOAD_STATISTICS) && !RELEASE_LOG_DISABLED
77 static NSString * const WebKitLogCookieInformationDefaultsKey = @"WebKitLogCookieInformation";
78 #endif
79
80 namespace WebKit {
81 using namespace WebCore;
82
83 static void registerUserDefaultsIfNeeded()
84 {
85     static bool didRegister;
86     if (didRegister)
87         return;
88
89     didRegister = true;
90     NSMutableDictionary *registrationDictionary = [NSMutableDictionary dictionary];
91     
92     [registrationDictionary setObject:@YES forKey:WebKitJSCJITEnabledDefaultsKey];
93     [registrationDictionary setObject:@YES forKey:WebKitJSCFTLJITEnabledDefaultsKey];
94
95     [registrationDictionary setObject:@NO forKey:WebKitNetworkCacheEfficacyLoggingEnabledDefaultsKey];
96
97     [[NSUserDefaults standardUserDefaults] registerDefaults:registrationDictionary];
98 }
99
100 void WebProcessPool::updateProcessSuppressionState()
101 {
102     if (m_networkProcess)
103         m_networkProcess->setProcessSuppressionEnabled(processSuppressionEnabled());
104
105 #if ENABLE(NETSCAPE_PLUGIN_API)
106     if (!m_processSuppressionDisabledForPageCounter.value())
107         m_pluginProcessManagerProcessSuppressionDisabledToken = nullptr;
108     else if (!m_pluginProcessManagerProcessSuppressionDisabledToken)
109         m_pluginProcessManagerProcessSuppressionDisabledToken = PluginProcessManager::singleton().processSuppressionDisabledToken();
110 #endif
111 }
112
113 NSMutableDictionary *WebProcessPool::ensureBundleParameters()
114 {
115     if (!m_bundleParameters)
116         m_bundleParameters = adoptNS([[NSMutableDictionary alloc] init]);
117
118     return m_bundleParameters.get();
119 }
120
121 void WebProcessPool::platformInitialize()
122 {
123     registerUserDefaultsIfNeeded();
124     registerNotificationObservers();
125
126     // FIXME: This should be able to share code with WebCore's MemoryPressureHandler (and be platform independent).
127     // Right now it cannot because WebKit1 and WebKit2 need to be able to coexist in the UI process,
128     // and you can only have one WebCore::MemoryPressureHandler.
129
130     if (![[NSUserDefaults standardUserDefaults] boolForKey:@"WebKitSuppressMemoryPressureHandler"])
131         installMemoryPressureHandler();
132
133     setLegacyCustomProtocolManagerClient(std::make_unique<LegacyCustomProtocolManagerClient>());
134 }
135
136 #if PLATFORM(IOS_FAMILY)
137 String WebProcessPool::cookieStorageDirectory() const
138 {
139     String path = pathForProcessContainer();
140     if (path.isEmpty())
141         path = NSHomeDirectory();
142
143     path = path + "/Library/Cookies";
144     path = stringByResolvingSymlinksInPath(path);
145     return path;
146 }
147 #endif
148
149 void WebProcessPool::platformResolvePathsForSandboxExtensions()
150 {
151     m_resolvedPaths.uiProcessBundleResourcePath = resolvePathForSandboxExtension([[NSBundle mainBundle] resourcePath]);
152
153 #if PLATFORM(IOS_FAMILY)
154     m_resolvedPaths.cookieStorageDirectory = resolveAndCreateReadWriteDirectoryForSandboxExtension(cookieStorageDirectory());
155     m_resolvedPaths.containerCachesDirectory = resolveAndCreateReadWriteDirectoryForSandboxExtension(webContentCachesDirectory());
156     m_resolvedPaths.containerTemporaryDirectory = resolveAndCreateReadWriteDirectoryForSandboxExtension(containerTemporaryDirectory());
157 #endif
158 }
159
160 void WebProcessPool::platformInitializeWebProcess(WebProcessCreationParameters& parameters)
161 {
162 #if PLATFORM(MAC)
163     ALLOW_DEPRECATED_DECLARATIONS_BEGIN
164     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanCommunicateWithWindowServer));
165     parameters.accessibilityEnhancedUserInterfaceEnabled = [[NSApp accessibilityAttributeValue:@"AXEnhancedUserInterface"] boolValue];
166     ALLOW_DEPRECATED_DECLARATIONS_END
167 #else
168     parameters.accessibilityEnhancedUserInterfaceEnabled = false;
169 #endif
170
171     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
172
173     parameters.shouldEnableJIT = [defaults boolForKey:WebKitJSCJITEnabledDefaultsKey];
174     parameters.shouldEnableFTLJIT = [defaults boolForKey:WebKitJSCFTLJITEnabledDefaultsKey];
175     parameters.shouldEnableMemoryPressureReliefLogging = [defaults boolForKey:@"LogMemoryJetsamDetails"];
176     parameters.shouldSuppressMemoryPressureHandler = [defaults boolForKey:WebKitSuppressMemoryPressureHandlerDefaultsKey];
177
178 #if HAVE(HOSTED_CORE_ANIMATION)
179 #if !PLATFORM(IOS_FAMILY)
180     parameters.acceleratedCompositingPort = MachSendRight::create([CARemoteLayerServer sharedServer].serverPort);
181 #endif
182 #endif
183
184     // FIXME: This should really be configurable; we shouldn't just blindly allow read access to the UI process bundle.
185     parameters.uiProcessBundleResourcePath = m_resolvedPaths.uiProcessBundleResourcePath;
186     SandboxExtension::createHandleWithoutResolvingPath(parameters.uiProcessBundleResourcePath, SandboxExtension::Type::ReadOnly, parameters.uiProcessBundleResourcePathExtensionHandle);
187
188     parameters.uiProcessBundleIdentifier = String([[NSBundle mainBundle] bundleIdentifier]);
189     parameters.uiProcessSDKVersion = dyld_get_program_sdk_version();
190
191 #if PLATFORM(IOS_FAMILY)
192     if (!m_resolvedPaths.cookieStorageDirectory.isEmpty())
193         SandboxExtension::createHandleWithoutResolvingPath(m_resolvedPaths.cookieStorageDirectory, SandboxExtension::Type::ReadWrite, parameters.cookieStorageDirectoryExtensionHandle);
194
195     if (!m_resolvedPaths.containerCachesDirectory.isEmpty())
196         SandboxExtension::createHandleWithoutResolvingPath(m_resolvedPaths.containerCachesDirectory, SandboxExtension::Type::ReadWrite, parameters.containerCachesDirectoryExtensionHandle);
197
198     if (!m_resolvedPaths.containerTemporaryDirectory.isEmpty())
199         SandboxExtension::createHandleWithoutResolvingPath(m_resolvedPaths.containerTemporaryDirectory, SandboxExtension::Type::ReadWrite, parameters.containerTemporaryDirectoryExtensionHandle);
200 #endif
201
202     parameters.fontWhitelist = m_fontWhitelist;
203
204     if (m_bundleParameters) {
205         auto keyedArchiver = secureArchiver();
206
207         @try {
208             [keyedArchiver encodeObject:m_bundleParameters.get() forKey:@"parameters"];
209             [keyedArchiver finishEncoding];
210         } @catch (NSException *exception) {
211             LOG_ERROR("Failed to encode bundle parameters: %@", exception);
212         }
213
214         auto data = keyedArchiver.get().encodedData;
215
216         parameters.bundleParameterData = API::Data::createWithoutCopying(WTFMove(data));
217     }
218     parameters.networkATSContext = adoptCF(_CFNetworkCopyATSContext());
219
220 #if ENABLE(MEDIA_STREAM)
221     // Allow microphone access if either preference is set because WebRTC requires microphone access.
222     bool mediaDevicesEnabled = m_defaultPageGroup->preferences().mediaDevicesEnabled();
223     bool webRTCEnabled = m_defaultPageGroup->preferences().peerConnectionEnabled();
224     if ([defaults objectForKey:@"ExperimentalPeerConnectionEnabled"])
225         webRTCEnabled = [defaults boolForKey:@"ExperimentalPeerConnectionEnabled"];
226
227     bool isSafari = false;
228 #if PLATFORM(IOS_FAMILY)
229     if (WebCore::IOSApplication::isMobileSafari())
230         isSafari = true;
231 #elif PLATFORM(MAC)
232     if (WebCore::MacApplication::isSafari())
233         isSafari = true;
234 #endif
235
236 #if !LOG_DISABLED || !RELEASE_LOG_DISABLED
237     parameters.webCoreLoggingChannels = [[NSUserDefaults standardUserDefaults] stringForKey:@"WebCoreLogging"];
238     parameters.webKitLoggingChannels = [[NSUserDefaults standardUserDefaults] stringForKey:@"WebKit2Logging"];
239 #endif
240
241     // FIXME: Remove this and related parameter when <rdar://problem/29448368> is fixed.
242     if (isSafari && !parameters.shouldCaptureAudioInUIProcess && mediaDevicesEnabled)
243         SandboxExtension::createHandleForGenericExtension("com.apple.webkit.microphone", parameters.audioCaptureExtensionHandle);
244 #endif
245
246 #if ENABLE(RESOURCE_LOAD_STATISTICS) && !RELEASE_LOG_DISABLED
247     parameters.shouldLogUserInteraction = [defaults boolForKey:WebKitLogCookieInformationDefaultsKey];
248 #endif
249     
250 #if PLATFORM(MAC)
251     auto screenProperties = WebCore::collectScreenProperties();
252     parameters.screenProperties = WTFMove(screenProperties);
253     parameters.useOverlayScrollbars = ([NSScroller preferredScrollerStyle] == NSScrollerStyleOverlay);
254 #endif
255 }
256
257 void WebProcessPool::platformInitializeNetworkProcess(NetworkProcessCreationParameters& parameters)
258 {
259     parameters.uiProcessBundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
260     parameters.uiProcessSDKVersion = dyld_get_program_sdk_version();
261
262     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
263
264     {
265         bool isSafari = false;
266 #if PLATFORM(IOS_FAMILY)
267         isSafari = WebCore::IOSApplication::isMobileSafari();
268 #elif PLATFORM(MAC)
269         isSafari = WebCore::MacApplication::isSafari();
270 #endif
271         if (isSafari) {
272             parameters.defaultDataStoreParameters.networkSessionParameters.httpProxy = URL(URL(), [defaults stringForKey:(NSString *)WebKit2HTTPProxyDefaultsKey]);
273             parameters.defaultDataStoreParameters.networkSessionParameters.httpsProxy = URL(URL(), [defaults stringForKey:(NSString *)WebKit2HTTPSProxyDefaultsKey]);
274         }
275     }
276
277     parameters.networkATSContext = adoptCF(_CFNetworkCopyATSContext());
278
279     parameters.shouldEnableNetworkCacheEfficacyLogging = [defaults boolForKey:WebKitNetworkCacheEfficacyLoggingEnabledDefaultsKey];
280
281 #if PLATFORM(IOS_FAMILY)
282     parameters.ctDataConnectionServiceType = m_configuration->ctDataConnectionServiceType();
283 #endif
284
285     parameters.shouldSuppressMemoryPressureHandler = [defaults boolForKey:WebKitSuppressMemoryPressureHandlerDefaultsKey];
286
287 #if PLATFORM(MAC)
288     ASSERT(parameters.uiProcessCookieStorageIdentifier.isEmpty());
289     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
290     parameters.uiProcessCookieStorageIdentifier = identifyingDataFromCookieStorage([[NSHTTPCookieStorage sharedHTTPCookieStorage] _cookieStorage]);
291 #endif
292
293     parameters.storageAccessAPIEnabled = storageAccessAPIEnabled();
294     parameters.suppressesConnectionTerminationOnSystemChange = m_configuration->suppressesConnectionTerminationOnSystemChange();
295
296 #if ENABLE(PROXIMITY_NETWORKING)
297     parameters.wirelessContextIdentifier = m_configuration->wirelessContextIdentifier();
298 #endif
299 }
300
301 void WebProcessPool::platformInvalidateContext()
302 {
303     unregisterNotificationObservers();
304 }
305
306 #if PLATFORM(IOS_FAMILY)
307 String WebProcessPool::parentBundleDirectory() const
308 {
309     return [[[NSBundle mainBundle] bundlePath] stringByStandardizingPath];
310 }
311
312 String WebProcessPool::networkingCachesDirectory() const
313 {
314     String path = pathForProcessContainer();
315     if (path.isEmpty())
316         path = NSHomeDirectory();
317
318     path = path + "/Library/Caches/com.apple.WebKit.Networking/";
319     path = stringByResolvingSymlinksInPath(path);
320
321     NSError *error = nil;
322     NSString* nsPath = path;
323     if (![[NSFileManager defaultManager] createDirectoryAtPath:nsPath withIntermediateDirectories:YES attributes:nil error:&error]) {
324         NSLog(@"could not create networking caches directory \"%@\", error %@", nsPath, error);
325         return String();
326     }
327
328     return path;
329 }
330
331 String WebProcessPool::webContentCachesDirectory() const
332 {
333     String path = pathForProcessContainer();
334     if (path.isEmpty())
335         path = NSHomeDirectory();
336
337     path = path + "/Library/Caches/com.apple.WebKit.WebContent/";
338     path = stringByResolvingSymlinksInPath(path);
339
340     NSError *error = nil;
341     NSString* nsPath = path;
342     if (![[NSFileManager defaultManager] createDirectoryAtPath:nsPath withIntermediateDirectories:YES attributes:nil error:&error]) {
343         NSLog(@"could not create web content caches directory \"%@\", error %@", nsPath, error);
344         return String();
345     }
346
347     return path;
348 }
349
350 String WebProcessPool::containerTemporaryDirectory() const
351 {
352     String path = NSTemporaryDirectory();
353     return stringByResolvingSymlinksInPath(path);
354 }
355 #endif
356
357 #if PLATFORM(IOS_FAMILY)
358 void WebProcessPool::setJavaScriptConfigurationFileEnabledFromDefaults()
359 {
360     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
361
362     setJavaScriptConfigurationFileEnabled([defaults boolForKey:@"WebKitJavaScriptCoreUseConfigFile"]);
363 }
364 #endif
365
366 bool WebProcessPool::omitPDFSupport()
367 {
368     // Since this is a "secret default" we don't bother registering it.
369     return [[NSUserDefaults standardUserDefaults] boolForKey:@"WebKitOmitPDFSupport"];
370 }
371
372 bool WebProcessPool::processSuppressionEnabled() const
373 {
374     return !m_userObservablePageCounter.value() && !m_processSuppressionDisabledForPageCounter.value();
375 }
376
377 bool WebProcessPool::networkProcessHasEntitlementForTesting(const String& entitlement)
378 {
379     return WTF::hasEntitlement(ensureNetworkProcess().connection()->xpcConnection(), entitlement.utf8().data());
380 }
381
382 void WebProcessPool::registerNotificationObservers()
383 {
384 #if !PLATFORM(IOS_FAMILY)
385     // Listen for enhanced accessibility changes and propagate them to the WebProcess.
386     m_enhancedAccessibilityObserver = [[NSNotificationCenter defaultCenter] addObserverForName:WebKitApplicationDidChangeAccessibilityEnhancedUserInterfaceNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *note) {
387         setEnhancedAccessibility([[[note userInfo] objectForKey:@"AXEnhancedUserInterface"] boolValue]);
388     }];
389
390     m_automaticTextReplacementNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSSpellCheckerDidChangeAutomaticTextReplacementNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) {
391         TextChecker::didChangeAutomaticTextReplacementEnabled();
392         textCheckerStateChanged();
393     }];
394     
395     m_automaticSpellingCorrectionNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSSpellCheckerDidChangeAutomaticSpellingCorrectionNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) {
396         TextChecker::didChangeAutomaticSpellingCorrectionEnabled();
397         textCheckerStateChanged();
398     }];
399
400     m_automaticQuoteSubstitutionNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSSpellCheckerDidChangeAutomaticQuoteSubstitutionNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) {
401         TextChecker::didChangeAutomaticQuoteSubstitutionEnabled();
402         textCheckerStateChanged();
403     }];
404
405     m_automaticDashSubstitutionNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSSpellCheckerDidChangeAutomaticDashSubstitutionNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) {
406         TextChecker::didChangeAutomaticDashSubstitutionEnabled();
407         textCheckerStateChanged();
408     }];
409
410     m_accessibilityDisplayOptionsNotificationObserver = [[NSWorkspace.sharedWorkspace notificationCenter] addObserverForName:NSWorkspaceAccessibilityDisplayOptionsDidChangeNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) {
411         screenPropertiesStateChanged();
412     }];
413
414 #if ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
415     m_scrollerStyleNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSPreferredScrollerStyleDidChangeNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) {
416         auto scrollbarStyle = [NSScroller preferredScrollerStyle];
417         sendToAllProcesses(Messages::WebProcess::ScrollerStylePreferenceChanged(scrollbarStyle));
418     }];
419 #endif
420
421     m_activationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSApplicationDidBecomeActiveNotification object:NSApp queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) {
422         setApplicationIsActive(true);
423     }];
424
425     m_deactivationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSApplicationDidResignActiveNotification object:NSApp queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) {
426         setApplicationIsActive(false);
427     }];
428
429 #endif // !PLATFORM(IOS_FAMILY)
430 }
431
432 void WebProcessPool::unregisterNotificationObservers()
433 {
434 #if !PLATFORM(IOS_FAMILY)
435     [[NSNotificationCenter defaultCenter] removeObserver:m_enhancedAccessibilityObserver.get()];    
436     [[NSNotificationCenter defaultCenter] removeObserver:m_automaticTextReplacementNotificationObserver.get()];
437     [[NSNotificationCenter defaultCenter] removeObserver:m_automaticSpellingCorrectionNotificationObserver.get()];
438     [[NSNotificationCenter defaultCenter] removeObserver:m_automaticQuoteSubstitutionNotificationObserver.get()];
439     [[NSNotificationCenter defaultCenter] removeObserver:m_automaticDashSubstitutionNotificationObserver.get()];
440     [[NSWorkspace.sharedWorkspace notificationCenter] removeObserver:m_accessibilityDisplayOptionsNotificationObserver.get()];
441 #if ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
442     [[NSNotificationCenter defaultCenter] removeObserver:m_scrollerStyleNotificationObserver.get()];
443 #endif
444     [[NSNotificationCenter defaultCenter] removeObserver:m_activationObserver.get()];
445     [[NSNotificationCenter defaultCenter] removeObserver:m_deactivationObserver.get()];
446 #endif // !PLATFORM(IOS_FAMILY)
447 }
448
449 static CFURLStorageSessionRef privateBrowsingSession()
450 {
451     static CFURLStorageSessionRef session;
452     static dispatch_once_t once;
453     dispatch_once(&once, ^{
454         NSString *identifier = [NSString stringWithFormat:@"%@.PrivateBrowsing", [[NSBundle mainBundle] bundleIdentifier]];
455         session = createPrivateStorageSession((__bridge CFStringRef)identifier);
456     });
457
458     return session;
459 }
460
461 bool WebProcessPool::isURLKnownHSTSHost(const String& urlString, bool privateBrowsingEnabled) const
462 {
463     RetainPtr<CFURLRef> url = URL(URL(), urlString).createCFURL();
464
465     return _CFNetworkIsKnownHSTSHostWithSession(url.get(), privateBrowsingEnabled ? privateBrowsingSession() : nullptr);
466 }
467
468 void WebProcessPool::resetHSTSHosts()
469 {
470     _CFNetworkResetHSTSHostsWithSession(nullptr);
471     _CFNetworkResetHSTSHostsWithSession(privateBrowsingSession());
472 }
473
474 void WebProcessPool::resetHSTSHostsAddedAfterDate(double startDateIntervalSince1970)
475 {
476     NSDate *startDate = [NSDate dateWithTimeIntervalSince1970:startDateIntervalSince1970];
477     _CFNetworkResetHSTSHostsSinceDate(nullptr, (__bridge CFDateRef)startDate);
478     _CFNetworkResetHSTSHostsSinceDate(privateBrowsingSession(), (__bridge CFDateRef)startDate);
479 }
480
481 #if PLATFORM(MAC) && ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
482 void WebProcessPool::startDisplayLink(IPC::Connection& connection, unsigned observerID, uint32_t displayID)
483 {
484     for (auto& displayLink : m_displayLinks) {
485         if (displayLink->displayID() == displayID) {
486             displayLink->addObserver(connection, observerID);
487             return;
488         }
489     }
490     auto displayLink = std::make_unique<DisplayLink>(displayID);
491     displayLink->addObserver(connection, observerID);
492     m_displayLinks.append(WTFMove(displayLink));
493 }
494
495 void WebProcessPool::stopDisplayLink(IPC::Connection& connection, unsigned observerID, uint32_t displayID)
496 {
497     for (auto& displayLink : m_displayLinks) {
498         if (displayLink->displayID() == displayID) {
499             displayLink->removeObserver(connection, observerID);
500             return;
501         }
502     }
503 }
504
505 void WebProcessPool::stopDisplayLinks(IPC::Connection& connection)
506 {
507     for (auto& displayLink : m_displayLinks)
508         displayLink->removeObservers(connection);
509 }
510 #endif
511
512 // FIXME: Deprecated. Left here until a final decision is made.
513 void WebProcessPool::setCookieStoragePartitioningEnabled(bool enabled)
514 {
515     m_cookieStoragePartitioningEnabled = enabled;
516 }
517
518 void WebProcessPool::setStorageAccessAPIEnabled(bool enabled)
519 {
520     m_storageAccessAPIEnabled = enabled;
521     sendToNetworkingProcess(Messages::NetworkProcess::SetStorageAccessAPIEnabled(enabled));
522 }
523
524 int networkProcessLatencyQOS()
525 {
526     static const int qos = [[NSUserDefaults standardUserDefaults] integerForKey:@"WebKitNetworkProcessLatencyQOS"];
527     return qos;
528 }
529
530 int networkProcessThroughputQOS()
531 {
532     static const int qos = [[NSUserDefaults standardUserDefaults] integerForKey:@"WebKitNetworkProcessThroughputQOS"];
533     return qos;
534 }
535
536 int webProcessLatencyQOS()
537 {
538     static const int qos = [[NSUserDefaults standardUserDefaults] integerForKey:@"WebKitWebProcessLatencyQOS"];
539     return qos;
540 }
541
542 int webProcessThroughputQOS()
543 {
544     static const int qos = [[NSUserDefaults standardUserDefaults] integerForKey:@"WebKitWebProcessThroughputQOS"];
545     return qos;
546 }
547
548 } // namespace WebKit