Unreviewed, rolling out r240446.
[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 WebPage* WebProcess::focusedWebPage() const
582 {    
583     for (auto& page : m_pageMap.values()) {
584         if (page->windowAndWebPageAreFocused())
585             return page.get();
586     }
587     return 0;
588 }
589     
590 WebPage* WebProcess::webPage(uint64_t pageID) const
591 {
592     return m_pageMap.get(pageID);
593 }
594
595 void WebProcess::createWebPage(uint64_t pageID, WebPageCreationParameters&& parameters)
596 {
597     // It is necessary to check for page existence here since during a window.open() (or targeted
598     // link) the WebPage gets created both in the synchronous handler and through the normal way. 
599     HashMap<uint64_t, RefPtr<WebPage>>::AddResult result = m_pageMap.add(pageID, nullptr);
600     if (result.isNewEntry) {
601         ASSERT(!result.iterator->value);
602         result.iterator->value = WebPage::create(pageID, WTFMove(parameters));
603
604         // Balanced by an enableTermination in removeWebPage.
605         disableTermination();
606         updateCPULimit();
607     } else
608         result.iterator->value->reinitializeWebPage(WTFMove(parameters));
609
610     ASSERT(result.iterator->value);
611 }
612
613 void WebProcess::removeWebPage(uint64_t pageID)
614 {
615     ASSERT(m_pageMap.contains(pageID));
616
617     pageWillLeaveWindow(pageID);
618     m_pageMap.remove(pageID);
619
620     enableTermination();
621     updateCPULimit();
622 }
623
624 bool WebProcess::shouldTerminate()
625 {
626     ASSERT(m_pageMap.isEmpty());
627
628     // FIXME: the ShouldTerminate message should also send termination parameters, such as any session cookies that need to be preserved.
629     bool shouldTerminate = false;
630     if (parentProcessConnection()->sendSync(Messages::WebProcessProxy::ShouldTerminate(), Messages::WebProcessProxy::ShouldTerminate::Reply(shouldTerminate), 0)
631         && !shouldTerminate)
632         return false;
633
634     return true;
635 }
636
637 void WebProcess::terminate()
638 {
639 #ifndef NDEBUG
640     GCController::singleton().garbageCollectNow();
641     FontCache::singleton().invalidate();
642     MemoryCache::singleton().setDisabled(true);
643 #endif
644
645     m_webConnection->invalidate();
646     m_webConnection = nullptr;
647
648     platformTerminate();
649
650     ChildProcess::terminate();
651 }
652
653 void WebProcess::didReceiveSyncMessage(IPC::Connection& connection, IPC::Decoder& decoder, std::unique_ptr<IPC::Encoder>& replyEncoder)
654 {
655     if (messageReceiverMap().dispatchSyncMessage(connection, decoder, replyEncoder))
656         return;
657
658     didReceiveSyncWebProcessMessage(connection, decoder, replyEncoder);
659 }
660
661 void WebProcess::didReceiveMessage(IPC::Connection& connection, IPC::Decoder& decoder)
662 {
663     if (messageReceiverMap().dispatchMessage(connection, decoder))
664         return;
665
666     if (decoder.messageReceiverName() == Messages::WebProcess::messageReceiverName()) {
667         didReceiveWebProcessMessage(connection, decoder);
668         return;
669     }
670
671     if (decoder.messageReceiverName() == Messages::ChildProcess::messageReceiverName()) {
672         ChildProcess::didReceiveMessage(connection, decoder);
673         return;
674     }
675
676 #if ENABLE(SERVICE_WORKER)
677     // FIXME: Remove?
678     if (decoder.messageReceiverName() == Messages::WebSWContextManagerConnection::messageReceiverName()) {
679         ASSERT(SWContextManager::singleton().connection());
680         if (auto* contextManagerConnection = SWContextManager::singleton().connection())
681             static_cast<WebSWContextManagerConnection&>(*contextManagerConnection).didReceiveMessage(connection, decoder);
682         return;
683     }
684 #endif
685
686     LOG_ERROR("Unhandled web process message '%s:%s'", decoder.messageReceiverName().toString().data(), decoder.messageName().toString().data());
687 }
688
689 WebFrame* WebProcess::webFrame(uint64_t frameID) const
690 {
691     return m_frameMap.get(frameID);
692 }
693
694 void WebProcess::addWebFrame(uint64_t frameID, WebFrame* frame)
695 {
696     m_frameMap.set(frameID, frame);
697 }
698
699 void WebProcess::removeWebFrame(uint64_t frameID)
700 {
701     m_frameMap.remove(frameID);
702
703     // We can end up here after our connection has closed when WebCore's frame life-support timer
704     // fires when the application is shutting down. There's no need (and no way) to update the UI
705     // process in this case.
706     if (!parentProcessConnection())
707         return;
708
709     parentProcessConnection()->send(Messages::WebProcessProxy::DidDestroyFrame(frameID), 0);
710 }
711
712 WebPageGroupProxy* WebProcess::webPageGroup(PageGroup* pageGroup)
713 {
714     for (auto& page : m_pageGroupMap.values()) {
715         if (page->corePageGroup() == pageGroup)
716             return page.get();
717     }
718
719     return 0;
720 }
721
722 WebPageGroupProxy* WebProcess::webPageGroup(uint64_t pageGroupID)
723 {
724     return m_pageGroupMap.get(pageGroupID);
725 }
726
727 WebPageGroupProxy* WebProcess::webPageGroup(const WebPageGroupData& pageGroupData)
728 {
729     auto result = m_pageGroupMap.add(pageGroupData.pageGroupID, nullptr);
730     if (result.isNewEntry) {
731         ASSERT(!result.iterator->value);
732         result.iterator->value = WebPageGroupProxy::create(pageGroupData);
733     }
734
735     return result.iterator->value.get();
736 }
737
738 static uint64_t nextUserGestureTokenIdentifier()
739 {
740     static uint64_t identifier = 1;
741     return identifier++;
742 }
743
744 uint64_t WebProcess::userGestureTokenIdentifier(RefPtr<UserGestureToken> token)
745 {
746     if (!token || !token->processingUserGesture())
747         return 0;
748
749     auto result = m_userGestureTokens.ensure(token.get(), [] { return nextUserGestureTokenIdentifier(); });
750     if (result.isNewEntry) {
751         result.iterator->key->addDestructionObserver([] (UserGestureToken& tokenBeingDestroyed) {
752             WebProcess::singleton().userGestureTokenDestroyed(tokenBeingDestroyed);
753         });
754     }
755     
756     return result.iterator->value;
757 }
758
759 void WebProcess::userGestureTokenDestroyed(UserGestureToken& token)
760 {
761     auto identifier = m_userGestureTokens.take(&token);
762     parentProcessConnection()->send(Messages::WebProcessProxy::DidDestroyUserGestureToken(identifier), 0);
763 }
764
765 void WebProcess::clearResourceCaches(ResourceCachesToClear resourceCachesToClear)
766 {
767     // Toggling the cache model like this forces the cache to evict all its in-memory resources.
768     // FIXME: We need a better way to do this.
769     CacheModel cacheModel = m_cacheModel;
770     setCacheModel(CacheModel::DocumentViewer);
771     setCacheModel(cacheModel);
772
773     MemoryCache::singleton().evictResources();
774
775     // Empty the cross-origin preflight cache.
776     CrossOriginPreflightResultCache::singleton().clear();
777 }
778
779 static inline void addCaseFoldedCharacters(StringHasher& hasher, const String& string)
780 {
781     if (string.isEmpty())
782         return;
783     if (string.is8Bit()) {
784         hasher.addCharacters<LChar, ASCIICaseInsensitiveHash::FoldCase<LChar>>(string.characters8(), string.length());
785         return;
786     }
787     hasher.addCharacters<UChar, ASCIICaseInsensitiveHash::FoldCase<UChar>>(string.characters16(), string.length());
788 }
789
790 static unsigned hashForPlugInOrigin(const String& pageOrigin, const String& pluginOrigin, const String& mimeType)
791 {
792     // We want to avoid concatenating the strings and then taking the hash, since that could lead to an expensive conversion.
793     // We also want to avoid using the hash() function in StringImpl or ASCIICaseInsensitiveHash because that masks out bits for the use of flags.
794     StringHasher hasher;
795     addCaseFoldedCharacters(hasher, pageOrigin);
796     hasher.addCharacter(0);
797     addCaseFoldedCharacters(hasher, pluginOrigin);
798     hasher.addCharacter(0);
799     addCaseFoldedCharacters(hasher, mimeType);
800     return hasher.hash();
801 }
802
803 bool WebProcess::isPlugInAutoStartOriginHash(unsigned plugInOriginHash, PAL::SessionID sessionID)
804 {
805     HashMap<PAL::SessionID, HashMap<unsigned, WallTime>>::const_iterator sessionIterator = m_plugInAutoStartOriginHashes.find(sessionID);
806     HashMap<unsigned, WallTime>::const_iterator it;
807     bool contains = false;
808
809     if (sessionIterator != m_plugInAutoStartOriginHashes.end()) {
810         it = sessionIterator->value.find(plugInOriginHash);
811         contains = it != sessionIterator->value.end();
812     }
813     if (!contains) {
814         sessionIterator = m_plugInAutoStartOriginHashes.find(PAL::SessionID::defaultSessionID());
815         it = sessionIterator->value.find(plugInOriginHash);
816         if (it == sessionIterator->value.end())
817             return false;
818     }
819     return WallTime::now() < it->value;
820 }
821
822 bool WebProcess::shouldPlugInAutoStartFromOrigin(WebPage& webPage, const String& pageOrigin, const String& pluginOrigin, const String& mimeType)
823 {
824     if (!pluginOrigin.isEmpty() && m_plugInAutoStartOrigins.contains(pluginOrigin))
825         return true;
826
827 #ifdef ENABLE_PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC
828     // 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).
829     if (webPage.matchesPrimaryPlugIn(pageOrigin, pluginOrigin, mimeType))
830         return true;
831 #else
832     UNUSED_PARAM(webPage);
833 #endif
834
835     // Lastly check against the more explicit hash list.
836     return isPlugInAutoStartOriginHash(hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType), webPage.sessionID());
837 }
838
839 void WebProcess::plugInDidStartFromOrigin(const String& pageOrigin, const String& pluginOrigin, const String& mimeType, PAL::SessionID sessionID)
840 {
841     if (pageOrigin.isEmpty()) {
842         LOG(Plugins, "Not adding empty page origin");
843         return;
844     }
845
846     unsigned plugInOriginHash = hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType);
847     if (isPlugInAutoStartOriginHash(plugInOriginHash, sessionID)) {
848         LOG(Plugins, "Hash %x already exists as auto-start origin (request for %s)", plugInOriginHash, pageOrigin.utf8().data());
849         return;
850     }
851
852     // We might attempt to start another plugin before the didAddPlugInAutoStartOrigin message
853     // comes back from the parent process. Temporarily add this hash to the list with a thirty
854     // second timeout. That way, even if the parent decides not to add it, we'll only be
855     // incorrect for a little while.
856     m_plugInAutoStartOriginHashes.add(sessionID, HashMap<unsigned, WallTime>()).iterator->value.set(plugInOriginHash, WallTime::now() + 30_s * 1000);
857
858     parentProcessConnection()->send(Messages::WebProcessPool::AddPlugInAutoStartOriginHash(pageOrigin, plugInOriginHash, sessionID), 0);
859 }
860
861 void WebProcess::didAddPlugInAutoStartOriginHash(unsigned plugInOriginHash, WallTime expirationTime, PAL::SessionID sessionID)
862 {
863     // When called, some web process (which also might be this one) added the origin for auto-starting,
864     // or received user interaction.
865     // Set the bit to avoid having redundantly call into the UI process upon user interaction.
866     m_plugInAutoStartOriginHashes.add(sessionID, HashMap<unsigned, WallTime>()).iterator->value.set(plugInOriginHash, expirationTime);
867 }
868
869 void WebProcess::resetPlugInAutoStartOriginDefaultHashes(const HashMap<unsigned, WallTime>& hashes)
870 {
871     m_plugInAutoStartOriginHashes.clear();
872     m_plugInAutoStartOriginHashes.add(PAL::SessionID::defaultSessionID(), HashMap<unsigned, WallTime>()).iterator->value.swap(const_cast<HashMap<unsigned, WallTime>&>(hashes));
873 }
874
875 void WebProcess::resetPlugInAutoStartOriginHashes(const HashMap<PAL::SessionID, HashMap<unsigned, WallTime>>& hashes)
876 {
877     m_plugInAutoStartOriginHashes.swap(const_cast<HashMap<PAL::SessionID, HashMap<unsigned, WallTime>>&>(hashes));
878 }
879
880 void WebProcess::plugInDidReceiveUserInteraction(const String& pageOrigin, const String& pluginOrigin, const String& mimeType, PAL::SessionID sessionID)
881 {
882     if (pageOrigin.isEmpty())
883         return;
884
885     unsigned plugInOriginHash = hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType);
886     if (!plugInOriginHash)
887         return;
888
889     HashMap<PAL::SessionID, HashMap<unsigned, WallTime>>::const_iterator sessionIterator = m_plugInAutoStartOriginHashes.find(sessionID);
890     HashMap<unsigned, WallTime>::const_iterator it;
891     bool contains = false;
892     if (sessionIterator != m_plugInAutoStartOriginHashes.end()) {
893         it = sessionIterator->value.find(plugInOriginHash);
894         contains = it != sessionIterator->value.end();
895     }
896     if (!contains) {
897         sessionIterator = m_plugInAutoStartOriginHashes.find(PAL::SessionID::defaultSessionID());
898         it = sessionIterator->value.find(plugInOriginHash);
899         if (it == sessionIterator->value.end())
900             return;
901     }
902
903     if (it->value - WallTime::now() > plugInAutoStartExpirationTimeUpdateThreshold)
904         return;
905
906     parentProcessConnection()->send(Messages::WebProcessPool::PlugInDidReceiveUserInteraction(plugInOriginHash, sessionID), 0);
907 }
908
909 void WebProcess::setPluginLoadClientPolicy(uint8_t policy, const String& host, const String& bundleIdentifier, const String& versionString)
910 {
911 #if ENABLE(NETSCAPE_PLUGIN_API) && PLATFORM(MAC)
912     WebPluginInfoProvider::singleton().setPluginLoadClientPolicy(static_cast<PluginLoadClientPolicy>(policy), host, bundleIdentifier, versionString);
913 #endif
914 }
915
916 void WebProcess::resetPluginLoadClientPolicies(const HashMap<WTF::String, HashMap<WTF::String, HashMap<WTF::String, uint8_t>>>& pluginLoadClientPolicies)
917 {
918 #if ENABLE(NETSCAPE_PLUGIN_API) && PLATFORM(MAC)
919     clearPluginClientPolicies();
920
921     for (auto& hostPair : pluginLoadClientPolicies) {
922         for (auto& bundleIdentifierPair : hostPair.value) {
923             for (auto& versionPair : bundleIdentifierPair.value)
924                 WebPluginInfoProvider::singleton().setPluginLoadClientPolicy(static_cast<PluginLoadClientPolicy>(versionPair.value), hostPair.key, bundleIdentifierPair.key, versionPair.key);
925         }
926     }
927 #endif
928 }
929
930 void WebProcess::isJITEnabled(CompletionHandler<void(bool)>&& completionHandler)
931 {
932     completionHandler(JSC::VM::canUseJIT());
933 }
934
935 void WebProcess::clearPluginClientPolicies()
936 {
937 #if ENABLE(NETSCAPE_PLUGIN_API) && PLATFORM(MAC)
938     WebPluginInfoProvider::singleton().clearPluginClientPolicies();
939 #endif
940 }
941
942 void WebProcess::refreshPlugins()
943 {
944 #if ENABLE(NETSCAPE_PLUGIN_API)
945     WebPluginInfoProvider::singleton().refresh(false);
946 #endif
947 }
948
949 static void fromCountedSetToHashMap(TypeCountSet* countedSet, HashMap<String, uint64_t>& map)
950 {
951     TypeCountSet::const_iterator end = countedSet->end();
952     for (TypeCountSet::const_iterator it = countedSet->begin(); it != end; ++it)
953         map.set(it->key, it->value);
954 }
955
956 static void getWebCoreMemoryCacheStatistics(Vector<HashMap<String, uint64_t>>& result)
957 {
958     String imagesString("Images"_s);
959     String cssString("CSS"_s);
960     String xslString("XSL"_s);
961     String javaScriptString("JavaScript"_s);
962     
963     MemoryCache::Statistics memoryCacheStatistics = MemoryCache::singleton().getStatistics();
964     
965     HashMap<String, uint64_t> counts;
966     counts.set(imagesString, memoryCacheStatistics.images.count);
967     counts.set(cssString, memoryCacheStatistics.cssStyleSheets.count);
968     counts.set(xslString, memoryCacheStatistics.xslStyleSheets.count);
969     counts.set(javaScriptString, memoryCacheStatistics.scripts.count);
970     result.append(counts);
971     
972     HashMap<String, uint64_t> sizes;
973     sizes.set(imagesString, memoryCacheStatistics.images.size);
974     sizes.set(cssString, memoryCacheStatistics.cssStyleSheets.size);
975     sizes.set(xslString, memoryCacheStatistics.xslStyleSheets.size);
976     sizes.set(javaScriptString, memoryCacheStatistics.scripts.size);
977     result.append(sizes);
978     
979     HashMap<String, uint64_t> liveSizes;
980     liveSizes.set(imagesString, memoryCacheStatistics.images.liveSize);
981     liveSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.liveSize);
982     liveSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.liveSize);
983     liveSizes.set(javaScriptString, memoryCacheStatistics.scripts.liveSize);
984     result.append(liveSizes);
985     
986     HashMap<String, uint64_t> decodedSizes;
987     decodedSizes.set(imagesString, memoryCacheStatistics.images.decodedSize);
988     decodedSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.decodedSize);
989     decodedSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.decodedSize);
990     decodedSizes.set(javaScriptString, memoryCacheStatistics.scripts.decodedSize);
991     result.append(decodedSizes);
992 }
993
994 void WebProcess::getWebCoreStatistics(uint64_t callbackID)
995 {
996     StatisticsData data;
997     
998     // Gather JavaScript statistics.
999     {
1000         JSLockHolder lock(commonVM());
1001         data.statisticsNumbers.set("JavaScriptObjectsCount"_s, commonVM().heap.objectCount());
1002         data.statisticsNumbers.set("JavaScriptGlobalObjectsCount"_s, commonVM().heap.globalObjectCount());
1003         data.statisticsNumbers.set("JavaScriptProtectedObjectsCount"_s, commonVM().heap.protectedObjectCount());
1004         data.statisticsNumbers.set("JavaScriptProtectedGlobalObjectsCount"_s, commonVM().heap.protectedGlobalObjectCount());
1005         
1006         std::unique_ptr<TypeCountSet> protectedObjectTypeCounts(commonVM().heap.protectedObjectTypeCounts());
1007         fromCountedSetToHashMap(protectedObjectTypeCounts.get(), data.javaScriptProtectedObjectTypeCounts);
1008         
1009         std::unique_ptr<TypeCountSet> objectTypeCounts(commonVM().heap.objectTypeCounts());
1010         fromCountedSetToHashMap(objectTypeCounts.get(), data.javaScriptObjectTypeCounts);
1011         
1012         uint64_t javaScriptHeapSize = commonVM().heap.size();
1013         data.statisticsNumbers.set("JavaScriptHeapSize"_s, javaScriptHeapSize);
1014         data.statisticsNumbers.set("JavaScriptFreeSize"_s, commonVM().heap.capacity() - javaScriptHeapSize);
1015     }
1016
1017     WTF::FastMallocStatistics fastMallocStatistics = WTF::fastMallocStatistics();
1018     data.statisticsNumbers.set("FastMallocReservedVMBytes"_s, fastMallocStatistics.reservedVMBytes);
1019     data.statisticsNumbers.set("FastMallocCommittedVMBytes"_s, fastMallocStatistics.committedVMBytes);
1020     data.statisticsNumbers.set("FastMallocFreeListBytes"_s, fastMallocStatistics.freeListBytes);
1021     
1022     // Gather font statistics.
1023     auto& fontCache = FontCache::singleton();
1024     data.statisticsNumbers.set("CachedFontDataCount"_s, fontCache.fontCount());
1025     data.statisticsNumbers.set("CachedFontDataInactiveCount"_s, fontCache.inactiveFontCount());
1026     
1027     // Gather glyph page statistics.
1028     data.statisticsNumbers.set("GlyphPageCount"_s, GlyphPage::count());
1029     
1030     // Get WebCore memory cache statistics
1031     getWebCoreMemoryCacheStatistics(data.webCoreCacheStatistics);
1032     
1033     parentProcessConnection()->send(Messages::WebProcessPool::DidGetStatistics(data, callbackID), 0);
1034 }
1035
1036 void WebProcess::garbageCollectJavaScriptObjects()
1037 {
1038     GCController::singleton().garbageCollectNow();
1039 }
1040
1041 void WebProcess::mainThreadPing()
1042 {
1043     parentProcessConnection()->send(Messages::WebProcessProxy::DidReceiveMainThreadPing(), 0);
1044 }
1045
1046 void WebProcess::backgroundResponsivenessPing()
1047 {
1048     parentProcessConnection()->send(Messages::WebProcessProxy::DidReceiveBackgroundResponsivenessPing(), 0);
1049 }
1050
1051 void WebProcess::didTakeAllMessagesForPort(Vector<MessageWithMessagePorts>&& messages, uint64_t messageCallbackIdentifier, uint64_t messageBatchIdentifier)
1052 {
1053     WebMessagePortChannelProvider::singleton().didTakeAllMessagesForPort(WTFMove(messages), messageCallbackIdentifier, messageBatchIdentifier);
1054 }
1055
1056 void WebProcess::checkProcessLocalPortForActivity(const MessagePortIdentifier& port, uint64_t callbackIdentifier)
1057 {
1058     WebMessagePortChannelProvider::singleton().checkProcessLocalPortForActivity(port, callbackIdentifier);
1059 }
1060
1061 void WebProcess::didCheckRemotePortForActivity(uint64_t callbackIdentifier, bool hasActivity)
1062 {
1063     WebMessagePortChannelProvider::singleton().didCheckRemotePortForActivity(callbackIdentifier, hasActivity);
1064 }
1065
1066 void WebProcess::messagesAvailableForPort(const MessagePortIdentifier& identifier)
1067 {
1068     MessagePort::notifyMessageAvailable(identifier);
1069 }
1070
1071 #if ENABLE(GAMEPAD)
1072
1073 void WebProcess::setInitialGamepads(const Vector<WebKit::GamepadData>& gamepadDatas)
1074 {
1075     WebGamepadProvider::singleton().setInitialGamepads(gamepadDatas);
1076 }
1077
1078 void WebProcess::gamepadConnected(const GamepadData& gamepadData)
1079 {
1080     WebGamepadProvider::singleton().gamepadConnected(gamepadData);
1081 }
1082
1083 void WebProcess::gamepadDisconnected(unsigned index)
1084 {
1085     WebGamepadProvider::singleton().gamepadDisconnected(index);
1086 }
1087
1088 #endif
1089
1090 void WebProcess::setJavaScriptGarbageCollectorTimerEnabled(bool flag)
1091 {
1092     GCController::singleton().setJavaScriptGarbageCollectorTimerEnabled(flag);
1093 }
1094
1095 void WebProcess::handleInjectedBundleMessage(const String& messageName, const UserData& messageBody)
1096 {
1097     InjectedBundle* injectedBundle = WebProcess::singleton().injectedBundle();
1098     if (!injectedBundle)
1099         return;
1100
1101     injectedBundle->didReceiveMessage(messageName, transformHandlesToObjects(messageBody.object()).get());
1102 }
1103
1104 void WebProcess::setInjectedBundleParameter(const String& key, const IPC::DataReference& value)
1105 {
1106     InjectedBundle* injectedBundle = WebProcess::singleton().injectedBundle();
1107     if (!injectedBundle)
1108         return;
1109
1110     injectedBundle->setBundleParameter(key, value);
1111 }
1112
1113 void WebProcess::setInjectedBundleParameters(const IPC::DataReference& value)
1114 {
1115     InjectedBundle* injectedBundle = WebProcess::singleton().injectedBundle();
1116     if (!injectedBundle)
1117         return;
1118
1119     injectedBundle->setBundleParameters(value);
1120 }
1121
1122 static IPC::Connection::Identifier getNetworkProcessConnection(IPC::Connection& connection)
1123 {
1124     IPC::Attachment encodedConnectionIdentifier;
1125     if (!connection.sendSync(Messages::WebProcessProxy::GetNetworkProcessConnection(), Messages::WebProcessProxy::GetNetworkProcessConnection::Reply(encodedConnectionIdentifier), 0)) {
1126 #if PLATFORM(GTK) || PLATFORM(WPE)
1127         // GTK+ and WPE ports don't exit on send sync message failure.
1128         // In this particular case, the network process can be terminated by the UI process while the
1129         // Web process is still initializing, so we always want to exit instead of crashing. This can
1130         // happen when the WebView is created and then destroyed quickly.
1131         // See https://bugs.webkit.org/show_bug.cgi?id=183348.
1132         exit(0);
1133 #else
1134         CRASH();
1135 #endif
1136     }
1137
1138 #if USE(UNIX_DOMAIN_SOCKETS)
1139     return encodedConnectionIdentifier.releaseFileDescriptor();
1140 #elif OS(DARWIN)
1141     return encodedConnectionIdentifier.port();
1142 #elif OS(WINDOWS)
1143     return encodedConnectionIdentifier.handle();
1144 #else
1145     ASSERT_NOT_REACHED();
1146     return IPC::Connection::Identifier();
1147 #endif
1148 }
1149
1150 NetworkProcessConnection& WebProcess::ensureNetworkProcessConnection()
1151 {
1152     RELEASE_ASSERT(RunLoop::isMain());
1153
1154     // If we've lost our connection to the network process (e.g. it crashed) try to re-establish it.
1155     if (!m_networkProcessConnection) {
1156         IPC::Connection::Identifier connectionIdentifier = getNetworkProcessConnection(*parentProcessConnection());
1157
1158         // Retry once if the IPC to get the connectionIdentifier succeeded but the connectionIdentifier we received
1159         // is invalid. This may indicate that the network process has crashed.
1160         if (!IPC::Connection::identifierIsValid(connectionIdentifier))
1161             connectionIdentifier = getNetworkProcessConnection(*parentProcessConnection());
1162
1163         if (!IPC::Connection::identifierIsValid(connectionIdentifier))
1164             CRASH();
1165
1166         m_networkProcessConnection = NetworkProcessConnection::create(connectionIdentifier);
1167     }
1168     
1169     return *m_networkProcessConnection;
1170 }
1171
1172 void WebProcess::logDiagnosticMessageForNetworkProcessCrash()
1173 {
1174     WebCore::Page* page = nullptr;
1175
1176     if (auto* webPage = focusedWebPage())
1177         page = webPage->corePage();
1178
1179     if (!page) {
1180         for (auto& webPage : m_pageMap.values()) {
1181             if (auto* corePage = webPage->corePage()) {
1182                 page = corePage;
1183                 break;
1184             }
1185         }
1186     }
1187
1188     if (page)
1189         page->diagnosticLoggingClient().logDiagnosticMessage(WebCore::DiagnosticLoggingKeys::internalErrorKey(), WebCore::DiagnosticLoggingKeys::networkProcessCrashedKey(), WebCore::ShouldSample::No);
1190 }
1191
1192 void WebProcess::networkProcessConnectionClosed(NetworkProcessConnection* connection)
1193 {
1194     ASSERT(m_networkProcessConnection);
1195     ASSERT_UNUSED(connection, m_networkProcessConnection == connection);
1196
1197 #if ENABLE(INDEXED_DATABASE)
1198     for (auto& page : m_pageMap.values()) {
1199         auto idbConnection = page->corePage()->optionalIDBConnection();
1200         if (!idbConnection)
1201             continue;
1202         
1203         if (connection->existingIDBConnectionToServerForIdentifier(idbConnection->identifier())) {
1204             ASSERT(idbConnection == &connection->existingIDBConnectionToServerForIdentifier(idbConnection->identifier())->coreConnectionToServer());
1205             page->corePage()->clearIDBConnection();
1206         }
1207     }
1208 #endif
1209
1210 #if ENABLE(SERVICE_WORKER)
1211     if (SWContextManager::singleton().connection()) {
1212         RELEASE_LOG(ServiceWorker, "Service worker process is exiting because network process is gone");
1213         _exit(EXIT_SUCCESS);
1214     }
1215 #endif
1216
1217     m_networkProcessConnection = nullptr;
1218
1219     logDiagnosticMessageForNetworkProcessCrash();
1220
1221     m_webLoaderStrategy.networkProcessCrashed();
1222     WebSocketStream::networkProcessCrashed();
1223
1224     for (auto& page : m_pageMap.values())
1225         page->stopAllURLSchemeTasks();
1226 }
1227
1228 WebLoaderStrategy& WebProcess::webLoaderStrategy()
1229 {
1230     return m_webLoaderStrategy;
1231 }
1232
1233 void WebProcess::setEnhancedAccessibility(bool flag)
1234 {
1235     WebCore::AXObjectCache::setEnhancedUserInterfaceAccessibility(flag);
1236 }
1237     
1238 void WebProcess::startMemorySampler(SandboxExtension::Handle&& sampleLogFileHandle, const String& sampleLogFilePath, const double interval)
1239 {
1240 #if ENABLE(MEMORY_SAMPLER)    
1241     WebMemorySampler::singleton()->start(WTFMove(sampleLogFileHandle), sampleLogFilePath, interval);
1242 #else
1243     UNUSED_PARAM(sampleLogFileHandle);
1244     UNUSED_PARAM(sampleLogFilePath);
1245     UNUSED_PARAM(interval);
1246 #endif
1247 }
1248     
1249 void WebProcess::stopMemorySampler()
1250 {
1251 #if ENABLE(MEMORY_SAMPLER)
1252     WebMemorySampler::singleton()->stop();
1253 #endif
1254 }
1255
1256 void WebProcess::setTextCheckerState(const TextCheckerState& textCheckerState)
1257 {
1258     bool continuousSpellCheckingTurnedOff = !textCheckerState.isContinuousSpellCheckingEnabled && m_textCheckerState.isContinuousSpellCheckingEnabled;
1259     bool grammarCheckingTurnedOff = !textCheckerState.isGrammarCheckingEnabled && m_textCheckerState.isGrammarCheckingEnabled;
1260
1261     m_textCheckerState = textCheckerState;
1262
1263     if (!continuousSpellCheckingTurnedOff && !grammarCheckingTurnedOff)
1264         return;
1265
1266     for (auto& page : m_pageMap.values()) {
1267         if (continuousSpellCheckingTurnedOff)
1268             page->unmarkAllMisspellings();
1269         if (grammarCheckingTurnedOff)
1270             page->unmarkAllBadGrammar();
1271     }
1272 }
1273
1274 void WebProcess::releasePageCache()
1275 {
1276     PageCache::singleton().pruneToSizeNow(0, PruningReason::MemoryPressure);
1277 }
1278
1279 void WebProcess::fetchWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, WebsiteData& websiteData)
1280 {
1281     if (websiteDataTypes.contains(WebsiteDataType::MemoryCache)) {
1282         for (auto& origin : MemoryCache::singleton().originsWithCache(sessionID))
1283             websiteData.entries.append(WebsiteData::Entry { origin->data(), WebsiteDataType::MemoryCache, 0 });
1284     }
1285 }
1286
1287 void WebProcess::deleteWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, WallTime modifiedSince)
1288 {
1289     UNUSED_PARAM(modifiedSince);
1290
1291     if (websiteDataTypes.contains(WebsiteDataType::MemoryCache)) {
1292         PageCache::singleton().pruneToSizeNow(0, PruningReason::None);
1293         MemoryCache::singleton().evictResources(sessionID);
1294
1295         CrossOriginPreflightResultCache::singleton().clear();
1296     }
1297 }
1298
1299 void WebProcess::deleteWebsiteDataForOrigins(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, const Vector<WebCore::SecurityOriginData>& originDatas)
1300 {
1301     if (websiteDataTypes.contains(WebsiteDataType::MemoryCache)) {
1302         HashSet<RefPtr<SecurityOrigin>> origins;
1303         for (auto& originData : originDatas)
1304             origins.add(originData.securityOrigin());
1305
1306         MemoryCache::singleton().removeResourcesWithOrigins(sessionID, origins);
1307     }
1308 }
1309
1310 void WebProcess::setHiddenPageDOMTimerThrottlingIncreaseLimit(int milliseconds)
1311 {
1312     for (auto& page : m_pageMap.values())
1313         page->setHiddenPageDOMTimerThrottlingIncreaseLimit(Seconds::fromMilliseconds(milliseconds));
1314 }
1315
1316 #if !PLATFORM(COCOA)
1317 void WebProcess::initializeProcessName(const ChildProcessInitializationParameters&)
1318 {
1319 }
1320
1321 void WebProcess::initializeSandbox(const ChildProcessInitializationParameters&, SandboxInitializationParameters&)
1322 {
1323 }
1324
1325 void WebProcess::platformInitializeProcess(const ChildProcessInitializationParameters&)
1326 {
1327 }
1328
1329 void WebProcess::updateActivePages()
1330 {
1331 }
1332
1333 void WebProcess::getActivePagesOriginsForTesting(CompletionHandler<void(Vector<String>&&)>&& completionHandler)
1334 {
1335     completionHandler({ });
1336 }
1337
1338 void WebProcess::updateCPULimit()
1339 {
1340 }
1341
1342 void WebProcess::updateCPUMonitorState(CPUMonitorUpdateReason)
1343 {
1344 }
1345
1346 #endif
1347
1348 void WebProcess::pageActivityStateDidChange(uint64_t, OptionSet<WebCore::ActivityState::Flag> changed)
1349 {
1350     if (changed & WebCore::ActivityState::IsVisible)
1351         updateCPUMonitorState(CPUMonitorUpdateReason::VisibilityHasChanged);
1352 }
1353
1354 #if PLATFORM(IOS_FAMILY)
1355 void WebProcess::resetAllGeolocationPermissions()
1356 {
1357     for (auto& page : m_pageMap.values()) {
1358         if (Frame* mainFrame = page->mainFrame())
1359             mainFrame->resetAllGeolocationPermission();
1360     }
1361 }
1362 #endif
1363
1364 void WebProcess::actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend shouldAcknowledgeWhenReadyToSuspend)
1365 {
1366     SetForScope<bool> suspensionScope(m_isSuspending, true);
1367
1368     if (!m_suppressMemoryPressureHandler)
1369         MemoryPressureHandler::singleton().releaseMemory(Critical::Yes, Synchronous::Yes);
1370
1371     freezeAllLayerTrees();
1372     
1373 #if PLATFORM(COCOA)
1374     destroyRenderingResources();
1375 #endif
1376
1377 #if PLATFORM(IOS_FAMILY)
1378     accessibilityProcessSuspendedNotification(true);
1379 #endif
1380
1381     markAllLayersVolatile([this, shouldAcknowledgeWhenReadyToSuspend](bool success) {
1382         if (success)
1383             RELEASE_LOG(ProcessSuspension, "%p - WebProcess::markAllLayersVolatile() Successfuly marked all layers as volatile", this);
1384         else
1385             RELEASE_LOG(ProcessSuspension, "%p - WebProcess::markAllLayersVolatile() Failed to mark all layers as volatile", this);
1386
1387         if (shouldAcknowledgeWhenReadyToSuspend == ShouldAcknowledgeWhenReadyToSuspend::Yes) {
1388             RELEASE_LOG(ProcessSuspension, "%p - WebProcess::actualPrepareToSuspend() Sending ProcessReadyToSuspend IPC message", this);
1389             parentProcessConnection()->send(Messages::WebProcessProxy::ProcessReadyToSuspend(), 0);
1390         }
1391     });
1392 }
1393
1394 void WebProcess::processWillSuspendImminently(bool& handled)
1395 {
1396     if (parentProcessConnection()->inSendSync()) {
1397         // Avoid reentrency bugs such as rdar://problem/21605505 by just bailing
1398         // if we get an incoming ProcessWillSuspendImminently message when waiting for a
1399         // reply to a sync message.
1400         // FIXME: ProcessWillSuspendImminently should not be a sync message.
1401         return;
1402     }
1403
1404     RELEASE_LOG(ProcessSuspension, "%p - WebProcess::processWillSuspendImminently()", this);
1405     DatabaseTracker::singleton().closeAllDatabases(CurrentQueryBehavior::Interrupt);
1406     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::No);
1407     handled = true;
1408 }
1409
1410 void WebProcess::prepareToSuspend()
1411 {
1412     RELEASE_LOG(ProcessSuspension, "%p - WebProcess::prepareToSuspend()", this);
1413     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::Yes);
1414 }
1415
1416 void WebProcess::cancelPrepareToSuspend()
1417 {
1418     RELEASE_LOG(ProcessSuspension, "%p - WebProcess::cancelPrepareToSuspend()", this);
1419     unfreezeAllLayerTrees();
1420
1421 #if PLATFORM(IOS_FAMILY)
1422     accessibilityProcessSuspendedNotification(false);
1423 #endif
1424     
1425     // If we've already finished cleaning up and sent ProcessReadyToSuspend, we
1426     // shouldn't send DidCancelProcessSuspension; the UI process strictly expects one or the other.
1427     if (!m_pageMarkingLayersAsVolatileCounter)
1428         return;
1429
1430     cancelMarkAllLayersVolatile();
1431
1432     RELEASE_LOG(ProcessSuspension, "%p - WebProcess::cancelPrepareToSuspend() Sending DidCancelProcessSuspension IPC message", this);
1433     parentProcessConnection()->send(Messages::WebProcessProxy::DidCancelProcessSuspension(), 0);
1434 }
1435
1436 void WebProcess::markAllLayersVolatile(WTF::Function<void(bool)>&& completionHandler)
1437 {
1438     RELEASE_LOG(ProcessSuspension, "%p - WebProcess::markAllLayersVolatile()", this);
1439     ASSERT(!m_pageMarkingLayersAsVolatileCounter);
1440     m_countOfPagesFailingToMarkVolatile = 0;
1441
1442     m_pageMarkingLayersAsVolatileCounter = std::make_unique<PageMarkingLayersAsVolatileCounter>([this, completionHandler = WTFMove(completionHandler)] (RefCounterEvent) {
1443         if (m_pageMarkingLayersAsVolatileCounter->value())
1444             return;
1445
1446         completionHandler(m_countOfPagesFailingToMarkVolatile == 0);
1447         m_pageMarkingLayersAsVolatileCounter = nullptr;
1448     });
1449     auto token = m_pageMarkingLayersAsVolatileCounter->count();
1450     for (auto& page : m_pageMap.values())
1451         page->markLayersVolatile([token, this] (bool succeeded) {
1452             if (!succeeded)
1453                 ++m_countOfPagesFailingToMarkVolatile;
1454         });
1455 }
1456
1457 void WebProcess::cancelMarkAllLayersVolatile()
1458 {
1459     if (!m_pageMarkingLayersAsVolatileCounter)
1460         return;
1461
1462     m_pageMarkingLayersAsVolatileCounter = nullptr;
1463     for (auto& page : m_pageMap.values())
1464         page->cancelMarkLayersVolatile();
1465 }
1466
1467 void WebProcess::freezeAllLayerTrees()
1468 {
1469     for (auto& page : m_pageMap.values())
1470         page->freezeLayerTree(WebPage::LayerTreeFreezeReason::ProcessSuspended);
1471 }
1472
1473 void WebProcess::unfreezeAllLayerTrees()
1474 {
1475     for (auto& page : m_pageMap.values())
1476         page->unfreezeLayerTree(WebPage::LayerTreeFreezeReason::ProcessSuspended);
1477 }
1478
1479 void WebProcess::processDidResume()
1480 {
1481     RELEASE_LOG(ProcessSuspension, "%p - WebProcess::processDidResume()", this);
1482
1483     cancelMarkAllLayersVolatile();
1484     unfreezeAllLayerTrees();
1485     
1486 #if PLATFORM(IOS_FAMILY)
1487     accessibilityProcessSuspendedNotification(false);
1488 #endif
1489 }
1490
1491 void WebProcess::sendPrewarmInformation(const URL& url)
1492 {
1493     auto registrableDomain = toRegistrableDomain(url);
1494     if (registrableDomain.isEmpty())
1495         return;
1496     parentProcessConnection()->send(Messages::WebProcessProxy::DidCollectPrewarmInformation(registrableDomain, WebCore::ProcessWarming::collectPrewarmInformation()), 0);
1497 }
1498
1499 void WebProcess::pageDidEnterWindow(uint64_t pageID)
1500 {
1501     m_pagesInWindows.add(pageID);
1502     m_nonVisibleProcessCleanupTimer.stop();
1503 }
1504
1505 void WebProcess::pageWillLeaveWindow(uint64_t pageID)
1506 {
1507     m_pagesInWindows.remove(pageID);
1508
1509     if (m_pagesInWindows.isEmpty() && !m_nonVisibleProcessCleanupTimer.isActive())
1510         m_nonVisibleProcessCleanupTimer.startOneShot(nonVisibleProcessCleanupDelay);
1511 }
1512     
1513 void WebProcess::nonVisibleProcessCleanupTimerFired()
1514 {
1515     ASSERT(m_pagesInWindows.isEmpty());
1516     if (!m_pagesInWindows.isEmpty())
1517         return;
1518
1519 #if PLATFORM(COCOA)
1520     destroyRenderingResources();
1521 #endif
1522 }
1523
1524 void WebProcess::setResourceLoadStatisticsEnabled(bool enabled)
1525 {
1526     WebCore::DeprecatedGlobalSettings::setResourceLoadStatisticsEnabled(enabled);
1527 }
1528
1529 void WebProcess::clearResourceLoadStatistics()
1530 {
1531     ResourceLoadObserver::shared().clearState();
1532 }
1533
1534 RefPtr<API::Object> WebProcess::transformHandlesToObjects(API::Object* object)
1535 {
1536     struct Transformer final : UserData::Transformer {
1537         Transformer(WebProcess& webProcess)
1538             : m_webProcess(webProcess)
1539         {
1540         }
1541
1542         bool shouldTransformObject(const API::Object& object) const override
1543         {
1544             switch (object.type()) {
1545             case API::Object::Type::FrameHandle:
1546                 return static_cast<const API::FrameHandle&>(object).isAutoconverting();
1547
1548             case API::Object::Type::PageHandle:
1549                 return static_cast<const API::PageHandle&>(object).isAutoconverting();
1550
1551             case API::Object::Type::PageGroupHandle:
1552 #if PLATFORM(COCOA)
1553             case API::Object::Type::ObjCObjectGraph:
1554 #endif
1555                 return true;
1556
1557             default:
1558                 return false;
1559             }
1560         }
1561
1562         RefPtr<API::Object> transformObject(API::Object& object) const override
1563         {
1564             switch (object.type()) {
1565             case API::Object::Type::FrameHandle:
1566                 return m_webProcess.webFrame(static_cast<const API::FrameHandle&>(object).frameID());
1567
1568             case API::Object::Type::PageGroupHandle:
1569                 return m_webProcess.webPageGroup(static_cast<const API::PageGroupHandle&>(object).webPageGroupData());
1570
1571             case API::Object::Type::PageHandle:
1572                 return m_webProcess.webPage(static_cast<const API::PageHandle&>(object).pageID());
1573
1574 #if PLATFORM(COCOA)
1575             case API::Object::Type::ObjCObjectGraph:
1576                 return m_webProcess.transformHandlesToObjects(static_cast<ObjCObjectGraph&>(object));
1577 #endif
1578             default:
1579                 return &object;
1580             }
1581         }
1582
1583         WebProcess& m_webProcess;
1584     };
1585
1586     return UserData::transform(object, Transformer(*this));
1587 }
1588
1589 RefPtr<API::Object> WebProcess::transformObjectsToHandles(API::Object* object)
1590 {
1591     struct Transformer final : UserData::Transformer {
1592         bool shouldTransformObject(const API::Object& object) const override
1593         {
1594             switch (object.type()) {
1595             case API::Object::Type::BundleFrame:
1596             case API::Object::Type::BundlePage:
1597             case API::Object::Type::BundlePageGroup:
1598 #if PLATFORM(COCOA)
1599             case API::Object::Type::ObjCObjectGraph:
1600 #endif
1601                 return true;
1602
1603             default:
1604                 return false;
1605             }
1606         }
1607
1608         RefPtr<API::Object> transformObject(API::Object& object) const override
1609         {
1610             switch (object.type()) {
1611             case API::Object::Type::BundleFrame:
1612                 return API::FrameHandle::createAutoconverting(static_cast<const WebFrame&>(object).frameID());
1613
1614             case API::Object::Type::BundlePage:
1615                 return API::PageHandle::createAutoconverting(static_cast<const WebPage&>(object).pageID());
1616
1617             case API::Object::Type::BundlePageGroup: {
1618                 WebPageGroupData pageGroupData;
1619                 pageGroupData.pageGroupID = static_cast<const WebPageGroupProxy&>(object).pageGroupID();
1620
1621                 return API::PageGroupHandle::create(WTFMove(pageGroupData));
1622             }
1623
1624 #if PLATFORM(COCOA)
1625             case API::Object::Type::ObjCObjectGraph:
1626                 return transformObjectsToHandles(static_cast<ObjCObjectGraph&>(object));
1627 #endif
1628
1629             default:
1630                 return &object;
1631             }
1632         }
1633     };
1634
1635     return UserData::transform(object, Transformer());
1636 }
1637
1638 void WebProcess::setMemoryCacheDisabled(bool disabled)
1639 {
1640     auto& memoryCache = MemoryCache::singleton();
1641     if (memoryCache.disabled() != disabled)
1642         memoryCache.setDisabled(disabled);
1643 }
1644
1645 #if ENABLE(SERVICE_CONTROLS)
1646 void WebProcess::setEnabledServices(bool hasImageServices, bool hasSelectionServices, bool hasRichContentServices)
1647 {
1648     m_hasImageServices = hasImageServices;
1649     m_hasSelectionServices = hasSelectionServices;
1650     m_hasRichContentServices = hasRichContentServices;
1651 }
1652 #endif
1653
1654 void WebProcess::ensureAutomationSessionProxy(const String& sessionIdentifier)
1655 {
1656     m_automationSessionProxy = std::make_unique<WebAutomationSessionProxy>(sessionIdentifier);
1657 }
1658
1659 void WebProcess::destroyAutomationSessionProxy()
1660 {
1661     m_automationSessionProxy = nullptr;
1662 }
1663
1664 void WebProcess::prefetchDNS(const String& hostname)
1665 {
1666     if (hostname.isEmpty())
1667         return;
1668
1669     if (m_dnsPrefetchedHosts.add(hostname).isNewEntry)
1670         ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::PrefetchDNS(hostname), 0);
1671     // The DNS prefetched hosts cache is only to avoid asking for the same hosts too many times
1672     // in a very short period of time, producing a lot of IPC traffic. So we clear this cache after
1673     // some time of no DNS requests.
1674     m_dnsPrefetchHystereris.impulse();
1675 }
1676
1677 bool WebProcess::hasVisibleWebPage() const
1678 {
1679     for (auto& page : m_pageMap.values()) {
1680         if (page->isVisible())
1681             return true;
1682     }
1683     return false;
1684 }
1685
1686 LibWebRTCNetwork& WebProcess::libWebRTCNetwork()
1687 {
1688     if (!m_libWebRTCNetwork)
1689         m_libWebRTCNetwork = std::make_unique<LibWebRTCNetwork>();
1690     return *m_libWebRTCNetwork;
1691 }
1692
1693 #if ENABLE(SERVICE_WORKER)
1694 void WebProcess::establishWorkerContextConnectionToNetworkProcess(uint64_t pageGroupID, uint64_t pageID, const WebPreferencesStore& store, PAL::SessionID initialSessionID)
1695 {
1696     // We are in the Service Worker context process and the call below establishes our connection to the Network Process
1697     // by calling ensureNetworkProcessConnection. SWContextManager needs to use the same underlying IPC::Connection as the
1698     // NetworkProcessConnection for synchronization purposes.
1699     auto& ipcConnection = ensureNetworkProcessConnection().connection();
1700     SWContextManager::singleton().setConnection(std::make_unique<WebSWContextManagerConnection>(ipcConnection, pageGroupID, pageID, store));
1701 }
1702
1703 void WebProcess::registerServiceWorkerClients()
1704 {
1705     // We do not want to register service worker dummy documents.
1706     ASSERT(!SWContextManager::singleton().connection());
1707     ServiceWorkerProvider::singleton().registerServiceWorkerClients();
1708 }
1709
1710 #endif
1711
1712 #if PLATFORM(MAC)
1713 void WebProcess::setScreenProperties(const WebCore::ScreenProperties& properties)
1714 {
1715     WebCore::setScreenProperties(properties);
1716 }
1717 #endif
1718
1719 #if ENABLE(MEDIA_STREAM)
1720 void WebProcess::addMockMediaDevice(const WebCore::MockMediaDevice& device)
1721 {
1722     MockRealtimeMediaSourceCenter::addDevice(device);
1723 }
1724
1725 void WebProcess::clearMockMediaDevices()
1726 {
1727     MockRealtimeMediaSourceCenter::setDevices({ });
1728 }
1729
1730 void WebProcess::removeMockMediaDevice(const String& persistentId)
1731 {
1732     MockRealtimeMediaSourceCenter::removeDevice(persistentId);
1733 }
1734
1735 void WebProcess::resetMockMediaDevices()
1736 {
1737     MockRealtimeMediaSourceCenter::resetDevices();
1738 }
1739 #endif
1740
1741 void WebProcess::clearCurrentModifierStateForTesting()
1742 {
1743     PlatformKeyboardEvent::setCurrentModifierState({ });
1744 }
1745
1746 } // namespace WebKit