2822050e4ab51a284912befc4d03ab252a0efdcf
[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 "AuxiliaryProcessMessages.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 "StatisticsData.h"
45 #include "UserData.h"
46 #include "WebAutomationSessionProxy.h"
47 #include "WebCacheStorageProvider.h"
48 #include "WebConnectionToUIProcess.h"
49 #include "WebCoreArgumentCoders.h"
50 #include "WebFrame.h"
51 #include "WebFrameNetworkingContext.h"
52 #include "WebGamepadProvider.h"
53 #include "WebGeolocationManager.h"
54 #include "WebLoaderStrategy.h"
55 #include "WebMediaKeyStorageManager.h"
56 #include "WebMemorySampler.h"
57 #include "WebMessagePortChannelProvider.h"
58 #include "WebPage.h"
59 #include "WebPageGroupProxy.h"
60 #include "WebPlatformStrategies.h"
61 #include "WebPluginInfoProvider.h"
62 #include "WebProcessCreationParameters.h"
63 #include "WebProcessMessages.h"
64 #include "WebProcessPoolMessages.h"
65 #include "WebProcessProxyMessages.h"
66 #include "WebResourceLoadStatisticsStoreMessages.h"
67 #include "WebSWContextManagerConnection.h"
68 #include "WebSWContextManagerConnectionMessages.h"
69 #include "WebServiceWorkerProvider.h"
70 #include "WebSocketStream.h"
71 #include "WebsiteData.h"
72 #include "WebsiteDataStoreParameters.h"
73 #include "WebsiteDataType.h"
74 #include <JavaScriptCore/JSLock.h>
75 #include <JavaScriptCore/MemoryStatistics.h>
76 #include <JavaScriptCore/WasmFaultSignalHandler.h>
77 #include <WebCore/AXObjectCache.h>
78 #include <WebCore/ApplicationCacheStorage.h>
79 #include <WebCore/AuthenticationChallenge.h>
80 #include <WebCore/CPUMonitor.h>
81 #include <WebCore/CommonVM.h>
82 #include <WebCore/CrossOriginPreflightResultCache.h>
83 #include <WebCore/DNS.h>
84 #include <WebCore/DOMWindow.h>
85 #include <WebCore/DatabaseManager.h>
86 #include <WebCore/DatabaseTracker.h>
87 #include <WebCore/DeprecatedGlobalSettings.h>
88 #include <WebCore/DiagnosticLoggingClient.h>
89 #include <WebCore/DiagnosticLoggingKeys.h>
90 #include <WebCore/FontCache.h>
91 #include <WebCore/FontCascade.h>
92 #include <WebCore/Frame.h>
93 #include <WebCore/FrameLoader.h>
94 #include <WebCore/GCController.h>
95 #include <WebCore/GlyphPage.h>
96 #include <WebCore/HTMLMediaElement.h>
97 #include <WebCore/JSDOMWindow.h>
98 #include <WebCore/MemoryCache.h>
99 #include <WebCore/MemoryRelease.h>
100 #include <WebCore/MessagePort.h>
101 #include <WebCore/MockRealtimeMediaSourceCenter.h>
102 #include <WebCore/NetworkStorageSession.h>
103 #include <WebCore/Page.h>
104 #include <WebCore/PageCache.h>
105 #include <WebCore/PageGroup.h>
106 #include <WebCore/PlatformKeyboardEvent.h>
107 #include <WebCore/PlatformMediaSessionManager.h>
108 #include <WebCore/ProcessWarming.h>
109 #include <WebCore/ResourceLoadObserver.h>
110 #include <WebCore/ResourceLoadStatistics.h>
111 #include <WebCore/RuntimeApplicationChecks.h>
112 #include <WebCore/RuntimeEnabledFeatures.h>
113 #include <WebCore/SchemeRegistry.h>
114 #include <WebCore/SecurityOrigin.h>
115 #include <WebCore/ServiceWorkerContextData.h>
116 #include <WebCore/Settings.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/URLParser.h>
123 #include <wtf/text/StringHash.h>
124
125 #if !OS(WINDOWS)
126 #include <unistd.h>
127 #endif
128
129 #if PLATFORM(WAYLAND)
130 #include "WaylandCompositorDisplay.h"
131 #endif
132
133 #if PLATFORM(COCOA)
134 #include "ObjCObjectGraph.h"
135 #include "UserMediaCaptureManager.h"
136 #endif
137
138 #if ENABLE(SEC_ITEM_SHIM)
139 #include "SecItemShim.h"
140 #endif
141
142 #if ENABLE(NOTIFICATIONS)
143 #include "WebNotificationManager.h"
144 #endif
145
146 #if ENABLE(REMOTE_INSPECTOR)
147 #include <JavaScriptCore/RemoteInspector.h>
148 #endif
149
150 // This should be less than plugInAutoStartExpirationTimeThreshold in PlugInAutoStartProvider.
151 static const Seconds plugInAutoStartExpirationTimeUpdateThreshold { 29 * 24 * 60 * 60 };
152
153 // This should be greater than tileRevalidationTimeout in TileController.
154 static const Seconds nonVisibleProcessCleanupDelay { 10_s };
155
156 namespace WebKit {
157 using namespace JSC;
158 using namespace WebCore;
159
160 NO_RETURN static void callExit(IPC::Connection*)
161 {
162     _exit(EXIT_SUCCESS);
163 }
164
165 WebProcess& WebProcess::singleton()
166 {
167     static WebProcess& process = *new WebProcess;
168     return process;
169 }
170
171 WebProcess::WebProcess()
172     : m_eventDispatcher(EventDispatcher::create())
173 #if PLATFORM(IOS_FAMILY)
174     , m_viewUpdateDispatcher(ViewUpdateDispatcher::create())
175 #endif
176     , m_webInspectorInterruptDispatcher(WebInspectorInterruptDispatcher::create())
177     , m_webLoaderStrategy(*new WebLoaderStrategy)
178     , m_cacheStorageProvider(WebCacheStorageProvider::create())
179     , m_dnsPrefetchHystereris([this](PAL::HysteresisState state) { if (state == PAL::HysteresisState::Stopped) m_dnsPrefetchedHosts.clear(); })
180 #if ENABLE(NETSCAPE_PLUGIN_API)
181     , m_pluginProcessConnectionManager(PluginProcessConnectionManager::create())
182 #endif
183     , m_nonVisibleProcessCleanupTimer(*this, &WebProcess::nonVisibleProcessCleanupTimerFired)
184 {
185     // Initialize our platform strategies.
186     WebPlatformStrategies::initialize();
187
188     // FIXME: This should moved to where WebProcess::initialize is called,
189     // so that ports have a chance to customize, and ifdefs in this file are
190     // limited.
191     addSupplement<WebGeolocationManager>();
192
193 #if ENABLE(NOTIFICATIONS)
194     addSupplement<WebNotificationManager>();
195 #endif
196
197 #if ENABLE(LEGACY_ENCRYPTED_MEDIA)
198     addSupplement<WebMediaKeyStorageManager>();
199 #endif
200
201 #if PLATFORM(COCOA) && ENABLE(MEDIA_STREAM)
202     addSupplement<UserMediaCaptureManager>();
203 #endif
204
205     m_plugInAutoStartOriginHashes.add(PAL::SessionID::defaultSessionID(), HashMap<unsigned, WallTime>());
206
207 #if ENABLE(RESOURCE_LOAD_STATISTICS)
208     ResourceLoadObserver::shared().setNotificationCallback([this] (Vector<ResourceLoadStatistics>&& statistics) {
209         parentProcessConnection()->send(Messages::WebResourceLoadStatisticsStore::ResourceLoadStatisticsUpdated(WTFMove(statistics)), 0);
210
211         m_networkProcessConnection->connection().send(Messages::NetworkConnectionToWebProcess::RequestResourceLoadStatisticsUpdate(), 0);
212     });
213
214     ResourceLoadObserver::shared().setRequestStorageAccessUnderOpenerCallback([this] (const String& domainInNeedOfStorageAccess, uint64_t openerPageID, const String& openerDomain) {
215         parentProcessConnection()->send(Messages::WebResourceLoadStatisticsStore::RequestStorageAccessUnderOpener(domainInNeedOfStorageAccess, openerPageID, openerDomain), 0);
216     });
217 #endif
218     
219     Gigacage::disableDisablingPrimitiveGigacageIfShouldBeEnabled();
220 }
221
222 WebProcess::~WebProcess()
223 {
224 }
225
226 void WebProcess::initializeProcess(const AuxiliaryProcessInitializationParameters& parameters)
227 {
228     WTF::setProcessPrivileges({ });
229
230     MessagePortChannelProvider::setSharedProvider(WebMessagePortChannelProvider::singleton());
231     
232     platformInitializeProcess(parameters);
233 }
234
235 void WebProcess::initializeConnection(IPC::Connection* connection)
236 {
237     AuxiliaryProcess::initializeConnection(connection);
238
239     // We call _exit() directly from the background queue in case the main thread is unresponsive
240     // and AuxiliaryProcess::didClose() does not get called.
241     connection->setDidCloseOnConnectionWorkQueueCallback(callExit);
242
243 #if !PLATFORM(GTK) && !PLATFORM(WPE)
244     connection->setShouldExitOnSyncMessageSendFailure(true);
245 #endif
246
247 #if HAVE(QOS_CLASSES)
248     connection->setShouldBoostMainThreadOnSyncMessage(true);
249 #endif
250
251     m_eventDispatcher->initializeConnection(connection);
252 #if PLATFORM(IOS_FAMILY)
253     m_viewUpdateDispatcher->initializeConnection(connection);
254 #endif // PLATFORM(IOS_FAMILY)
255     m_webInspectorInterruptDispatcher->initializeConnection(connection);
256
257 #if ENABLE(NETSCAPE_PLUGIN_API)
258     m_pluginProcessConnectionManager->initializeConnection(connection);
259 #endif
260
261     for (auto& supplement : m_supplements.values())
262         supplement->initializeConnection(connection);
263
264     m_webConnection = WebConnectionToUIProcess::create(this);
265 }
266
267 void WebProcess::initializeWebProcess(WebProcessCreationParameters&& parameters)
268 {    
269     TraceScope traceScope(InitializeWebProcessStart, InitializeWebProcessEnd);
270
271     ASSERT(m_pageMap.isEmpty());
272
273     WebCore::setPresentingApplicationPID(parameters.presentingApplicationPID);
274
275 #if OS(LINUX)
276     MemoryPressureHandler::ReliefLogger::setLoggingEnabled(parameters.shouldEnableMemoryPressureReliefLogging);
277 #endif
278
279     platformInitializeWebProcess(WTFMove(parameters));
280
281     // Match the QoS of the UIProcess and the scrolling thread but use a slightly lower priority.
282     WTF::Thread::setCurrentThreadIsUserInteractive(-1);
283
284     m_suppressMemoryPressureHandler = parameters.shouldSuppressMemoryPressureHandler;
285     if (!m_suppressMemoryPressureHandler) {
286         auto& memoryPressureHandler = MemoryPressureHandler::singleton();
287         memoryPressureHandler.setLowMemoryHandler([this] (Critical critical, Synchronous synchronous) {
288             auto maintainPageCache = m_isSuspending && hasPageRequiringPageCacheWhileSuspended() ? WebCore::MaintainPageCache::Yes : WebCore::MaintainPageCache::No;
289             WebCore::releaseMemory(critical, synchronous, maintainPageCache);
290         });
291 #if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 101200) || PLATFORM(GTK) || PLATFORM(WPE)
292         memoryPressureHandler.setShouldUsePeriodicMemoryMonitor(true);
293         memoryPressureHandler.setMemoryKillCallback([this] () {
294             WebCore::logMemoryStatisticsAtTimeOfDeath();
295             if (MemoryPressureHandler::singleton().processState() == WebsamProcessState::Active)
296                 parentProcessConnection()->send(Messages::WebProcessProxy::DidExceedActiveMemoryLimit(), 0);
297             else
298                 parentProcessConnection()->send(Messages::WebProcessProxy::DidExceedInactiveMemoryLimit(), 0);
299         });
300         memoryPressureHandler.setDidExceedInactiveLimitWhileActiveCallback([this] () {
301             parentProcessConnection()->send(Messages::WebProcessProxy::DidExceedInactiveMemoryLimitWhileActive(), 0);
302         });
303 #endif
304         memoryPressureHandler.setMemoryPressureStatusChangedCallback([this](bool isUnderMemoryPressure) {
305             if (parentProcessConnection())
306                 parentProcessConnection()->send(Messages::WebProcessProxy::MemoryPressureStatusChanged(isUnderMemoryPressure), 0);
307         });
308         memoryPressureHandler.install();
309     }
310
311     for (size_t i = 0, size = parameters.additionalSandboxExtensionHandles.size(); i < size; ++i)
312         SandboxExtension::consumePermanently(parameters.additionalSandboxExtensionHandles[i]);
313
314     if (!parameters.injectedBundlePath.isEmpty())
315         m_injectedBundle = InjectedBundle::create(parameters, transformHandlesToObjects(parameters.initializationUserData.object()).get());
316
317     for (auto& supplement : m_supplements.values())
318         supplement->initialize(parameters);
319
320     auto& databaseManager = DatabaseManager::singleton();
321     databaseManager.initialize(parameters.webSQLDatabaseDirectory);
322
323     // FIXME: This should be constructed per data store, not per process.
324     m_applicationCacheStorage = ApplicationCacheStorage::create(parameters.applicationCacheDirectory, parameters.applicationCacheFlatFileSubdirectoryName);
325 #if PLATFORM(IOS_FAMILY)
326     m_applicationCacheStorage->setDefaultOriginQuota(25ULL * 1024 * 1024);
327 #endif
328
329 #if ENABLE(VIDEO)
330     if (!parameters.mediaCacheDirectory.isEmpty())
331         WebCore::HTMLMediaElement::setMediaCacheDirectory(parameters.mediaCacheDirectory);
332 #endif
333
334     setCacheModel(parameters.cacheModel);
335
336     if (!parameters.languages.isEmpty())
337         overrideUserPreferredLanguages(parameters.languages);
338
339     m_textCheckerState = parameters.textCheckerState;
340
341     m_fullKeyboardAccessEnabled = parameters.fullKeyboardAccessEnabled;
342
343     for (auto& scheme : parameters.urlSchemesRegisteredAsEmptyDocument)
344         registerURLSchemeAsEmptyDocument(scheme);
345
346     for (auto& scheme : parameters.urlSchemesRegisteredAsSecure)
347         registerURLSchemeAsSecure(scheme);
348
349     for (auto& scheme : parameters.urlSchemesRegisteredAsBypassingContentSecurityPolicy)
350         registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
351
352     for (auto& scheme : parameters.urlSchemesForWhichDomainRelaxationIsForbidden)
353         setDomainRelaxationForbiddenForURLScheme(scheme);
354
355     for (auto& scheme : parameters.urlSchemesRegisteredAsLocal)
356         registerURLSchemeAsLocal(scheme);
357
358     for (auto& scheme : parameters.urlSchemesRegisteredAsNoAccess)
359         registerURLSchemeAsNoAccess(scheme);
360
361     for (auto& scheme : parameters.urlSchemesRegisteredAsDisplayIsolated)
362         registerURLSchemeAsDisplayIsolated(scheme);
363
364     for (auto& scheme : parameters.urlSchemesRegisteredAsCORSEnabled)
365         registerURLSchemeAsCORSEnabled(scheme);
366
367     for (auto& scheme : parameters.urlSchemesRegisteredAsAlwaysRevalidated)
368         registerURLSchemeAsAlwaysRevalidated(scheme);
369
370     for (auto& scheme : parameters.urlSchemesRegisteredAsCachePartitioned)
371         registerURLSchemeAsCachePartitioned(scheme);
372
373     for (auto& scheme : parameters.urlSchemesServiceWorkersCanHandle)
374         registerURLSchemeServiceWorkersCanHandle(scheme);
375
376     for (auto& scheme : parameters.urlSchemesRegisteredAsCanDisplayOnlyIfCanRequest)
377         registerURLSchemeAsCanDisplayOnlyIfCanRequest(scheme);
378
379     setDefaultRequestTimeoutInterval(parameters.defaultRequestTimeoutInterval);
380
381     setResourceLoadStatisticsEnabled(parameters.resourceLoadStatisticsEnabled);
382
383     setAlwaysUsesComplexTextCodePath(parameters.shouldAlwaysUseComplexTextCodePath);
384
385     setShouldUseFontSmoothing(parameters.shouldUseFontSmoothing);
386
387     ensureNetworkProcessConnection();
388
389 #if ENABLE(RESOURCE_LOAD_STATISTICS)
390     ResourceLoadObserver::shared().setLogUserInteractionNotificationCallback([this] (PAL::SessionID sessionID, const String& topLevelOrigin) {
391         m_networkProcessConnection->connection().send(Messages::NetworkConnectionToWebProcess::LogUserInteraction(sessionID, topLevelOrigin), 0);
392     });
393
394     ResourceLoadObserver::shared().setLogWebSocketLoadingNotificationCallback([this] (PAL::SessionID sessionID, const String& targetPrimaryDomain, const String& mainFramePrimaryDomain, WallTime lastSeen) {
395         m_networkProcessConnection->connection().send(Messages::NetworkConnectionToWebProcess::LogWebSocketLoading(sessionID, targetPrimaryDomain, mainFramePrimaryDomain, lastSeen), 0);
396     });
397     
398     ResourceLoadObserver::shared().setLogSubresourceLoadingNotificationCallback([this] (PAL::SessionID sessionID, const String& targetPrimaryDomain, const String& mainFramePrimaryDomain, WallTime lastSeen) {
399         m_networkProcessConnection->connection().send(Messages::NetworkConnectionToWebProcess::LogSubresourceLoading(sessionID, targetPrimaryDomain, mainFramePrimaryDomain, lastSeen), 0);
400     });
401
402     ResourceLoadObserver::shared().setLogSubresourceRedirectNotificationCallback([this] (PAL::SessionID sessionID, const String& sourcePrimaryDomain, const String& targetPrimaryDomain) {
403         m_networkProcessConnection->connection().send(Messages::NetworkConnectionToWebProcess::LogSubresourceRedirect(sessionID, sourcePrimaryDomain, targetPrimaryDomain), 0);
404     });
405 #endif
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     WebCore::RuntimeEnabledFeatures::sharedFeatures().setAttrStyleEnabled(parameters.attrStyleEnabled);
416
417 #if ENABLE(SERVICE_CONTROLS)
418     setEnabledServices(parameters.hasImageServices, parameters.hasSelectionServices, parameters.hasRichContentServices);
419 #endif
420
421 #if ENABLE(REMOTE_INSPECTOR) && PLATFORM(COCOA)
422     if (Optional<audit_token_t> auditToken = parentProcessConnection()->getAuditToken()) {
423         RetainPtr<CFDataRef> auditData = adoptCF(CFDataCreate(nullptr, (const UInt8*)&*auditToken, sizeof(*auditToken)));
424         Inspector::RemoteInspector::singleton().setParentProcessInformation(WebCore::presentingApplicationPID(), auditData);
425     }
426 #endif
427
428 #if ENABLE(NETSCAPE_PLUGIN_API) && PLATFORM(MAC)
429     resetPluginLoadClientPolicies(parameters.pluginLoadClientPolicies);
430 #endif
431
432 #if ENABLE(GAMEPAD)
433     GamepadProvider::singleton().setSharedProvider(WebGamepadProvider::singleton());
434 #endif
435
436 #if ENABLE(SERVICE_WORKER)
437     ServiceWorkerProvider::setSharedProvider(WebServiceWorkerProvider::singleton());
438 #endif
439
440 #if ENABLE(WEBASSEMBLY)
441     JSC::Wasm::enableFastMemory();
442 #endif
443
444 #if ENABLE(RESOURCE_LOAD_STATISTICS) && !RELEASE_LOG_DISABLED
445     ResourceLoadObserver::shared().setShouldLogUserInteraction(parameters.shouldLogUserInteraction);
446 #endif
447
448     RELEASE_LOG(Process, "%p - WebProcess::initializeWebProcess: Presenting process = %d", this, WebCore::presentingApplicationPID());
449 }
450
451 bool WebProcess::hasPageRequiringPageCacheWhileSuspended() const
452 {
453     for (auto& page : m_pageMap.values()) {
454         if (page->isSuspended())
455             return true;
456     }
457     return false;
458 }
459
460 void WebProcess::markIsNoLongerPrewarmed()
461 {
462 #if PLATFORM(MAC)
463     ASSERT(m_processType == ProcessType::PrewarmedWebContent);
464     m_processType = ProcessType::WebContent;
465
466     updateProcessName();
467 #endif
468 }
469
470 void WebProcess::prewarmGlobally()
471 {
472     WebCore::ProcessWarming::prewarmGlobally();
473 }
474
475 void WebProcess::prewarmWithDomainInformation(const WebCore::PrewarmInformation& prewarmInformation)
476 {
477     WebCore::ProcessWarming::prewarmWithInformation(prewarmInformation);
478 }
479
480 void WebProcess::registerURLSchemeAsEmptyDocument(const String& urlScheme)
481 {
482     SchemeRegistry::registerURLSchemeAsEmptyDocument(urlScheme);
483 }
484
485 void WebProcess::registerURLSchemeAsSecure(const String& urlScheme) const
486 {
487     SchemeRegistry::registerURLSchemeAsSecure(urlScheme);
488 }
489
490 void WebProcess::registerURLSchemeAsBypassingContentSecurityPolicy(const String& urlScheme) const
491 {
492     SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(urlScheme);
493 }
494
495 void WebProcess::setDomainRelaxationForbiddenForURLScheme(const String& urlScheme) const
496 {
497     SchemeRegistry::setDomainRelaxationForbiddenForURLScheme(true, urlScheme);
498 }
499
500 void WebProcess::registerURLSchemeAsLocal(const String& urlScheme) const
501 {
502     SchemeRegistry::registerURLSchemeAsLocal(urlScheme);
503 }
504
505 void WebProcess::registerURLSchemeAsNoAccess(const String& urlScheme) const
506 {
507     SchemeRegistry::registerURLSchemeAsNoAccess(urlScheme);
508 }
509
510 void WebProcess::registerURLSchemeAsDisplayIsolated(const String& urlScheme) const
511 {
512     SchemeRegistry::registerURLSchemeAsDisplayIsolated(urlScheme);
513 }
514
515 void WebProcess::registerURLSchemeAsCORSEnabled(const String& urlScheme) const
516 {
517     SchemeRegistry::registerURLSchemeAsCORSEnabled(urlScheme);
518 }
519
520 void WebProcess::registerURLSchemeAsAlwaysRevalidated(const String& urlScheme) const
521 {
522     SchemeRegistry::registerURLSchemeAsAlwaysRevalidated(urlScheme);
523 }
524
525 void WebProcess::registerURLSchemeAsCachePartitioned(const String& urlScheme) const
526 {
527     SchemeRegistry::registerURLSchemeAsCachePartitioned(urlScheme);
528 }
529
530 void WebProcess::registerURLSchemeAsCanDisplayOnlyIfCanRequest(const String& urlScheme) const
531 {
532     SchemeRegistry::registerAsCanDisplayOnlyIfCanRequest(urlScheme);
533 }
534
535 void WebProcess::setDefaultRequestTimeoutInterval(double timeoutInterval)
536 {
537     ResourceRequest::setDefaultTimeoutInterval(timeoutInterval);
538 }
539
540 void WebProcess::setAlwaysUsesComplexTextCodePath(bool alwaysUseComplexText)
541 {
542     WebCore::FontCascade::setCodePath(alwaysUseComplexText ? WebCore::FontCascade::Complex : WebCore::FontCascade::Auto);
543 }
544
545 void WebProcess::setShouldUseFontSmoothing(bool useFontSmoothing)
546 {
547     WebCore::FontCascade::setShouldUseSmoothing(useFontSmoothing);
548 }
549
550 void WebProcess::userPreferredLanguagesChanged(const Vector<String>& languages) const
551 {
552     overrideUserPreferredLanguages(languages);
553 }
554
555 void WebProcess::fullKeyboardAccessModeChanged(bool fullKeyboardAccessEnabled)
556 {
557     m_fullKeyboardAccessEnabled = fullKeyboardAccessEnabled;
558 }
559
560 void WebProcess::ensureLegacyPrivateBrowsingSessionInNetworkProcess()
561 {
562     ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::EnsureLegacyPrivateBrowsingSession(), 0);
563 }
564
565 #if ENABLE(NETSCAPE_PLUGIN_API)
566 PluginProcessConnectionManager& WebProcess::pluginProcessConnectionManager()
567 {
568     return *m_pluginProcessConnectionManager;
569 }
570 #endif
571
572 void WebProcess::setCacheModel(CacheModel cacheModel)
573 {
574     if (m_hasSetCacheModel && (cacheModel == m_cacheModel))
575         return;
576
577     m_hasSetCacheModel = true;
578     m_cacheModel = cacheModel;
579
580     unsigned cacheTotalCapacity = 0;
581     unsigned cacheMinDeadCapacity = 0;
582     unsigned cacheMaxDeadCapacity = 0;
583     Seconds deadDecodedDataDeletionInterval;
584     unsigned pageCacheSize = 0;
585     calculateMemoryCacheSizes(cacheModel, cacheTotalCapacity, cacheMinDeadCapacity, cacheMaxDeadCapacity, deadDecodedDataDeletionInterval, pageCacheSize);
586
587     auto& memoryCache = MemoryCache::singleton();
588     memoryCache.setCapacities(cacheMinDeadCapacity, cacheMaxDeadCapacity, cacheTotalCapacity);
589     memoryCache.setDeadDecodedDataDeletionInterval(deadDecodedDataDeletionInterval);
590     PageCache::singleton().setMaxSize(pageCacheSize);
591
592     platformSetCacheModel(cacheModel);
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     AuxiliaryProcess::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::AuxiliaryProcess::messageReceiverName()) {
686         AuxiliaryProcess::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(CacheModel::DocumentViewer);
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
1301 void WebProcess::deleteWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, WallTime modifiedSince)
1302 {
1303     UNUSED_PARAM(modifiedSince);
1304
1305     if (websiteDataTypes.contains(WebsiteDataType::MemoryCache)) {
1306         PageCache::singleton().pruneToSizeNow(0, PruningReason::None);
1307         MemoryCache::singleton().evictResources(sessionID);
1308
1309         CrossOriginPreflightResultCache::singleton().clear();
1310     }
1311 }
1312
1313 void WebProcess::deleteWebsiteDataForOrigins(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, const Vector<WebCore::SecurityOriginData>& originDatas)
1314 {
1315     if (websiteDataTypes.contains(WebsiteDataType::MemoryCache)) {
1316         HashSet<RefPtr<SecurityOrigin>> origins;
1317         for (auto& originData : originDatas)
1318             origins.add(originData.securityOrigin());
1319
1320         MemoryCache::singleton().removeResourcesWithOrigins(sessionID, origins);
1321     }
1322 }
1323
1324 void WebProcess::setHiddenPageDOMTimerThrottlingIncreaseLimit(int milliseconds)
1325 {
1326     for (auto& page : m_pageMap.values())
1327         page->setHiddenPageDOMTimerThrottlingIncreaseLimit(Seconds::fromMilliseconds(milliseconds));
1328 }
1329
1330 #if !PLATFORM(COCOA)
1331 void WebProcess::initializeProcessName(const AuxiliaryProcessInitializationParameters&)
1332 {
1333 }
1334
1335 void WebProcess::initializeSandbox(const AuxiliaryProcessInitializationParameters&, SandboxInitializationParameters&)
1336 {
1337 }
1338
1339 void WebProcess::platformInitializeProcess(const AuxiliaryProcessInitializationParameters&)
1340 {
1341 }
1342
1343 void WebProcess::updateActivePages()
1344 {
1345 }
1346
1347 void WebProcess::getActivePagesOriginsForTesting(CompletionHandler<void(Vector<String>&&)>&& completionHandler)
1348 {
1349     completionHandler({ });
1350 }
1351
1352 void WebProcess::updateCPULimit()
1353 {
1354 }
1355
1356 void WebProcess::updateCPUMonitorState(CPUMonitorUpdateReason)
1357 {
1358 }
1359
1360 #endif
1361
1362 void WebProcess::pageActivityStateDidChange(uint64_t, OptionSet<WebCore::ActivityState::Flag> changed)
1363 {
1364     if (changed & WebCore::ActivityState::IsVisible)
1365         updateCPUMonitorState(CPUMonitorUpdateReason::VisibilityHasChanged);
1366 }
1367
1368 #if PLATFORM(IOS_FAMILY)
1369 void WebProcess::resetAllGeolocationPermissions()
1370 {
1371     for (auto& page : m_pageMap.values()) {
1372         if (Frame* mainFrame = page->mainFrame())
1373             mainFrame->resetAllGeolocationPermission();
1374     }
1375 }
1376 #endif
1377
1378 void WebProcess::actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend shouldAcknowledgeWhenReadyToSuspend)
1379 {
1380     SetForScope<bool> suspensionScope(m_isSuspending, true);
1381
1382     if (!m_suppressMemoryPressureHandler)
1383         MemoryPressureHandler::singleton().releaseMemory(Critical::Yes, Synchronous::Yes);
1384
1385     freezeAllLayerTrees();
1386     
1387 #if PLATFORM(COCOA)
1388     destroyRenderingResources();
1389 #endif
1390
1391 #if PLATFORM(IOS_FAMILY)
1392     accessibilityProcessSuspendedNotification(true);
1393 #endif
1394
1395     markAllLayersVolatile([this, shouldAcknowledgeWhenReadyToSuspend](bool success) {
1396         if (success)
1397             RELEASE_LOG(ProcessSuspension, "%p - WebProcess::markAllLayersVolatile() Successfuly marked all layers as volatile", this);
1398         else
1399             RELEASE_LOG(ProcessSuspension, "%p - WebProcess::markAllLayersVolatile() Failed to mark all layers as volatile", this);
1400
1401         if (shouldAcknowledgeWhenReadyToSuspend == ShouldAcknowledgeWhenReadyToSuspend::Yes) {
1402             RELEASE_LOG(ProcessSuspension, "%p - WebProcess::actualPrepareToSuspend() Sending ProcessReadyToSuspend IPC message", this);
1403             parentProcessConnection()->send(Messages::WebProcessProxy::ProcessReadyToSuspend(), 0);
1404         }
1405     });
1406 }
1407
1408 void WebProcess::processWillSuspendImminently(bool& handled)
1409 {
1410     if (parentProcessConnection()->inSendSync()) {
1411         // Avoid reentrency bugs such as rdar://problem/21605505 by just bailing
1412         // if we get an incoming ProcessWillSuspendImminently message when waiting for a
1413         // reply to a sync message.
1414         // FIXME: ProcessWillSuspendImminently should not be a sync message.
1415         return;
1416     }
1417
1418     RELEASE_LOG(ProcessSuspension, "%p - WebProcess::processWillSuspendImminently()", this);
1419     DatabaseTracker::singleton().closeAllDatabases(CurrentQueryBehavior::Interrupt);
1420     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::No);
1421     handled = true;
1422 }
1423
1424 void WebProcess::prepareToSuspend()
1425 {
1426     RELEASE_LOG(ProcessSuspension, "%p - WebProcess::prepareToSuspend()", this);
1427     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::Yes);
1428 }
1429
1430 void WebProcess::cancelPrepareToSuspend()
1431 {
1432     RELEASE_LOG(ProcessSuspension, "%p - WebProcess::cancelPrepareToSuspend()", this);
1433     unfreezeAllLayerTrees();
1434
1435 #if PLATFORM(IOS_FAMILY)
1436     accessibilityProcessSuspendedNotification(false);
1437 #endif
1438     
1439     // If we've already finished cleaning up and sent ProcessReadyToSuspend, we
1440     // shouldn't send DidCancelProcessSuspension; the UI process strictly expects one or the other.
1441     if (!m_pageMarkingLayersAsVolatileCounter)
1442         return;
1443
1444     cancelMarkAllLayersVolatile();
1445
1446     RELEASE_LOG(ProcessSuspension, "%p - WebProcess::cancelPrepareToSuspend() Sending DidCancelProcessSuspension IPC message", this);
1447     parentProcessConnection()->send(Messages::WebProcessProxy::DidCancelProcessSuspension(), 0);
1448 }
1449
1450 void WebProcess::markAllLayersVolatile(WTF::Function<void(bool)>&& completionHandler)
1451 {
1452     RELEASE_LOG(ProcessSuspension, "%p - WebProcess::markAllLayersVolatile()", this);
1453     ASSERT(!m_pageMarkingLayersAsVolatileCounter);
1454     m_countOfPagesFailingToMarkVolatile = 0;
1455
1456     m_pageMarkingLayersAsVolatileCounter = std::make_unique<PageMarkingLayersAsVolatileCounter>([this, completionHandler = WTFMove(completionHandler)] (RefCounterEvent) {
1457         if (m_pageMarkingLayersAsVolatileCounter->value())
1458             return;
1459
1460         completionHandler(m_countOfPagesFailingToMarkVolatile == 0);
1461         m_pageMarkingLayersAsVolatileCounter = nullptr;
1462     });
1463     auto token = m_pageMarkingLayersAsVolatileCounter->count();
1464     for (auto& page : m_pageMap.values())
1465         page->markLayersVolatile([token, this] (bool succeeded) {
1466             if (!succeeded)
1467                 ++m_countOfPagesFailingToMarkVolatile;
1468         });
1469 }
1470
1471 void WebProcess::cancelMarkAllLayersVolatile()
1472 {
1473     if (!m_pageMarkingLayersAsVolatileCounter)
1474         return;
1475
1476     m_pageMarkingLayersAsVolatileCounter = nullptr;
1477     for (auto& page : m_pageMap.values())
1478         page->cancelMarkLayersVolatile();
1479 }
1480
1481 void WebProcess::freezeAllLayerTrees()
1482 {
1483     for (auto& page : m_pageMap.values())
1484         page->freezeLayerTree(WebPage::LayerTreeFreezeReason::ProcessSuspended);
1485 }
1486
1487 void WebProcess::unfreezeAllLayerTrees()
1488 {
1489     for (auto& page : m_pageMap.values())
1490         page->unfreezeLayerTree(WebPage::LayerTreeFreezeReason::ProcessSuspended);
1491 }
1492
1493 void WebProcess::processDidResume()
1494 {
1495     RELEASE_LOG(ProcessSuspension, "%p - WebProcess::processDidResume()", this);
1496
1497     cancelMarkAllLayersVolatile();
1498     unfreezeAllLayerTrees();
1499     
1500 #if PLATFORM(IOS_FAMILY)
1501     accessibilityProcessSuspendedNotification(false);
1502 #endif
1503 }
1504
1505 void WebProcess::sendPrewarmInformation(const URL& url)
1506 {
1507     auto registrableDomain = toRegistrableDomain(url);
1508     if (registrableDomain.isEmpty())
1509         return;
1510     parentProcessConnection()->send(Messages::WebProcessProxy::DidCollectPrewarmInformation(registrableDomain, WebCore::ProcessWarming::collectPrewarmInformation()), 0);
1511 }
1512
1513 void WebProcess::pageDidEnterWindow(uint64_t pageID)
1514 {
1515     m_pagesInWindows.add(pageID);
1516     m_nonVisibleProcessCleanupTimer.stop();
1517 }
1518
1519 void WebProcess::pageWillLeaveWindow(uint64_t pageID)
1520 {
1521     m_pagesInWindows.remove(pageID);
1522
1523     if (m_pagesInWindows.isEmpty() && !m_nonVisibleProcessCleanupTimer.isActive())
1524         m_nonVisibleProcessCleanupTimer.startOneShot(nonVisibleProcessCleanupDelay);
1525 }
1526     
1527 void WebProcess::nonVisibleProcessCleanupTimerFired()
1528 {
1529     ASSERT(m_pagesInWindows.isEmpty());
1530     if (!m_pagesInWindows.isEmpty())
1531         return;
1532
1533 #if PLATFORM(COCOA)
1534     destroyRenderingResources();
1535 #endif
1536 }
1537
1538 void WebProcess::setResourceLoadStatisticsEnabled(bool enabled)
1539 {
1540     WebCore::DeprecatedGlobalSettings::setResourceLoadStatisticsEnabled(enabled);
1541 }
1542
1543 void WebProcess::clearResourceLoadStatistics()
1544 {
1545     ResourceLoadObserver::shared().clearState();
1546 }
1547
1548 RefPtr<API::Object> WebProcess::transformHandlesToObjects(API::Object* object)
1549 {
1550     struct Transformer final : UserData::Transformer {
1551         Transformer(WebProcess& webProcess)
1552             : m_webProcess(webProcess)
1553         {
1554         }
1555
1556         bool shouldTransformObject(const API::Object& object) const override
1557         {
1558             switch (object.type()) {
1559             case API::Object::Type::FrameHandle:
1560                 return static_cast<const API::FrameHandle&>(object).isAutoconverting();
1561
1562             case API::Object::Type::PageHandle:
1563                 return static_cast<const API::PageHandle&>(object).isAutoconverting();
1564
1565             case API::Object::Type::PageGroupHandle:
1566 #if PLATFORM(COCOA)
1567             case API::Object::Type::ObjCObjectGraph:
1568 #endif
1569                 return true;
1570
1571             default:
1572                 return false;
1573             }
1574         }
1575
1576         RefPtr<API::Object> transformObject(API::Object& object) const override
1577         {
1578             switch (object.type()) {
1579             case API::Object::Type::FrameHandle:
1580                 return m_webProcess.webFrame(static_cast<const API::FrameHandle&>(object).frameID());
1581
1582             case API::Object::Type::PageGroupHandle:
1583                 return m_webProcess.webPageGroup(static_cast<const API::PageGroupHandle&>(object).webPageGroupData());
1584
1585             case API::Object::Type::PageHandle:
1586                 return m_webProcess.webPage(static_cast<const API::PageHandle&>(object).pageID());
1587
1588 #if PLATFORM(COCOA)
1589             case API::Object::Type::ObjCObjectGraph:
1590                 return m_webProcess.transformHandlesToObjects(static_cast<ObjCObjectGraph&>(object));
1591 #endif
1592             default:
1593                 return &object;
1594             }
1595         }
1596
1597         WebProcess& m_webProcess;
1598     };
1599
1600     return UserData::transform(object, Transformer(*this));
1601 }
1602
1603 RefPtr<API::Object> WebProcess::transformObjectsToHandles(API::Object* object)
1604 {
1605     struct Transformer final : UserData::Transformer {
1606         bool shouldTransformObject(const API::Object& object) const override
1607         {
1608             switch (object.type()) {
1609             case API::Object::Type::BundleFrame:
1610             case API::Object::Type::BundlePage:
1611             case API::Object::Type::BundlePageGroup:
1612 #if PLATFORM(COCOA)
1613             case API::Object::Type::ObjCObjectGraph:
1614 #endif
1615                 return true;
1616
1617             default:
1618                 return false;
1619             }
1620         }
1621
1622         RefPtr<API::Object> transformObject(API::Object& object) const override
1623         {
1624             switch (object.type()) {
1625             case API::Object::Type::BundleFrame:
1626                 return API::FrameHandle::createAutoconverting(static_cast<const WebFrame&>(object).frameID());
1627
1628             case API::Object::Type::BundlePage:
1629                 return API::PageHandle::createAutoconverting(static_cast<const WebPage&>(object).pageID());
1630
1631             case API::Object::Type::BundlePageGroup: {
1632                 WebPageGroupData pageGroupData;
1633                 pageGroupData.pageGroupID = static_cast<const WebPageGroupProxy&>(object).pageGroupID();
1634
1635                 return API::PageGroupHandle::create(WTFMove(pageGroupData));
1636             }
1637
1638 #if PLATFORM(COCOA)
1639             case API::Object::Type::ObjCObjectGraph:
1640                 return transformObjectsToHandles(static_cast<ObjCObjectGraph&>(object));
1641 #endif
1642
1643             default:
1644                 return &object;
1645             }
1646         }
1647     };
1648
1649     return UserData::transform(object, Transformer());
1650 }
1651
1652 void WebProcess::setMemoryCacheDisabled(bool disabled)
1653 {
1654     auto& memoryCache = MemoryCache::singleton();
1655     if (memoryCache.disabled() != disabled)
1656         memoryCache.setDisabled(disabled);
1657 }
1658
1659 #if ENABLE(SERVICE_CONTROLS)
1660 void WebProcess::setEnabledServices(bool hasImageServices, bool hasSelectionServices, bool hasRichContentServices)
1661 {
1662     m_hasImageServices = hasImageServices;
1663     m_hasSelectionServices = hasSelectionServices;
1664     m_hasRichContentServices = hasRichContentServices;
1665 }
1666 #endif
1667
1668 void WebProcess::ensureAutomationSessionProxy(const String& sessionIdentifier)
1669 {
1670     m_automationSessionProxy = std::make_unique<WebAutomationSessionProxy>(sessionIdentifier);
1671 }
1672
1673 void WebProcess::destroyAutomationSessionProxy()
1674 {
1675     m_automationSessionProxy = nullptr;
1676 }
1677
1678 void WebProcess::prefetchDNS(const String& hostname)
1679 {
1680     if (hostname.isEmpty())
1681         return;
1682
1683     if (m_dnsPrefetchedHosts.add(hostname).isNewEntry)
1684         ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::PrefetchDNS(hostname), 0);
1685     // The DNS prefetched hosts cache is only to avoid asking for the same hosts too many times
1686     // in a very short period of time, producing a lot of IPC traffic. So we clear this cache after
1687     // some time of no DNS requests.
1688     m_dnsPrefetchHystereris.impulse();
1689 }
1690
1691 bool WebProcess::hasVisibleWebPage() const
1692 {
1693     for (auto& page : m_pageMap.values()) {
1694         if (page->isVisible())
1695             return true;
1696     }
1697     return false;
1698 }
1699
1700 LibWebRTCNetwork& WebProcess::libWebRTCNetwork()
1701 {
1702     if (!m_libWebRTCNetwork)
1703         m_libWebRTCNetwork = std::make_unique<LibWebRTCNetwork>();
1704     return *m_libWebRTCNetwork;
1705 }
1706
1707 #if ENABLE(SERVICE_WORKER)
1708 void WebProcess::establishWorkerContextConnectionToNetworkProcess(uint64_t pageGroupID, uint64_t pageID, const WebPreferencesStore& store, PAL::SessionID initialSessionID)
1709 {
1710     // We are in the Service Worker context process and the call below establishes our connection to the Network Process
1711     // by calling ensureNetworkProcessConnection. SWContextManager needs to use the same underlying IPC::Connection as the
1712     // NetworkProcessConnection for synchronization purposes.
1713     auto& ipcConnection = ensureNetworkProcessConnection().connection();
1714     SWContextManager::singleton().setConnection(std::make_unique<WebSWContextManagerConnection>(ipcConnection, pageGroupID, pageID, store));
1715 }
1716
1717 void WebProcess::registerServiceWorkerClients()
1718 {
1719     // We do not want to register service worker dummy documents.
1720     ASSERT(!SWContextManager::singleton().connection());
1721     ServiceWorkerProvider::singleton().registerServiceWorkerClients();
1722 }
1723
1724 #endif
1725
1726 #if PLATFORM(MAC)
1727 void WebProcess::setScreenProperties(const WebCore::ScreenProperties& properties)
1728 {
1729     WebCore::setScreenProperties(properties);
1730 }
1731 #endif
1732
1733 #if ENABLE(MEDIA_STREAM)
1734 void WebProcess::addMockMediaDevice(const WebCore::MockMediaDevice& device)
1735 {
1736     MockRealtimeMediaSourceCenter::addDevice(device);
1737 }
1738
1739 void WebProcess::clearMockMediaDevices()
1740 {
1741     MockRealtimeMediaSourceCenter::setDevices({ });
1742 }
1743
1744 void WebProcess::removeMockMediaDevice(const String& persistentId)
1745 {
1746     MockRealtimeMediaSourceCenter::removeDevice(persistentId);
1747 }
1748
1749 void WebProcess::resetMockMediaDevices()
1750 {
1751     MockRealtimeMediaSourceCenter::resetDevices();
1752 }
1753 #endif
1754
1755 void WebProcess::clearCurrentModifierStateForTesting()
1756 {
1757     PlatformKeyboardEvent::setCurrentModifierState({ });
1758 }
1759
1760 } // namespace WebKit