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