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