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