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