Unreviewed, reverting r260769.
[WebKit.git] / Source / WebKit / UIProcess / Cocoa / WebProcessPoolCocoa.mm
1 /*
2  * Copyright (C) 2010-2020 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 "AccessibilitySupportSPI.h"
30 #import "CookieStorageUtilsCF.h"
31 #import "LegacyCustomProtocolManagerClient.h"
32 #import "Logging.h"
33 #import "NetworkProcessCreationParameters.h"
34 #import "NetworkProcessMessages.h"
35 #import "NetworkProcessProxy.h"
36 #import "PluginProcessManager.h"
37 #import "PreferenceObserver.h"
38 #import "SandboxUtilities.h"
39 #import "TextChecker.h"
40 #import "UserInterfaceIdiom.h"
41 #import "VersionChecks.h"
42 #import "WKBrowsingContextControllerInternal.h"
43 #import "WebBackForwardCache.h"
44 #import "WebMemoryPressureHandler.h"
45 #import "WebPageGroup.h"
46 #import "WebPreferencesKeys.h"
47 #import "WebProcessCache.h"
48 #import "WebProcessCreationParameters.h"
49 #import "WebProcessMessages.h"
50 #import "WindowServerConnection.h"
51 #import <WebCore/AGXCompilerService.h>
52 #import <WebCore/Color.h>
53 #import <WebCore/LocalizedDeviceModel.h>
54 #import <WebCore/MIMETypeRegistry.h>
55 #import <WebCore/NetworkStorageSession.h>
56 #import <WebCore/NotImplemented.h>
57 #import <WebCore/PictureInPictureSupport.h>
58 #import <WebCore/PlatformPasteboard.h>
59 #import <WebCore/RuntimeApplicationChecks.h>
60 #import <WebCore/SharedBuffer.h>
61 #import <WebCore/UTIUtilities.h>
62 #import <objc/runtime.h>
63 #import <pal/cf/CoreMediaSoftLink.h>
64 #import <pal/cocoa/MediaToolboxSoftLink.h>
65 #import <pal/spi/cf/CFNetworkSPI.h>
66 #import <sys/param.h>
67 #import <wtf/FileSystem.h>
68 #import <wtf/ProcessPrivilege.h>
69 #import <wtf/SoftLinking.h>
70 #import <wtf/cocoa/Entitlements.h>
71 #import <wtf/spi/darwin/SandboxSPI.h>
72 #import <wtf/spi/darwin/dyldSPI.h>
73
74 #if ENABLE(REMOTE_INSPECTOR)
75 #import <JavaScriptCore/RemoteInspector.h>
76 #import <JavaScriptCore/RemoteInspectorConstants.h>
77 #endif
78
79 #if PLATFORM(MAC)
80 #import <QuartzCore/CARemoteLayerServer.h>
81 #else
82 #import "UIKitSPI.h"
83 #import <pal/ios/ManagedConfigurationSoftLink.h>
84 #import <pal/spi/ios/ManagedConfigurationSPI.h>
85 #endif
86
87 #if PLATFORM(IOS)
88 #import <pal/spi/cocoa/WebFilterEvaluatorSPI.h>
89 #import <pal/spi/ios/MobileGestaltSPI.h>
90
91 SOFT_LINK_PRIVATE_FRAMEWORK(WebContentAnalysis);
92 SOFT_LINK_CLASS(WebContentAnalysis, WebFilterEvaluator);
93 #endif
94
95 #if PLATFORM(COCOA)
96 #import <WebCore/SystemBattery.h>
97 #import <pal/spi/cocoa/NEFilterSourceSPI.h>
98
99 SOFT_LINK_FRAMEWORK_OPTIONAL(NetworkExtension);
100 SOFT_LINK_CLASS_OPTIONAL(NetworkExtension, NEFilterSource);
101 #endif
102
103 NSString *WebServiceWorkerRegistrationDirectoryDefaultsKey = @"WebServiceWorkerRegistrationDirectory";
104 NSString *WebKitLocalCacheDefaultsKey = @"WebKitLocalCache";
105 NSString *WebKitJSCJITEnabledDefaultsKey = @"WebKitJSCJITEnabledDefaultsKey";
106 NSString *WebKitJSCFTLJITEnabledDefaultsKey = @"WebKitJSCFTLJITEnabledDefaultsKey";
107
108 #if !PLATFORM(IOS_FAMILY) || PLATFORM(MACCATALYST)
109 static NSString *WebKitApplicationDidChangeAccessibilityEnhancedUserInterfaceNotification = @"NSApplicationDidChangeAccessibilityEnhancedUserInterfaceNotification";
110 #endif
111
112 static NSString * const WebKitSuppressMemoryPressureHandlerDefaultsKey = @"WebKitSuppressMemoryPressureHandler";
113
114 #if ENABLE(RESOURCE_LOAD_STATISTICS) && !RELEASE_LOG_DISABLED
115 static NSString * const WebKitLogCookieInformationDefaultsKey = @"WebKitLogCookieInformation";
116 #endif
117
118 #if PLATFORM(IOS_FAMILY) && !PLATFORM(MACCATALYST)
119 SOFT_LINK_PRIVATE_FRAMEWORK(BackBoardServices)
120 SOFT_LINK(BackBoardServices, BKSDisplayBrightnessGetCurrent, float, (), ());
121 #endif
122
123 #define WEBPROCESSPOOL_RELEASE_LOG(channel, fmt, ...) RELEASE_LOG(channel, "%p - WebProcessPool::" fmt, this, ##__VA_ARGS__)
124
125 namespace WebKit {
126 using namespace WebCore;
127
128 static void registerUserDefaultsIfNeeded()
129 {
130     static bool didRegister;
131     if (didRegister)
132         return;
133
134     didRegister = true;
135     NSMutableDictionary *registrationDictionary = [NSMutableDictionary dictionary];
136     
137     [registrationDictionary setObject:@YES forKey:WebKitJSCJITEnabledDefaultsKey];
138     [registrationDictionary setObject:@YES forKey:WebKitJSCFTLJITEnabledDefaultsKey];
139
140     [[NSUserDefaults standardUserDefaults] registerDefaults:registrationDictionary];
141 }
142
143 void WebProcessPool::updateProcessSuppressionState()
144 {
145     if (m_networkProcess)
146         m_networkProcess->setProcessSuppressionEnabled(processSuppressionEnabled());
147
148 #if ENABLE(NETSCAPE_PLUGIN_API)
149     if (!m_processSuppressionDisabledForPageCounter.value())
150         m_pluginProcessManagerProcessSuppressionDisabledToken = nullptr;
151     else if (!m_pluginProcessManagerProcessSuppressionDisabledToken)
152         m_pluginProcessManagerProcessSuppressionDisabledToken = PluginProcessManager::singleton().processSuppressionDisabledToken();
153 #endif
154 }
155
156 NSMutableDictionary *WebProcessPool::ensureBundleParameters()
157 {
158     if (!m_bundleParameters)
159         m_bundleParameters = adoptNS([[NSMutableDictionary alloc] init]);
160
161     return m_bundleParameters.get();
162 }
163
164 void WebProcessPool::platformInitialize()
165 {
166     registerUserDefaultsIfNeeded();
167     registerNotificationObservers();
168     initializeClassesForParameterCoding();
169
170     // FIXME: This should be able to share code with WebCore's MemoryPressureHandler (and be platform independent).
171     // Right now it cannot because WebKit1 and WebKit2 need to be able to coexist in the UI process,
172     // and you can only have one WebCore::MemoryPressureHandler.
173
174     if (![[NSUserDefaults standardUserDefaults] boolForKey:@"WebKitSuppressMemoryPressureHandler"])
175         installMemoryPressureHandler();
176
177     setLegacyCustomProtocolManagerClient(makeUnique<LegacyCustomProtocolManagerClient>());
178 }
179
180 #if PLATFORM(IOS_FAMILY)
181 String WebProcessPool::cookieStorageDirectory()
182 {
183     String path = pathForProcessContainer();
184     if (path.isEmpty())
185         path = NSHomeDirectory();
186
187     path = path + "/Library/Cookies";
188     path = stringByResolvingSymlinksInPath(path);
189     return path;
190 }
191 #endif
192
193 void WebProcessPool::platformResolvePathsForSandboxExtensions()
194 {
195     m_resolvedPaths.uiProcessBundleResourcePath = resolvePathForSandboxExtension([[NSBundle mainBundle] resourcePath]);
196
197 #if PLATFORM(IOS_FAMILY)
198     m_resolvedPaths.cookieStorageDirectory = resolveAndCreateReadWriteDirectoryForSandboxExtension(WebProcessPool::cookieStorageDirectory());
199     m_resolvedPaths.containerCachesDirectory = resolveAndCreateReadWriteDirectoryForSandboxExtension(WebProcessPool::webContentCachesDirectory());
200     m_resolvedPaths.containerTemporaryDirectory = resolveAndCreateReadWriteDirectoryForSandboxExtension(WebProcessPool::containerTemporaryDirectory());
201 #endif
202 }
203
204 #if PLATFORM(IOS_FAMILY)
205 static bool isInternalInstall()
206 {
207     static bool isInternal = MGGetBoolAnswer(kMGQAppleInternalInstallCapability);
208     return isInternal;
209 }
210 #endif
211
212 // FIXME(207716): The following should be removed when the GPU process is complete.
213 static const Vector<String>& mediaRelatedMachServices()
214 {
215     ASSERT(isMainThread());
216     static const auto services = makeNeverDestroyed(Vector<String> {
217         "com.apple.audio.AudioComponentRegistrar", "com.apple.coremedia.endpoint.xpc",
218         "com.apple.coremedia.routediscoverer.xpc", "com.apple.coremedia.routingcontext.xpc",
219         "com.apple.coremedia.volumecontroller.xpc", "com.apple.accessibility.mediaaccessibilityd",
220         "com.apple.mediaremoted.xpc",
221 #if PLATFORM(IOS_FAMILY)
222         "com.apple.audio.AudioSession", "com.apple.MediaPlayer.RemotePlayerService",
223         "com.apple.audio.toolbox.reporting.service", "com.apple.coremedia.admin",
224         "com.apple.coremedia.asset.xpc", "com.apple.coremedia.assetimagegenerator.xpc",
225         "com.apple.coremedia.audiodeviceclock.xpc", "com.apple.coremedia.audioprocessingtap.xpc",
226         "com.apple.coremedia.capturesession", "com.apple.coremedia.capturesource",
227         "com.apple.coremedia.compressionsession", "com.apple.coremedia.cpe.xpc",
228         "com.apple.coremedia.cpeprotector.xpc", "com.apple.coremedia.customurlloader.xpc",
229         "com.apple.coremedia.decompressionsession", "com.apple.coremedia.figcontentkeysession.xpc",
230         "com.apple.coremedia.figcpecryptor", "com.apple.coremedia.formatreader.xpc",
231         "com.apple.coremedia.player.xpc", "com.apple.coremedia.remaker",
232         "com.apple.coremedia.remotequeue", "com.apple.coremedia.routingsessionmanager.xpc",
233         "com.apple.coremedia.samplebufferaudiorenderer.xpc", "com.apple.coremedia.samplebufferrendersynchronizer.xpc",
234         "com.apple.coremedia.sandboxserver.xpc", "com.apple.coremedia.sts",
235         "com.apple.coremedia.systemcontroller.xpc", "com.apple.coremedia.videoqueue",
236         "com.apple.coremedia.visualcontext.xpc", "com.apple.airplay.apsynccontroller.xpc",
237         "com.apple.audio.AURemoteIOServer"
238 #endif
239 #if PLATFORM(MAC) || PLATFORM(MACCATALYST)
240         "com.apple.coremedia.endpointstream.xpc", "com.apple.coremedia.endpointplaybacksession.xpc",
241         "com.apple.coremedia.endpointremotecontrolsession.xpc", "com.apple.coremedia.videodecoder",
242         "com.apple.coremedia.videoencoder", "com.apple.BluetoothServices"
243 #endif
244     });
245     return services;
246 }
247
248 #if PLATFORM(IOS_FAMILY)
249 static const Vector<String>& nonBrowserServices()
250 {
251     ASSERT(isMainThread());
252     static const auto services = makeNeverDestroyed(Vector<String> {
253         "com.apple.lsd.open",
254         "com.apple.mobileassetd",
255         "com.apple.iconservices",
256         "com.apple.PowerManagement.control",
257         "com.apple.frontboard.systemappservices"
258     });
259     return services;
260 }
261
262 static const Vector<String>& agxCompilerClasses()
263 {
264     ASSERT(isMainThread());
265     static const auto iokitClasses = makeNeverDestroyed(Vector<String> {
266         "AGXCommandQueue",
267         "AGXDevice",
268         "AGXSharedUserClient",
269         "IOAccelContext",
270         "IOAccelContext2",
271         "IOAccelDevice",
272         "IOAccelDevice2",
273         "IOAccelSharedUserClient",
274         "IOAccelSharedUserClient2"
275         "IOAccelSubmitter2",
276     });
277     return iokitClasses;
278 }
279 #endif
280
281 void WebProcessPool::platformInitializeWebProcess(const WebProcessProxy& process, WebProcessCreationParameters& parameters)
282 {
283     parameters.mediaMIMETypes = process.mediaMIMETypes();
284
285 #if PLATFORM(MAC)
286     ALLOW_DEPRECATED_DECLARATIONS_BEGIN
287     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanCommunicateWithWindowServer));
288     parameters.accessibilityEnhancedUserInterfaceEnabled = [[NSApp accessibilityAttributeValue:@"AXEnhancedUserInterface"] boolValue];
289     ALLOW_DEPRECATED_DECLARATIONS_END
290 #else
291     parameters.accessibilityEnhancedUserInterfaceEnabled = false;
292 #endif
293
294     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
295
296     parameters.shouldEnableJIT = [defaults boolForKey:WebKitJSCJITEnabledDefaultsKey];
297     parameters.shouldEnableFTLJIT = [defaults boolForKey:WebKitJSCFTLJITEnabledDefaultsKey];
298     parameters.shouldEnableMemoryPressureReliefLogging = [defaults boolForKey:@"LogMemoryJetsamDetails"];
299     parameters.shouldSuppressMemoryPressureHandler = [defaults boolForKey:WebKitSuppressMemoryPressureHandlerDefaultsKey];
300
301 #if HAVE(HOSTED_CORE_ANIMATION)
302     parameters.acceleratedCompositingPort = MachSendRight::create([CARemoteLayerServer sharedServer].serverPort);
303 #endif
304
305     // FIXME: This should really be configurable; we shouldn't just blindly allow read access to the UI process bundle.
306     parameters.uiProcessBundleResourcePath = m_resolvedPaths.uiProcessBundleResourcePath;
307     SandboxExtension::createHandleWithoutResolvingPath(parameters.uiProcessBundleResourcePath, SandboxExtension::Type::ReadOnly, parameters.uiProcessBundleResourcePathExtensionHandle);
308
309     parameters.uiProcessBundleIdentifier = applicationBundleIdentifier();
310     parameters.uiProcessSDKVersion = dyld_get_program_sdk_version();
311
312 #if PLATFORM(IOS_FAMILY)
313     if (!m_resolvedPaths.cookieStorageDirectory.isEmpty())
314         SandboxExtension::createHandleWithoutResolvingPath(m_resolvedPaths.cookieStorageDirectory, SandboxExtension::Type::ReadWrite, parameters.cookieStorageDirectoryExtensionHandle);
315
316     if (!m_resolvedPaths.containerCachesDirectory.isEmpty())
317         SandboxExtension::createHandleWithoutResolvingPath(m_resolvedPaths.containerCachesDirectory, SandboxExtension::Type::ReadWrite, parameters.containerCachesDirectoryExtensionHandle);
318
319     if (!m_resolvedPaths.containerTemporaryDirectory.isEmpty())
320         SandboxExtension::createHandleWithoutResolvingPath(m_resolvedPaths.containerTemporaryDirectory, SandboxExtension::Type::ReadWrite, parameters.containerTemporaryDirectoryExtensionHandle);
321 #endif
322
323     parameters.fontWhitelist = m_fontWhitelist;
324
325     if (m_bundleParameters) {
326         auto keyedArchiver = adoptNS([[NSKeyedArchiver alloc] initRequiringSecureCoding:YES]);
327
328         @try {
329             [keyedArchiver encodeObject:m_bundleParameters.get() forKey:@"parameters"];
330             [keyedArchiver finishEncoding];
331         } @catch (NSException *exception) {
332             LOG_ERROR("Failed to encode bundle parameters: %@", exception);
333         }
334
335         auto data = keyedArchiver.get().encodedData;
336
337         parameters.bundleParameterData = API::Data::createWithoutCopying(WTFMove(data));
338     }
339     parameters.networkATSContext = adoptCF(_CFNetworkCopyATSContext());
340
341 #if ENABLE(MEDIA_STREAM)
342     // Allow microphone access if either preference is set because WebRTC requires microphone access.
343     bool mediaDevicesEnabled = m_defaultPageGroup->preferences().mediaDevicesEnabled();
344     bool webRTCEnabled = m_defaultPageGroup->preferences().peerConnectionEnabled();
345     if ([defaults objectForKey:@"ExperimentalPeerConnectionEnabled"])
346         webRTCEnabled = [defaults boolForKey:@"ExperimentalPeerConnectionEnabled"];
347
348     bool isSafari = false;
349 #if PLATFORM(IOS_FAMILY)
350     if (WebCore::IOSApplication::isMobileSafari())
351         isSafari = true;
352 #elif PLATFORM(MAC)
353     if (WebCore::MacApplication::isSafari())
354         isSafari = true;
355 #endif
356
357 #if !LOG_DISABLED || !RELEASE_LOG_DISABLED
358     parameters.webCoreLoggingChannels = [[NSUserDefaults standardUserDefaults] stringForKey:@"WebCoreLogging"];
359     parameters.webKitLoggingChannels = [[NSUserDefaults standardUserDefaults] stringForKey:@"WebKit2Logging"];
360 #endif
361
362     // FIXME: Remove this and related parameter when <rdar://problem/29448368> is fixed.
363     if (isSafari && mediaDevicesEnabled && !m_defaultPageGroup->preferences().captureAudioInUIProcessEnabled() && !m_defaultPageGroup->preferences().captureAudioInGPUProcessEnabled())
364         SandboxExtension::createHandleForGenericExtension("com.apple.webkit.microphone", parameters.audioCaptureExtensionHandle);
365 #endif
366
367 #if ENABLE(RESOURCE_LOAD_STATISTICS) && !RELEASE_LOG_DISABLED
368     parameters.shouldLogUserInteraction = [defaults boolForKey:WebKitLogCookieInformationDefaultsKey];
369 #endif
370
371     auto screenProperties = WebCore::collectScreenProperties();
372     parameters.screenProperties = WTFMove(screenProperties);
373 #if PLATFORM(MAC)
374     parameters.useOverlayScrollbars = ([NSScroller preferredScrollerStyle] == NSScrollerStyleOverlay);
375 #endif
376     
377 #if PLATFORM(IOS)
378     if (WebCore::deviceHasAGXCompilerService()) {
379         SandboxExtension::Handle compilerServiceExtensionHandle;
380         SandboxExtension::createHandleForMachLookup("com.apple.AGXCompilerService", WTF::nullopt, compilerServiceExtensionHandle);
381         parameters.compilerServiceExtensionHandle = WTFMove(compilerServiceExtensionHandle);
382     }
383 #endif
384
385 #if PLATFORM(IOS_FAMILY)
386     if (!WebCore::IOSApplication::isMobileSafari())
387         parameters.dynamicMachExtensionHandles = SandboxExtension::createHandlesForMachLookup(nonBrowserServices(), WTF::nullopt);
388     
389     if (isInternalInstall()) {
390         SandboxExtension::Handle diagnosticsExtensionHandle;
391         SandboxExtension::createHandleForMachLookup("com.apple.diagnosticd", WTF::nullopt, diagnosticsExtensionHandle, SandboxExtension::Flags::NoReport);
392         parameters.diagnosticsExtensionHandle = WTFMove(diagnosticsExtensionHandle);
393     }
394
395     SandboxExtension::Handle runningboardExtensionHandle;
396     if (SandboxExtension::createHandleForMachLookup("com.apple.runningboard", WTF::nullopt, runningboardExtensionHandle, SandboxExtension::Flags::NoReport))
397         parameters.runningboardExtensionHandle = WTFMove(runningboardExtensionHandle);
398
399     if (WebCore::deviceHasAGXCompilerService())
400         parameters.dynamicIOKitExtensionHandles = SandboxExtension::createHandlesForIOKitClassExtensions(agxCompilerClasses(), WTF::nullopt);
401 #endif
402     
403 #if PLATFORM(COCOA)
404     if ([getNEFilterSourceClass() filterRequired]) {
405         SandboxExtension::Handle helperHandle;
406         SandboxExtension::createHandleForMachLookup("com.apple.nehelper", WTF::nullopt, helperHandle);
407         parameters.neHelperExtensionHandle = WTFMove(helperHandle);
408         SandboxExtension::Handle managerHandle;
409 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
410         SandboxExtension::createHandleForMachLookup("com.apple.nesessionmanager", WTF::nullopt, managerHandle);
411 #else
412         SandboxExtension::createHandleForMachLookup("com.apple.nesessionmanager.content-filter", WTF::nullopt, managerHandle);
413 #endif
414         parameters.neSessionManagerExtensionHandle = WTFMove(managerHandle);
415     }
416     parameters.systemHasBattery = systemHasBattery();
417     parameters.mimeTypesMap = commonMimeTypesMap();
418
419     SandboxExtension::Handle mapDBHandle;
420     if (SandboxExtension::createHandleForMachLookup("com.apple.lsd.mapdb", WTF::nullopt, mapDBHandle, SandboxExtension::Flags::NoReport))
421         parameters.mapDBExtensionHandle = WTFMove(mapDBHandle);
422 #endif
423     
424 #if PLATFORM(IOS)
425     if ([getWebFilterEvaluatorClass() isManagedSession]) {
426         SandboxExtension::Handle handle;
427         SandboxExtension::createHandleForMachLookup("com.apple.uikit.viewservice.com.apple.WebContentFilter.remoteUI", WTF::nullopt, handle);
428         parameters.contentFilterExtensionHandle = WTFMove(handle);
429
430         SandboxExtension::Handle frontboardServiceExtensionHandle;
431         if (SandboxExtension::createHandleForMachLookup("com.apple.frontboard.systemappservices", WTF::nullopt, frontboardServiceExtensionHandle))
432             parameters.frontboardServiceExtensionHandle = WTFMove(frontboardServiceExtensionHandle);
433     }
434 #endif
435     
436 #if PLATFORM(IOS_FAMILY)
437     parameters.currentUserInterfaceIdiomIsPad = currentUserInterfaceIdiomIsPad();
438     parameters.supportsPictureInPicture = supportsPictureInPicture();
439     parameters.cssValueToSystemColorMap = RenderThemeIOS::cssValueToSystemColorMap();
440     parameters.focusRingColor = RenderTheme::singleton().focusRingColor(OptionSet<StyleColor::Options>());
441     parameters.localizedDeviceModel = localizedDeviceModel();
442 #endif
443     
444     // Allow microphone access if either preference is set because WebRTC requires microphone access.
445     bool needWebProcessExtensions = !m_defaultPageGroup->preferences().useGPUProcessForMedia()
446         || !m_defaultPageGroup->preferences().captureAudioInGPUProcessEnabled()
447         || !m_defaultPageGroup->preferences().captureVideoInGPUProcessEnabled();
448
449     if (needWebProcessExtensions) {
450         // FIXME(207716): The following should be removed when the GPU process is complete.
451         parameters.mediaExtensionHandles = SandboxExtension::createHandlesForMachLookup(mediaRelatedMachServices(), WTF::nullopt);
452     }
453
454 #if ENABLE(CFPREFS_DIRECT_MODE)
455 #if PLATFORM(IOS_FAMILY)
456     if (_AXSApplicationAccessibilityEnabled())
457         parameters.preferencesExtensionHandles = SandboxExtension::createHandlesForMachLookup({ "com.apple.cfprefsd.agent"_s, "com.apple.cfprefsd.daemon"_s }, WTF::nullopt);
458 #endif
459
460     auto globalPreferencesDictionary = adoptCF(CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr));
461     static CFStringRef keys[] = {
462         CFSTR("AppleLanguages"),
463         CFSTR("AppleLanguagesSchemaVersion"),
464         CFSTR("AppleLocale")
465     };
466     for (size_t i = 0; i < std::size(keys); ++i) {
467         auto value = adoptCF(CFPreferencesCopyAppValue(keys[i], CFSTR("kCFPreferencesAnyApplication")));
468         if (!value)
469             continue;
470         CFDictionaryAddValue(globalPreferencesDictionary.get(), keys[i], value.get());
471     }
472     if (CFDictionaryGetCount(globalPreferencesDictionary.get()) > 0) {
473         NSError *e = nil;
474         auto data = retainPtr([NSKeyedArchiver archivedDataWithRootObject:(__bridge NSMutableDictionary *)globalPreferencesDictionary.get() requiringSecureCoding:YES error:&e]);
475         if (e) {
476             ASSERT_NOT_REACHED();
477             WTFLogAlways("Failed to archive global preferences dictionary with NSKeyedArchiver.");
478         } else
479             parameters.encodedGlobalPreferences = String([data base64EncodedStringWithOptions:0]);
480     }
481 #endif
482 }
483
484 void WebProcessPool::platformInitializeNetworkProcess(NetworkProcessCreationParameters& parameters)
485 {
486     parameters.uiProcessBundleIdentifier = applicationBundleIdentifier();
487     parameters.uiProcessSDKVersion = dyld_get_program_sdk_version();
488
489     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
490
491     {
492         bool isSafari = false;
493         bool isMiniBrowser = false;
494 #if PLATFORM(IOS_FAMILY)
495         isSafari = WebCore::IOSApplication::isMobileSafari();
496         isMiniBrowser = WebCore::IOSApplication::isMiniBrowser();
497 #elif PLATFORM(MAC)
498         isSafari = WebCore::MacApplication::isSafari();
499         isMiniBrowser = WebCore::MacApplication::isMiniBrowser();
500 #endif
501         if (isSafari || isMiniBrowser) {
502             parameters.defaultDataStoreParameters.networkSessionParameters.httpProxy = URL(URL(), [defaults stringForKey:(NSString *)WebKit2HTTPProxyDefaultsKey]);
503             parameters.defaultDataStoreParameters.networkSessionParameters.httpsProxy = URL(URL(), [defaults stringForKey:(NSString *)WebKit2HTTPSProxyDefaultsKey]);
504         }
505     }
506
507     parameters.networkATSContext = adoptCF(_CFNetworkCopyATSContext());
508
509     parameters.shouldSuppressMemoryPressureHandler = [defaults boolForKey:WebKitSuppressMemoryPressureHandlerDefaultsKey];
510
511 #if PLATFORM(MAC) || PLATFORM(MACCATALYST)
512     ASSERT(parameters.uiProcessCookieStorageIdentifier.isEmpty());
513     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
514     parameters.uiProcessCookieStorageIdentifier = identifyingDataFromCookieStorage([[NSHTTPCookieStorage sharedHTTPCookieStorage] _cookieStorage]);
515 #endif
516
517     parameters.storageAccessAPIEnabled = storageAccessAPIEnabled();
518
519     NSNumber *databaseEnabledValue = [defaults objectForKey:[NSString stringWithFormat:@"InternalDebug%@", WebPreferencesKey::isITPDatabaseEnabledKey().createCFString().get()]];
520     if (databaseEnabledValue)
521         parameters.shouldEnableITPDatabase = databaseEnabledValue.boolValue;
522     else
523         parameters.shouldEnableITPDatabase = m_defaultPageGroup->preferences().isITPDatabaseEnabled();
524
525     parameters.enableAdClickAttributionDebugMode = [defaults boolForKey:[NSString stringWithFormat:@"Experimental%@", WebPreferencesKey::adClickAttributionDebugModeEnabledKey().createCFString().get()]];
526 }
527
528 void WebProcessPool::platformInvalidateContext()
529 {
530     unregisterNotificationObservers();
531 }
532
533 #if PLATFORM(IOS_FAMILY)
534 String WebProcessPool::parentBundleDirectory()
535 {
536     return [[[NSBundle mainBundle] bundlePath] stringByStandardizingPath];
537 }
538
539 String WebProcessPool::networkingCachesDirectory()
540 {
541     String path = pathForProcessContainer();
542     if (path.isEmpty())
543         path = NSHomeDirectory();
544
545     path = path + "/Library/Caches/com.apple.WebKit.Networking/";
546     path = stringByResolvingSymlinksInPath(path);
547
548     NSError *error = nil;
549     NSString* nsPath = path;
550     if (![[NSFileManager defaultManager] createDirectoryAtPath:nsPath withIntermediateDirectories:YES attributes:nil error:&error]) {
551         NSLog(@"could not create networking caches directory \"%@\", error %@", nsPath, error);
552         return String();
553     }
554
555     return path;
556 }
557
558 String WebProcessPool::webContentCachesDirectory()
559 {
560     String path = pathForProcessContainer();
561     if (path.isEmpty())
562         path = NSHomeDirectory();
563
564     path = path + "/Library/Caches/com.apple.WebKit.WebContent/";
565     path = stringByResolvingSymlinksInPath(path);
566
567     NSError *error = nil;
568     NSString* nsPath = path;
569     if (![[NSFileManager defaultManager] createDirectoryAtPath:nsPath withIntermediateDirectories:YES attributes:nil error:&error]) {
570         NSLog(@"could not create web content caches directory \"%@\", error %@", nsPath, error);
571         return String();
572     }
573
574     return path;
575 }
576
577 String WebProcessPool::containerTemporaryDirectory()
578 {
579     String path = NSTemporaryDirectory();
580     return stringByResolvingSymlinksInPath(path);
581 }
582 #endif
583
584 #if PLATFORM(IOS_FAMILY)
585 void WebProcessPool::setJavaScriptConfigurationFileEnabledFromDefaults()
586 {
587     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
588
589     setJavaScriptConfigurationFileEnabled([defaults boolForKey:@"WebKitJavaScriptCoreUseConfigFile"]);
590 }
591 #endif
592
593 bool WebProcessPool::omitPDFSupport()
594 {
595     // Since this is a "secret default" we don't bother registering it.
596     return [[NSUserDefaults standardUserDefaults] boolForKey:@"WebKitOmitPDFSupport"];
597 }
598
599 bool WebProcessPool::processSuppressionEnabled() const
600 {
601     return !m_userObservablePageCounter.value() && !m_processSuppressionDisabledForPageCounter.value();
602 }
603
604 bool WebProcessPool::networkProcessHasEntitlementForTesting(const String& entitlement)
605 {
606     return WTF::hasEntitlement(ensureNetworkProcess().connection()->xpcConnection(), entitlement.utf8().data());
607 }
608
609 #if PLATFORM(IOS_FAMILY) && !PLATFORM(MACCATALYST)
610 float WebProcessPool::displayBrightness()
611 {
612     return BKSDisplayBrightnessGetCurrent();
613 }
614     
615 void WebProcessPool::backlightLevelDidChangeCallback(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo)
616 {
617     auto* pool = reinterpret_cast<WebProcessPool*>(observer);
618     pool->sendToAllProcesses(Messages::WebProcess::BacklightLevelDidChange(BKSDisplayBrightnessGetCurrent()));
619 }
620 #endif
621
622 #if ENABLE(REMOTE_INSPECTOR) && PLATFORM(IOS_FAMILY) && !PLATFORM(MACCATALYST)
623 void WebProcessPool::remoteWebInspectorEnabledCallback(CFNotificationCenterRef, void *observer, CFStringRef name, const void *, CFDictionaryRef userInfo)
624 {
625     auto* pool = reinterpret_cast<WebProcessPool*>(observer);
626     for (size_t i = 0; i < pool->m_processes.size(); ++i) {
627         auto process = pool->m_processes[i];
628         process->enableRemoteInspectorIfNeeded();
629     }
630 }
631 #endif
632
633 #if ENABLE(CFPREFS_DIRECT_MODE)
634 void WebProcessPool::startObservingPreferenceChanges()
635 {
636     static dispatch_once_t onceToken;
637     dispatch_once(&onceToken, ^{
638         dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
639             // Start observing preference changes.
640             [WKPreferenceObserver sharedInstance];
641         });
642     });
643 }
644 #endif
645
646 void WebProcessPool::registerNotificationObservers()
647 {
648 #if !PLATFORM(IOS_FAMILY)
649     // Listen for enhanced accessibility changes and propagate them to the WebProcess.
650     m_enhancedAccessibilityObserver = [[NSNotificationCenter defaultCenter] addObserverForName:WebKitApplicationDidChangeAccessibilityEnhancedUserInterfaceNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *note) {
651 #if ENABLE(CFPREFS_DIRECT_MODE)
652         for (auto& process : m_processes)
653             process->unblockPreferenceServiceIfNeeded();
654 #endif
655         setEnhancedAccessibility([[[note userInfo] objectForKey:@"AXEnhancedUserInterface"] boolValue]);
656     }];
657
658     m_automaticTextReplacementNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSSpellCheckerDidChangeAutomaticTextReplacementNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) {
659         TextChecker::didChangeAutomaticTextReplacementEnabled();
660         textCheckerStateChanged();
661     }];
662     
663     m_automaticSpellingCorrectionNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSSpellCheckerDidChangeAutomaticSpellingCorrectionNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) {
664         TextChecker::didChangeAutomaticSpellingCorrectionEnabled();
665         textCheckerStateChanged();
666     }];
667
668     m_automaticQuoteSubstitutionNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSSpellCheckerDidChangeAutomaticQuoteSubstitutionNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) {
669         TextChecker::didChangeAutomaticQuoteSubstitutionEnabled();
670         textCheckerStateChanged();
671     }];
672
673     m_automaticDashSubstitutionNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSSpellCheckerDidChangeAutomaticDashSubstitutionNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) {
674         TextChecker::didChangeAutomaticDashSubstitutionEnabled();
675         textCheckerStateChanged();
676     }];
677
678     m_accessibilityDisplayOptionsNotificationObserver = [[NSWorkspace.sharedWorkspace notificationCenter] addObserverForName:NSWorkspaceAccessibilityDisplayOptionsDidChangeNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) {
679         screenPropertiesStateChanged();
680     }];
681
682 #if ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
683     m_scrollerStyleNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSPreferredScrollerStyleDidChangeNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) {
684         auto scrollbarStyle = [NSScroller preferredScrollerStyle];
685         sendToAllProcesses(Messages::WebProcess::ScrollerStylePreferenceChanged(scrollbarStyle));
686     }];
687 #endif
688
689     m_activationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSApplicationDidBecomeActiveNotification object:NSApp queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) {
690 #if ENABLE(CFPREFS_DIRECT_MODE)
691         startObservingPreferenceChanges();
692 #endif
693         setApplicationIsActive(true);
694     }];
695
696     m_deactivationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSApplicationDidResignActiveNotification object:NSApp queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) {
697         setApplicationIsActive(false);
698     }];
699 #elif !PLATFORM(MACCATALYST)
700     CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), this, backlightLevelDidChangeCallback, static_cast<CFStringRef>(UIBacklightLevelChangedNotification), nullptr, CFNotificationSuspensionBehaviorCoalesce);
701 #if PLATFORM(IOS)
702 #if ENABLE(REMOTE_INSPECTOR)
703     CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), this, remoteWebInspectorEnabledCallback, static_cast<CFStringRef>(CFSTR(WIRServiceEnabledNotification)), nullptr, CFNotificationSuspensionBehaviorCoalesce);
704 #endif
705 #endif // PLATFORM(IOS)
706 #endif // !PLATFORM(IOS_FAMILY)
707
708 #if PLATFORM(IOS_FAMILY)
709     m_accessibilityEnabledObserver = [[NSNotificationCenter defaultCenter] addObserverForName:(__bridge id)kAXSApplicationAccessibilityEnabledNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *) {
710         for (size_t i = 0; i < m_processes.size(); ++i) {
711 #if ENABLE(CFPREFS_DIRECT_MODE)
712             m_processes[i]->unblockPreferenceServiceIfNeeded();
713 #endif
714             m_processes[i]->unblockAccessibilityServerIfNeeded();
715         }
716     }];
717 #if ENABLE(CFPREFS_DIRECT_MODE)
718     m_activationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"UIApplicationDidBecomeActiveNotification" object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) {
719         startObservingPreferenceChanges();
720     }];
721 #endif
722 #endif
723 }
724
725 void WebProcessPool::unregisterNotificationObservers()
726 {
727 #if !PLATFORM(IOS_FAMILY)
728     [[NSNotificationCenter defaultCenter] removeObserver:m_enhancedAccessibilityObserver.get()];
729     [[NSNotificationCenter defaultCenter] removeObserver:m_automaticTextReplacementNotificationObserver.get()];
730     [[NSNotificationCenter defaultCenter] removeObserver:m_automaticSpellingCorrectionNotificationObserver.get()];
731     [[NSNotificationCenter defaultCenter] removeObserver:m_automaticQuoteSubstitutionNotificationObserver.get()];
732     [[NSNotificationCenter defaultCenter] removeObserver:m_automaticDashSubstitutionNotificationObserver.get()];
733     [[NSWorkspace.sharedWorkspace notificationCenter] removeObserver:m_accessibilityDisplayOptionsNotificationObserver.get()];
734 #if ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
735     [[NSNotificationCenter defaultCenter] removeObserver:m_scrollerStyleNotificationObserver.get()];
736 #endif
737     [[NSNotificationCenter defaultCenter] removeObserver:m_deactivationObserver.get()];
738 #elif !PLATFORM(MACCATALYST)
739     CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), this, static_cast<CFStringRef>(UIBacklightLevelChangedNotification) , nullptr);
740 #if PLATFORM(IOS)
741 #if ENABLE(REMOTE_INSPECTOR)
742     CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), this, CFSTR(WIRServiceEnabledNotification), nullptr);
743 #endif
744 #endif // PLATFORM(IOS)
745 #endif // !PLATFORM(IOS_FAMILY)
746
747 #if PLATFORM(IOS_FAMILY)
748     [[NSNotificationCenter defaultCenter] removeObserver:m_accessibilityEnabledObserver.get()];
749 #endif
750
751     [[NSNotificationCenter defaultCenter] removeObserver:m_activationObserver.get()];
752 }
753
754 static CFURLStorageSessionRef privateBrowsingSession()
755 {
756     static CFURLStorageSessionRef session;
757     static dispatch_once_t once;
758     dispatch_once(&once, ^{
759         NSString *identifier = [NSString stringWithFormat:@"%@.PrivateBrowsing", [[NSBundle mainBundle] bundleIdentifier]];
760         session = createPrivateStorageSession((__bridge CFStringRef)identifier);
761     });
762
763     return session;
764 }
765
766 bool WebProcessPool::isURLKnownHSTSHost(const String& urlString) const
767 {
768     RetainPtr<CFURLRef> url = URL(URL(), urlString).createCFURL();
769
770     return _CFNetworkIsKnownHSTSHostWithSession(url.get(), nullptr);
771 }
772
773 void WebProcessPool::resetHSTSHosts()
774 {
775     _CFNetworkResetHSTSHostsWithSession(nullptr);
776     _CFNetworkResetHSTSHostsWithSession(privateBrowsingSession());
777 }
778
779 void WebProcessPool::resetHSTSHostsAddedAfterDate(double startDateIntervalSince1970)
780 {
781     NSDate *startDate = [NSDate dateWithTimeIntervalSince1970:startDateIntervalSince1970];
782     _CFNetworkResetHSTSHostsSinceDate(nullptr, (__bridge CFDateRef)startDate);
783     _CFNetworkResetHSTSHostsSinceDate(privateBrowsingSession(), (__bridge CFDateRef)startDate);
784 }
785
786 #if PLATFORM(MAC) && ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
787 void WebProcessPool::startDisplayLink(IPC::Connection& connection, unsigned observerID, uint32_t displayID)
788 {
789     for (auto& displayLink : m_displayLinks) {
790         if (displayLink->displayID() == displayID) {
791             displayLink->addObserver(connection, observerID);
792             return;
793         }
794     }
795     auto displayLink = makeUnique<DisplayLink>(displayID);
796     displayLink->addObserver(connection, observerID);
797     m_displayLinks.append(WTFMove(displayLink));
798 }
799
800 void WebProcessPool::stopDisplayLink(IPC::Connection& connection, unsigned observerID, uint32_t displayID)
801 {
802     for (auto& displayLink : m_displayLinks) {
803         if (displayLink->displayID() == displayID) {
804             displayLink->removeObserver(connection, observerID);
805             return;
806         }
807     }
808 }
809
810 void WebProcessPool::stopDisplayLinks(IPC::Connection& connection)
811 {
812     for (auto& displayLink : m_displayLinks)
813         displayLink->removeObservers(connection);
814 }
815 #endif
816
817 // FIXME: Deprecated. Left here until a final decision is made.
818 void WebProcessPool::setCookieStoragePartitioningEnabled(bool enabled)
819 {
820     m_cookieStoragePartitioningEnabled = enabled;
821 }
822
823 void WebProcessPool::clearPermanentCredentialsForProtectionSpace(WebCore::ProtectionSpace&& protectionSpace)
824 {
825     auto sharedStorage = [NSURLCredentialStorage sharedCredentialStorage];
826     auto credentials = [sharedStorage credentialsForProtectionSpace:protectionSpace.nsSpace()];
827     for (NSString* user in credentials) {
828         auto credential = credentials[user];
829         if (credential.persistence == NSURLCredentialPersistencePermanent)
830             [sharedStorage removeCredential:credentials[user] forProtectionSpace:protectionSpace.nsSpace()];
831     }
832 }
833
834 int networkProcessLatencyQOS()
835 {
836     static const int qos = [[NSUserDefaults standardUserDefaults] integerForKey:@"WebKitNetworkProcessLatencyQOS"];
837     return qos;
838 }
839
840 int networkProcessThroughputQOS()
841 {
842     static const int qos = [[NSUserDefaults standardUserDefaults] integerForKey:@"WebKitNetworkProcessThroughputQOS"];
843     return qos;
844 }
845
846 int webProcessLatencyQOS()
847 {
848     static const int qos = [[NSUserDefaults standardUserDefaults] integerForKey:@"WebKitWebProcessLatencyQOS"];
849     return qos;
850 }
851
852 int webProcessThroughputQOS()
853 {
854     static const int qos = [[NSUserDefaults standardUserDefaults] integerForKey:@"WebKitWebProcessThroughputQOS"];
855     return qos;
856 }
857
858 #if PLATFORM(IOS_FAMILY)
859 void WebProcessPool::applicationIsAboutToSuspend()
860 {
861     WEBPROCESSPOOL_RELEASE_LOG(ProcessSuspension, "applicationIsAboutToSuspend: Terminating non-critical processes");
862
863     m_backForwardCache->pruneToSize(1);
864     m_webProcessCache->clear();
865 }
866
867 void WebProcessPool::notifyProcessPoolsApplicationIsAboutToSuspend()
868 {
869     for (auto* processPool : allProcessPools())
870         processPool->applicationIsAboutToSuspend();
871 }
872 #endif
873
874 void WebProcessPool::initializeClassesForParameterCoding()
875 {
876     const auto& customClasses = m_configuration->customClassesForParameterCoder();
877     if (customClasses.isEmpty())
878         return;
879
880     auto standardClasses = [NSSet setWithObjects:[NSArray class], [NSData class], [NSDate class], [NSDictionary class], [NSNull class],
881         [NSNumber class], [NSSet class], [NSString class], [NSTimeZone class], [NSURL class], [NSUUID class], nil];
882     
883     auto mutableSet = adoptNS([standardClasses mutableCopy]);
884
885     for (const auto& customClass : customClasses) {
886         auto className = customClass.utf8();
887         Class objectClass = objc_lookUpClass(className.data());
888         if (!objectClass) {
889             WTFLogAlways("InjectedBundle::extendClassesForParameterCoder - Class %s is not a valid Objective C class.\n", className.data());
890             break;
891         }
892
893         [mutableSet.get() addObject:objectClass];
894     }
895
896     m_classesForParameterCoder = mutableSet;
897 }
898
899 NSSet *WebProcessPool::allowedClassesForParameterCoding() const
900 {
901     return m_classesForParameterCoder.get();
902 }
903
904 #if ENABLE(CFPREFS_DIRECT_MODE)
905 void WebProcessPool::notifyPreferencesChanged(const String& domain, const String& key, const Optional<String>& encodedValue)
906 {
907     for (auto process : m_processes)
908         process->send(Messages::WebProcess::NotifyPreferencesChanged(domain, key, encodedValue), 0);
909 }
910 #endif
911
912 #if PLATFORM(MAC)
913 static void webProcessPoolHighDynamicRangeDidChangeCallback(CMNotificationCenterRef, const void*, CFStringRef notificationName, const void*, CFTypeRef)
914 {
915     auto screenProperties = WebCore::collectScreenProperties();
916     for (auto& processPool : WebProcessPool::allProcessPools())
917         processPool->sendToAllProcesses(Messages::WebProcess::SetScreenProperties(screenProperties));
918 }
919
920 void WebProcessPool::registerHighDynamicRangeChangeCallback()
921 {
922     static std::once_flag onceFlag;
923     std::call_once(
924         onceFlag,
925         [] {
926         if (!PAL::isMediaToolboxFrameworkAvailable()
927             || !PAL::canLoad_MediaToolbox_MTShouldPlayHDRVideo()
928             || !PAL::canLoad_MediaToolbox_MT_GetShouldPlayHDRVideoNotificationSingleton()
929             || !PAL::canLoad_MediaToolbox_kMTSupportNotification_ShouldPlayHDRVideoChanged())
930             return;
931
932         auto center = PAL::softLink_CoreMedia_CMNotificationCenterGetDefaultLocalCenter();
933         auto notification = PAL::get_MediaToolbox_kMTSupportNotification_ShouldPlayHDRVideoChanged();
934         auto object = PAL::softLinkMediaToolboxMT_GetShouldPlayHDRVideoNotificationSingleton();
935
936         // Note: CMNotificationCenterAddListener requires a non-null listener pointer. Just use the singleton
937         // object itself as the "listener", since the notification method is a static global and doesn't need
938         // the listener pointer at all.
939         PAL::softLink_CoreMedia_CMNotificationCenterAddListener(center, object, webProcessPoolHighDynamicRangeDidChangeCallback, notification, object, 0);
940     });
941 }
942 #endif
943
944 } // namespace WebKit