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