Add ENABLE_PERIODIC_MEMORY_MONITOR flag.
[WebKit-https.git] / Source / WebKit / WebProcess / WebProcess.cpp
1 /*
2  * Copyright (C) 2009-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 #include "config.h"
27 #include "WebProcess.h"
28
29 #include "APIFrameHandle.h"
30 #include "APIPageGroupHandle.h"
31 #include "APIPageHandle.h"
32 #include "AuthenticationManager.h"
33 #include "AuxiliaryProcessMessages.h"
34 #include "DrawingArea.h"
35 #include "EventDispatcher.h"
36 #include "InjectedBundle.h"
37 #include "LibWebRTCNetwork.h"
38 #include "Logging.h"
39 #include "NetworkConnectionToWebProcessMessages.h"
40 #include "NetworkProcessConnection.h"
41 #include "NetworkProcessConnectionInfo.h"
42 #include "NetworkSession.h"
43 #include "NetworkSessionCreationParameters.h"
44 #include "PluginProcessConnectionManager.h"
45 #include "ProcessAssertion.h"
46 #include "RemoteAudioSession.h"
47 #include "RemoteLegacyCDMFactory.h"
48 #include "StorageAreaMap.h"
49 #include "UserData.h"
50 #include "WebAutomationSessionProxy.h"
51 #include "WebCacheStorageProvider.h"
52 #include "WebConnectionToUIProcess.h"
53 #include "WebCookieJar.h"
54 #include "WebCoreArgumentCoders.h"
55 #include "WebFrame.h"
56 #include "WebFrameNetworkingContext.h"
57 #include "WebGamepadProvider.h"
58 #include "WebGeolocationManager.h"
59 #include "WebIDBConnectionToServer.h"
60 #include "WebLoaderStrategy.h"
61 #include "WebMediaKeyStorageManager.h"
62 #include "WebMemorySampler.h"
63 #include "WebMessagePortChannelProvider.h"
64 #include "WebPage.h"
65 #include "WebPageCreationParameters.h"
66 #include "WebPageGroupProxy.h"
67 #include "WebPaymentCoordinator.h"
68 #include "WebPlatformStrategies.h"
69 #include "WebPluginInfoProvider.h"
70 #include "WebProcessCreationParameters.h"
71 #include "WebProcessDataStoreParameters.h"
72 #include "WebProcessMessages.h"
73 #include "WebProcessPoolMessages.h"
74 #include "WebProcessProxyMessages.h"
75 #include "WebResourceLoadObserver.h"
76 #include "WebSWClientConnection.h"
77 #include "WebSWContextManagerConnection.h"
78 #include "WebSWContextManagerConnectionMessages.h"
79 #include "WebServiceWorkerProvider.h"
80 #include "WebSocketStream.h"
81 #include "WebsiteData.h"
82 #include "WebsiteDataStoreParameters.h"
83 #include "WebsiteDataType.h"
84 #include <JavaScriptCore/JSLock.h>
85 #include <JavaScriptCore/MemoryStatistics.h>
86 #include <JavaScriptCore/WasmFaultSignalHandler.h>
87 #include <WebCore/AXObjectCache.h>
88 #include <WebCore/ApplicationCacheStorage.h>
89 #include <WebCore/AuthenticationChallenge.h>
90 #include <WebCore/BackForwardCache.h>
91 #include <WebCore/CPUMonitor.h>
92 #include <WebCore/CommonVM.h>
93 #include <WebCore/CrossOriginPreflightResultCache.h>
94 #include <WebCore/DNS.h>
95 #include <WebCore/DOMWindow.h>
96 #include <WebCore/DatabaseManager.h>
97 #include <WebCore/DatabaseTracker.h>
98 #include <WebCore/DeprecatedGlobalSettings.h>
99 #include <WebCore/DiagnosticLoggingClient.h>
100 #include <WebCore/DiagnosticLoggingKeys.h>
101 #include <WebCore/FontCache.h>
102 #include <WebCore/FontCascade.h>
103 #include <WebCore/Frame.h>
104 #include <WebCore/FrameLoader.h>
105 #include <WebCore/GCController.h>
106 #include <WebCore/GlyphPage.h>
107 #include <WebCore/HTMLMediaElement.h>
108 #include <WebCore/JSDOMWindow.h>
109 #include <WebCore/LegacySchemeRegistry.h>
110 #include <WebCore/MemoryCache.h>
111 #include <WebCore/MemoryRelease.h>
112 #include <WebCore/MessagePort.h>
113 #include <WebCore/MockRealtimeMediaSourceCenter.h>
114 #include <WebCore/NetworkStorageSession.h>
115 #include <WebCore/Page.h>
116 #include <WebCore/PageGroup.h>
117 #include <WebCore/PlatformKeyboardEvent.h>
118 #include <WebCore/PlatformMediaSessionManager.h>
119 #include <WebCore/ProcessWarming.h>
120 #include <WebCore/RegistrableDomain.h>
121 #include <WebCore/ResourceLoadStatistics.h>
122 #include <WebCore/RuntimeApplicationChecks.h>
123 #include <WebCore/RuntimeEnabledFeatures.h>
124 #include <WebCore/SecurityOrigin.h>
125 #include <WebCore/ServiceWorkerContextData.h>
126 #include <WebCore/Settings.h>
127 #include <WebCore/UserGestureIndicator.h>
128 #include <wtf/Algorithms.h>
129 #include <wtf/Language.h>
130 #include <wtf/ProcessPrivilege.h>
131 #include <wtf/RunLoop.h>
132 #include <wtf/SystemTracing.h>
133 #include <wtf/URLParser.h>
134 #include <wtf/text/StringHash.h>
135
136 #if !OS(WINDOWS)
137 #include <unistd.h>
138 #endif
139
140 #if PLATFORM(WAYLAND)
141 #include "WaylandCompositorDisplay.h"
142 #endif
143
144 #if PLATFORM(COCOA)
145 #include "ObjCObjectGraph.h"
146 #include "UserMediaCaptureManager.h"
147 #endif
148
149 #if ENABLE(SEC_ITEM_SHIM)
150 #include "SecItemShim.h"
151 #endif
152
153 #if ENABLE(NOTIFICATIONS)
154 #include "WebNotificationManager.h"
155 #endif
156
157 #if ENABLE(GPU_PROCESS)
158 #include "GPUConnectionToWebProcessMessages.h"
159 #include "GPUProcessConnection.h"
160 #include "GPUProcessConnectionInfo.h"
161 #endif
162
163 #if ENABLE(REMOTE_INSPECTOR)
164 #include <JavaScriptCore/RemoteInspector.h>
165 #endif
166
167 #if ENABLE(GPU_PROCESS)
168 #include "RemoteMediaPlayerManager.h"
169 #endif
170
171 #if USE(LIBWEBRTC) && PLATFORM(COCOA) && ENABLE(GPU_PROCESS)
172 #include "LibWebRTCCodecs.h"
173 #endif
174
175 #if ENABLE(ENCRYPTED_MEDIA)
176 #include "RemoteCDMFactory.h"
177 #endif
178
179 #if PLATFORM(IOS_FAMILY)
180 #include "RemoteMediaSessionHelper.h"
181 #endif
182
183 #if ENABLE(ROUTING_ARBITRATION)
184 #include "AudioSessionRoutingArbitrator.h"
185 #endif
186
187 #define RELEASE_LOG_SESSION_ID (m_sessionID ? m_sessionID->toUInt64() : 0)
188 #define RELEASE_LOG_IF_ALLOWED(channel, fmt, ...) RELEASE_LOG_IF(isAlwaysOnLoggingAllowed(), channel, "%p - [sessionID=%" PRIu64 "] WebProcess::" fmt, this, RELEASE_LOG_SESSION_ID, ##__VA_ARGS__)
189 #define RELEASE_LOG_ERROR_IF_ALLOWED(channel, fmt, ...) RELEASE_LOG_ERROR_IF(isAlwaysOnLoggingAllowed(), channel, "%p - [sessionID=%" PRIu64 "] WebProcess::" fmt, this, RELEASE_LOG_SESSION_ID, ##__VA_ARGS__)
190
191 // This should be less than plugInAutoStartExpirationTimeThreshold in PlugInAutoStartProvider.
192 static const Seconds plugInAutoStartExpirationTimeUpdateThreshold { 29 * 24 * 60 * 60 };
193
194 // This should be greater than tileRevalidationTimeout in TileController.
195 static const Seconds nonVisibleProcessCleanupDelay { 10_s };
196
197 namespace WebKit {
198 using namespace JSC;
199 using namespace WebCore;
200
201 NO_RETURN static void callExit(IPC::Connection*)
202 {
203     _exit(EXIT_SUCCESS);
204 }
205
206 WebProcess& WebProcess::singleton()
207 {
208     static WebProcess& process = *new WebProcess;
209     return process;
210 }
211
212 WebProcess::WebProcess()
213     : m_eventDispatcher(EventDispatcher::create())
214 #if PLATFORM(IOS_FAMILY)
215     , m_viewUpdateDispatcher(ViewUpdateDispatcher::create())
216 #endif
217     , m_webInspectorInterruptDispatcher(WebInspectorInterruptDispatcher::create())
218     , m_webLoaderStrategy(*new WebLoaderStrategy)
219     , m_cacheStorageProvider(WebCacheStorageProvider::create())
220     , m_cookieJar(WebCookieJar::create())
221     , m_dnsPrefetchHystereris([this](PAL::HysteresisState state) { if (state == PAL::HysteresisState::Stopped) m_dnsPrefetchedHosts.clear(); })
222 #if ENABLE(NETSCAPE_PLUGIN_API)
223     , m_pluginProcessConnectionManager(PluginProcessConnectionManager::create())
224 #endif
225     , m_nonVisibleProcessCleanupTimer(*this, &WebProcess::nonVisibleProcessCleanupTimerFired)
226 {
227     // Initialize our platform strategies.
228     WebPlatformStrategies::initialize();
229
230     // FIXME: This should moved to where WebProcess::initialize is called,
231     // so that ports have a chance to customize, and ifdefs in this file are
232     // limited.
233     addSupplement<WebGeolocationManager>();
234
235 #if ENABLE(NOTIFICATIONS)
236     addSupplement<WebNotificationManager>();
237 #endif
238
239 #if ENABLE(LEGACY_ENCRYPTED_MEDIA)
240     addSupplement<WebMediaKeyStorageManager>();
241 #endif
242
243 #if PLATFORM(COCOA) && ENABLE(MEDIA_STREAM)
244     addSupplement<UserMediaCaptureManager>();
245 #endif
246
247 #if ENABLE(GPU_PROCESS)
248     addSupplement<RemoteMediaPlayerManager>();
249 #endif
250
251 #if ENABLE(GPU_PROCESS) && ENABLE(ENCRYPTED_MEDIA)
252     addSupplement<RemoteCDMFactory>();
253 #endif
254
255 #if ENABLE(GPU_PROCESS) && ENABLE(LEGACY_ENCRYPTED_MEDIA)
256     addSupplement<RemoteLegacyCDMFactory>();
257 #endif
258
259 #if ENABLE(ROUTING_ARBITRATION)
260     addSupplement<AudioSessionRoutingArbitrator>();
261 #endif
262
263     Gigacage::forbidDisablingPrimitiveGigacage();
264 }
265
266 WebProcess::~WebProcess()
267 {
268     ASSERT_NOT_REACHED();
269 }
270
271 void WebProcess::initializeProcess(const AuxiliaryProcessInitializationParameters& parameters)
272 {
273     WTF::setProcessPrivileges({ });
274
275     MessagePortChannelProvider::setSharedProvider(WebMessagePortChannelProvider::singleton());
276     
277     platformInitializeProcess(parameters);
278     updateCPULimit();
279 }
280
281 void WebProcess::initializeConnection(IPC::Connection* connection)
282 {
283     AuxiliaryProcess::initializeConnection(connection);
284
285     // We call _exit() directly from the background queue in case the main thread is unresponsive
286     // and AuxiliaryProcess::didClose() does not get called.
287     connection->setDidCloseOnConnectionWorkQueueCallback(callExit);
288
289 #if !PLATFORM(GTK) && !PLATFORM(WPE)
290     connection->setShouldExitOnSyncMessageSendFailure(true);
291 #endif
292
293 #if HAVE(QOS_CLASSES)
294     connection->setShouldBoostMainThreadOnSyncMessage(true);
295 #endif
296
297     m_eventDispatcher->initializeConnection(connection);
298 #if PLATFORM(IOS_FAMILY)
299     m_viewUpdateDispatcher->initializeConnection(connection);
300 #endif // PLATFORM(IOS_FAMILY)
301
302     m_webInspectorInterruptDispatcher->initializeConnection(connection);
303
304 #if ENABLE(NETSCAPE_PLUGIN_API)
305     m_pluginProcessConnectionManager->initializeConnection(connection);
306 #endif
307
308     for (auto& supplement : m_supplements.values())
309         supplement->initializeConnection(connection);
310
311     m_webConnection = WebConnectionToUIProcess::create(this);
312 }
313
314 void WebProcess::initializeWebProcess(WebProcessCreationParameters&& parameters)
315 {    
316     TraceScope traceScope(InitializeWebProcessStart, InitializeWebProcessEnd);
317
318     ASSERT(m_pageMap.isEmpty());
319
320     if (parameters.websiteDataStoreParameters)
321         setWebsiteDataStoreParameters(WTFMove(*parameters.websiteDataStoreParameters));
322
323     WebCore::setPresentingApplicationPID(parameters.presentingApplicationPID);
324
325 #if OS(LINUX)
326     MemoryPressureHandler::ReliefLogger::setLoggingEnabled(parameters.shouldEnableMemoryPressureReliefLogging);
327 #endif
328
329     platformInitializeWebProcess(parameters);
330
331     // Match the QoS of the UIProcess and the scrolling thread but use a slightly lower priority.
332     WTF::Thread::setCurrentThreadIsUserInteractive(-1);
333
334     m_suppressMemoryPressureHandler = parameters.shouldSuppressMemoryPressureHandler;
335     if (!m_suppressMemoryPressureHandler) {
336         auto& memoryPressureHandler = MemoryPressureHandler::singleton();
337         memoryPressureHandler.setLowMemoryHandler([this] (Critical critical, Synchronous synchronous) {
338 #if PLATFORM(MAC)
339             // If this is a process we keep around for performance, kill it on memory pressure instead of trying to free up its memory.
340             if (m_processType == ProcessType::CachedWebContent || m_processType == ProcessType::PrewarmedWebContent || areAllPagesSuspended()) {
341                 if (m_processType == ProcessType::CachedWebContent)
342                     RELEASE_LOG_IF_ALLOWED(Process, "initializeWebProcess: Cached WebProcess is exiting due to memory pressure");
343                 else if (m_processType == ProcessType::PrewarmedWebContent)
344                     RELEASE_LOG_IF_ALLOWED(Process, "initializeWebProcess: Prewarmed WebProcess is exiting due to memory pressure");
345                 else
346                     RELEASE_LOG_IF_ALLOWED(Process, "initializeWebProcess: Suspended WebProcess is exiting due to memory pressure");
347                 stopRunLoop();
348                 return;
349             }
350 #endif
351
352             auto maintainBackForwardCache = m_isSuspending ? WebCore::MaintainBackForwardCache::Yes : WebCore::MaintainBackForwardCache::No;
353             auto maintainMemoryCache = m_isSuspending && m_hasSuspendedPageProxy ? WebCore::MaintainMemoryCache::Yes : WebCore::MaintainMemoryCache::No;
354             WebCore::releaseMemory(critical, synchronous, maintainBackForwardCache, maintainMemoryCache);
355         });
356 #if ENABLE(PERIODIC_MEMORY_MONITOR)
357         memoryPressureHandler.setShouldUsePeriodicMemoryMonitor(true);
358         memoryPressureHandler.setMemoryKillCallback([this] () {
359             WebCore::logMemoryStatisticsAtTimeOfDeath();
360             if (MemoryPressureHandler::singleton().processState() == WebsamProcessState::Active)
361                 parentProcessConnection()->send(Messages::WebProcessProxy::DidExceedActiveMemoryLimit(), 0);
362             else
363                 parentProcessConnection()->send(Messages::WebProcessProxy::DidExceedInactiveMemoryLimit(), 0);
364         });
365         memoryPressureHandler.setDidExceedInactiveLimitWhileActiveCallback([this] () {
366             parentProcessConnection()->send(Messages::WebProcessProxy::DidExceedInactiveMemoryLimitWhileActive(), 0);
367         });
368 #endif
369         memoryPressureHandler.setMemoryPressureStatusChangedCallback([this](bool isUnderMemoryPressure) {
370             if (parentProcessConnection())
371                 parentProcessConnection()->send(Messages::WebProcessProxy::MemoryPressureStatusChanged(isUnderMemoryPressure), 0);
372         });
373         memoryPressureHandler.install();
374     }
375
376     SandboxExtension::consumePermanently(parameters.additionalSandboxExtensionHandles);
377
378     if (!parameters.injectedBundlePath.isEmpty())
379         m_injectedBundle = InjectedBundle::create(parameters, transformHandlesToObjects(parameters.initializationUserData.object()).get());
380
381     for (auto& supplement : m_supplements.values())
382         supplement->initialize(parameters);
383
384     setCacheModel(parameters.cacheModel);
385
386     if (!parameters.languages.isEmpty())
387         overrideUserPreferredLanguages(parameters.languages);
388
389     m_textCheckerState = parameters.textCheckerState;
390
391     m_fullKeyboardAccessEnabled = parameters.fullKeyboardAccessEnabled;
392
393     for (auto& scheme : parameters.urlSchemesRegisteredAsEmptyDocument)
394         registerURLSchemeAsEmptyDocument(scheme);
395
396     for (auto& scheme : parameters.urlSchemesRegisteredAsSecure)
397         registerURLSchemeAsSecure(scheme);
398
399     for (auto& scheme : parameters.urlSchemesRegisteredAsBypassingContentSecurityPolicy)
400         registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
401
402     for (auto& scheme : parameters.urlSchemesForWhichDomainRelaxationIsForbidden)
403         setDomainRelaxationForbiddenForURLScheme(scheme);
404
405     for (auto& scheme : parameters.urlSchemesRegisteredAsLocal)
406         registerURLSchemeAsLocal(scheme);
407
408     for (auto& scheme : parameters.urlSchemesRegisteredAsNoAccess)
409         registerURLSchemeAsNoAccess(scheme);
410
411     for (auto& scheme : parameters.urlSchemesRegisteredAsDisplayIsolated)
412         registerURLSchemeAsDisplayIsolated(scheme);
413
414     for (auto& scheme : parameters.urlSchemesRegisteredAsCORSEnabled)
415         LegacySchemeRegistry::registerURLSchemeAsCORSEnabled(scheme);
416
417     for (auto& scheme : parameters.urlSchemesRegisteredAsAlwaysRevalidated)
418         registerURLSchemeAsAlwaysRevalidated(scheme);
419
420     for (auto& scheme : parameters.urlSchemesRegisteredAsCachePartitioned)
421         registerURLSchemeAsCachePartitioned(scheme);
422
423     for (auto& scheme : parameters.urlSchemesRegisteredAsCanDisplayOnlyIfCanRequest)
424         registerURLSchemeAsCanDisplayOnlyIfCanRequest(scheme);
425
426     setDefaultRequestTimeoutInterval(parameters.defaultRequestTimeoutInterval);
427
428     setBackForwardCacheCapacity(parameters.backForwardCacheCapacity);
429
430     setAlwaysUsesComplexTextCodePath(parameters.shouldAlwaysUseComplexTextCodePath);
431
432     setShouldUseFontSmoothing(parameters.shouldUseFontSmoothing);
433
434     setTerminationTimeout(parameters.terminationTimeout);
435
436     for (auto& origin : parameters.plugInAutoStartOrigins)
437         m_plugInAutoStartOrigins.add(origin);
438
439     setMemoryCacheDisabled(parameters.memoryCacheDisabled);
440
441     WebCore::RuntimeEnabledFeatures::sharedFeatures().setAttrStyleEnabled(parameters.attrStyleEnabled);
442
443 #if ENABLE(SERVICE_CONTROLS)
444     setEnabledServices(parameters.hasImageServices, parameters.hasSelectionServices, parameters.hasRichContentServices);
445 #endif
446
447 #if ENABLE(REMOTE_INSPECTOR) && PLATFORM(COCOA)
448 #if PLATFORM(IOS)
449     Inspector::RemoteInspector::setNeedMachSandboxExtension(true);
450 #endif
451     if (Optional<audit_token_t> auditToken = parentProcessConnection()->getAuditToken()) {
452         RetainPtr<CFDataRef> auditData = adoptCF(CFDataCreate(nullptr, (const UInt8*)&*auditToken, sizeof(*auditToken)));
453         Inspector::RemoteInspector::singleton().setParentProcessInformation(WebCore::presentingApplicationPID(), auditData);
454     }
455 #endif
456
457 #if ENABLE(NETSCAPE_PLUGIN_API) && PLATFORM(MAC)
458     resetPluginLoadClientPolicies(parameters.pluginLoadClientPolicies);
459 #endif
460
461 #if ENABLE(GAMEPAD)
462     GamepadProvider::singleton().setSharedProvider(WebGamepadProvider::singleton());
463 #endif
464
465 #if ENABLE(SERVICE_WORKER)
466     ServiceWorkerProvider::setSharedProvider(WebServiceWorkerProvider::singleton());
467 #endif
468
469 #if ENABLE(WEBASSEMBLY)
470     JSC::Wasm::enableFastMemory();
471 #endif
472
473 #if ENABLE(RESOURCE_LOAD_STATISTICS) && !RELEASE_LOG_DISABLED
474     WebResourceLoadObserver::setShouldLogUserInteraction(parameters.shouldLogUserInteraction);
475 #endif
476
477     RELEASE_LOG_IF_ALLOWED(Process, "initializeWebProcess: Presenting process = %d", WebCore::presentingApplicationPID());
478 }
479
480 void WebProcess::setWebsiteDataStoreParameters(WebProcessDataStoreParameters&& parameters)
481 {
482     ASSERT(!m_sessionID);
483     m_sessionID = parameters.sessionID;
484     
485     auto& databaseManager = DatabaseManager::singleton();
486     databaseManager.initialize(parameters.webSQLDatabaseDirectory);
487
488     // FIXME: This should be constructed per data store, not per process.
489     m_applicationCacheStorage = ApplicationCacheStorage::create(parameters.applicationCacheDirectory, parameters.applicationCacheFlatFileSubdirectoryName);
490 #if PLATFORM(IOS_FAMILY)
491     m_applicationCacheStorage->setDefaultOriginQuota(25ULL * 1024 * 1024);
492 #endif
493
494 #if ENABLE(VIDEO)
495     if (!parameters.mediaCacheDirectory.isEmpty())
496         WebCore::HTMLMediaElement::setMediaCacheDirectory(parameters.mediaCacheDirectory);
497 #endif
498
499     setResourceLoadStatisticsEnabled(parameters.resourceLoadStatisticsEnabled);
500
501 #if ENABLE(RESOURCE_LOAD_STATISTICS)
502     m_thirdPartyCookieBlockingMode = parameters.thirdPartyCookieBlockingMode;
503     if (parameters.resourceLoadStatisticsEnabled && !ResourceLoadObserver::sharedIfExists())
504         ResourceLoadObserver::setShared(*new WebResourceLoadObserver(parameters.sessionID.isEphemeral() ? WebCore::ResourceLoadStatistics::IsEphemeral::Yes : WebCore::ResourceLoadStatistics::IsEphemeral::No));
505 #endif
506
507     resetPlugInAutoStartOriginHashes(WTFMove(parameters.plugInAutoStartOriginHashes));
508
509     for (auto& supplement : m_supplements.values())
510         supplement->setWebsiteDataStore(parameters);
511
512     platformSetWebsiteDataStoreParameters(WTFMove(parameters));
513     
514     ensureNetworkProcessConnection();
515 }
516
517 bool WebProcess::areAllPagesSuspended() const
518 {
519     for (auto& page : m_pageMap.values()) {
520         if (!page->isSuspended())
521             return false;
522     }
523     return true;
524 }
525
526 void WebProcess::setHasSuspendedPageProxy(bool hasSuspendedPageProxy)
527 {
528     ASSERT(m_hasSuspendedPageProxy != hasSuspendedPageProxy);
529     m_hasSuspendedPageProxy = hasSuspendedPageProxy;
530 }
531
532 void WebProcess::setIsInProcessCache(bool isInProcessCache)
533 {
534 #if PLATFORM(COCOA)
535     if (isInProcessCache) {
536         ASSERT(m_processType == ProcessType::WebContent);
537         m_processType = ProcessType::CachedWebContent;
538     } else {
539         ASSERT(m_processType == ProcessType::CachedWebContent);
540         m_processType = ProcessType::WebContent;
541     }
542
543     updateProcessName();
544 #else
545     UNUSED_PARAM(isInProcessCache);
546 #endif
547 }
548
549 void WebProcess::markIsNoLongerPrewarmed()
550 {
551 #if PLATFORM(COCOA)
552     ASSERT(m_processType == ProcessType::PrewarmedWebContent);
553     m_processType = ProcessType::WebContent;
554
555     updateProcessName();
556 #endif
557 }
558
559 void WebProcess::prewarmGlobally()
560 {
561     WebCore::ProcessWarming::prewarmGlobally();
562 }
563
564 void WebProcess::prewarmWithDomainInformation(const WebCore::PrewarmInformation& prewarmInformation)
565 {
566     WebCore::ProcessWarming::prewarmWithInformation(prewarmInformation);
567 }
568
569 void WebProcess::registerURLSchemeAsEmptyDocument(const String& urlScheme)
570 {
571     LegacySchemeRegistry::registerURLSchemeAsEmptyDocument(urlScheme);
572 }
573
574 void WebProcess::registerURLSchemeAsSecure(const String& urlScheme) const
575 {
576     LegacySchemeRegistry::registerURLSchemeAsSecure(urlScheme);
577 }
578
579 void WebProcess::registerURLSchemeAsBypassingContentSecurityPolicy(const String& urlScheme) const
580 {
581     LegacySchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(urlScheme);
582 }
583
584 void WebProcess::setDomainRelaxationForbiddenForURLScheme(const String& urlScheme) const
585 {
586     LegacySchemeRegistry::setDomainRelaxationForbiddenForURLScheme(true, urlScheme);
587 }
588
589 void WebProcess::registerURLSchemeAsLocal(const String& urlScheme) const
590 {
591     LegacySchemeRegistry::registerURLSchemeAsLocal(urlScheme);
592 }
593
594 void WebProcess::registerURLSchemeAsNoAccess(const String& urlScheme) const
595 {
596     LegacySchemeRegistry::registerURLSchemeAsNoAccess(urlScheme);
597 }
598
599 void WebProcess::registerURLSchemeAsDisplayIsolated(const String& urlScheme) const
600 {
601     LegacySchemeRegistry::registerURLSchemeAsDisplayIsolated(urlScheme);
602 }
603
604 void WebProcess::registerURLSchemeAsCORSEnabled(const String& urlScheme)
605 {
606     LegacySchemeRegistry::registerURLSchemeAsCORSEnabled(urlScheme);
607     ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::RegisterURLSchemesAsCORSEnabled({ urlScheme }), 0);
608 }
609
610 void WebProcess::registerURLSchemeAsAlwaysRevalidated(const String& urlScheme) const
611 {
612     LegacySchemeRegistry::registerURLSchemeAsAlwaysRevalidated(urlScheme);
613 }
614
615 void WebProcess::registerURLSchemeAsCachePartitioned(const String& urlScheme) const
616 {
617     LegacySchemeRegistry::registerURLSchemeAsCachePartitioned(urlScheme);
618 }
619
620 void WebProcess::registerURLSchemeAsCanDisplayOnlyIfCanRequest(const String& urlScheme) const
621 {
622     LegacySchemeRegistry::registerAsCanDisplayOnlyIfCanRequest(urlScheme);
623 }
624
625 void WebProcess::setDefaultRequestTimeoutInterval(double timeoutInterval)
626 {
627     ResourceRequest::setDefaultTimeoutInterval(timeoutInterval);
628 }
629
630 void WebProcess::setAlwaysUsesComplexTextCodePath(bool alwaysUseComplexText)
631 {
632     WebCore::FontCascade::setCodePath(alwaysUseComplexText ? WebCore::FontCascade::Complex : WebCore::FontCascade::Auto);
633 }
634
635 void WebProcess::setShouldUseFontSmoothing(bool useFontSmoothing)
636 {
637     WebCore::FontCascade::setShouldUseSmoothing(useFontSmoothing);
638 }
639
640 void WebProcess::userPreferredLanguagesChanged(const Vector<String>& languages) const
641 {
642     overrideUserPreferredLanguages(languages);
643 }
644
645 void WebProcess::fullKeyboardAccessModeChanged(bool fullKeyboardAccessEnabled)
646 {
647     m_fullKeyboardAccessEnabled = fullKeyboardAccessEnabled;
648 }
649
650 #if ENABLE(NETSCAPE_PLUGIN_API)
651 PluginProcessConnectionManager& WebProcess::pluginProcessConnectionManager()
652 {
653     return *m_pluginProcessConnectionManager;
654 }
655 #endif
656
657 void WebProcess::setCacheModel(CacheModel cacheModel)
658 {
659     if (m_hasSetCacheModel && (cacheModel == m_cacheModel))
660         return;
661
662     m_hasSetCacheModel = true;
663     m_cacheModel = cacheModel;
664
665     unsigned cacheTotalCapacity = 0;
666     unsigned cacheMinDeadCapacity = 0;
667     unsigned cacheMaxDeadCapacity = 0;
668     Seconds deadDecodedDataDeletionInterval;
669     unsigned backForwardCacheSize = 0;
670     calculateMemoryCacheSizes(cacheModel, cacheTotalCapacity, cacheMinDeadCapacity, cacheMaxDeadCapacity, deadDecodedDataDeletionInterval, backForwardCacheSize);
671
672     auto& memoryCache = MemoryCache::singleton();
673     memoryCache.setCapacities(cacheMinDeadCapacity, cacheMaxDeadCapacity, cacheTotalCapacity);
674     memoryCache.setDeadDecodedDataDeletionInterval(deadDecodedDataDeletionInterval);
675     BackForwardCache::singleton().setMaxSize(backForwardCacheSize);
676
677     platformSetCacheModel(cacheModel);
678 }
679
680 WebPage* WebProcess::focusedWebPage() const
681 {    
682     for (auto& page : m_pageMap.values()) {
683         if (page->windowAndWebPageAreFocused())
684             return page.get();
685     }
686     return 0;
687 }
688     
689 WebPage* WebProcess::webPage(PageIdentifier pageID) const
690 {
691     return m_pageMap.get(pageID);
692 }
693
694 void WebProcess::createWebPage(PageIdentifier pageID, WebPageCreationParameters&& parameters)
695 {
696     // It is necessary to check for page existence here since during a window.open() (or targeted
697     // link) the WebPage gets created both in the synchronous handler and through the normal way. 
698     auto result = m_pageMap.add(pageID, nullptr);
699     if (result.isNewEntry) {
700         ASSERT(!result.iterator->value);
701         result.iterator->value = WebPage::create(pageID, WTFMove(parameters));
702
703         // Balanced by an enableTermination in removeWebPage.
704         disableTermination();
705         updateCPULimit();
706     } else
707         result.iterator->value->reinitializeWebPage(WTFMove(parameters));
708
709     ASSERT(result.iterator->value);
710 }
711
712 void WebProcess::removeWebPage(PageIdentifier pageID)
713 {
714     ASSERT(m_pageMap.contains(pageID));
715
716     flushResourceLoadStatistics();
717
718     pageWillLeaveWindow(pageID);
719     m_pageMap.remove(pageID);
720
721     enableTermination();
722     updateCPULimit();
723 }
724
725 bool WebProcess::shouldTerminate()
726 {
727     ASSERT(m_pageMap.isEmpty());
728
729     // FIXME: the ShouldTerminate message should also send termination parameters, such as any session cookies that need to be preserved.
730     bool shouldTerminate = false;
731     if (parentProcessConnection()->sendSync(Messages::WebProcessProxy::ShouldTerminate(), Messages::WebProcessProxy::ShouldTerminate::Reply(shouldTerminate), 0)
732         && !shouldTerminate)
733         return false;
734
735     return true;
736 }
737
738 void WebProcess::terminate()
739 {
740 #ifndef NDEBUG
741     GCController::singleton().garbageCollectNow();
742     FontCache::singleton().invalidate();
743     MemoryCache::singleton().setDisabled(true);
744 #endif
745
746     m_webConnection->invalidate();
747     m_webConnection = nullptr;
748
749     platformTerminate();
750
751     AuxiliaryProcess::terminate();
752 }
753
754 void WebProcess::didReceiveSyncMessage(IPC::Connection& connection, IPC::Decoder& decoder, std::unique_ptr<IPC::Encoder>& replyEncoder)
755 {
756     if (messageReceiverMap().dispatchSyncMessage(connection, decoder, replyEncoder))
757         return;
758 }
759
760 void WebProcess::didReceiveMessage(IPC::Connection& connection, IPC::Decoder& decoder)
761 {
762     if (messageReceiverMap().dispatchMessage(connection, decoder))
763         return;
764
765     if (decoder.messageReceiverName() == Messages::WebProcess::messageReceiverName()) {
766         didReceiveWebProcessMessage(connection, decoder);
767         return;
768     }
769
770     if (decoder.messageReceiverName() == Messages::AuxiliaryProcess::messageReceiverName()) {
771         AuxiliaryProcess::didReceiveMessage(connection, decoder);
772         return;
773     }
774
775 #if ENABLE(SERVICE_WORKER)
776     // FIXME: Remove?
777     if (decoder.messageReceiverName() == Messages::WebSWContextManagerConnection::messageReceiverName()) {
778         ASSERT(SWContextManager::singleton().connection());
779         if (auto* contextManagerConnection = SWContextManager::singleton().connection())
780             static_cast<WebSWContextManagerConnection&>(*contextManagerConnection).didReceiveMessage(connection, decoder);
781         return;
782     }
783 #endif
784
785     LOG_ERROR("Unhandled web process message '%s' (destination: %" PRIu64 " pid: %d)", description(decoder.messageName()), decoder.destinationID(), static_cast<int>(getCurrentProcessID()));
786 }
787
788 WebFrame* WebProcess::webFrame(FrameIdentifier frameID) const
789 {
790     return m_frameMap.get(frameID);
791 }
792
793 Vector<WebFrame*> WebProcess::webFrames() const
794 {
795     return copyToVector(m_frameMap.values());
796 }
797
798 void WebProcess::addWebFrame(FrameIdentifier frameID, WebFrame* frame)
799 {
800     m_frameMap.set(frameID, frame);
801 }
802
803 void WebProcess::removeWebFrame(FrameIdentifier frameID)
804 {
805     m_frameMap.remove(frameID);
806
807     // We can end up here after our connection has closed when WebCore's frame life-support timer
808     // fires when the application is shutting down. There's no need (and no way) to update the UI
809     // process in this case.
810     if (!parentProcessConnection())
811         return;
812
813     parentProcessConnection()->send(Messages::WebProcessProxy::DidDestroyFrame(frameID), 0);
814 }
815
816 WebPageGroupProxy* WebProcess::webPageGroup(PageGroup* pageGroup)
817 {
818     for (auto& page : m_pageGroupMap.values()) {
819         if (page->corePageGroup() == pageGroup)
820             return page.get();
821     }
822
823     return 0;
824 }
825
826 WebPageGroupProxy* WebProcess::webPageGroup(uint64_t pageGroupID)
827 {
828     return m_pageGroupMap.get(pageGroupID);
829 }
830
831 WebPageGroupProxy* WebProcess::webPageGroup(const WebPageGroupData& pageGroupData)
832 {
833     auto result = m_pageGroupMap.add(pageGroupData.pageGroupID, nullptr);
834     if (result.isNewEntry) {
835         ASSERT(!result.iterator->value);
836         result.iterator->value = WebPageGroupProxy::create(pageGroupData);
837     }
838
839     return result.iterator->value.get();
840 }
841
842 static uint64_t nextUserGestureTokenIdentifier()
843 {
844     static uint64_t identifier = 1;
845     return identifier++;
846 }
847
848 uint64_t WebProcess::userGestureTokenIdentifier(RefPtr<UserGestureToken> token)
849 {
850     if (!token || !token->processingUserGesture())
851         return 0;
852
853     auto result = m_userGestureTokens.ensure(token.get(), [] { return nextUserGestureTokenIdentifier(); });
854     if (result.isNewEntry) {
855         result.iterator->key->addDestructionObserver([] (UserGestureToken& tokenBeingDestroyed) {
856             WebProcess::singleton().userGestureTokenDestroyed(tokenBeingDestroyed);
857         });
858     }
859     
860     return result.iterator->value;
861 }
862
863 void WebProcess::userGestureTokenDestroyed(UserGestureToken& token)
864 {
865     auto identifier = m_userGestureTokens.take(&token);
866     parentProcessConnection()->send(Messages::WebProcessProxy::DidDestroyUserGestureToken(identifier), 0);
867 }
868
869 static inline void addCaseFoldedCharacters(StringHasher& hasher, const String& string)
870 {
871     if (string.isEmpty())
872         return;
873     if (string.is8Bit()) {
874         hasher.addCharacters<LChar, ASCIICaseInsensitiveHash::FoldCase<LChar>>(string.characters8(), string.length());
875         return;
876     }
877     hasher.addCharacters<UChar, ASCIICaseInsensitiveHash::FoldCase<UChar>>(string.characters16(), string.length());
878 }
879
880 static unsigned hashForPlugInOrigin(const String& pageOrigin, const String& pluginOrigin, const String& mimeType)
881 {
882     // We want to avoid concatenating the strings and then taking the hash, since that could lead to an expensive conversion.
883     // We also want to avoid using the hash() function in StringImpl or ASCIICaseInsensitiveHash because that masks out bits for the use of flags.
884     StringHasher hasher;
885     addCaseFoldedCharacters(hasher, pageOrigin);
886     hasher.addCharacter(0);
887     addCaseFoldedCharacters(hasher, pluginOrigin);
888     hasher.addCharacter(0);
889     addCaseFoldedCharacters(hasher, mimeType);
890     return hasher.hash();
891 }
892
893 bool WebProcess::isPlugInAutoStartOriginHash(unsigned plugInOriginHash)
894 {
895     auto it = m_plugInAutoStartOriginHashes.find(plugInOriginHash);
896     if (it == m_plugInAutoStartOriginHashes.end())
897         return false;
898
899     return WallTime::now() < it->value;
900 }
901
902 bool WebProcess::shouldPlugInAutoStartFromOrigin(WebPage& webPage, const String& pageOrigin, const String& pluginOrigin, const String& mimeType)
903 {
904     if (!pluginOrigin.isEmpty() && m_plugInAutoStartOrigins.contains(pluginOrigin))
905         return true;
906
907 #if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC)
908     // The plugin wasn't in the general whitelist, so check if it similar to the primary plugin for the page (if we've found one).
909     if (webPage.matchesPrimaryPlugIn(pageOrigin, pluginOrigin, mimeType))
910         return true;
911 #else
912     UNUSED_PARAM(webPage);
913 #endif
914
915     // Lastly check against the more explicit hash list.
916     return isPlugInAutoStartOriginHash(hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType));
917 }
918
919 void WebProcess::plugInDidStartFromOrigin(const String& pageOrigin, const String& pluginOrigin, const String& mimeType)
920 {
921     if (pageOrigin.isEmpty()) {
922         LOG(Plugins, "Not adding empty page origin");
923         return;
924     }
925
926     unsigned plugInOriginHash = hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType);
927     if (isPlugInAutoStartOriginHash(plugInOriginHash)) {
928         LOG(Plugins, "Hash %x already exists as auto-start origin (request for %s)", plugInOriginHash, pageOrigin.utf8().data());
929         return;
930     }
931
932     // We might attempt to start another plugin before the didAddPlugInAutoStartOrigin message
933     // comes back from the parent process. Temporarily add this hash to the list with a thirty
934     // second timeout. That way, even if the parent decides not to add it, we'll only be
935     // incorrect for a little while.
936     m_plugInAutoStartOriginHashes.set(plugInOriginHash, WallTime::now() + 30_s * 1000);
937
938     parentProcessConnection()->send(Messages::WebProcessProxy::AddPlugInAutoStartOriginHash(pageOrigin, plugInOriginHash), 0);
939 }
940
941 void WebProcess::didAddPlugInAutoStartOriginHash(unsigned plugInOriginHash, WallTime expirationTime)
942 {
943     // When called, some web process (which also might be this one) added the origin for auto-starting,
944     // or received user interaction.
945     // Set the bit to avoid having redundantly call into the UI process upon user interaction.
946     m_plugInAutoStartOriginHashes.set(plugInOriginHash, expirationTime);
947 }
948
949 void WebProcess::resetPlugInAutoStartOriginHashes(HashMap<unsigned, WallTime>&& hashes)
950 {
951     m_plugInAutoStartOriginHashes = WTFMove(hashes);
952 }
953
954 void WebProcess::plugInDidReceiveUserInteraction(const String& pageOrigin, const String& pluginOrigin, const String& mimeType)
955 {
956     if (pageOrigin.isEmpty())
957         return;
958
959     unsigned plugInOriginHash = hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType);
960     if (!plugInOriginHash)
961         return;
962
963     auto it = m_plugInAutoStartOriginHashes.find(plugInOriginHash);
964     if (it == m_plugInAutoStartOriginHashes.end())
965         return;
966
967     if (it->value - WallTime::now() > plugInAutoStartExpirationTimeUpdateThreshold)
968         return;
969
970     parentProcessConnection()->send(Messages::WebProcessProxy::PlugInDidReceiveUserInteraction(plugInOriginHash), 0);
971 }
972
973 void WebProcess::setPluginLoadClientPolicy(uint8_t policy, const String& host, const String& bundleIdentifier, const String& versionString)
974 {
975 #if ENABLE(NETSCAPE_PLUGIN_API) && PLATFORM(MAC)
976     WebPluginInfoProvider::singleton().setPluginLoadClientPolicy(static_cast<PluginLoadClientPolicy>(policy), host, bundleIdentifier, versionString);
977 #endif
978 }
979
980 void WebProcess::resetPluginLoadClientPolicies(const HashMap<WTF::String, HashMap<WTF::String, HashMap<WTF::String, uint8_t>>>& pluginLoadClientPolicies)
981 {
982 #if ENABLE(NETSCAPE_PLUGIN_API) && PLATFORM(MAC)
983     clearPluginClientPolicies();
984
985     for (auto& hostPair : pluginLoadClientPolicies) {
986         for (auto& bundleIdentifierPair : hostPair.value) {
987             for (auto& versionPair : bundleIdentifierPair.value)
988                 WebPluginInfoProvider::singleton().setPluginLoadClientPolicy(static_cast<PluginLoadClientPolicy>(versionPair.value), hostPair.key, bundleIdentifierPair.key, versionPair.key);
989         }
990     }
991 #endif
992 }
993
994 void WebProcess::isJITEnabled(CompletionHandler<void(bool)>&& completionHandler)
995 {
996     completionHandler(JSC::VM::canUseJIT());
997 }
998
999 void WebProcess::clearPluginClientPolicies()
1000 {
1001 #if ENABLE(NETSCAPE_PLUGIN_API) && PLATFORM(MAC)
1002     WebPluginInfoProvider::singleton().clearPluginClientPolicies();
1003 #endif
1004 }
1005
1006 void WebProcess::refreshPlugins()
1007 {
1008 #if ENABLE(NETSCAPE_PLUGIN_API)
1009     WebPluginInfoProvider::singleton().refresh(false);
1010 #endif
1011 }
1012
1013 void WebProcess::garbageCollectJavaScriptObjects()
1014 {
1015     GCController::singleton().garbageCollectNow();
1016 }
1017
1018 void WebProcess::mainThreadPing()
1019 {
1020     parentProcessConnection()->send(Messages::WebProcessProxy::DidReceiveMainThreadPing(), 0);
1021 }
1022
1023 void WebProcess::backgroundResponsivenessPing()
1024 {
1025     parentProcessConnection()->send(Messages::WebProcessProxy::DidReceiveBackgroundResponsivenessPing(), 0);
1026 }
1027
1028 void WebProcess::messagesAvailableForPort(const MessagePortIdentifier& identifier)
1029 {
1030     MessagePort::notifyMessageAvailable(identifier);
1031 }
1032
1033 #if ENABLE(GAMEPAD)
1034
1035 void WebProcess::setInitialGamepads(const Vector<WebKit::GamepadData>& gamepadDatas)
1036 {
1037     WebGamepadProvider::singleton().setInitialGamepads(gamepadDatas);
1038 }
1039
1040 void WebProcess::gamepadConnected(const GamepadData& gamepadData)
1041 {
1042     WebGamepadProvider::singleton().gamepadConnected(gamepadData);
1043 }
1044
1045 void WebProcess::gamepadDisconnected(unsigned index)
1046 {
1047     WebGamepadProvider::singleton().gamepadDisconnected(index);
1048 }
1049
1050 #endif
1051
1052 void WebProcess::setJavaScriptGarbageCollectorTimerEnabled(bool flag)
1053 {
1054     GCController::singleton().setJavaScriptGarbageCollectorTimerEnabled(flag);
1055 }
1056
1057 void WebProcess::handleInjectedBundleMessage(const String& messageName, const UserData& messageBody)
1058 {
1059     InjectedBundle* injectedBundle = WebProcess::singleton().injectedBundle();
1060     if (!injectedBundle)
1061         return;
1062
1063     injectedBundle->didReceiveMessage(messageName, transformHandlesToObjects(messageBody.object()).get());
1064 }
1065
1066 void WebProcess::setInjectedBundleParameter(const String& key, const IPC::DataReference& value)
1067 {
1068     InjectedBundle* injectedBundle = WebProcess::singleton().injectedBundle();
1069     if (!injectedBundle)
1070         return;
1071
1072     injectedBundle->setBundleParameter(key, value);
1073 }
1074
1075 void WebProcess::setInjectedBundleParameters(const IPC::DataReference& value)
1076 {
1077     InjectedBundle* injectedBundle = WebProcess::singleton().injectedBundle();
1078     if (!injectedBundle)
1079         return;
1080
1081     injectedBundle->setBundleParameters(value);
1082 }
1083
1084 static NetworkProcessConnectionInfo getNetworkProcessConnection(IPC::Connection& connection)
1085 {
1086     NetworkProcessConnectionInfo connectionInfo;
1087     if (!connection.sendSync(Messages::WebProcessProxy::GetNetworkProcessConnection(), Messages::WebProcessProxy::GetNetworkProcessConnection::Reply(connectionInfo), 0)) {
1088         // If we failed the first time, retry once. The attachment may have become invalid
1089         // before it was received by the web process if the network process crashed.
1090         if (!connection.sendSync(Messages::WebProcessProxy::GetNetworkProcessConnection(), Messages::WebProcessProxy::GetNetworkProcessConnection::Reply(connectionInfo), 0)) {
1091 #if PLATFORM(GTK) || PLATFORM(WPE)
1092             // GTK+ and WPE ports don't exit on send sync message failure.
1093             // In this particular case, the network process can be terminated by the UI process while the
1094             // Web process is still initializing, so we always want to exit instead of crashing. This can
1095             // happen when the WebView is created and then destroyed quickly.
1096             // See https://bugs.webkit.org/show_bug.cgi?id=183348.
1097             exit(0);
1098 #else
1099             CRASH();
1100 #endif
1101         }
1102     }
1103
1104     return connectionInfo;
1105 }
1106
1107 NetworkProcessConnection& WebProcess::ensureNetworkProcessConnection()
1108 {
1109     RELEASE_ASSERT(RunLoop::isMain());
1110     ASSERT(m_sessionID);
1111
1112     // If we've lost our connection to the network process (e.g. it crashed) try to re-establish it.
1113     if (!m_networkProcessConnection) {
1114         auto connectionInfo = getNetworkProcessConnection(*parentProcessConnection());
1115
1116         // Retry once if the IPC to get the connectionIdentifier succeeded but the connectionIdentifier we received
1117         // is invalid. This may indicate that the network process has crashed.
1118         if (!IPC::Connection::identifierIsValid(connectionInfo.identifier()))
1119             connectionInfo = getNetworkProcessConnection(*parentProcessConnection());
1120
1121         if (!IPC::Connection::identifierIsValid(connectionInfo.identifier()))
1122             CRASH();
1123
1124         m_networkProcessConnection = NetworkProcessConnection::create(connectionInfo.releaseIdentifier(), connectionInfo.cookieAcceptPolicy);
1125 #if HAVE(AUDIT_TOKEN)
1126         m_networkProcessConnection->setNetworkProcessAuditToken(WTFMove(connectionInfo.auditToken));
1127 #endif
1128         m_networkProcessConnection->connection().send(Messages::NetworkConnectionToWebProcess::RegisterURLSchemesAsCORSEnabled(WebCore::LegacySchemeRegistry::allURLSchemesRegisteredAsCORSEnabled()), 0);
1129
1130 #if ENABLE(SERVICE_WORKER)
1131         if (!Document::allDocuments().isEmpty())
1132             m_networkProcessConnection->serviceWorkerConnection().registerServiceWorkerClients();
1133 #endif
1134     }
1135     
1136     return *m_networkProcessConnection;
1137 }
1138
1139 void WebProcess::logDiagnosticMessageForNetworkProcessCrash()
1140 {
1141     WebCore::Page* page = nullptr;
1142
1143     if (auto* webPage = focusedWebPage())
1144         page = webPage->corePage();
1145
1146     if (!page) {
1147         for (auto& webPage : m_pageMap.values()) {
1148             if (auto* corePage = webPage->corePage()) {
1149                 page = corePage;
1150                 break;
1151             }
1152         }
1153     }
1154
1155     if (page)
1156         page->diagnosticLoggingClient().logDiagnosticMessage(WebCore::DiagnosticLoggingKeys::internalErrorKey(), WebCore::DiagnosticLoggingKeys::networkProcessCrashedKey(), WebCore::ShouldSample::No);
1157 }
1158
1159 void WebProcess::networkProcessConnectionClosed(NetworkProcessConnection* connection)
1160 {
1161     ASSERT(m_networkProcessConnection);
1162     ASSERT_UNUSED(connection, m_networkProcessConnection == connection);
1163
1164     for (auto* storageAreaMap : copyToVector(m_storageAreaMaps.values()))
1165         storageAreaMap->disconnect();
1166
1167 #if ENABLE(INDEXED_DATABASE)
1168     for (auto& page : m_pageMap.values()) {
1169         auto idbConnection = page->corePage()->optionalIDBConnection();
1170         if (!idbConnection)
1171             continue;
1172         
1173         if (auto* existingIDBConnectionToServer = connection->existingIDBConnectionToServer()) {
1174             ASSERT_UNUSED(existingIDBConnectionToServer, idbConnection == &existingIDBConnectionToServer->coreConnectionToServer());
1175             page->corePage()->clearIDBConnection();
1176         }
1177     }
1178 #endif
1179
1180 #if ENABLE(SERVICE_WORKER)
1181     if (SWContextManager::singleton().connection())
1182         SWContextManager::singleton().stopAllServiceWorkers();
1183 #endif
1184
1185     m_networkProcessConnection = nullptr;
1186
1187     logDiagnosticMessageForNetworkProcessCrash();
1188
1189     m_webLoaderStrategy.networkProcessCrashed();
1190     WebSocketStream::networkProcessCrashed();
1191     m_webSocketChannelManager.networkProcessCrashed();
1192
1193     if (m_libWebRTCNetwork)
1194         m_libWebRTCNetwork->networkProcessCrashed();
1195
1196     for (auto& page : m_pageMap.values()) {
1197         page->stopAllURLSchemeTasks();
1198 #if ENABLE(APPLE_PAY)
1199         if (auto paymentCoordinator = page->paymentCoordinator())
1200             paymentCoordinator->networkProcessConnectionClosed();
1201 #endif
1202     }
1203 }
1204
1205 WebLoaderStrategy& WebProcess::webLoaderStrategy()
1206 {
1207     return m_webLoaderStrategy;
1208 }
1209
1210 #if ENABLE(GPU_PROCESS)
1211
1212 static GPUProcessConnectionInfo getGPUProcessConnection(IPC::Connection& connection)
1213 {
1214     GPUProcessConnectionInfo connectionInfo;
1215     if (!connection.sendSync(Messages::WebProcessProxy::GetGPUProcessConnection(), Messages::WebProcessProxy::GetGPUProcessConnection::Reply(connectionInfo), 0)) {
1216         // If we failed the first time, retry once. The attachment may have become invalid
1217         // before it was received by the web process if the network process crashed.
1218         if (!connection.sendSync(Messages::WebProcessProxy::GetGPUProcessConnection(), Messages::WebProcessProxy::GetGPUProcessConnection::Reply(connectionInfo), 0))
1219             CRASH();
1220     }
1221
1222     return connectionInfo;
1223 }
1224
1225 GPUProcessConnection& WebProcess::ensureGPUProcessConnection()
1226 {
1227     RELEASE_ASSERT(RunLoop::isMain());
1228
1229     // If we've lost our connection to the GPU process (e.g. it crashed) try to re-establish it.
1230     if (!m_gpuProcessConnection) {
1231         auto connectionInfo = getGPUProcessConnection(*parentProcessConnection());
1232
1233         // Retry once if the IPC to get the connectionIdentifier succeeded but the connectionIdentifier we received
1234         // is invalid. This may indicate that the GPU process has crashed.
1235         if (!IPC::Connection::identifierIsValid(connectionInfo.identifier()))
1236             connectionInfo = getGPUProcessConnection(*parentProcessConnection());
1237
1238         if (!IPC::Connection::identifierIsValid(connectionInfo.identifier()))
1239             CRASH();
1240
1241         m_gpuProcessConnection = GPUProcessConnection::create(connectionInfo.releaseIdentifier());
1242 #if HAVE(AUDIT_TOKEN)
1243         ASSERT(connectionInfo.auditToken);
1244         m_gpuProcessConnection->setAuditToken(WTFMove(connectionInfo.auditToken));
1245 #endif
1246     }
1247     
1248     return *m_gpuProcessConnection;
1249 }
1250
1251 void WebProcess::gpuProcessConnectionClosed(GPUProcessConnection* connection)
1252 {
1253     ASSERT(m_gpuProcessConnection);
1254     ASSERT_UNUSED(connection, m_gpuProcessConnection == connection);
1255
1256     m_gpuProcessConnection = nullptr;
1257 }
1258
1259 #if PLATFORM(COCOA) && USE(LIBWEBRTC)
1260 LibWebRTCCodecs& WebProcess::libWebRTCCodecs()
1261 {
1262     if (!m_libWebRTCCodecs)
1263         m_libWebRTCCodecs = makeUnique<LibWebRTCCodecs>();
1264     return *m_libWebRTCCodecs;
1265 }
1266 #endif
1267
1268 #endif // ENABLE(GPU_PROCESS)
1269
1270 void WebProcess::setEnhancedAccessibility(bool flag)
1271 {
1272     WebCore::AXObjectCache::setEnhancedUserInterfaceAccessibility(flag);
1273 }
1274     
1275 void WebProcess::startMemorySampler(SandboxExtension::Handle&& sampleLogFileHandle, const String& sampleLogFilePath, const double interval)
1276 {
1277 #if ENABLE(MEMORY_SAMPLER)    
1278     WebMemorySampler::singleton()->start(WTFMove(sampleLogFileHandle), sampleLogFilePath, interval);
1279 #else
1280     UNUSED_PARAM(sampleLogFileHandle);
1281     UNUSED_PARAM(sampleLogFilePath);
1282     UNUSED_PARAM(interval);
1283 #endif
1284 }
1285     
1286 void WebProcess::stopMemorySampler()
1287 {
1288 #if ENABLE(MEMORY_SAMPLER)
1289     WebMemorySampler::singleton()->stop();
1290 #endif
1291 }
1292
1293 void WebProcess::setTextCheckerState(const TextCheckerState& textCheckerState)
1294 {
1295     bool continuousSpellCheckingTurnedOff = !textCheckerState.isContinuousSpellCheckingEnabled && m_textCheckerState.isContinuousSpellCheckingEnabled;
1296     bool grammarCheckingTurnedOff = !textCheckerState.isGrammarCheckingEnabled && m_textCheckerState.isGrammarCheckingEnabled;
1297
1298     m_textCheckerState = textCheckerState;
1299
1300     if (!continuousSpellCheckingTurnedOff && !grammarCheckingTurnedOff)
1301         return;
1302
1303     for (auto& page : m_pageMap.values()) {
1304         if (continuousSpellCheckingTurnedOff)
1305             page->unmarkAllMisspellings();
1306         if (grammarCheckingTurnedOff)
1307             page->unmarkAllBadGrammar();
1308     }
1309 }
1310
1311 void WebProcess::fetchWebsiteData(OptionSet<WebsiteDataType> websiteDataTypes, CompletionHandler<void(WebsiteData&&)>&& completionHandler)
1312 {
1313     WebsiteData websiteData;
1314     if (websiteDataTypes.contains(WebsiteDataType::MemoryCache)) {
1315         for (auto& origin : MemoryCache::singleton().originsWithCache(sessionID()))
1316             websiteData.entries.append(WebsiteData::Entry { origin->data(), WebsiteDataType::MemoryCache, 0 });
1317     }
1318     completionHandler(WTFMove(websiteData));
1319 }
1320
1321 void WebProcess::deleteWebsiteData(OptionSet<WebsiteDataType> websiteDataTypes, WallTime modifiedSince, CompletionHandler<void()>&& completionHandler)
1322 {
1323     UNUSED_PARAM(modifiedSince);
1324
1325     if (websiteDataTypes.contains(WebsiteDataType::MemoryCache)) {
1326         BackForwardCache::singleton().pruneToSizeNow(0, PruningReason::None);
1327         MemoryCache::singleton().evictResources(sessionID());
1328
1329         CrossOriginPreflightResultCache::singleton().clear();
1330     }
1331     completionHandler();
1332 }
1333
1334 void WebProcess::deleteWebsiteDataForOrigins(OptionSet<WebsiteDataType> websiteDataTypes, const Vector<WebCore::SecurityOriginData>& originDatas, CompletionHandler<void()>&& completionHandler)
1335 {
1336     if (websiteDataTypes.contains(WebsiteDataType::MemoryCache)) {
1337         HashSet<RefPtr<SecurityOrigin>> origins;
1338         for (auto& originData : originDatas)
1339             origins.add(originData.securityOrigin());
1340
1341         MemoryCache::singleton().removeResourcesWithOrigins(sessionID(), origins);
1342     }
1343     completionHandler();
1344 }
1345
1346 void WebProcess::setHiddenPageDOMTimerThrottlingIncreaseLimit(int milliseconds)
1347 {
1348     for (auto& page : m_pageMap.values())
1349         page->setHiddenPageDOMTimerThrottlingIncreaseLimit(Seconds::fromMilliseconds(milliseconds));
1350 }
1351
1352 #if !PLATFORM(COCOA)
1353 void WebProcess::initializeProcessName(const AuxiliaryProcessInitializationParameters&)
1354 {
1355 }
1356
1357 void WebProcess::initializeSandbox(const AuxiliaryProcessInitializationParameters&, SandboxInitializationParameters&)
1358 {
1359 }
1360
1361 void WebProcess::platformInitializeProcess(const AuxiliaryProcessInitializationParameters&)
1362 {
1363 }
1364
1365 void WebProcess::updateActivePages(const String& overrideDisplayName)
1366 {
1367 }
1368
1369 void WebProcess::getActivePagesOriginsForTesting(CompletionHandler<void(Vector<String>&&)>&& completionHandler)
1370 {
1371     completionHandler({ });
1372 }
1373
1374 void WebProcess::updateCPULimit()
1375 {
1376 }
1377
1378 void WebProcess::updateCPUMonitorState(CPUMonitorUpdateReason)
1379 {
1380 }
1381
1382 #endif
1383
1384 void WebProcess::pageActivityStateDidChange(PageIdentifier, OptionSet<WebCore::ActivityState::Flag> changed)
1385 {
1386     if (changed & WebCore::ActivityState::IsVisible)
1387         updateCPUMonitorState(CPUMonitorUpdateReason::VisibilityHasChanged);
1388 }
1389
1390 #if PLATFORM(IOS_FAMILY)
1391 void WebProcess::resetAllGeolocationPermissions()
1392 {
1393     for (auto& page : m_pageMap.values()) {
1394         if (Frame* mainFrame = page->mainFrame())
1395             mainFrame->resetAllGeolocationPermission();
1396     }
1397 }
1398 #endif
1399
1400 void WebProcess::prepareToSuspend(bool isSuspensionImminent, CompletionHandler<void()>&& completionHandler)
1401 {
1402     RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "prepareToSuspend: isSuspensionImminent: %d", isSuspensionImminent);
1403     SetForScope<bool> suspensionScope(m_isSuspending, true);
1404     m_processIsSuspended = true;
1405
1406     flushResourceLoadStatistics();
1407
1408 #if PLATFORM(COCOA)
1409     if (m_processType == ProcessType::PrewarmedWebContent) {
1410         RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "prepareToSuspend: Process is ready to suspend");
1411         return completionHandler();
1412     }
1413 #endif
1414
1415 #if ENABLE(VIDEO)
1416     suspendAllMediaBuffering();
1417     if (auto* platformMediaSessionManager = PlatformMediaSessionManager::sharedManagerIfExists())
1418         platformMediaSessionManager->processWillSuspend();
1419 #endif
1420
1421     if (!m_suppressMemoryPressureHandler)
1422         MemoryPressureHandler::singleton().releaseMemory(Critical::Yes, Synchronous::Yes);
1423
1424     freezeAllLayerTrees();
1425
1426 #if PLATFORM(COCOA)
1427     destroyRenderingResources();
1428 #endif
1429
1430 #if PLATFORM(IOS_FAMILY)
1431     SQLiteDatabase::setIsDatabaseOpeningForbidden(true);
1432     if (DatabaseTracker::isInitialized())
1433         DatabaseTracker::singleton().closeAllDatabases(CurrentQueryBehavior::Interrupt);
1434     accessibilityProcessSuspendedNotification(true);
1435     updateFreezerStatus();
1436 #endif
1437
1438     markAllLayersVolatile([this, completionHandler = WTFMove(completionHandler)](bool success) mutable {
1439         if (success)
1440             RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "markAllLayersVolatile: Successfuly marked all layers as volatile");
1441         else
1442             RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "markAllLayersVolatile: Failed to mark all layers as volatile");
1443
1444         RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "prepareToSuspend: Process is ready to suspend");
1445         completionHandler();
1446     });
1447 }
1448
1449 void WebProcess::markAllLayersVolatile(WTF::Function<void(bool)>&& completionHandler)
1450 {
1451     RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "markAllLayersVolatile:");
1452     ASSERT(!m_pageMarkingLayersAsVolatileCounter);
1453     m_countOfPagesFailingToMarkVolatile = 0;
1454
1455     m_pageMarkingLayersAsVolatileCounter = makeUnique<PageMarkingLayersAsVolatileCounter>([this, completionHandler = WTFMove(completionHandler)] (RefCounterEvent) {
1456         if (m_pageMarkingLayersAsVolatileCounter->value())
1457             return;
1458
1459         completionHandler(m_countOfPagesFailingToMarkVolatile == 0);
1460         m_pageMarkingLayersAsVolatileCounter = nullptr;
1461     });
1462     auto token = m_pageMarkingLayersAsVolatileCounter->count();
1463     for (auto& page : m_pageMap.values())
1464         page->markLayersVolatile([token, this] (bool succeeded) {
1465             if (!succeeded)
1466                 ++m_countOfPagesFailingToMarkVolatile;
1467         });
1468 }
1469
1470 void WebProcess::cancelMarkAllLayersVolatile()
1471 {
1472     if (!m_pageMarkingLayersAsVolatileCounter)
1473         return;
1474
1475     m_pageMarkingLayersAsVolatileCounter = nullptr;
1476     for (auto& page : m_pageMap.values())
1477         page->cancelMarkLayersVolatile();
1478 }
1479
1480 void WebProcess::freezeAllLayerTrees()
1481 {
1482     RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "freezeAllLayerTrees: WebProcess is freezing all layer trees");
1483     for (auto& page : m_pageMap.values())
1484         page->freezeLayerTree(WebPage::LayerTreeFreezeReason::ProcessSuspended);
1485 }
1486
1487 void WebProcess::unfreezeAllLayerTrees()
1488 {
1489     RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "unfreezeAllLayerTrees: WebProcess is unfreezing all layer trees");
1490     for (auto& page : m_pageMap.values())
1491         page->unfreezeLayerTree(WebPage::LayerTreeFreezeReason::ProcessSuspended);
1492 }
1493
1494 void WebProcess::processDidResume()
1495 {
1496     RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "processDidResume:");
1497
1498     m_processIsSuspended = false;
1499
1500 #if PLATFORM(COCOA)
1501     if (m_processType == ProcessType::PrewarmedWebContent)
1502         return;
1503 #endif
1504
1505     cancelMarkAllLayersVolatile();
1506     unfreezeAllLayerTrees();
1507     
1508 #if PLATFORM(IOS_FAMILY)
1509     SQLiteDatabase::setIsDatabaseOpeningForbidden(false);
1510     accessibilityProcessSuspendedNotification(false);
1511 #endif
1512
1513 #if ENABLE(VIDEO)
1514     if (auto* platformMediaSessionManager = PlatformMediaSessionManager::sharedManagerIfExists())
1515         platformMediaSessionManager->processDidResume();
1516     resumeAllMediaBuffering();
1517 #endif
1518 }
1519
1520 void WebProcess::sendPrewarmInformation(const URL& url)
1521 {
1522     auto registrableDomain = WebCore::RegistrableDomain { url };
1523     if (registrableDomain.isEmpty())
1524         return;
1525     parentProcessConnection()->send(Messages::WebProcessProxy::DidCollectPrewarmInformation(registrableDomain, WebCore::ProcessWarming::collectPrewarmInformation()), 0);
1526 }
1527
1528 void WebProcess::pageDidEnterWindow(PageIdentifier pageID)
1529 {
1530     m_pagesInWindows.add(pageID);
1531     m_nonVisibleProcessCleanupTimer.stop();
1532 }
1533
1534 void WebProcess::pageWillLeaveWindow(PageIdentifier pageID)
1535 {
1536     m_pagesInWindows.remove(pageID);
1537
1538     if (m_pagesInWindows.isEmpty() && !m_nonVisibleProcessCleanupTimer.isActive())
1539         m_nonVisibleProcessCleanupTimer.startOneShot(nonVisibleProcessCleanupDelay);
1540 }
1541     
1542 void WebProcess::nonVisibleProcessCleanupTimerFired()
1543 {
1544     ASSERT(m_pagesInWindows.isEmpty());
1545     if (!m_pagesInWindows.isEmpty())
1546         return;
1547
1548 #if PLATFORM(COCOA)
1549     destroyRenderingResources();
1550 #endif
1551 }
1552
1553 void WebProcess::registerStorageAreaMap(StorageAreaMap& storageAreaMap)
1554 {
1555     ASSERT(storageAreaMap.identifier());
1556     ASSERT(!m_storageAreaMaps.contains(*storageAreaMap.identifier()));
1557     m_storageAreaMaps.set(*storageAreaMap.identifier(), &storageAreaMap);
1558 }
1559
1560 void WebProcess::unregisterStorageAreaMap(StorageAreaMap& storageAreaMap)
1561 {
1562     ASSERT(storageAreaMap.identifier());
1563     ASSERT(m_storageAreaMaps.contains(*storageAreaMap.identifier()));
1564     ASSERT(m_storageAreaMaps.get(*storageAreaMap.identifier()) == &storageAreaMap);
1565     m_storageAreaMaps.remove(*storageAreaMap.identifier());
1566 }
1567
1568 StorageAreaMap* WebProcess::storageAreaMap(StorageAreaIdentifier identifier) const
1569 {
1570     return m_storageAreaMaps.get(identifier);
1571 }
1572
1573 void WebProcess::setResourceLoadStatisticsEnabled(bool enabled)
1574 {
1575     if (WebCore::DeprecatedGlobalSettings::resourceLoadStatisticsEnabled() == enabled)
1576         return;
1577     WebCore::DeprecatedGlobalSettings::setResourceLoadStatisticsEnabled(enabled);
1578 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1579     if (enabled && !ResourceLoadObserver::sharedIfExists())
1580         WebCore::ResourceLoadObserver::setShared(*new WebResourceLoadObserver(m_sessionID && m_sessionID->isEphemeral() ? WebCore::ResourceLoadStatistics::IsEphemeral::Yes : WebCore::ResourceLoadStatistics::IsEphemeral::No));
1581 #endif
1582 }
1583
1584 void WebProcess::clearResourceLoadStatistics()
1585 {
1586 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1587     if (auto* observer = ResourceLoadObserver::sharedIfExists())
1588         observer->clearState();
1589 #endif
1590 }
1591
1592 void WebProcess::flushResourceLoadStatistics()
1593 {
1594 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1595     if (auto* observer = ResourceLoadObserver::sharedIfExists())
1596         observer->updateCentralStatisticsStore();
1597 #endif
1598 }
1599
1600 void WebProcess::seedResourceLoadStatisticsForTesting(const RegistrableDomain& firstPartyDomain, const RegistrableDomain& thirdPartyDomain, bool shouldScheduleNotification, CompletionHandler<void()>&& completionHandler)
1601 {
1602 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1603     if (auto* observer = ResourceLoadObserver::sharedIfExists())
1604         observer->logSubresourceLoadingForTesting(firstPartyDomain, thirdPartyDomain, shouldScheduleNotification);
1605 #endif
1606     completionHandler();
1607 }
1608
1609 RefPtr<API::Object> WebProcess::transformHandlesToObjects(API::Object* object)
1610 {
1611     struct Transformer final : UserData::Transformer {
1612         Transformer(WebProcess& webProcess)
1613             : m_webProcess(webProcess)
1614         {
1615         }
1616
1617         bool shouldTransformObject(const API::Object& object) const override
1618         {
1619             switch (object.type()) {
1620             case API::Object::Type::FrameHandle:
1621                 return static_cast<const API::FrameHandle&>(object).isAutoconverting();
1622
1623             case API::Object::Type::PageHandle:
1624                 return static_cast<const API::PageHandle&>(object).isAutoconverting();
1625
1626             case API::Object::Type::PageGroupHandle:
1627 #if PLATFORM(COCOA)
1628             case API::Object::Type::ObjCObjectGraph:
1629 #endif
1630                 return true;
1631
1632             default:
1633                 return false;
1634             }
1635         }
1636
1637         RefPtr<API::Object> transformObject(API::Object& object) const override
1638         {
1639             switch (object.type()) {
1640             case API::Object::Type::FrameHandle:
1641                 return m_webProcess.webFrame(static_cast<const API::FrameHandle&>(object).frameID());
1642
1643             case API::Object::Type::PageGroupHandle:
1644                 return m_webProcess.webPageGroup(static_cast<const API::PageGroupHandle&>(object).webPageGroupData());
1645
1646             case API::Object::Type::PageHandle:
1647                 return m_webProcess.webPage(static_cast<const API::PageHandle&>(object).webPageID());
1648
1649 #if PLATFORM(COCOA)
1650             case API::Object::Type::ObjCObjectGraph:
1651                 return m_webProcess.transformHandlesToObjects(static_cast<ObjCObjectGraph&>(object));
1652 #endif
1653             default:
1654                 return &object;
1655             }
1656         }
1657
1658         WebProcess& m_webProcess;
1659     };
1660
1661     return UserData::transform(object, Transformer(*this));
1662 }
1663
1664 RefPtr<API::Object> WebProcess::transformObjectsToHandles(API::Object* object)
1665 {
1666     struct Transformer final : UserData::Transformer {
1667         bool shouldTransformObject(const API::Object& object) const override
1668         {
1669             switch (object.type()) {
1670             case API::Object::Type::BundleFrame:
1671             case API::Object::Type::BundlePage:
1672             case API::Object::Type::BundlePageGroup:
1673 #if PLATFORM(COCOA)
1674             case API::Object::Type::ObjCObjectGraph:
1675 #endif
1676                 return true;
1677
1678             default:
1679                 return false;
1680             }
1681         }
1682
1683         RefPtr<API::Object> transformObject(API::Object& object) const override
1684         {
1685             switch (object.type()) {
1686             case API::Object::Type::BundleFrame:
1687                 return API::FrameHandle::createAutoconverting(static_cast<const WebFrame&>(object).frameID());
1688
1689             case API::Object::Type::BundlePage:
1690                 return API::PageHandle::createAutoconverting(static_cast<const WebPage&>(object).webPageProxyIdentifier(), static_cast<const WebPage&>(object).identifier());
1691
1692             case API::Object::Type::BundlePageGroup: {
1693                 WebPageGroupData pageGroupData;
1694                 pageGroupData.pageGroupID = static_cast<const WebPageGroupProxy&>(object).pageGroupID();
1695
1696                 return API::PageGroupHandle::create(WTFMove(pageGroupData));
1697             }
1698
1699 #if PLATFORM(COCOA)
1700             case API::Object::Type::ObjCObjectGraph:
1701                 return transformObjectsToHandles(static_cast<ObjCObjectGraph&>(object));
1702 #endif
1703
1704             default:
1705                 return &object;
1706             }
1707         }
1708     };
1709
1710     return UserData::transform(object, Transformer());
1711 }
1712
1713 void WebProcess::setMemoryCacheDisabled(bool disabled)
1714 {
1715     auto& memoryCache = MemoryCache::singleton();
1716     if (memoryCache.disabled() != disabled)
1717         memoryCache.setDisabled(disabled);
1718 }
1719
1720 #if ENABLE(SERVICE_CONTROLS)
1721 void WebProcess::setEnabledServices(bool hasImageServices, bool hasSelectionServices, bool hasRichContentServices)
1722 {
1723     m_hasImageServices = hasImageServices;
1724     m_hasSelectionServices = hasSelectionServices;
1725     m_hasRichContentServices = hasRichContentServices;
1726 }
1727 #endif
1728
1729 void WebProcess::ensureAutomationSessionProxy(const String& sessionIdentifier)
1730 {
1731     m_automationSessionProxy = makeUnique<WebAutomationSessionProxy>(sessionIdentifier);
1732 }
1733
1734 void WebProcess::destroyAutomationSessionProxy()
1735 {
1736     m_automationSessionProxy = nullptr;
1737 }
1738
1739 void WebProcess::prefetchDNS(const String& hostname)
1740 {
1741     if (hostname.isEmpty())
1742         return;
1743
1744     if (m_dnsPrefetchedHosts.add(hostname).isNewEntry)
1745         ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::PrefetchDNS(hostname), 0);
1746     // The DNS prefetched hosts cache is only to avoid asking for the same hosts too many times
1747     // in a very short period of time, producing a lot of IPC traffic. So we clear this cache after
1748     // some time of no DNS requests.
1749     m_dnsPrefetchHystereris.impulse();
1750 }
1751
1752 bool WebProcess::hasVisibleWebPage() const
1753 {
1754     for (auto& page : m_pageMap.values()) {
1755         if (page->isVisible())
1756             return true;
1757     }
1758     return false;
1759 }
1760
1761 void WebProcess::setBackForwardCacheCapacity(unsigned capacity)
1762 {
1763     BackForwardCache::singleton().setMaxSize(capacity);
1764 }
1765
1766 void WebProcess::clearCachedPage(BackForwardItemIdentifier backForwardItemID, CompletionHandler<void()>&& completionHandler)
1767 {
1768     HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
1769     if (!item)
1770         return completionHandler();
1771
1772     BackForwardCache::singleton().remove(*item);
1773     completionHandler();
1774 }
1775
1776 LibWebRTCNetwork& WebProcess::libWebRTCNetwork()
1777 {
1778     if (!m_libWebRTCNetwork)
1779         m_libWebRTCNetwork = makeUnique<LibWebRTCNetwork>();
1780     return *m_libWebRTCNetwork;
1781 }
1782
1783 #if ENABLE(SERVICE_WORKER)
1784 void WebProcess::establishWorkerContextConnectionToNetworkProcess(uint64_t pageGroupID, WebPageProxyIdentifier webPageProxyID, PageIdentifier pageID, const WebPreferencesStore& store, RegistrableDomain&& registrableDomain, ServiceWorkerInitializationData&& initializationData, CompletionHandler<void()>&& completionHandler)
1785 {
1786     // We are in the Service Worker context process and the call below establishes our connection to the Network Process
1787     // by calling ensureNetworkProcessConnection. SWContextManager needs to use the same underlying IPC::Connection as the
1788     // NetworkProcessConnection for synchronization purposes.
1789     auto& ipcConnection = ensureNetworkProcessConnection().connection();
1790     SWContextManager::singleton().setConnection(makeUnique<WebSWContextManagerConnection>(ipcConnection, WTFMove(registrableDomain), pageGroupID, webPageProxyID, pageID, store, WTFMove(initializationData)));
1791     SWContextManager::singleton().connection()->establishConnection(WTFMove(completionHandler));
1792 }
1793
1794 void WebProcess::addServiceWorkerRegistration(WebCore::ServiceWorkerRegistrationIdentifier identifier)
1795 {
1796     m_swRegistrationCounts.add(identifier);
1797 }
1798
1799 bool WebProcess::removeServiceWorkerRegistration(WebCore::ServiceWorkerRegistrationIdentifier identifier)
1800 {
1801     ASSERT(m_swRegistrationCounts.contains(identifier));
1802     return m_swRegistrationCounts.remove(identifier);
1803 }
1804 #endif
1805
1806 #if ENABLE(MEDIA_STREAM)
1807 void WebProcess::addMockMediaDevice(const WebCore::MockMediaDevice& device)
1808 {
1809     MockRealtimeMediaSourceCenter::addDevice(device);
1810 }
1811
1812 void WebProcess::clearMockMediaDevices()
1813 {
1814     MockRealtimeMediaSourceCenter::setDevices({ });
1815 }
1816
1817 void WebProcess::removeMockMediaDevice(const String& persistentId)
1818 {
1819     MockRealtimeMediaSourceCenter::removeDevice(persistentId);
1820 }
1821
1822 void WebProcess::resetMockMediaDevices()
1823 {
1824     MockRealtimeMediaSourceCenter::resetDevices();
1825 }
1826
1827 #if ENABLE(SANDBOX_EXTENSIONS)
1828 void WebProcess::grantUserMediaDeviceSandboxExtensions(MediaDeviceSandboxExtensions&& extensions)
1829 {
1830     for (size_t i = 0; i < extensions.size(); i++) {
1831         const auto& extension = extensions[i];
1832         extension.second->consume();
1833         RELEASE_LOG_IF_ALLOWED(WebRTC, "grantUserMediaDeviceSandboxExtensions: granted extension %s", extension.first.utf8().data());
1834         m_mediaCaptureSandboxExtensions.add(extension.first, extension.second.copyRef());
1835     }
1836 }
1837
1838 static inline void checkDocumentsCaptureStateConsistency(const Vector<String>& extensionIDs)
1839 {
1840 #if ASSERT_ENABLED
1841     bool isCapturingAudio = WTF::anyOf(Document::allDocumentsMap().values(), [](auto* document) {
1842         return document->mediaState() & MediaProducer::AudioCaptureMask;
1843     });
1844     bool isCapturingVideo = WTF::anyOf(Document::allDocumentsMap().values(), [](auto* document) {
1845         return document->mediaState() & MediaProducer::VideoCaptureMask;
1846     });
1847
1848     if (isCapturingAudio)
1849         ASSERT(extensionIDs.findMatching([](auto& id) { return id.contains("microphone"); }) == notFound);
1850     if (isCapturingVideo)
1851         ASSERT(extensionIDs.findMatching([](auto& id) { return id.contains("camera"); }) == notFound);
1852 #endif // ASSERT_ENABLED
1853 }
1854
1855 void WebProcess::revokeUserMediaDeviceSandboxExtensions(const Vector<String>& extensionIDs)
1856 {
1857     checkDocumentsCaptureStateConsistency(extensionIDs);
1858
1859     for (const auto& extensionID : extensionIDs) {
1860         auto extension = m_mediaCaptureSandboxExtensions.take(extensionID);
1861         ASSERT(extension || MockRealtimeMediaSourceCenter::mockRealtimeMediaSourceCenterEnabled());
1862         if (extension) {
1863             extension->revoke();
1864             RELEASE_LOG_IF_ALLOWED(WebRTC, "revokeUserMediaDeviceSandboxExtensions: revoked extension %s", extensionID.utf8().data());
1865         }
1866     }
1867 }
1868 #endif
1869 #endif
1870
1871 #if ENABLE(VIDEO)
1872 void WebProcess::suspendAllMediaBuffering()
1873 {
1874     for (auto& page : m_pageMap.values())
1875         page->suspendAllMediaBuffering();
1876 }
1877
1878 void WebProcess::resumeAllMediaBuffering()
1879 {
1880     for (auto& page : m_pageMap.values())
1881         page->resumeAllMediaBuffering();
1882 }
1883 #endif
1884
1885 void WebProcess::clearCurrentModifierStateForTesting()
1886 {
1887     PlatformKeyboardEvent::setCurrentModifierState({ });
1888 }
1889
1890 bool WebProcess::areAllPagesThrottleable() const
1891 {
1892     return WTF::allOf(m_pageMap.values(), [](auto& page) {
1893         return page->isThrottleable();
1894     });
1895 }
1896
1897 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1898 void WebProcess::setThirdPartyCookieBlockingMode(ThirdPartyCookieBlockingMode thirdPartyCookieBlockingMode, CompletionHandler<void()>&& completionHandler)
1899 {
1900     m_thirdPartyCookieBlockingMode = thirdPartyCookieBlockingMode;
1901     completionHandler();
1902 }
1903 #endif
1904
1905 #if ENABLE(GPU_PROCESS)
1906 void WebProcess::setUseGPUProcessForMedia(bool useGPUProcessForMedia)
1907 {
1908     if (useGPUProcessForMedia == m_useGPUProcessForMedia)
1909         return;
1910
1911     m_useGPUProcessForMedia = useGPUProcessForMedia;
1912
1913 #if ENABLE(ENCRYPTED_MEDIA)
1914     auto& cdmFactories = CDMFactory::registeredFactories();
1915     cdmFactories.clear();
1916
1917     if (useGPUProcessForMedia)
1918         ensureGPUProcessConnection().cdmFactory().registerFactory(cdmFactories);
1919     else
1920         CDMFactory::platformRegisterFactories(cdmFactories);
1921 #endif
1922
1923 #if USE(AUDIO_SESSION)
1924     if (useGPUProcessForMedia)
1925         AudioSession::setSharedSession(RemoteAudioSession::create(*this));
1926     else
1927         AudioSession::setSharedSession(AudioSession::create());
1928 #endif
1929
1930 #if PLATFORM(IOS_FAMILY)
1931     if (useGPUProcessForMedia)
1932         MediaSessionHelper::setSharedHelper(makeUniqueRef<RemoteMediaSessionHelper>(*this));
1933     else
1934         MediaSessionHelper::resetSharedHelper();
1935 #endif
1936
1937 #if ENABLE(LEGACY_ENCRYPTED_MEDIA)
1938     if (useGPUProcessForMedia)
1939         ensureGPUProcessConnection().legacyCDMFactory().registerFactory();
1940     else
1941         LegacyCDM::resetFactories();
1942 #endif
1943 }
1944 #endif
1945
1946 } // namespace WebKit
1947
1948 #undef RELEASE_LOG_SESSION_ID
1949 #undef RELEASE_LOG_IF_ALLOWED
1950 #undef RELEASE_LOG_ERROR_IF_ALLOWED