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