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