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