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