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