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