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