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