Cleanup WK2 platform gamepad handling.
[WebKit-https.git] / Source / WebKit2 / WebProcess / WebProcess.cpp
1 /*
2  * Copyright (C) 2009-2016 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 "Logging.h"
38 #include "NetworkConnectionToWebProcessMessages.h"
39 #include "NetworkProcessConnection.h"
40 #include "PluginProcessConnectionManager.h"
41 #include "SessionTracker.h"
42 #include "StatisticsData.h"
43 #include "UserData.h"
44 #include "WebAutomationSessionProxy.h"
45 #include "WebConnectionToUIProcess.h"
46 #include "WebCookieManager.h"
47 #include "WebCoreArgumentCoders.h"
48 #include "WebFrame.h"
49 #include "WebFrameNetworkingContext.h"
50 #include "WebGamepadProvider.h"
51 #include "WebGeolocationManager.h"
52 #include "WebIconDatabaseProxy.h"
53 #include "WebLoaderStrategy.h"
54 #include "WebMediaKeyStorageManager.h"
55 #include "WebMemorySampler.h"
56 #include "WebPage.h"
57 #include "WebPageGroupProxy.h"
58 #include "WebPlatformStrategies.h"
59 #include "WebPluginInfoProvider.h"
60 #include "WebProcessCreationParameters.h"
61 #include "WebProcessMessages.h"
62 #include "WebProcessPoolMessages.h"
63 #include "WebProcessProxyMessages.h"
64 #include "WebResourceLoadStatisticsStoreMessages.h"
65 #include "WebsiteData.h"
66 #include "WebsiteDataType.h"
67 #include <JavaScriptCore/JSLock.h>
68 #include <JavaScriptCore/MemoryStatistics.h>
69 #include <WebCore/AXObjectCache.h>
70 #include <WebCore/ApplicationCacheStorage.h>
71 #include <WebCore/AuthenticationChallenge.h>
72 #include <WebCore/CrossOriginPreflightResultCache.h>
73 #include <WebCore/DNS.h>
74 #include <WebCore/DatabaseManager.h>
75 #include <WebCore/DatabaseTracker.h>
76 #include <WebCore/FontCache.h>
77 #include <WebCore/FontCascade.h>
78 #include <WebCore/Frame.h>
79 #include <WebCore/FrameLoader.h>
80 #include <WebCore/GCController.h>
81 #include <WebCore/GlyphPage.h>
82 #include <WebCore/HTMLMediaElement.h>
83 #include <WebCore/IconDatabase.h>
84 #include <WebCore/JSDOMWindow.h>
85 #include <WebCore/Language.h>
86 #include <WebCore/MainFrame.h>
87 #include <WebCore/MemoryCache.h>
88 #include <WebCore/MemoryPressureHandler.h>
89 #include <WebCore/NetworkStorageSession.h>
90 #include <WebCore/Page.h>
91 #include <WebCore/PageCache.h>
92 #include <WebCore/PageGroup.h>
93 #include <WebCore/PlatformMediaSessionManager.h>
94 #include <WebCore/ResourceHandle.h>
95 #include <WebCore/ResourceLoadObserver.h>
96 #include <WebCore/ResourceLoadStatistics.h>
97 #include <WebCore/ResourceLoadStatisticsStore.h>
98 #include <WebCore/RuntimeApplicationChecks.h>
99 #include <WebCore/RuntimeEnabledFeatures.h>
100 #include <WebCore/SchemeRegistry.h>
101 #include <WebCore/SecurityOrigin.h>
102 #include <WebCore/Settings.h>
103 #include <WebCore/UserGestureIndicator.h>
104 #include <unistd.h>
105 #include <wtf/CurrentTime.h>
106 #include <wtf/HashCountedSet.h>
107 #include <wtf/RunLoop.h>
108 #include <wtf/text/StringHash.h>
109
110 #if PLATFORM(COCOA)
111 #include "ObjCObjectGraph.h"
112 #endif
113
114 #if PLATFORM(COCOA)
115 #include "CookieStorageShim.h"
116 #endif
117
118 #if ENABLE(SEC_ITEM_SHIM)
119 #include "SecItemShim.h"
120 #endif
121
122 #if ENABLE(DATABASE_PROCESS)
123 #include "WebToDatabaseProcessConnection.h"
124 #endif
125
126 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
127 #include "WebNotificationManager.h"
128 #endif
129
130 #if ENABLE(BATTERY_STATUS)
131 #include "WebBatteryManager.h"
132 #endif
133
134 #if ENABLE(REMOTE_INSPECTOR)
135 #include <JavaScriptCore/RemoteInspector.h>
136 #endif
137
138 using namespace JSC;
139 using namespace WebCore;
140
141 // This should be less than plugInAutoStartExpirationTimeThreshold in PlugInAutoStartProvider.
142 static const double plugInAutoStartExpirationTimeUpdateThreshold = 29 * 24 * 60 * 60;
143
144 // This should be greater than tileRevalidationTimeout in TileController.
145 static const double nonVisibleProcessCleanupDelay = 10;
146
147 namespace WebKit {
148
149 WebProcess& WebProcess::singleton()
150 {
151     static WebProcess& process = *new WebProcess;
152     return process;
153 }
154
155 WebProcess::WebProcess()
156     : m_eventDispatcher(EventDispatcher::create())
157 #if PLATFORM(IOS)
158     , m_viewUpdateDispatcher(ViewUpdateDispatcher::create())
159 #endif
160     , m_inDidClose(false)
161     , m_hasSetCacheModel(false)
162     , m_cacheModel(CacheModelDocumentViewer)
163     , m_fullKeyboardAccessEnabled(false)
164     , m_textCheckerState()
165     , m_iconDatabaseProxy(*new WebIconDatabaseProxy(this))
166     , m_webLoaderStrategy(*new WebLoaderStrategy)
167     , m_dnsPrefetchHystereris([this](HysteresisState state) { if (state == HysteresisState::Stopped) m_dnsPrefetchedHosts.clear(); })
168 #if ENABLE(NETSCAPE_PLUGIN_API)
169     , m_pluginProcessConnectionManager(PluginProcessConnectionManager::create())
170 #endif
171 #if ENABLE(SERVICE_CONTROLS)
172     , m_hasImageServices(false)
173     , m_hasSelectionServices(false)
174     , m_hasRichContentServices(false)
175 #endif
176     , m_nonVisibleProcessCleanupTimer(*this, &WebProcess::nonVisibleProcessCleanupTimerFired)
177     , m_statisticsChangedTimer(*this, &WebProcess::statisticsChangedTimerFired)
178 #if PLATFORM(IOS)
179     , m_webSQLiteDatabaseTracker(*this)
180 #endif
181     , m_resourceLoadStatisticsStorage(WebCore::ResourceLoadStatisticsStore::create())
182 {
183     // Initialize our platform strategies.
184     WebPlatformStrategies::initialize();
185
186     // FIXME: This should moved to where WebProcess::initialize is called,
187     // so that ports have a chance to customize, and ifdefs in this file are
188     // limited.
189     addSupplement<WebGeolocationManager>();
190     addSupplement<WebCookieManager>();
191     addSupplement<AuthenticationManager>();
192
193 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
194     addSupplement<WebNotificationManager>();
195 #endif
196 #if ENABLE(BATTERY_STATUS)
197     addSupplement<WebBatteryManager>();
198 #endif
199 #if ENABLE(ENCRYPTED_MEDIA_V2)
200     addSupplement<WebMediaKeyStorageManager>();
201 #endif
202     m_plugInAutoStartOriginHashes.add(SessionID::defaultSessionID(), HashMap<unsigned, double>());
203
204 #if ENABLE(INDEXED_DATABASE)
205     RuntimeEnabledFeatures::sharedFeatures().setWebkitIndexedDBEnabled(true);
206 #endif
207
208 #if PLATFORM(IOS) || PLATFORM(GTK)
209     PageCache::singleton().setShouldClearBackingStores(true);
210 #endif
211
212     ResourceLoadObserver::sharedObserver().setStatisticsStore(m_resourceLoadStatisticsStorage.copyRef());
213     m_resourceLoadStatisticsStorage->setNotificationCallback([this] {
214         if (m_statisticsChangedTimer.isActive())
215             return;
216         
217         m_statisticsChangedTimer.startOneShot(std::chrono::seconds(5));
218     });
219 }
220
221 WebProcess::~WebProcess()
222 {
223 }
224
225 void WebProcess::initializeProcess(const ChildProcessInitializationParameters& parameters)
226 {
227     platformInitializeProcess(parameters);
228 }
229
230 void WebProcess::initializeConnection(IPC::Connection* connection)
231 {
232     ChildProcess::initializeConnection(connection);
233
234     connection->setShouldExitOnSyncMessageSendFailure(true);
235
236 #if HAVE(QOS_CLASSES)
237     connection->setShouldBoostMainThreadOnSyncMessage(true);
238 #endif
239
240     m_eventDispatcher->initializeConnection(connection);
241 #if PLATFORM(IOS)
242     m_viewUpdateDispatcher->initializeConnection(connection);
243 #endif // PLATFORM(IOS)
244
245 #if ENABLE(NETSCAPE_PLUGIN_API)
246     m_pluginProcessConnectionManager->initializeConnection(connection);
247 #endif
248
249 #if ENABLE(SEC_ITEM_SHIM)
250     SecItemShim::singleton().initializeConnection(connection);
251 #endif
252
253     for (auto& supplement : m_supplements.values())
254         supplement->initializeConnection(connection);
255
256     m_webConnection = WebConnectionToUIProcess::create(this);
257
258     // In order to ensure that the asynchronous messages that are used for notifying the UI process
259     // about when WebFrame objects come and go are always delivered before the synchronous policy messages,
260     // use this flag to force synchronous messages to be treated as asynchronous messages in the UI process
261     // unless when doing so would lead to a deadlock.
262     connection->setOnlySendMessagesAsDispatchWhenWaitingForSyncReplyWhenProcessingSuchAMessage(true);
263 }
264
265 void WebProcess::initializeWebProcess(WebProcessCreationParameters&& parameters)
266 {
267     ASSERT(m_pageMap.isEmpty());
268
269 #if OS(LINUX)
270     if (parameters.memoryPressureMonitorHandle.fileDescriptor() != -1)
271         MemoryPressureHandler::singleton().setMemoryPressureMonitorHandle(parameters.memoryPressureMonitorHandle.releaseFileDescriptor());
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::setCurrentThreadIsUserInteractive(-1);
279
280     m_suppressMemoryPressureHandler = parameters.shouldSuppressMemoryPressureHandler;
281     if (!m_suppressMemoryPressureHandler)
282         MemoryPressureHandler::singleton().install();
283
284     if (!parameters.injectedBundlePath.isEmpty())
285         m_injectedBundle = InjectedBundle::create(parameters, transformHandlesToObjects(parameters.initializationUserData.object()).get());
286
287     for (auto& supplement : m_supplements.values())
288         supplement->initialize(parameters);
289
290     auto& databaseManager = DatabaseManager::singleton();
291     databaseManager.initialize(parameters.webSQLDatabaseDirectory);
292
293 #if ENABLE(ICONDATABASE)
294     m_iconDatabaseProxy.setEnabled(parameters.iconDatabaseEnabled);
295 #endif
296
297     // FIXME: This should be constructed per data store, not per process.
298     m_applicationCacheStorage = ApplicationCacheStorage::create(parameters.applicationCacheDirectory, parameters.applicationCacheFlatFileSubdirectoryName);
299 #if PLATFORM(IOS)
300     m_applicationCacheStorage->setDefaultOriginQuota(25ULL * 1024 * 1024);
301 #endif
302
303 #if ENABLE(VIDEO)
304     if (!parameters.mediaCacheDirectory.isEmpty())
305         WebCore::HTMLMediaElement::setMediaCacheDirectory(parameters.mediaCacheDirectory);
306 #endif
307
308     setCacheModel(static_cast<uint32_t>(parameters.cacheModel));
309
310     if (!parameters.languages.isEmpty())
311         overrideUserPreferredLanguages(parameters.languages);
312
313     m_textCheckerState = parameters.textCheckerState;
314
315     m_fullKeyboardAccessEnabled = parameters.fullKeyboardAccessEnabled;
316
317     for (auto& scheme : parameters.urlSchemesRegisteredAsEmptyDocument)
318         registerURLSchemeAsEmptyDocument(scheme);
319
320     for (auto& scheme : parameters.urlSchemesRegisteredAsSecure)
321         registerURLSchemeAsSecure(scheme);
322
323     for (auto& scheme : parameters.urlSchemesRegisteredAsBypassingContentSecurityPolicy)
324         registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
325
326     for (auto& scheme : parameters.urlSchemesForWhichDomainRelaxationIsForbidden)
327         setDomainRelaxationForbiddenForURLScheme(scheme);
328
329     for (auto& scheme : parameters.urlSchemesRegisteredAsLocal)
330         registerURLSchemeAsLocal(scheme);
331
332     for (auto& scheme : parameters.urlSchemesRegisteredAsNoAccess)
333         registerURLSchemeAsNoAccess(scheme);
334
335     for (auto& scheme : parameters.urlSchemesRegisteredAsDisplayIsolated)
336         registerURLSchemeAsDisplayIsolated(scheme);
337
338     for (auto& scheme : parameters.urlSchemesRegisteredAsCORSEnabled)
339         registerURLSchemeAsCORSEnabled(scheme);
340
341     for (auto& scheme : parameters.urlSchemesRegisteredAsAlwaysRevalidated)
342         registerURLSchemeAsAlwaysRevalidated(scheme);
343
344 #if ENABLE(CACHE_PARTITIONING)
345     for (auto& scheme : parameters.urlSchemesRegisteredAsCachePartitioned)
346         registerURLSchemeAsCachePartitioned(scheme);
347 #endif
348
349     setDefaultRequestTimeoutInterval(parameters.defaultRequestTimeoutInterval);
350
351     setResourceLoadStatisticsEnabled(parameters.resourceLoadStatisticsEnabled);
352
353     if (parameters.shouldAlwaysUseComplexTextCodePath)
354         setAlwaysUsesComplexTextCodePath(true);
355
356     if (parameters.shouldUseFontSmoothing)
357         setShouldUseFontSmoothing(true);
358
359 #if PLATFORM(COCOA) || USE(CFNETWORK)
360     SessionTracker::setIdentifierBase(parameters.uiProcessBundleIdentifier);
361 #endif
362
363     if (parameters.shouldUseTestingNetworkSession)
364         NetworkStorageSession::switchToNewTestingSession();
365
366     ensureNetworkProcessConnection();
367
368 #if PLATFORM(COCOA)
369     CookieStorageShim::singleton().initialize();
370 #endif
371     setTerminationTimeout(parameters.terminationTimeout);
372
373     resetPlugInAutoStartOriginHashes(parameters.plugInAutoStartOriginHashes);
374     for (auto& origin : parameters.plugInAutoStartOrigins)
375         m_plugInAutoStartOrigins.add(origin);
376
377     setMemoryCacheDisabled(parameters.memoryCacheDisabled);
378
379 #if ENABLE(SERVICE_CONTROLS)
380     setEnabledServices(parameters.hasImageServices, parameters.hasSelectionServices, parameters.hasRichContentServices);
381 #endif
382
383 #if ENABLE(REMOTE_INSPECTOR)
384     audit_token_t auditToken;
385     if (parentProcessConnection()->getAuditToken(auditToken)) {
386         RetainPtr<CFDataRef> auditData = adoptCF(CFDataCreate(nullptr, (const UInt8*)&auditToken, sizeof(auditToken)));
387         Inspector::RemoteInspector::singleton().setParentProcessInformation(presenterApplicationPid(), auditData);
388     }
389 #endif
390
391 #if USE(NETWORK_SESSION)
392     NetworkSession::setSourceApplicationAuditTokenData(sourceApplicationAuditData());
393 #endif
394
395 #if ENABLE(NETSCAPE_PLUGIN_API) && PLATFORM(MAC)
396     for (auto hostIter = parameters.pluginLoadClientPolicies.begin(); hostIter != parameters.pluginLoadClientPolicies.end(); ++hostIter) {
397         for (auto bundleIdentifierIter = hostIter->value.begin(); bundleIdentifierIter != hostIter->value.end(); ++bundleIdentifierIter) {
398             for (auto versionIter = bundleIdentifierIter->value.begin(); versionIter != bundleIdentifierIter->value.end(); ++versionIter)
399                 WebPluginInfoProvider::singleton().setPluginLoadClientPolicy(static_cast<PluginLoadClientPolicy>(versionIter->value), hostIter->key, bundleIdentifierIter->key, versionIter->key);
400         }
401     }
402 #endif
403
404 #if ENABLE(GAMEPAD)
405     GamepadProvider::singleton().setSharedProvider(WebGamepadProvider::singleton());
406 #endif
407 }
408
409 void WebProcess::ensureNetworkProcessConnection()
410 {
411     if (m_networkProcessConnection)
412         return;
413
414     IPC::Attachment encodedConnectionIdentifier;
415
416     if (!parentProcessConnection()->sendSync(Messages::WebProcessProxy::GetNetworkProcessConnection(),
417         Messages::WebProcessProxy::GetNetworkProcessConnection::Reply(encodedConnectionIdentifier), 0))
418         return;
419
420 #if USE(UNIX_DOMAIN_SOCKETS)
421     IPC::Connection::Identifier connectionIdentifier = encodedConnectionIdentifier.releaseFileDescriptor();
422 #elif OS(DARWIN)
423     IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.port());
424 #else
425     ASSERT_NOT_REACHED();
426 #endif
427     if (IPC::Connection::identifierIsNull(connectionIdentifier))
428         return;
429     m_networkProcessConnection = NetworkProcessConnection::create(connectionIdentifier);
430 }
431
432 void WebProcess::registerURLSchemeAsEmptyDocument(const String& urlScheme)
433 {
434     SchemeRegistry::registerURLSchemeAsEmptyDocument(urlScheme);
435 }
436
437 void WebProcess::registerURLSchemeAsSecure(const String& urlScheme) const
438 {
439     SchemeRegistry::registerURLSchemeAsSecure(urlScheme);
440 }
441
442 void WebProcess::registerURLSchemeAsBypassingContentSecurityPolicy(const String& urlScheme) const
443 {
444     SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(urlScheme);
445 }
446
447 void WebProcess::setDomainRelaxationForbiddenForURLScheme(const String& urlScheme) const
448 {
449     SchemeRegistry::setDomainRelaxationForbiddenForURLScheme(true, urlScheme);
450 }
451
452 void WebProcess::registerURLSchemeAsLocal(const String& urlScheme) const
453 {
454     SchemeRegistry::registerURLSchemeAsLocal(urlScheme);
455 }
456
457 void WebProcess::registerURLSchemeAsNoAccess(const String& urlScheme) const
458 {
459     SchemeRegistry::registerURLSchemeAsNoAccess(urlScheme);
460 }
461
462 void WebProcess::registerURLSchemeAsDisplayIsolated(const String& urlScheme) const
463 {
464     SchemeRegistry::registerURLSchemeAsDisplayIsolated(urlScheme);
465 }
466
467 void WebProcess::registerURLSchemeAsCORSEnabled(const String& urlScheme) const
468 {
469     SchemeRegistry::registerURLSchemeAsCORSEnabled(urlScheme);
470 }
471
472 void WebProcess::registerURLSchemeAsAlwaysRevalidated(const String& urlScheme) const
473 {
474     SchemeRegistry::registerURLSchemeAsAlwaysRevalidated(urlScheme);
475 }
476
477 #if ENABLE(CACHE_PARTITIONING)
478 void WebProcess::registerURLSchemeAsCachePartitioned(const String& urlScheme) const
479 {
480     SchemeRegistry::registerURLSchemeAsCachePartitioned(urlScheme);
481 }
482 #endif
483
484 void WebProcess::setDefaultRequestTimeoutInterval(double timeoutInterval)
485 {
486     ResourceRequest::setDefaultTimeoutInterval(timeoutInterval);
487 }
488
489 void WebProcess::setAlwaysUsesComplexTextCodePath(bool alwaysUseComplexText)
490 {
491     WebCore::FontCascade::setCodePath(alwaysUseComplexText ? WebCore::FontCascade::Complex : WebCore::FontCascade::Auto);
492 }
493
494 void WebProcess::setShouldUseFontSmoothing(bool useFontSmoothing)
495 {
496     WebCore::FontCascade::setShouldUseSmoothing(useFontSmoothing);
497 }
498
499 void WebProcess::userPreferredLanguagesChanged(const Vector<String>& languages) const
500 {
501     overrideUserPreferredLanguages(languages);
502     languageDidChange();
503 }
504
505 void WebProcess::fullKeyboardAccessModeChanged(bool fullKeyboardAccessEnabled)
506 {
507     m_fullKeyboardAccessEnabled = fullKeyboardAccessEnabled;
508 }
509
510 void WebProcess::ensurePrivateBrowsingSession(SessionID sessionID)
511 {
512     WebFrameNetworkingContext::ensurePrivateBrowsingSession(sessionID);
513 }
514
515 void WebProcess::destroyPrivateBrowsingSession(SessionID sessionID)
516 {
517     SessionTracker::destroySession(sessionID);
518 }
519
520 void WebProcess::ensureLegacyPrivateBrowsingSessionInNetworkProcess()
521 {
522     networkConnection().connection().send(Messages::NetworkConnectionToWebProcess::EnsureLegacyPrivateBrowsingSession(), 0);
523 }
524
525 #if ENABLE(NETSCAPE_PLUGIN_API)
526 PluginProcessConnectionManager& WebProcess::pluginProcessConnectionManager()
527 {
528     return *m_pluginProcessConnectionManager;
529 }
530 #endif
531
532 void WebProcess::setCacheModel(uint32_t cm)
533 {
534     CacheModel cacheModel = static_cast<CacheModel>(cm);
535
536     if (m_hasSetCacheModel && (cacheModel == m_cacheModel))
537         return;
538
539     m_hasSetCacheModel = true;
540     m_cacheModel = cacheModel;
541
542     unsigned cacheTotalCapacity = 0;
543     unsigned cacheMinDeadCapacity = 0;
544     unsigned cacheMaxDeadCapacity = 0;
545     auto deadDecodedDataDeletionInterval = std::chrono::seconds { 0 };
546     unsigned pageCacheSize = 0;
547     calculateMemoryCacheSizes(cacheModel, cacheTotalCapacity, cacheMinDeadCapacity, cacheMaxDeadCapacity, deadDecodedDataDeletionInterval, pageCacheSize);
548
549     auto& memoryCache = MemoryCache::singleton();
550     memoryCache.setCapacities(cacheMinDeadCapacity, cacheMaxDeadCapacity, cacheTotalCapacity);
551     memoryCache.setDeadDecodedDataDeletionInterval(deadDecodedDataDeletionInterval);
552     PageCache::singleton().setMaxSize(pageCacheSize);
553
554     platformSetCacheModel(cacheModel);
555 }
556
557 void WebProcess::clearCachedCredentials()
558 {
559     NetworkStorageSession::defaultStorageSession().credentialStorage().clearCredentials();
560 #if USE(NETWORK_SESSION)
561     NetworkSession::defaultSession().clearCredentials();
562 #endif
563 }
564
565 WebPage* WebProcess::focusedWebPage() const
566 {    
567     for (auto& page : m_pageMap.values()) {
568         if (page->windowAndWebPageAreFocused())
569             return page.get();
570     }
571     return 0;
572 }
573     
574 WebPage* WebProcess::webPage(uint64_t pageID) const
575 {
576     return m_pageMap.get(pageID);
577 }
578
579 void WebProcess::createWebPage(uint64_t pageID, const WebPageCreationParameters& parameters)
580 {
581     // It is necessary to check for page existence here since during a window.open() (or targeted
582     // link) the WebPage gets created both in the synchronous handler and through the normal way. 
583     HashMap<uint64_t, RefPtr<WebPage>>::AddResult result = m_pageMap.add(pageID, nullptr);
584     if (result.isNewEntry) {
585         ASSERT(!result.iterator->value);
586         result.iterator->value = WebPage::create(pageID, parameters);
587
588         // Balanced by an enableTermination in removeWebPage.
589         disableTermination();
590     } else
591         result.iterator->value->reinitializeWebPage(parameters);
592
593     ASSERT(result.iterator->value);
594 }
595
596 void WebProcess::removeWebPage(uint64_t pageID)
597 {
598     ASSERT(m_pageMap.contains(pageID));
599
600     pageWillLeaveWindow(pageID);
601     m_pageMap.remove(pageID);
602
603     enableTermination();
604 }
605
606 bool WebProcess::shouldTerminate()
607 {
608     ASSERT(m_pageMap.isEmpty());
609
610     // FIXME: the ShouldTerminate message should also send termination parameters, such as any session cookies that need to be preserved.
611     bool shouldTerminate = false;
612     if (parentProcessConnection()->sendSync(Messages::WebProcessProxy::ShouldTerminate(), Messages::WebProcessProxy::ShouldTerminate::Reply(shouldTerminate), 0)
613         && !shouldTerminate)
614         return false;
615
616     return true;
617 }
618
619 void WebProcess::terminate()
620 {
621 #ifndef NDEBUG
622     GCController::singleton().garbageCollectNow();
623     FontCache::singleton().invalidate();
624     MemoryCache::singleton().setDisabled(true);
625 #endif
626
627     m_webConnection->invalidate();
628     m_webConnection = nullptr;
629
630     platformTerminate();
631
632     ChildProcess::terminate();
633 }
634
635 void WebProcess::didReceiveSyncMessage(IPC::Connection& connection, IPC::MessageDecoder& decoder, std::unique_ptr<IPC::MessageEncoder>& replyEncoder)
636 {
637     if (messageReceiverMap().dispatchSyncMessage(connection, decoder, replyEncoder))
638         return;
639
640     didReceiveSyncWebProcessMessage(connection, decoder, replyEncoder);
641 }
642
643 void WebProcess::didReceiveMessage(IPC::Connection& connection, IPC::MessageDecoder& decoder)
644 {
645     if (messageReceiverMap().dispatchMessage(connection, decoder))
646         return;
647
648     if (decoder.messageReceiverName() == Messages::WebProcess::messageReceiverName()) {
649         didReceiveWebProcessMessage(connection, decoder);
650         return;
651     }
652
653     if (decoder.messageReceiverName() == Messages::ChildProcess::messageReceiverName()) {
654         ChildProcess::didReceiveMessage(connection, decoder);
655         return;
656     }
657
658     LOG_ERROR("Unhandled web process message '%s:%s'", decoder.messageReceiverName().toString().data(), decoder.messageName().toString().data());
659 }
660
661 void WebProcess::didClose(IPC::Connection&)
662 {
663 #ifndef NDEBUG
664     m_inDidClose = true;
665
666     // Close all the live pages.
667     Vector<RefPtr<WebPage>> pages;
668     copyValuesToVector(m_pageMap, pages);
669     for (auto& page : pages)
670         page->close();
671     pages.clear();
672
673     GCController::singleton().garbageCollectSoon();
674     FontCache::singleton().invalidate();
675     MemoryCache::singleton().setDisabled(true);
676 #endif
677
678 #if ENABLE(VIDEO)
679     // FIXME(146657): This explicit media stop command should not be necessary
680     if (auto* platformMediaSessionManager = PlatformMediaSessionManager::sharedManagerIfExists())
681         platformMediaSessionManager->stopAllMediaPlaybackForProcess();
682 #endif
683
684     // The UI process closed this connection, shut down.
685     stopRunLoop();
686 }
687
688 void WebProcess::didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference, IPC::StringReference)
689 {
690     // We received an invalid message, but since this is from the UI process (which we trust),
691     // we'll let it slide.
692 }
693
694 WebFrame* WebProcess::webFrame(uint64_t frameID) const
695 {
696     return m_frameMap.get(frameID);
697 }
698
699 void WebProcess::addWebFrame(uint64_t frameID, WebFrame* frame)
700 {
701     m_frameMap.set(frameID, frame);
702 }
703
704 void WebProcess::removeWebFrame(uint64_t frameID)
705 {
706     m_frameMap.remove(frameID);
707
708     // We can end up here after our connection has closed when WebCore's frame life-support timer
709     // fires when the application is shutting down. There's no need (and no way) to update the UI
710     // process in this case.
711     if (!parentProcessConnection())
712         return;
713
714     parentProcessConnection()->send(Messages::WebProcessProxy::DidDestroyFrame(frameID), 0);
715 }
716
717 WebPageGroupProxy* WebProcess::webPageGroup(PageGroup* pageGroup)
718 {
719     for (auto& page : m_pageGroupMap.values()) {
720         if (page->corePageGroup() == pageGroup)
721             return page.get();
722     }
723
724     return 0;
725 }
726
727 WebPageGroupProxy* WebProcess::webPageGroup(uint64_t pageGroupID)
728 {
729     return m_pageGroupMap.get(pageGroupID);
730 }
731
732 WebPageGroupProxy* WebProcess::webPageGroup(const WebPageGroupData& pageGroupData)
733 {
734     auto result = m_pageGroupMap.add(pageGroupData.pageGroupID, nullptr);
735     if (result.isNewEntry) {
736         ASSERT(!result.iterator->value);
737         result.iterator->value = WebPageGroupProxy::create(pageGroupData);
738     }
739
740     return result.iterator->value.get();
741 }
742
743 static uint64_t nextUserGestureTokenIdentifier()
744 {
745     static uint64_t identifier = 1;
746     return identifier++;
747 }
748
749 uint64_t WebProcess::userGestureTokenIdentifier(RefPtr<UserGestureToken> token)
750 {
751     if (!token || !token->processingUserGesture())
752         return 0;
753
754     auto result = m_userGestureTokens.ensure(token.get(), [] { return nextUserGestureTokenIdentifier(); });
755     if (result.isNewEntry) {
756         result.iterator->key->addDestructionObserver([] (UserGestureToken& tokenBeingDestroyed) {
757             WebProcess::singleton().userGestureTokenDestroyed(tokenBeingDestroyed);
758         });
759     }
760     
761     return result.iterator->value;
762 }
763
764 void WebProcess::userGestureTokenDestroyed(UserGestureToken& token)
765 {
766     auto identifier = m_userGestureTokens.take(&token);
767     parentProcessConnection()->send(Messages::WebProcessProxy::DidDestroyUserGestureToken(identifier), 0);
768 }
769
770 void WebProcess::clearResourceCaches(ResourceCachesToClear resourceCachesToClear)
771 {
772     // Toggling the cache model like this forces the cache to evict all its in-memory resources.
773     // FIXME: We need a better way to do this.
774     CacheModel cacheModel = m_cacheModel;
775     setCacheModel(CacheModelDocumentViewer);
776     setCacheModel(cacheModel);
777
778     MemoryCache::singleton().evictResources();
779
780     // Empty the cross-origin preflight cache.
781     CrossOriginPreflightResultCache::singleton().empty();
782 }
783
784 static inline void addCaseFoldedCharacters(StringHasher& hasher, const String& string)
785 {
786     if (string.isEmpty())
787         return;
788     if (string.is8Bit()) {
789         hasher.addCharacters<LChar, ASCIICaseInsensitiveHash::foldCase<LChar>>(string.characters8(), string.length());
790         return;
791     }
792     hasher.addCharacters<UChar, ASCIICaseInsensitiveHash::foldCase<UChar>>(string.characters16(), string.length());
793 }
794
795 static unsigned hashForPlugInOrigin(const String& pageOrigin, const String& pluginOrigin, const String& mimeType)
796 {
797     // We want to avoid concatenating the strings and then taking the hash, since that could lead to an expensive conversion.
798     // We also want to avoid using the hash() function in StringImpl or ASCIICaseInsensitiveHash because that masks out bits for the use of flags.
799     StringHasher hasher;
800     addCaseFoldedCharacters(hasher, pageOrigin);
801     hasher.addCharacter(0);
802     addCaseFoldedCharacters(hasher, pluginOrigin);
803     hasher.addCharacter(0);
804     addCaseFoldedCharacters(hasher, mimeType);
805     return hasher.hash();
806 }
807
808 bool WebProcess::isPlugInAutoStartOriginHash(unsigned plugInOriginHash, SessionID sessionID)
809 {
810     HashMap<WebCore::SessionID, HashMap<unsigned, double>>::const_iterator sessionIterator = m_plugInAutoStartOriginHashes.find(sessionID);
811     HashMap<unsigned, double>::const_iterator it;
812     bool contains = false;
813
814     if (sessionIterator != m_plugInAutoStartOriginHashes.end()) {
815         it = sessionIterator->value.find(plugInOriginHash);
816         contains = it != sessionIterator->value.end();
817     }
818     if (!contains) {
819         sessionIterator = m_plugInAutoStartOriginHashes.find(SessionID::defaultSessionID());
820         it = sessionIterator->value.find(plugInOriginHash);
821         if (it == sessionIterator->value.end())
822             return false;
823     }
824     return currentTime() < it->value;
825 }
826
827 bool WebProcess::shouldPlugInAutoStartFromOrigin(WebPage& webPage, const String& pageOrigin, const String& pluginOrigin, const String& mimeType)
828 {
829     if (!pluginOrigin.isEmpty() && m_plugInAutoStartOrigins.contains(pluginOrigin))
830         return true;
831
832 #ifdef ENABLE_PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC
833     // The plugin wasn't in the general whitelist, so check if it similar to the primary plugin for the page (if we've found one).
834     if (webPage.matchesPrimaryPlugIn(pageOrigin, pluginOrigin, mimeType))
835         return true;
836 #else
837     UNUSED_PARAM(webPage);
838 #endif
839
840     // Lastly check against the more explicit hash list.
841     return isPlugInAutoStartOriginHash(hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType), webPage.sessionID());
842 }
843
844 void WebProcess::plugInDidStartFromOrigin(const String& pageOrigin, const String& pluginOrigin, const String& mimeType, SessionID sessionID)
845 {
846     if (pageOrigin.isEmpty()) {
847         LOG(Plugins, "Not adding empty page origin");
848         return;
849     }
850
851     unsigned plugInOriginHash = hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType);
852     if (isPlugInAutoStartOriginHash(plugInOriginHash, sessionID)) {
853         LOG(Plugins, "Hash %x already exists as auto-start origin (request for %s)", plugInOriginHash, pageOrigin.utf8().data());
854         return;
855     }
856
857     // We might attempt to start another plugin before the didAddPlugInAutoStartOrigin message
858     // comes back from the parent process. Temporarily add this hash to the list with a thirty
859     // second timeout. That way, even if the parent decides not to add it, we'll only be
860     // incorrect for a little while.
861     m_plugInAutoStartOriginHashes.add(sessionID, HashMap<unsigned, double>()).iterator->value.set(plugInOriginHash, currentTime() + 30 * 1000);
862
863     parentProcessConnection()->send(Messages::WebProcessPool::AddPlugInAutoStartOriginHash(pageOrigin, plugInOriginHash, sessionID), 0);
864 }
865
866 void WebProcess::didAddPlugInAutoStartOriginHash(unsigned plugInOriginHash, double expirationTime, SessionID sessionID)
867 {
868     // When called, some web process (which also might be this one) added the origin for auto-starting,
869     // or received user interaction.
870     // Set the bit to avoid having redundantly call into the UI process upon user interaction.
871     m_plugInAutoStartOriginHashes.add(sessionID, HashMap<unsigned, double>()).iterator->value.set(plugInOriginHash, expirationTime);
872 }
873
874 void WebProcess::resetPlugInAutoStartOriginDefaultHashes(const HashMap<unsigned, double>& hashes)
875 {
876     m_plugInAutoStartOriginHashes.clear();
877     m_plugInAutoStartOriginHashes.add(SessionID::defaultSessionID(), HashMap<unsigned, double>()).iterator->value.swap(const_cast<HashMap<unsigned, double>&>(hashes));
878 }
879
880 void WebProcess::resetPlugInAutoStartOriginHashes(const HashMap<SessionID, HashMap<unsigned, double>>& hashes)
881 {
882     m_plugInAutoStartOriginHashes.swap(const_cast<HashMap<SessionID, HashMap<unsigned, double>>&>(hashes));
883 }
884
885 void WebProcess::plugInDidReceiveUserInteraction(const String& pageOrigin, const String& pluginOrigin, const String& mimeType, SessionID sessionID)
886 {
887     if (pageOrigin.isEmpty())
888         return;
889
890     unsigned plugInOriginHash = hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType);
891     if (!plugInOriginHash)
892         return;
893
894     HashMap<WebCore::SessionID, HashMap<unsigned, double>>::const_iterator sessionIterator = m_plugInAutoStartOriginHashes.find(sessionID);
895     HashMap<unsigned, double>::const_iterator it;
896     bool contains = false;
897     if (sessionIterator != m_plugInAutoStartOriginHashes.end()) {
898         it = sessionIterator->value.find(plugInOriginHash);
899         contains = it != sessionIterator->value.end();
900     }
901     if (!contains) {
902         sessionIterator = m_plugInAutoStartOriginHashes.find(SessionID::defaultSessionID());
903         it = sessionIterator->value.find(plugInOriginHash);
904         if (it == sessionIterator->value.end())
905             return;
906     }
907
908     if (it->value - currentTime() > plugInAutoStartExpirationTimeUpdateThreshold)
909         return;
910
911     parentProcessConnection()->send(Messages::WebProcessPool::PlugInDidReceiveUserInteraction(plugInOriginHash, sessionID), 0);
912 }
913
914 void WebProcess::setPluginLoadClientPolicy(uint8_t policy, const String& host, const String& bundleIdentifier, const String& versionString)
915 {
916 #if ENABLE(NETSCAPE_PLUGIN_API) && PLATFORM(MAC)
917     WebPluginInfoProvider::singleton().setPluginLoadClientPolicy(static_cast<PluginLoadClientPolicy>(policy), host, bundleIdentifier, versionString);
918 #endif
919 }
920
921 void WebProcess::clearPluginClientPolicies()
922 {
923 #if ENABLE(NETSCAPE_PLUGIN_API) && PLATFORM(MAC)
924     WebPluginInfoProvider::singleton().clearPluginClientPolicies();
925 #endif
926 }
927
928 static void fromCountedSetToHashMap(TypeCountSet* countedSet, HashMap<String, uint64_t>& map)
929 {
930     TypeCountSet::const_iterator end = countedSet->end();
931     for (TypeCountSet::const_iterator it = countedSet->begin(); it != end; ++it)
932         map.set(it->key, it->value);
933 }
934
935 static void getWebCoreMemoryCacheStatistics(Vector<HashMap<String, uint64_t>>& result)
936 {
937     String imagesString(ASCIILiteral("Images"));
938     String cssString(ASCIILiteral("CSS"));
939     String xslString(ASCIILiteral("XSL"));
940     String javaScriptString(ASCIILiteral("JavaScript"));
941     
942     MemoryCache::Statistics memoryCacheStatistics = MemoryCache::singleton().getStatistics();
943     
944     HashMap<String, uint64_t> counts;
945     counts.set(imagesString, memoryCacheStatistics.images.count);
946     counts.set(cssString, memoryCacheStatistics.cssStyleSheets.count);
947     counts.set(xslString, memoryCacheStatistics.xslStyleSheets.count);
948     counts.set(javaScriptString, memoryCacheStatistics.scripts.count);
949     result.append(counts);
950     
951     HashMap<String, uint64_t> sizes;
952     sizes.set(imagesString, memoryCacheStatistics.images.size);
953     sizes.set(cssString, memoryCacheStatistics.cssStyleSheets.size);
954     sizes.set(xslString, memoryCacheStatistics.xslStyleSheets.size);
955     sizes.set(javaScriptString, memoryCacheStatistics.scripts.size);
956     result.append(sizes);
957     
958     HashMap<String, uint64_t> liveSizes;
959     liveSizes.set(imagesString, memoryCacheStatistics.images.liveSize);
960     liveSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.liveSize);
961     liveSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.liveSize);
962     liveSizes.set(javaScriptString, memoryCacheStatistics.scripts.liveSize);
963     result.append(liveSizes);
964     
965     HashMap<String, uint64_t> decodedSizes;
966     decodedSizes.set(imagesString, memoryCacheStatistics.images.decodedSize);
967     decodedSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.decodedSize);
968     decodedSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.decodedSize);
969     decodedSizes.set(javaScriptString, memoryCacheStatistics.scripts.decodedSize);
970     result.append(decodedSizes);
971 }
972
973 void WebProcess::getWebCoreStatistics(uint64_t callbackID)
974 {
975     StatisticsData data;
976     
977     // Gather JavaScript statistics.
978     {
979         JSLockHolder lock(JSDOMWindow::commonVM());
980         data.statisticsNumbers.set(ASCIILiteral("JavaScriptObjectsCount"), JSDOMWindow::commonVM().heap.objectCount());
981         data.statisticsNumbers.set(ASCIILiteral("JavaScriptGlobalObjectsCount"), JSDOMWindow::commonVM().heap.globalObjectCount());
982         data.statisticsNumbers.set(ASCIILiteral("JavaScriptProtectedObjectsCount"), JSDOMWindow::commonVM().heap.protectedObjectCount());
983         data.statisticsNumbers.set(ASCIILiteral("JavaScriptProtectedGlobalObjectsCount"), JSDOMWindow::commonVM().heap.protectedGlobalObjectCount());
984         
985         std::unique_ptr<TypeCountSet> protectedObjectTypeCounts(JSDOMWindow::commonVM().heap.protectedObjectTypeCounts());
986         fromCountedSetToHashMap(protectedObjectTypeCounts.get(), data.javaScriptProtectedObjectTypeCounts);
987         
988         std::unique_ptr<TypeCountSet> objectTypeCounts(JSDOMWindow::commonVM().heap.objectTypeCounts());
989         fromCountedSetToHashMap(objectTypeCounts.get(), data.javaScriptObjectTypeCounts);
990         
991         uint64_t javaScriptHeapSize = JSDOMWindow::commonVM().heap.size();
992         data.statisticsNumbers.set(ASCIILiteral("JavaScriptHeapSize"), javaScriptHeapSize);
993         data.statisticsNumbers.set(ASCIILiteral("JavaScriptFreeSize"), JSDOMWindow::commonVM().heap.capacity() - javaScriptHeapSize);
994     }
995
996     WTF::FastMallocStatistics fastMallocStatistics = WTF::fastMallocStatistics();
997     data.statisticsNumbers.set(ASCIILiteral("FastMallocReservedVMBytes"), fastMallocStatistics.reservedVMBytes);
998     data.statisticsNumbers.set(ASCIILiteral("FastMallocCommittedVMBytes"), fastMallocStatistics.committedVMBytes);
999     data.statisticsNumbers.set(ASCIILiteral("FastMallocFreeListBytes"), fastMallocStatistics.freeListBytes);
1000     
1001     // Gather icon statistics.
1002     data.statisticsNumbers.set(ASCIILiteral("IconPageURLMappingCount"), iconDatabase().pageURLMappingCount());
1003     data.statisticsNumbers.set(ASCIILiteral("IconRetainedPageURLCount"), iconDatabase().retainedPageURLCount());
1004     data.statisticsNumbers.set(ASCIILiteral("IconRecordCount"), iconDatabase().iconRecordCount());
1005     data.statisticsNumbers.set(ASCIILiteral("IconsWithDataCount"), iconDatabase().iconRecordCountWithData());
1006     
1007     // Gather font statistics.
1008     auto& fontCache = FontCache::singleton();
1009     data.statisticsNumbers.set(ASCIILiteral("CachedFontDataCount"), fontCache.fontCount());
1010     data.statisticsNumbers.set(ASCIILiteral("CachedFontDataInactiveCount"), fontCache.inactiveFontCount());
1011     
1012     // Gather glyph page statistics.
1013     data.statisticsNumbers.set(ASCIILiteral("GlyphPageCount"), GlyphPage::count());
1014     
1015     // Get WebCore memory cache statistics
1016     getWebCoreMemoryCacheStatistics(data.webCoreCacheStatistics);
1017     
1018     parentProcessConnection()->send(Messages::WebProcessPool::DidGetStatistics(data, callbackID), 0);
1019 }
1020
1021 void WebProcess::garbageCollectJavaScriptObjects()
1022 {
1023     GCController::singleton().garbageCollectNow();
1024 }
1025
1026 void WebProcess::mainThreadPing()
1027 {
1028     parentProcessConnection()->send(Messages::WebProcessProxy::DidReceiveMainThreadPing(), 0);
1029 }
1030
1031 #if ENABLE(GAMEPAD)
1032
1033 void WebProcess::setInitialGamepads(const Vector<WebKit::GamepadData>& gamepadDatas)
1034 {
1035     WebGamepadProvider::singleton().setInitialGamepads(gamepadDatas);
1036 }
1037
1038 void WebProcess::gamepadConnected(const GamepadData& gamepadData)
1039 {
1040     WebGamepadProvider::singleton().gamepadConnected(gamepadData);
1041 }
1042
1043 void WebProcess::gamepadDisconnected(unsigned index)
1044 {
1045     WebGamepadProvider::singleton().gamepadDisconnected(index);
1046 }
1047
1048 #endif
1049
1050 void WebProcess::setJavaScriptGarbageCollectorTimerEnabled(bool flag)
1051 {
1052     GCController::singleton().setJavaScriptGarbageCollectorTimerEnabled(flag);
1053 }
1054
1055 void WebProcess::handleInjectedBundleMessage(const String& messageName, const UserData& messageBody)
1056 {
1057     InjectedBundle* injectedBundle = WebProcess::singleton().injectedBundle();
1058     if (!injectedBundle)
1059         return;
1060
1061     injectedBundle->didReceiveMessage(messageName, transformHandlesToObjects(messageBody.object()).get());
1062 }
1063
1064 void WebProcess::setInjectedBundleParameter(const String& key, const IPC::DataReference& value)
1065 {
1066     InjectedBundle* injectedBundle = WebProcess::singleton().injectedBundle();
1067     if (!injectedBundle)
1068         return;
1069
1070     injectedBundle->setBundleParameter(key, value);
1071 }
1072
1073 void WebProcess::setInjectedBundleParameters(const IPC::DataReference& value)
1074 {
1075     InjectedBundle* injectedBundle = WebProcess::singleton().injectedBundle();
1076     if (!injectedBundle)
1077         return;
1078
1079     injectedBundle->setBundleParameters(value);
1080 }
1081
1082 NetworkProcessConnection& WebProcess::networkConnection()
1083 {
1084     // If we've lost our connection to the network process (e.g. it crashed) try to re-establish it.
1085     if (!m_networkProcessConnection)
1086         ensureNetworkProcessConnection();
1087     
1088     // If we failed to re-establish it then we are beyond recovery and should crash.
1089     if (!m_networkProcessConnection)
1090         CRASH();
1091     
1092     return *m_networkProcessConnection;
1093 }
1094
1095 void WebProcess::networkProcessConnectionClosed(NetworkProcessConnection* connection)
1096 {
1097     ASSERT(m_networkProcessConnection);
1098     ASSERT_UNUSED(connection, m_networkProcessConnection == connection);
1099
1100     m_networkProcessConnection = nullptr;
1101     
1102     m_webLoaderStrategy.networkProcessCrashed();
1103 }
1104
1105 WebLoaderStrategy& WebProcess::webLoaderStrategy()
1106 {
1107     return m_webLoaderStrategy;
1108 }
1109
1110 #if ENABLE(DATABASE_PROCESS)
1111 void WebProcess::webToDatabaseProcessConnectionClosed(WebToDatabaseProcessConnection* connection)
1112 {
1113     ASSERT(m_webToDatabaseProcessConnection);
1114     ASSERT(m_webToDatabaseProcessConnection == connection);
1115
1116     m_webToDatabaseProcessConnection = nullptr;
1117 }
1118
1119 WebToDatabaseProcessConnection* WebProcess::webToDatabaseProcessConnection()
1120 {
1121     if (!m_webToDatabaseProcessConnection)
1122         ensureWebToDatabaseProcessConnection();
1123
1124     return m_webToDatabaseProcessConnection.get();
1125 }
1126
1127 void WebProcess::ensureWebToDatabaseProcessConnection()
1128 {
1129     if (m_webToDatabaseProcessConnection)
1130         return;
1131
1132     IPC::Attachment encodedConnectionIdentifier;
1133
1134     if (!parentProcessConnection()->sendSync(Messages::WebProcessProxy::GetDatabaseProcessConnection(),
1135         Messages::WebProcessProxy::GetDatabaseProcessConnection::Reply(encodedConnectionIdentifier), 0))
1136         return;
1137
1138 #if USE(UNIX_DOMAIN_SOCKETS)
1139     IPC::Connection::Identifier connectionIdentifier = encodedConnectionIdentifier.releaseFileDescriptor();
1140 #elif OS(DARWIN)
1141     IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.port());
1142 #else
1143     ASSERT_NOT_REACHED();
1144 #endif
1145     if (IPC::Connection::identifierIsNull(connectionIdentifier))
1146         return;
1147     m_webToDatabaseProcessConnection = WebToDatabaseProcessConnection::create(connectionIdentifier);
1148 }
1149
1150 #endif // ENABLED(DATABASE_PROCESS)
1151
1152 void WebProcess::setEnhancedAccessibility(bool flag)
1153 {
1154     WebCore::AXObjectCache::setEnhancedUserInterfaceAccessibility(flag);
1155 }
1156     
1157 void WebProcess::startMemorySampler(const SandboxExtension::Handle& sampleLogFileHandle, const String& sampleLogFilePath, const double interval)
1158 {
1159 #if ENABLE(MEMORY_SAMPLER)    
1160     WebMemorySampler::singleton()->start(sampleLogFileHandle, sampleLogFilePath, interval);
1161 #else
1162     UNUSED_PARAM(sampleLogFileHandle);
1163     UNUSED_PARAM(sampleLogFilePath);
1164     UNUSED_PARAM(interval);
1165 #endif
1166 }
1167     
1168 void WebProcess::stopMemorySampler()
1169 {
1170 #if ENABLE(MEMORY_SAMPLER)
1171     WebMemorySampler::singleton()->stop();
1172 #endif
1173 }
1174
1175 void WebProcess::setTextCheckerState(const TextCheckerState& textCheckerState)
1176 {
1177     bool continuousSpellCheckingTurnedOff = !textCheckerState.isContinuousSpellCheckingEnabled && m_textCheckerState.isContinuousSpellCheckingEnabled;
1178     bool grammarCheckingTurnedOff = !textCheckerState.isGrammarCheckingEnabled && m_textCheckerState.isGrammarCheckingEnabled;
1179
1180     m_textCheckerState = textCheckerState;
1181
1182     if (!continuousSpellCheckingTurnedOff && !grammarCheckingTurnedOff)
1183         return;
1184
1185     for (auto& page : m_pageMap.values()) {
1186         if (continuousSpellCheckingTurnedOff)
1187             page->unmarkAllMisspellings();
1188         if (grammarCheckingTurnedOff)
1189             page->unmarkAllBadGrammar();
1190     }
1191 }
1192
1193 void WebProcess::releasePageCache()
1194 {
1195     PageCache::singleton().pruneToSizeNow(0, PruningReason::MemoryPressure);
1196 }
1197
1198 void WebProcess::fetchWebsiteData(SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, uint64_t callbackID)
1199 {
1200     WebsiteData websiteData;
1201
1202     if (websiteDataTypes.contains(WebsiteDataType::MemoryCache)) {
1203         for (auto& origin : MemoryCache::singleton().originsWithCache(sessionID))
1204             websiteData.entries.append(WebsiteData::Entry { origin, WebsiteDataType::MemoryCache, 0 });
1205     }
1206
1207     parentProcessConnection()->send(Messages::WebProcessProxy::DidFetchWebsiteData(callbackID, websiteData), 0);
1208 }
1209
1210 void WebProcess::deleteWebsiteData(SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, std::chrono::system_clock::time_point modifiedSince, uint64_t callbackID)
1211 {
1212     UNUSED_PARAM(modifiedSince);
1213
1214     if (websiteDataTypes.contains(WebsiteDataType::MemoryCache)) {
1215         PageCache::singleton().pruneToSizeNow(0, PruningReason::None);
1216         MemoryCache::singleton().evictResources(sessionID);
1217
1218         CrossOriginPreflightResultCache::singleton().empty();
1219     }
1220
1221     parentProcessConnection()->send(Messages::WebProcessProxy::DidDeleteWebsiteData(callbackID), 0);
1222 }
1223
1224 void WebProcess::deleteWebsiteDataForOrigins(WebCore::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, const Vector<WebCore::SecurityOriginData>& originDatas, uint64_t callbackID)
1225 {
1226     if (websiteDataTypes.contains(WebsiteDataType::MemoryCache)) {
1227         HashSet<RefPtr<SecurityOrigin>> origins;
1228         for (auto& originData : originDatas)
1229             origins.add(originData.securityOrigin());
1230
1231         MemoryCache::singleton().removeResourcesWithOrigins(sessionID, origins);
1232     }
1233
1234     parentProcessConnection()->send(Messages::WebProcessProxy::DidDeleteWebsiteDataForOrigins(callbackID), 0);
1235 }
1236
1237 void WebProcess::setHiddenPageTimerThrottlingIncreaseLimit(int milliseconds)
1238 {
1239     for (auto& page : m_pageMap.values())
1240         page->setHiddenPageTimerThrottlingIncreaseLimit(std::chrono::milliseconds(milliseconds));
1241 }
1242
1243 #if !PLATFORM(COCOA)
1244 void WebProcess::initializeProcessName(const ChildProcessInitializationParameters&)
1245 {
1246 }
1247
1248 void WebProcess::initializeSandbox(const ChildProcessInitializationParameters&, SandboxInitializationParameters&)
1249 {
1250 }
1251
1252 void WebProcess::platformInitializeProcess(const ChildProcessInitializationParameters&)
1253 {
1254 }
1255
1256 void WebProcess::updateActivePages()
1257 {
1258 }
1259
1260 #endif
1261
1262 #if PLATFORM(IOS)
1263 void WebProcess::resetAllGeolocationPermissions()
1264 {
1265     for (auto& page : m_pageMap.values()) {
1266         if (Frame* mainFrame = page->mainFrame())
1267             mainFrame->resetAllGeolocationPermission();
1268     }
1269 }
1270 #endif
1271
1272 void WebProcess::actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend shouldAcknowledgeWhenReadyToSuspend)
1273 {
1274     if (!m_suppressMemoryPressureHandler)
1275         MemoryPressureHandler::singleton().releaseMemory(Critical::Yes, Synchronous::Yes);
1276
1277     setAllLayerTreeStatesFrozen(true);
1278
1279     markAllLayersVolatile([this, shouldAcknowledgeWhenReadyToSuspend] {
1280         RELEASE_LOG("%p - WebProcess::markAllLayersVolatile() Successfuly marked all layers as volatile", this);
1281
1282         if (shouldAcknowledgeWhenReadyToSuspend == ShouldAcknowledgeWhenReadyToSuspend::Yes) {
1283             RELEASE_LOG("%p - WebProcess::actualPrepareToSuspend() Sending ProcessReadyToSuspend IPC message", this);
1284             parentProcessConnection()->send(Messages::WebProcessProxy::ProcessReadyToSuspend(), 0);
1285         }
1286     });
1287 }
1288
1289 void WebProcess::processWillSuspendImminently(bool& handled)
1290 {
1291     if (parentProcessConnection()->inSendSync()) {
1292         // Avoid reentrency bugs such as rdar://problem/21605505 by just bailing
1293         // if we get an incoming ProcessWillSuspendImminently message when waiting for a
1294         // reply to a sync message.
1295         // FIXME: ProcessWillSuspendImminently should not be a sync message.
1296         return;
1297     }
1298
1299     RELEASE_LOG("%p - WebProcess::processWillSuspendImminently()", this);
1300     DatabaseTracker::tracker().closeAllDatabases(CurrentQueryBehavior::Interrupt);
1301     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::No);
1302     handled = true;
1303 }
1304
1305 void WebProcess::prepareToSuspend()
1306 {
1307     RELEASE_LOG("%p - WebProcess::prepareToSuspend()", this);
1308     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::Yes);
1309 }
1310
1311 void WebProcess::cancelPrepareToSuspend()
1312 {
1313     RELEASE_LOG("%p - WebProcess::cancelPrepareToSuspend()", this);
1314     setAllLayerTreeStatesFrozen(false);
1315
1316     // If we've already finished cleaning up and sent ProcessReadyToSuspend, we
1317     // shouldn't send DidCancelProcessSuspension; the UI process strictly expects one or the other.
1318     if (!m_pagesMarkingLayersAsVolatile)
1319         return;
1320
1321     cancelMarkAllLayersVolatile();
1322
1323     RELEASE_LOG("%p - WebProcess::cancelPrepareToSuspend() Sending DidCancelProcessSuspension IPC message", this);
1324     parentProcessConnection()->send(Messages::WebProcessProxy::DidCancelProcessSuspension(), 0);
1325 }
1326
1327 void WebProcess::markAllLayersVolatile(std::function<void()> completionHandler)
1328 {
1329     RELEASE_LOG("%p - WebProcess::markAllLayersVolatile()", this);
1330     m_pagesMarkingLayersAsVolatile = m_pageMap.size();
1331     if (!m_pagesMarkingLayersAsVolatile) {
1332         completionHandler();
1333         return;
1334     }
1335     for (auto& page : m_pageMap.values()) {
1336         page->markLayersVolatile([this, completionHandler] {
1337             ASSERT(m_pagesMarkingLayersAsVolatile);
1338             if (!--m_pagesMarkingLayersAsVolatile)
1339                 completionHandler();
1340         });
1341     }
1342 }
1343
1344 void WebProcess::cancelMarkAllLayersVolatile()
1345 {
1346     if (!m_pagesMarkingLayersAsVolatile)
1347         return;
1348
1349     for (auto& page : m_pageMap.values())
1350         page->cancelMarkLayersVolatile();
1351     m_pagesMarkingLayersAsVolatile = 0;
1352 }
1353
1354 void WebProcess::setAllLayerTreeStatesFrozen(bool frozen)
1355 {
1356     for (auto& page : m_pageMap.values())
1357         page->setLayerTreeStateIsFrozen(frozen);
1358 }
1359     
1360 void WebProcess::processDidResume()
1361 {
1362     RELEASE_LOG("%p - WebProcess::processDidResume()", this);
1363
1364     cancelMarkAllLayersVolatile();
1365     setAllLayerTreeStatesFrozen(false);
1366 }
1367
1368 void WebProcess::pageDidEnterWindow(uint64_t pageID)
1369 {
1370     m_pagesInWindows.add(pageID);
1371     m_nonVisibleProcessCleanupTimer.stop();
1372 }
1373
1374 void WebProcess::pageWillLeaveWindow(uint64_t pageID)
1375 {
1376     m_pagesInWindows.remove(pageID);
1377
1378     if (m_pagesInWindows.isEmpty() && !m_nonVisibleProcessCleanupTimer.isActive())
1379         m_nonVisibleProcessCleanupTimer.startOneShot(nonVisibleProcessCleanupDelay);
1380 }
1381     
1382 void WebProcess::nonVisibleProcessCleanupTimerFired()
1383 {
1384     ASSERT(m_pagesInWindows.isEmpty());
1385     if (!m_pagesInWindows.isEmpty())
1386         return;
1387
1388 #if PLATFORM(COCOA)
1389     destroyRenderingResources();
1390 #endif
1391 }
1392
1393 void WebProcess::statisticsChangedTimerFired()
1394 {
1395     if (m_resourceLoadStatisticsStorage->isEmpty())
1396         return;
1397
1398     parentProcessConnection()->send(Messages::WebResourceLoadStatisticsStore::ResourceLoadStatisticsUpdated(m_resourceLoadStatisticsStorage->takeStatistics()), 0);
1399 }
1400
1401 void WebProcess::setResourceLoadStatisticsEnabled(bool enabled)
1402 {
1403     WebCore::Settings::setResourceLoadStatisticsEnabled(enabled);
1404 }
1405
1406 RefPtr<API::Object> WebProcess::transformHandlesToObjects(API::Object* object)
1407 {
1408     struct Transformer final : UserData::Transformer {
1409         Transformer(WebProcess& webProcess)
1410             : m_webProcess(webProcess)
1411         {
1412         }
1413
1414         bool shouldTransformObject(const API::Object& object) const override
1415         {
1416             switch (object.type()) {
1417             case API::Object::Type::FrameHandle:
1418                 return static_cast<const API::FrameHandle&>(object).isAutoconverting();
1419
1420             case API::Object::Type::PageHandle:
1421                 return static_cast<const API::PageHandle&>(object).isAutoconverting();
1422
1423             case API::Object::Type::PageGroupHandle:
1424 #if PLATFORM(COCOA)
1425             case API::Object::Type::ObjCObjectGraph:
1426 #endif
1427                 return true;
1428
1429             default:
1430                 return false;
1431             }
1432         }
1433
1434         RefPtr<API::Object> transformObject(API::Object& object) const override
1435         {
1436             switch (object.type()) {
1437             case API::Object::Type::FrameHandle:
1438                 return m_webProcess.webFrame(static_cast<const API::FrameHandle&>(object).frameID());
1439
1440             case API::Object::Type::PageGroupHandle:
1441                 return m_webProcess.webPageGroup(static_cast<const API::PageGroupHandle&>(object).webPageGroupData());
1442
1443             case API::Object::Type::PageHandle:
1444                 return m_webProcess.webPage(static_cast<const API::PageHandle&>(object).pageID());
1445
1446 #if PLATFORM(COCOA)
1447             case API::Object::Type::ObjCObjectGraph:
1448                 return m_webProcess.transformHandlesToObjects(static_cast<ObjCObjectGraph&>(object));
1449 #endif
1450             default:
1451                 return &object;
1452             }
1453         }
1454
1455         WebProcess& m_webProcess;
1456     };
1457
1458     return UserData::transform(object, Transformer(*this));
1459 }
1460
1461 RefPtr<API::Object> WebProcess::transformObjectsToHandles(API::Object* object)
1462 {
1463     struct Transformer final : UserData::Transformer {
1464         bool shouldTransformObject(const API::Object& object) const override
1465         {
1466             switch (object.type()) {
1467             case API::Object::Type::BundleFrame:
1468             case API::Object::Type::BundlePage:
1469             case API::Object::Type::BundlePageGroup:
1470 #if PLATFORM(COCOA)
1471             case API::Object::Type::ObjCObjectGraph:
1472 #endif
1473                 return true;
1474
1475             default:
1476                 return false;
1477             }
1478         }
1479
1480         RefPtr<API::Object> transformObject(API::Object& object) const override
1481         {
1482             switch (object.type()) {
1483             case API::Object::Type::BundleFrame:
1484                 return API::FrameHandle::createAutoconverting(static_cast<const WebFrame&>(object).frameID());
1485
1486             case API::Object::Type::BundlePage:
1487                 return API::PageHandle::createAutoconverting(static_cast<const WebPage&>(object).pageID());
1488
1489             case API::Object::Type::BundlePageGroup: {
1490                 WebPageGroupData pageGroupData;
1491                 pageGroupData.pageGroupID = static_cast<const WebPageGroupProxy&>(object).pageGroupID();
1492
1493                 return API::PageGroupHandle::create(WTFMove(pageGroupData));
1494             }
1495
1496 #if PLATFORM(COCOA)
1497             case API::Object::Type::ObjCObjectGraph:
1498                 return transformObjectsToHandles(static_cast<ObjCObjectGraph&>(object));
1499 #endif
1500
1501             default:
1502                 return &object;
1503             }
1504         }
1505     };
1506
1507     return UserData::transform(object, Transformer());
1508 }
1509
1510 void WebProcess::setMemoryCacheDisabled(bool disabled)
1511 {
1512     auto& memoryCache = MemoryCache::singleton();
1513     if (memoryCache.disabled() != disabled)
1514         memoryCache.setDisabled(disabled);
1515 }
1516
1517 #if ENABLE(SERVICE_CONTROLS)
1518 void WebProcess::setEnabledServices(bool hasImageServices, bool hasSelectionServices, bool hasRichContentServices)
1519 {
1520     m_hasImageServices = hasImageServices;
1521     m_hasSelectionServices = hasSelectionServices;
1522     m_hasRichContentServices = hasRichContentServices;
1523 }
1524 #endif
1525
1526 void WebProcess::ensureAutomationSessionProxy(const String& sessionIdentifier)
1527 {
1528     m_automationSessionProxy = std::make_unique<WebAutomationSessionProxy>(sessionIdentifier);
1529 }
1530
1531 void WebProcess::destroyAutomationSessionProxy()
1532 {
1533     m_automationSessionProxy = nullptr;
1534 }
1535
1536 void WebProcess::prefetchDNS(const String& hostname)
1537 {
1538     if (hostname.isEmpty())
1539         return;
1540
1541     if (m_dnsPrefetchedHosts.add(hostname).isNewEntry)
1542         networkConnection().connection().send(Messages::NetworkConnectionToWebProcess::PrefetchDNS(hostname), 0);
1543     // The DNS prefetched hosts cache is only to avoid asking for the same hosts too many times
1544     // in a very short period of time, producing a lot of IPC traffic. So we clear this cache after
1545     // some time of no DNS requests.
1546     m_dnsPrefetchHystereris.impulse();
1547 }
1548
1549 } // namespace WebKit