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