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