Remove support for legacy Notifications
[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 "WebSocketStream.h"
67 #include "WebsiteData.h"
68 #include "WebsiteDataType.h"
69 #include <JavaScriptCore/JSLock.h>
70 #include <JavaScriptCore/MemoryStatistics.h>
71 #include <JavaScriptCore/WasmFaultSignalHandler.h>
72 #include <WebCore/AXObjectCache.h>
73 #include <WebCore/ApplicationCacheStorage.h>
74 #include <WebCore/AuthenticationChallenge.h>
75 #include <WebCore/CPUMonitor.h>
76 #include <WebCore/CommonVM.h>
77 #include <WebCore/CrossOriginPreflightResultCache.h>
78 #include <WebCore/DNS.h>
79 #include <WebCore/DatabaseManager.h>
80 #include <WebCore/DatabaseTracker.h>
81 #include <WebCore/DiagnosticLoggingClient.h>
82 #include <WebCore/DiagnosticLoggingKeys.h>
83 #include <WebCore/FontCache.h>
84 #include <WebCore/FontCascade.h>
85 #include <WebCore/Frame.h>
86 #include <WebCore/FrameLoader.h>
87 #include <WebCore/GCController.h>
88 #include <WebCore/GlyphPage.h>
89 #include <WebCore/HTMLMediaElement.h>
90 #include <WebCore/IconDatabase.h>
91 #include <WebCore/JSDOMWindow.h>
92 #include <WebCore/Language.h>
93 #include <WebCore/MainFrame.h>
94 #include <WebCore/MemoryCache.h>
95 #include <WebCore/MemoryRelease.h>
96 #include <WebCore/NetworkStorageSession.h>
97 #include <WebCore/Page.h>
98 #include <WebCore/PageCache.h>
99 #include <WebCore/PageGroup.h>
100 #include <WebCore/PlatformMediaSessionManager.h>
101 #include <WebCore/ResourceHandle.h>
102 #include <WebCore/ResourceLoadObserver.h>
103 #include <WebCore/ResourceLoadStatistics.h>
104 #include <WebCore/ResourceLoadStatisticsStore.h>
105 #include <WebCore/RuntimeApplicationChecks.h>
106 #include <WebCore/SchemeRegistry.h>
107 #include <WebCore/SecurityOrigin.h>
108 #include <WebCore/Settings.h>
109 #include <WebCore/URLParser.h>
110 #include <WebCore/UserGestureIndicator.h>
111 #include <unistd.h>
112 #include <wtf/CurrentTime.h>
113 #include <wtf/HashCountedSet.h>
114 #include <wtf/RunLoop.h>
115 #include <wtf/text/StringHash.h>
116
117 #if PLATFORM(COCOA)
118 #include "CookieStorageShim.h"
119 #include "ObjCObjectGraph.h"
120 #include "UserMediaCaptureManager.h"
121 #endif
122
123 #if ENABLE(SEC_ITEM_SHIM)
124 #include "SecItemShim.h"
125 #endif
126
127 #if ENABLE(DATABASE_PROCESS)
128 #include "WebToDatabaseProcessConnection.h"
129 #endif
130
131 #if ENABLE(NOTIFICATIONS)
132 #include "WebNotificationManager.h"
133 #endif
134
135 #if ENABLE(REMOTE_INSPECTOR)
136 #include <JavaScriptCore/RemoteInspector.h>
137 #endif
138
139 using namespace JSC;
140 using namespace WebCore;
141
142 // This should be less than plugInAutoStartExpirationTimeThreshold in PlugInAutoStartProvider.
143 static const double plugInAutoStartExpirationTimeUpdateThreshold = 29 * 24 * 60 * 60;
144
145 // This should be greater than tileRevalidationTimeout in TileController.
146 static const Seconds nonVisibleProcessCleanupDelay { 10_s };
147
148 namespace WebKit {
149
150 WebProcess& WebProcess::singleton()
151 {
152     static WebProcess& process = *new WebProcess;
153     return process;
154 }
155
156 WebProcess::WebProcess()
157     : m_eventDispatcher(EventDispatcher::create())
158 #if PLATFORM(IOS)
159     , m_viewUpdateDispatcher(ViewUpdateDispatcher::create())
160 #endif
161     , m_webInspectorInterruptDispatcher(WebInspectorInterruptDispatcher::create())
162     , m_iconDatabaseProxy(*new WebIconDatabaseProxy(*this))
163     , m_webLoaderStrategy(*new WebLoaderStrategy)
164     , m_dnsPrefetchHystereris([this](HysteresisState state) { if (state == HysteresisState::Stopped) m_dnsPrefetchedHosts.clear(); })
165 #if ENABLE(NETSCAPE_PLUGIN_API)
166     , m_pluginProcessConnectionManager(PluginProcessConnectionManager::create())
167 #endif
168     , m_nonVisibleProcessCleanupTimer(*this, &WebProcess::nonVisibleProcessCleanupTimerFired)
169     , m_statisticsChangedTimer(*this, &WebProcess::statisticsChangedTimerFired)
170 #if PLATFORM(IOS)
171     , m_webSQLiteDatabaseTracker(*this)
172 #endif
173     , m_resourceLoadStatisticsStore(WebCore::ResourceLoadStatisticsStore::create())
174 {
175     // Initialize our platform strategies.
176     WebPlatformStrategies::initialize();
177
178     // FIXME: This should moved to where WebProcess::initialize is called,
179     // so that ports have a chance to customize, and ifdefs in this file are
180     // limited.
181     addSupplement<WebGeolocationManager>();
182     addSupplement<WebCookieManager>();
183     addSupplement<AuthenticationManager>();
184
185 #if ENABLE(NOTIFICATIONS)
186     addSupplement<WebNotificationManager>();
187 #endif
188
189 #if ENABLE(LEGACY_ENCRYPTED_MEDIA)
190     addSupplement<WebMediaKeyStorageManager>();
191 #endif
192
193 #if PLATFORM(COCOA) && ENABLE(MEDIA_STREAM)
194     addSupplement<UserMediaCaptureManager>();
195 #endif
196
197     m_plugInAutoStartOriginHashes.add(SessionID::defaultSessionID(), HashMap<unsigned, double>());
198
199     ResourceLoadObserver::sharedObserver().setStatisticsStore(m_resourceLoadStatisticsStore.copyRef());
200     m_resourceLoadStatisticsStore->setNotificationCallback([this] {
201         if (m_statisticsChangedTimer.isActive())
202             return;
203         m_statisticsChangedTimer.startOneShot(5_s);
204     });
205 }
206
207 WebProcess::~WebProcess()
208 {
209 }
210
211 void WebProcess::initializeProcess(const ChildProcessInitializationParameters& parameters)
212 {
213     platformInitializeProcess(parameters);
214 }
215
216 void WebProcess::initializeConnection(IPC::Connection* connection)
217 {
218     ChildProcess::initializeConnection(connection);
219
220     connection->setShouldExitOnSyncMessageSendFailure(true);
221
222 #if HAVE(QOS_CLASSES)
223     connection->setShouldBoostMainThreadOnSyncMessage(true);
224 #endif
225
226     m_eventDispatcher->initializeConnection(connection);
227 #if PLATFORM(IOS)
228     m_viewUpdateDispatcher->initializeConnection(connection);
229 #endif // PLATFORM(IOS)
230     m_webInspectorInterruptDispatcher->initializeConnection(connection);
231
232 #if ENABLE(NETSCAPE_PLUGIN_API)
233     m_pluginProcessConnectionManager->initializeConnection(connection);
234 #endif
235
236     for (auto& supplement : m_supplements.values())
237         supplement->initializeConnection(connection);
238
239     m_webConnection = WebConnectionToUIProcess::create(this);
240
241     // In order to ensure that the asynchronous messages that are used for notifying the UI process
242     // about when WebFrame objects come and go are always delivered before the synchronous policy messages,
243     // use this flag to force synchronous messages to be treated as asynchronous messages in the UI process
244     // unless when doing so would lead to a deadlock.
245     connection->setOnlySendMessagesAsDispatchWhenWaitingForSyncReplyWhenProcessingSuchAMessage(true);
246 }
247
248 void WebProcess::initializeWebProcess(WebProcessCreationParameters&& parameters)
249 {    
250     ASSERT(m_pageMap.isEmpty());
251
252 #if OS(LINUX)
253     if (parameters.memoryPressureMonitorHandle.fileDescriptor() != -1)
254         MemoryPressureHandler::singleton().setMemoryPressureMonitorHandle(parameters.memoryPressureMonitorHandle.releaseFileDescriptor());
255     MemoryPressureHandler::ReliefLogger::setLoggingEnabled(parameters.shouldEnableMemoryPressureReliefLogging);
256 #endif
257
258     platformInitializeWebProcess(WTFMove(parameters));
259
260     // Match the QoS of the UIProcess and the scrolling thread but use a slightly lower priority.
261     WTF::Thread::setCurrentThreadIsUserInteractive(-1);
262
263     m_suppressMemoryPressureHandler = parameters.shouldSuppressMemoryPressureHandler;
264     if (!m_suppressMemoryPressureHandler) {
265         auto& memoryPressureHandler = MemoryPressureHandler::singleton();
266         memoryPressureHandler.setLowMemoryHandler([] (Critical critical, Synchronous synchronous) {
267             WebCore::releaseMemory(critical, synchronous);
268         });
269 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
270         memoryPressureHandler.setShouldUsePeriodicMemoryMonitor(true);
271         memoryPressureHandler.setMemoryKillCallback([this] () {
272             WebCore::logMemoryStatisticsAtTimeOfDeath();
273             if (MemoryPressureHandler::singleton().processState() == WebsamProcessState::Active)
274                 parentProcessConnection()->send(Messages::WebProcessProxy::DidExceedActiveMemoryLimit(), 0);
275             else
276                 parentProcessConnection()->send(Messages::WebProcessProxy::DidExceedInactiveMemoryLimit(), 0);
277         });
278 #endif
279         memoryPressureHandler.setMemoryPressureStatusChangedCallback([this](bool isUnderMemoryPressure) {
280             if (parentProcessConnection())
281                 parentProcessConnection()->send(Messages::WebProcessProxy::MemoryPressureStatusChanged(isUnderMemoryPressure), 0);
282         });
283         memoryPressureHandler.install();
284     }
285
286     if (!parameters.injectedBundlePath.isEmpty())
287         m_injectedBundle = InjectedBundle::create(parameters, transformHandlesToObjects(parameters.initializationUserData.object()).get());
288
289     for (size_t i = 0, size = parameters.additionalSandboxExtensionHandles.size(); i < size; ++i)
290         SandboxExtension::consumePermanently(parameters.additionalSandboxExtensionHandles[i]);
291
292     for (auto& supplement : m_supplements.values())
293         supplement->initialize(parameters);
294
295     auto& databaseManager = DatabaseManager::singleton();
296     databaseManager.initialize(parameters.webSQLDatabaseDirectory);
297
298 #if ENABLE(ICONDATABASE)
299     m_iconDatabaseProxy.setEnabled(parameters.iconDatabaseEnabled);
300 #endif
301
302     // FIXME: This should be constructed per data store, not per process.
303     m_applicationCacheStorage = ApplicationCacheStorage::create(parameters.applicationCacheDirectory, parameters.applicationCacheFlatFileSubdirectoryName);
304 #if PLATFORM(IOS)
305     m_applicationCacheStorage->setDefaultOriginQuota(25ULL * 1024 * 1024);
306 #endif
307
308 #if PLATFORM(WAYLAND)
309     m_waylandCompositorDisplayName = parameters.waylandCompositorDisplayName;
310 #endif
311
312 #if ENABLE(VIDEO)
313     if (!parameters.mediaCacheDirectory.isEmpty())
314         WebCore::HTMLMediaElement::setMediaCacheDirectory(parameters.mediaCacheDirectory);
315 #endif
316
317     setCacheModel(static_cast<uint32_t>(parameters.cacheModel));
318
319     if (!parameters.languages.isEmpty())
320         overrideUserPreferredLanguages(parameters.languages);
321
322     m_textCheckerState = parameters.textCheckerState;
323
324     m_fullKeyboardAccessEnabled = parameters.fullKeyboardAccessEnabled;
325
326     for (auto& scheme : parameters.urlSchemesRegisteredAsEmptyDocument)
327         registerURLSchemeAsEmptyDocument(scheme);
328
329     for (auto& scheme : parameters.urlSchemesRegisteredAsSecure)
330         registerURLSchemeAsSecure(scheme);
331
332     for (auto& scheme : parameters.urlSchemesRegisteredAsBypassingContentSecurityPolicy)
333         registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
334
335     for (auto& scheme : parameters.urlSchemesForWhichDomainRelaxationIsForbidden)
336         setDomainRelaxationForbiddenForURLScheme(scheme);
337
338     for (auto& scheme : parameters.urlSchemesRegisteredAsLocal)
339         registerURLSchemeAsLocal(scheme);
340
341     for (auto& scheme : parameters.urlSchemesRegisteredAsNoAccess)
342         registerURLSchemeAsNoAccess(scheme);
343
344     for (auto& scheme : parameters.urlSchemesRegisteredAsDisplayIsolated)
345         registerURLSchemeAsDisplayIsolated(scheme);
346
347     for (auto& scheme : parameters.urlSchemesRegisteredAsCORSEnabled)
348         registerURLSchemeAsCORSEnabled(scheme);
349
350     for (auto& scheme : parameters.urlSchemesRegisteredAsAlwaysRevalidated)
351         registerURLSchemeAsAlwaysRevalidated(scheme);
352
353     for (auto& scheme : parameters.urlSchemesRegisteredAsCachePartitioned)
354         registerURLSchemeAsCachePartitioned(scheme);
355
356     setDefaultRequestTimeoutInterval(parameters.defaultRequestTimeoutInterval);
357
358     setResourceLoadStatisticsEnabled(parameters.resourceLoadStatisticsEnabled);
359
360     if (parameters.shouldAlwaysUseComplexTextCodePath)
361         setAlwaysUsesComplexTextCodePath(true);
362
363     if (parameters.shouldUseFontSmoothing)
364         setShouldUseFontSmoothing(true);
365
366     if (parameters.shouldUseTestingNetworkSession)
367         NetworkStorageSession::switchToNewTestingSession();
368
369     ensureNetworkProcessConnection();
370
371 #if PLATFORM(COCOA)
372     CookieStorageShim::singleton().initialize();
373 #endif
374     setTerminationTimeout(parameters.terminationTimeout);
375
376     resetPlugInAutoStartOriginHashes(parameters.plugInAutoStartOriginHashes);
377     for (auto& origin : parameters.plugInAutoStartOrigins)
378         m_plugInAutoStartOrigins.add(origin);
379
380     setMemoryCacheDisabled(parameters.memoryCacheDisabled);
381
382 #if ENABLE(SERVICE_CONTROLS)
383     setEnabledServices(parameters.hasImageServices, parameters.hasSelectionServices, parameters.hasRichContentServices);
384 #endif
385
386 #if ENABLE(REMOTE_INSPECTOR) && PLATFORM(COCOA)
387     audit_token_t auditToken;
388     if (parentProcessConnection()->getAuditToken(auditToken)) {
389         RetainPtr<CFDataRef> auditData = adoptCF(CFDataCreate(nullptr, (const UInt8*)&auditToken, sizeof(auditToken)));
390         Inspector::RemoteInspector::singleton().setParentProcessInformation(presenterApplicationPid(), auditData);
391     }
392 #endif
393
394 #if ENABLE(NETSCAPE_PLUGIN_API) && PLATFORM(MAC)
395     for (auto hostIter = parameters.pluginLoadClientPolicies.begin(); hostIter != parameters.pluginLoadClientPolicies.end(); ++hostIter) {
396         for (auto bundleIdentifierIter = hostIter->value.begin(); bundleIdentifierIter != hostIter->value.end(); ++bundleIdentifierIter) {
397             for (auto versionIter = bundleIdentifierIter->value.begin(); versionIter != bundleIdentifierIter->value.end(); ++versionIter)
398                 WebPluginInfoProvider::singleton().setPluginLoadClientPolicy(static_cast<PluginLoadClientPolicy>(versionIter->value), hostIter->key, bundleIdentifierIter->key, versionIter->key);
399         }
400     }
401 #endif
402
403 #if ENABLE(GAMEPAD)
404     GamepadProvider::singleton().setSharedProvider(WebGamepadProvider::singleton());
405 #endif
406
407 #if ENABLE(WEBASSEMBLY)
408     JSC::Wasm::enableFastMemory();
409 #endif
410 }
411
412 void WebProcess::ensureNetworkProcessConnection()
413 {
414     if (m_networkProcessConnection)
415         return;
416
417     IPC::Attachment encodedConnectionIdentifier;
418
419     if (!parentProcessConnection()->sendSync(Messages::WebProcessProxy::GetNetworkProcessConnection(),
420         Messages::WebProcessProxy::GetNetworkProcessConnection::Reply(encodedConnectionIdentifier), 0))
421         return;
422
423 #if USE(UNIX_DOMAIN_SOCKETS)
424     IPC::Connection::Identifier connectionIdentifier = encodedConnectionIdentifier.releaseFileDescriptor();
425 #elif OS(DARWIN)
426     IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.port());
427 #else
428     ASSERT_NOT_REACHED();
429 #endif
430     if (IPC::Connection::identifierIsNull(connectionIdentifier))
431         return;
432     m_networkProcessConnection = NetworkProcessConnection::create(connectionIdentifier);
433 }
434
435 void WebProcess::registerURLSchemeAsEmptyDocument(const String& urlScheme)
436 {
437     SchemeRegistry::registerURLSchemeAsEmptyDocument(urlScheme);
438 }
439
440 void WebProcess::registerURLSchemeAsSecure(const String& urlScheme) const
441 {
442     SchemeRegistry::registerURLSchemeAsSecure(urlScheme);
443 }
444
445 void WebProcess::registerURLSchemeAsBypassingContentSecurityPolicy(const String& urlScheme) const
446 {
447     SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(urlScheme);
448 }
449
450 void WebProcess::setDomainRelaxationForbiddenForURLScheme(const String& urlScheme) const
451 {
452     SchemeRegistry::setDomainRelaxationForbiddenForURLScheme(true, urlScheme);
453 }
454
455 void WebProcess::registerURLSchemeAsLocal(const String& urlScheme) const
456 {
457     SchemeRegistry::registerURLSchemeAsLocal(urlScheme);
458 }
459
460 void WebProcess::registerURLSchemeAsNoAccess(const String& urlScheme) const
461 {
462     SchemeRegistry::registerURLSchemeAsNoAccess(urlScheme);
463 }
464
465 void WebProcess::registerURLSchemeAsDisplayIsolated(const String& urlScheme) const
466 {
467     SchemeRegistry::registerURLSchemeAsDisplayIsolated(urlScheme);
468 }
469
470 void WebProcess::registerURLSchemeAsCORSEnabled(const String& urlScheme) const
471 {
472     SchemeRegistry::registerURLSchemeAsCORSEnabled(urlScheme);
473 }
474
475 void WebProcess::registerURLSchemeAsAlwaysRevalidated(const String& urlScheme) const
476 {
477     SchemeRegistry::registerURLSchemeAsAlwaysRevalidated(urlScheme);
478 }
479
480 void WebProcess::registerURLSchemeAsCachePartitioned(const String& urlScheme) const
481 {
482     SchemeRegistry::registerURLSchemeAsCachePartitioned(urlScheme);
483 }
484
485 void WebProcess::setDefaultRequestTimeoutInterval(double timeoutInterval)
486 {
487     ResourceRequest::setDefaultTimeoutInterval(timeoutInterval);
488 }
489
490 void WebProcess::setAlwaysUsesComplexTextCodePath(bool alwaysUseComplexText)
491 {
492     WebCore::FontCascade::setCodePath(alwaysUseComplexText ? WebCore::FontCascade::Complex : WebCore::FontCascade::Auto);
493 }
494
495 void WebProcess::setShouldUseFontSmoothing(bool useFontSmoothing)
496 {
497     WebCore::FontCascade::setShouldUseSmoothing(useFontSmoothing);
498 }
499
500 void WebProcess::userPreferredLanguagesChanged(const Vector<String>& languages) const
501 {
502     overrideUserPreferredLanguages(languages);
503     languageDidChange();
504 }
505
506 void WebProcess::fullKeyboardAccessModeChanged(bool fullKeyboardAccessEnabled)
507 {
508     m_fullKeyboardAccessEnabled = fullKeyboardAccessEnabled;
509 }
510
511 void WebProcess::ensurePrivateBrowsingSession(SessionID sessionID)
512 {
513     WebFrameNetworkingContext::ensurePrivateBrowsingSession(sessionID);
514 }
515
516 void WebProcess::addWebsiteDataStore(WebsiteDataStoreParameters&& parameters)
517 {
518     WebFrameNetworkingContext::ensureWebsiteDataStoreSession(WTFMove(parameters));
519 }
520
521 void WebProcess::destroySession(SessionID sessionID)
522 {
523     SessionTracker::destroySession(sessionID);
524 }
525
526 void WebProcess::ensureLegacyPrivateBrowsingSessionInNetworkProcess()
527 {
528     networkConnection().connection().send(Messages::NetworkConnectionToWebProcess::EnsureLegacyPrivateBrowsingSession(), 0);
529 }
530
531 #if ENABLE(NETSCAPE_PLUGIN_API)
532 PluginProcessConnectionManager& WebProcess::pluginProcessConnectionManager()
533 {
534     return *m_pluginProcessConnectionManager;
535 }
536 #endif
537
538 void WebProcess::setCacheModel(uint32_t cm)
539 {
540     CacheModel cacheModel = static_cast<CacheModel>(cm);
541
542     if (m_hasSetCacheModel && (cacheModel == m_cacheModel))
543         return;
544
545     m_hasSetCacheModel = true;
546     m_cacheModel = cacheModel;
547
548     unsigned cacheTotalCapacity = 0;
549     unsigned cacheMinDeadCapacity = 0;
550     unsigned cacheMaxDeadCapacity = 0;
551     Seconds deadDecodedDataDeletionInterval;
552     unsigned pageCacheSize = 0;
553     calculateMemoryCacheSizes(cacheModel, cacheTotalCapacity, cacheMinDeadCapacity, cacheMaxDeadCapacity, deadDecodedDataDeletionInterval, pageCacheSize);
554
555     auto& memoryCache = MemoryCache::singleton();
556     memoryCache.setCapacities(cacheMinDeadCapacity, cacheMaxDeadCapacity, cacheTotalCapacity);
557     memoryCache.setDeadDecodedDataDeletionInterval(deadDecodedDataDeletionInterval);
558     PageCache::singleton().setMaxSize(pageCacheSize);
559
560     platformSetCacheModel(cacheModel);
561 }
562
563 void WebProcess::clearCachedCredentials()
564 {
565     NetworkStorageSession::defaultStorageSession().credentialStorage().clearCredentials();
566 #if USE(NETWORK_SESSION)
567     NetworkSession::defaultSession().clearCredentials();
568 #endif
569 }
570
571 WebPage* WebProcess::focusedWebPage() const
572 {    
573     for (auto& page : m_pageMap.values()) {
574         if (page->windowAndWebPageAreFocused())
575             return page.get();
576     }
577     return 0;
578 }
579     
580 WebPage* WebProcess::webPage(uint64_t pageID) const
581 {
582     return m_pageMap.get(pageID);
583 }
584
585 void WebProcess::createWebPage(uint64_t pageID, WebPageCreationParameters&& parameters)
586 {
587     // It is necessary to check for page existence here since during a window.open() (or targeted
588     // link) the WebPage gets created both in the synchronous handler and through the normal way. 
589     HashMap<uint64_t, RefPtr<WebPage>>::AddResult result = m_pageMap.add(pageID, nullptr);
590     if (result.isNewEntry) {
591         ASSERT(!result.iterator->value);
592         result.iterator->value = WebPage::create(pageID, WTFMove(parameters));
593
594         // Balanced by an enableTermination in removeWebPage.
595         disableTermination();
596         updateBackgroundCPULimit();
597     } else
598         result.iterator->value->reinitializeWebPage(WTFMove(parameters));
599
600     ASSERT(result.iterator->value);
601 }
602
603 void WebProcess::removeWebPage(uint64_t pageID)
604 {
605     ASSERT(m_pageMap.contains(pageID));
606
607     pageWillLeaveWindow(pageID);
608     m_pageMap.remove(pageID);
609
610     enableTermination();
611     updateBackgroundCPULimit();
612 }
613
614 bool WebProcess::shouldTerminate()
615 {
616     ASSERT(m_pageMap.isEmpty());
617
618     // FIXME: the ShouldTerminate message should also send termination parameters, such as any session cookies that need to be preserved.
619     bool shouldTerminate = false;
620     if (parentProcessConnection()->sendSync(Messages::WebProcessProxy::ShouldTerminate(), Messages::WebProcessProxy::ShouldTerminate::Reply(shouldTerminate), 0)
621         && !shouldTerminate)
622         return false;
623
624     return true;
625 }
626
627 void WebProcess::terminate()
628 {
629 #ifndef NDEBUG
630     GCController::singleton().garbageCollectNow();
631     FontCache::singleton().invalidate();
632     MemoryCache::singleton().setDisabled(true);
633 #endif
634
635     m_webConnection->invalidate();
636     m_webConnection = nullptr;
637
638     platformTerminate();
639
640     ChildProcess::terminate();
641 }
642
643 void WebProcess::didReceiveSyncMessage(IPC::Connection& connection, IPC::Decoder& decoder, std::unique_ptr<IPC::Encoder>& replyEncoder)
644 {
645     if (messageReceiverMap().dispatchSyncMessage(connection, decoder, replyEncoder))
646         return;
647
648     didReceiveSyncWebProcessMessage(connection, decoder, replyEncoder);
649 }
650
651 void WebProcess::didReceiveMessage(IPC::Connection& connection, IPC::Decoder& decoder)
652 {
653     if (messageReceiverMap().dispatchMessage(connection, decoder))
654         return;
655
656     if (decoder.messageReceiverName() == Messages::WebProcess::messageReceiverName()) {
657         didReceiveWebProcessMessage(connection, decoder);
658         return;
659     }
660
661     if (decoder.messageReceiverName() == Messages::ChildProcess::messageReceiverName()) {
662         ChildProcess::didReceiveMessage(connection, decoder);
663         return;
664     }
665
666     LOG_ERROR("Unhandled web process message '%s:%s'", decoder.messageReceiverName().toString().data(), decoder.messageName().toString().data());
667 }
668
669 void WebProcess::didClose(IPC::Connection&)
670 {
671 #ifndef NDEBUG
672     // Close all the live pages.
673     Vector<RefPtr<WebPage>> pages;
674     copyValuesToVector(m_pageMap, pages);
675     for (auto& page : pages)
676         page->close();
677     pages.clear();
678
679     GCController::singleton().garbageCollectSoon();
680     FontCache::singleton().invalidate();
681     MemoryCache::singleton().setDisabled(true);
682 #endif
683
684 #if ENABLE(VIDEO)
685     // FIXME(146657): This explicit media stop command should not be necessary
686     if (auto* platformMediaSessionManager = PlatformMediaSessionManager::sharedManagerIfExists())
687         platformMediaSessionManager->stopAllMediaPlaybackForProcess();
688 #endif
689
690     // The UI process closed this connection, shut down.
691     stopRunLoop();
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 void WebProcess::refreshPlugins()
929 {
930 #if ENABLE(NETSCAPE_PLUGIN_API)
931     WebPluginInfoProvider::singleton().refresh(false);
932 #endif
933 }
934
935 static void fromCountedSetToHashMap(TypeCountSet* countedSet, HashMap<String, uint64_t>& map)
936 {
937     TypeCountSet::const_iterator end = countedSet->end();
938     for (TypeCountSet::const_iterator it = countedSet->begin(); it != end; ++it)
939         map.set(it->key, it->value);
940 }
941
942 static void getWebCoreMemoryCacheStatistics(Vector<HashMap<String, uint64_t>>& result)
943 {
944     String imagesString(ASCIILiteral("Images"));
945     String cssString(ASCIILiteral("CSS"));
946     String xslString(ASCIILiteral("XSL"));
947     String javaScriptString(ASCIILiteral("JavaScript"));
948     
949     MemoryCache::Statistics memoryCacheStatistics = MemoryCache::singleton().getStatistics();
950     
951     HashMap<String, uint64_t> counts;
952     counts.set(imagesString, memoryCacheStatistics.images.count);
953     counts.set(cssString, memoryCacheStatistics.cssStyleSheets.count);
954     counts.set(xslString, memoryCacheStatistics.xslStyleSheets.count);
955     counts.set(javaScriptString, memoryCacheStatistics.scripts.count);
956     result.append(counts);
957     
958     HashMap<String, uint64_t> sizes;
959     sizes.set(imagesString, memoryCacheStatistics.images.size);
960     sizes.set(cssString, memoryCacheStatistics.cssStyleSheets.size);
961     sizes.set(xslString, memoryCacheStatistics.xslStyleSheets.size);
962     sizes.set(javaScriptString, memoryCacheStatistics.scripts.size);
963     result.append(sizes);
964     
965     HashMap<String, uint64_t> liveSizes;
966     liveSizes.set(imagesString, memoryCacheStatistics.images.liveSize);
967     liveSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.liveSize);
968     liveSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.liveSize);
969     liveSizes.set(javaScriptString, memoryCacheStatistics.scripts.liveSize);
970     result.append(liveSizes);
971     
972     HashMap<String, uint64_t> decodedSizes;
973     decodedSizes.set(imagesString, memoryCacheStatistics.images.decodedSize);
974     decodedSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.decodedSize);
975     decodedSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.decodedSize);
976     decodedSizes.set(javaScriptString, memoryCacheStatistics.scripts.decodedSize);
977     result.append(decodedSizes);
978 }
979
980 void WebProcess::getWebCoreStatistics(uint64_t callbackID)
981 {
982     StatisticsData data;
983     
984     // Gather JavaScript statistics.
985     {
986         JSLockHolder lock(commonVM());
987         data.statisticsNumbers.set(ASCIILiteral("JavaScriptObjectsCount"), commonVM().heap.objectCount());
988         data.statisticsNumbers.set(ASCIILiteral("JavaScriptGlobalObjectsCount"), commonVM().heap.globalObjectCount());
989         data.statisticsNumbers.set(ASCIILiteral("JavaScriptProtectedObjectsCount"), commonVM().heap.protectedObjectCount());
990         data.statisticsNumbers.set(ASCIILiteral("JavaScriptProtectedGlobalObjectsCount"), commonVM().heap.protectedGlobalObjectCount());
991         
992         std::unique_ptr<TypeCountSet> protectedObjectTypeCounts(commonVM().heap.protectedObjectTypeCounts());
993         fromCountedSetToHashMap(protectedObjectTypeCounts.get(), data.javaScriptProtectedObjectTypeCounts);
994         
995         std::unique_ptr<TypeCountSet> objectTypeCounts(commonVM().heap.objectTypeCounts());
996         fromCountedSetToHashMap(objectTypeCounts.get(), data.javaScriptObjectTypeCounts);
997         
998         uint64_t javaScriptHeapSize = commonVM().heap.size();
999         data.statisticsNumbers.set(ASCIILiteral("JavaScriptHeapSize"), javaScriptHeapSize);
1000         data.statisticsNumbers.set(ASCIILiteral("JavaScriptFreeSize"), commonVM().heap.capacity() - javaScriptHeapSize);
1001     }
1002
1003     WTF::FastMallocStatistics fastMallocStatistics = WTF::fastMallocStatistics();
1004     data.statisticsNumbers.set(ASCIILiteral("FastMallocReservedVMBytes"), fastMallocStatistics.reservedVMBytes);
1005     data.statisticsNumbers.set(ASCIILiteral("FastMallocCommittedVMBytes"), fastMallocStatistics.committedVMBytes);
1006     data.statisticsNumbers.set(ASCIILiteral("FastMallocFreeListBytes"), fastMallocStatistics.freeListBytes);
1007     
1008     // Gather icon statistics.
1009     data.statisticsNumbers.set(ASCIILiteral("IconPageURLMappingCount"), iconDatabase().pageURLMappingCount());
1010     data.statisticsNumbers.set(ASCIILiteral("IconRetainedPageURLCount"), iconDatabase().retainedPageURLCount());
1011     data.statisticsNumbers.set(ASCIILiteral("IconRecordCount"), iconDatabase().iconRecordCount());
1012     data.statisticsNumbers.set(ASCIILiteral("IconsWithDataCount"), iconDatabase().iconRecordCountWithData());
1013     
1014     // Gather font statistics.
1015     auto& fontCache = FontCache::singleton();
1016     data.statisticsNumbers.set(ASCIILiteral("CachedFontDataCount"), fontCache.fontCount());
1017     data.statisticsNumbers.set(ASCIILiteral("CachedFontDataInactiveCount"), fontCache.inactiveFontCount());
1018     
1019     // Gather glyph page statistics.
1020     data.statisticsNumbers.set(ASCIILiteral("GlyphPageCount"), GlyphPage::count());
1021     
1022     // Get WebCore memory cache statistics
1023     getWebCoreMemoryCacheStatistics(data.webCoreCacheStatistics);
1024     
1025     parentProcessConnection()->send(Messages::WebProcessPool::DidGetStatistics(data, callbackID), 0);
1026 }
1027
1028 void WebProcess::garbageCollectJavaScriptObjects()
1029 {
1030     GCController::singleton().garbageCollectNow();
1031 }
1032
1033 void WebProcess::mainThreadPing()
1034 {
1035     parentProcessConnection()->send(Messages::WebProcessProxy::DidReceiveMainThreadPing(), 0);
1036 }
1037
1038 void WebProcess::backgroundResponsivenessPing()
1039 {
1040     parentProcessConnection()->send(Messages::WebProcessProxy::DidReceiveBackgroundResponsivenessPing(), 0);
1041 }
1042
1043 #if ENABLE(GAMEPAD)
1044
1045 void WebProcess::setInitialGamepads(const Vector<WebKit::GamepadData>& gamepadDatas)
1046 {
1047     WebGamepadProvider::singleton().setInitialGamepads(gamepadDatas);
1048 }
1049
1050 void WebProcess::gamepadConnected(const GamepadData& gamepadData)
1051 {
1052     WebGamepadProvider::singleton().gamepadConnected(gamepadData);
1053 }
1054
1055 void WebProcess::gamepadDisconnected(unsigned index)
1056 {
1057     WebGamepadProvider::singleton().gamepadDisconnected(index);
1058 }
1059
1060 #endif
1061
1062 void WebProcess::setJavaScriptGarbageCollectorTimerEnabled(bool flag)
1063 {
1064     GCController::singleton().setJavaScriptGarbageCollectorTimerEnabled(flag);
1065 }
1066
1067 void WebProcess::handleInjectedBundleMessage(const String& messageName, const UserData& messageBody)
1068 {
1069     InjectedBundle* injectedBundle = WebProcess::singleton().injectedBundle();
1070     if (!injectedBundle)
1071         return;
1072
1073     injectedBundle->didReceiveMessage(messageName, transformHandlesToObjects(messageBody.object()).get());
1074 }
1075
1076 void WebProcess::setInjectedBundleParameter(const String& key, const IPC::DataReference& value)
1077 {
1078     InjectedBundle* injectedBundle = WebProcess::singleton().injectedBundle();
1079     if (!injectedBundle)
1080         return;
1081
1082     injectedBundle->setBundleParameter(key, value);
1083 }
1084
1085 void WebProcess::setInjectedBundleParameters(const IPC::DataReference& value)
1086 {
1087     InjectedBundle* injectedBundle = WebProcess::singleton().injectedBundle();
1088     if (!injectedBundle)
1089         return;
1090
1091     injectedBundle->setBundleParameters(value);
1092 }
1093
1094 NetworkProcessConnection& WebProcess::networkConnection()
1095 {
1096     // If we've lost our connection to the network process (e.g. it crashed) try to re-establish it.
1097     if (!m_networkProcessConnection)
1098         ensureNetworkProcessConnection();
1099     
1100     // If we failed to re-establish it then we are beyond recovery and should crash.
1101     if (!m_networkProcessConnection)
1102         CRASH();
1103     
1104     return *m_networkProcessConnection;
1105 }
1106
1107 void WebProcess::logDiagnosticMessageForNetworkProcessCrash()
1108 {
1109     WebCore::Page* page = nullptr;
1110
1111     if (auto* webPage = focusedWebPage())
1112         page = webPage->corePage();
1113
1114     if (!page) {
1115         for (auto& webPage : m_pageMap.values()) {
1116             if (auto* corePage = webPage->corePage()) {
1117                 page = corePage;
1118                 break;
1119             }
1120         }
1121     }
1122
1123     if (page)
1124         page->diagnosticLoggingClient().logDiagnosticMessage(WebCore::DiagnosticLoggingKeys::internalErrorKey(), WebCore::DiagnosticLoggingKeys::networkProcessCrashedKey(), WebCore::ShouldSample::No);
1125 }
1126
1127 void WebProcess::networkProcessConnectionClosed(NetworkProcessConnection* connection)
1128 {
1129     ASSERT(m_networkProcessConnection);
1130     ASSERT_UNUSED(connection, m_networkProcessConnection == connection);
1131
1132     m_networkProcessConnection = nullptr;
1133
1134     logDiagnosticMessageForNetworkProcessCrash();
1135
1136     m_webLoaderStrategy.networkProcessCrashed();
1137     WebSocketStream::networkProcessCrashed();
1138 }
1139
1140 WebLoaderStrategy& WebProcess::webLoaderStrategy()
1141 {
1142     return m_webLoaderStrategy;
1143 }
1144
1145 #if ENABLE(DATABASE_PROCESS)
1146 void WebProcess::webToDatabaseProcessConnectionClosed(WebToDatabaseProcessConnection* connection)
1147 {
1148     ASSERT(m_webToDatabaseProcessConnection);
1149     ASSERT(m_webToDatabaseProcessConnection == connection);
1150
1151     m_webToDatabaseProcessConnection = nullptr;
1152 }
1153
1154 WebToDatabaseProcessConnection* WebProcess::webToDatabaseProcessConnection()
1155 {
1156     if (!m_webToDatabaseProcessConnection)
1157         ensureWebToDatabaseProcessConnection();
1158
1159     return m_webToDatabaseProcessConnection.get();
1160 }
1161
1162 void WebProcess::ensureWebToDatabaseProcessConnection()
1163 {
1164     if (m_webToDatabaseProcessConnection)
1165         return;
1166
1167     IPC::Attachment encodedConnectionIdentifier;
1168
1169     if (!parentProcessConnection()->sendSync(Messages::WebProcessProxy::GetDatabaseProcessConnection(),
1170         Messages::WebProcessProxy::GetDatabaseProcessConnection::Reply(encodedConnectionIdentifier), 0))
1171         return;
1172
1173 #if USE(UNIX_DOMAIN_SOCKETS)
1174     IPC::Connection::Identifier connectionIdentifier = encodedConnectionIdentifier.releaseFileDescriptor();
1175 #elif OS(DARWIN)
1176     IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.port());
1177 #else
1178     ASSERT_NOT_REACHED();
1179 #endif
1180     if (IPC::Connection::identifierIsNull(connectionIdentifier))
1181         return;
1182     m_webToDatabaseProcessConnection = WebToDatabaseProcessConnection::create(connectionIdentifier);
1183 }
1184
1185 #endif // ENABLED(DATABASE_PROCESS)
1186
1187 void WebProcess::setEnhancedAccessibility(bool flag)
1188 {
1189     WebCore::AXObjectCache::setEnhancedUserInterfaceAccessibility(flag);
1190 }
1191     
1192 void WebProcess::startMemorySampler(const SandboxExtension::Handle& sampleLogFileHandle, const String& sampleLogFilePath, const double interval)
1193 {
1194 #if ENABLE(MEMORY_SAMPLER)    
1195     WebMemorySampler::singleton()->start(sampleLogFileHandle, sampleLogFilePath, interval);
1196 #else
1197     UNUSED_PARAM(sampleLogFileHandle);
1198     UNUSED_PARAM(sampleLogFilePath);
1199     UNUSED_PARAM(interval);
1200 #endif
1201 }
1202     
1203 void WebProcess::stopMemorySampler()
1204 {
1205 #if ENABLE(MEMORY_SAMPLER)
1206     WebMemorySampler::singleton()->stop();
1207 #endif
1208 }
1209
1210 void WebProcess::setTextCheckerState(const TextCheckerState& textCheckerState)
1211 {
1212     bool continuousSpellCheckingTurnedOff = !textCheckerState.isContinuousSpellCheckingEnabled && m_textCheckerState.isContinuousSpellCheckingEnabled;
1213     bool grammarCheckingTurnedOff = !textCheckerState.isGrammarCheckingEnabled && m_textCheckerState.isGrammarCheckingEnabled;
1214
1215     m_textCheckerState = textCheckerState;
1216
1217     if (!continuousSpellCheckingTurnedOff && !grammarCheckingTurnedOff)
1218         return;
1219
1220     for (auto& page : m_pageMap.values()) {
1221         if (continuousSpellCheckingTurnedOff)
1222             page->unmarkAllMisspellings();
1223         if (grammarCheckingTurnedOff)
1224             page->unmarkAllBadGrammar();
1225     }
1226 }
1227
1228 void WebProcess::releasePageCache()
1229 {
1230     PageCache::singleton().pruneToSizeNow(0, PruningReason::MemoryPressure);
1231 }
1232
1233 void WebProcess::fetchWebsiteData(WebCore::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, WebsiteData& websiteData)
1234 {
1235     if (websiteDataTypes.contains(WebsiteDataType::MemoryCache)) {
1236         for (auto& origin : MemoryCache::singleton().originsWithCache(sessionID))
1237             websiteData.entries.append(WebsiteData::Entry { SecurityOriginData::fromSecurityOrigin(*origin), WebsiteDataType::MemoryCache, 0 });
1238     }
1239 }
1240
1241 void WebProcess::deleteWebsiteData(SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, std::chrono::system_clock::time_point modifiedSince)
1242 {
1243     UNUSED_PARAM(modifiedSince);
1244
1245     if (websiteDataTypes.contains(WebsiteDataType::MemoryCache)) {
1246         PageCache::singleton().pruneToSizeNow(0, PruningReason::None);
1247         MemoryCache::singleton().evictResources(sessionID);
1248
1249         CrossOriginPreflightResultCache::singleton().empty();
1250     }
1251 }
1252
1253 void WebProcess::deleteWebsiteDataForOrigins(WebCore::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, const Vector<WebCore::SecurityOriginData>& originDatas)
1254 {
1255     if (websiteDataTypes.contains(WebsiteDataType::MemoryCache)) {
1256         HashSet<RefPtr<SecurityOrigin>> origins;
1257         for (auto& originData : originDatas)
1258             origins.add(originData.securityOrigin());
1259
1260         MemoryCache::singleton().removeResourcesWithOrigins(sessionID, origins);
1261     }
1262 }
1263
1264 void WebProcess::setHiddenPageDOMTimerThrottlingIncreaseLimit(int milliseconds)
1265 {
1266     for (auto& page : m_pageMap.values())
1267         page->setHiddenPageDOMTimerThrottlingIncreaseLimit(Seconds::fromMilliseconds(milliseconds));
1268 }
1269
1270 #if !PLATFORM(COCOA)
1271 void WebProcess::initializeProcessName(const ChildProcessInitializationParameters&)
1272 {
1273 }
1274
1275 void WebProcess::initializeSandbox(const ChildProcessInitializationParameters&, SandboxInitializationParameters&)
1276 {
1277 }
1278
1279 void WebProcess::platformInitializeProcess(const ChildProcessInitializationParameters&)
1280 {
1281 }
1282
1283 void WebProcess::updateActivePages()
1284 {
1285 }
1286
1287 void WebProcess::updateBackgroundCPULimit()
1288 {
1289 }
1290
1291 void WebProcess::updateBackgroundCPUMonitorState()
1292 {
1293 }
1294
1295 #endif
1296
1297 void WebProcess::pageActivityStateDidChange(uint64_t, WebCore::ActivityState::Flags changed)
1298 {
1299     if (changed & WebCore::ActivityState::IsVisible)
1300         updateBackgroundCPUMonitorState();
1301 }
1302
1303 #if PLATFORM(IOS)
1304 void WebProcess::resetAllGeolocationPermissions()
1305 {
1306     for (auto& page : m_pageMap.values()) {
1307         if (Frame* mainFrame = page->mainFrame())
1308             mainFrame->resetAllGeolocationPermission();
1309     }
1310 }
1311 #endif
1312
1313 void WebProcess::actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend shouldAcknowledgeWhenReadyToSuspend)
1314 {
1315     if (!m_suppressMemoryPressureHandler)
1316         MemoryPressureHandler::singleton().releaseMemory(Critical::Yes, Synchronous::Yes);
1317
1318     setAllLayerTreeStatesFrozen(true);
1319     
1320 #if PLATFORM(COCOA)
1321     destroyRenderingResources();
1322 #endif
1323
1324     markAllLayersVolatile([this, shouldAcknowledgeWhenReadyToSuspend] {
1325         RELEASE_LOG(ProcessSuspension, "%p - WebProcess::markAllLayersVolatile() Successfuly marked all layers as volatile", this);
1326
1327         if (shouldAcknowledgeWhenReadyToSuspend == ShouldAcknowledgeWhenReadyToSuspend::Yes) {
1328             RELEASE_LOG(ProcessSuspension, "%p - WebProcess::actualPrepareToSuspend() Sending ProcessReadyToSuspend IPC message", this);
1329             parentProcessConnection()->send(Messages::WebProcessProxy::ProcessReadyToSuspend(), 0);
1330         }
1331     });
1332 }
1333
1334 void WebProcess::processWillSuspendImminently(bool& handled)
1335 {
1336     if (parentProcessConnection()->inSendSync()) {
1337         // Avoid reentrency bugs such as rdar://problem/21605505 by just bailing
1338         // if we get an incoming ProcessWillSuspendImminently message when waiting for a
1339         // reply to a sync message.
1340         // FIXME: ProcessWillSuspendImminently should not be a sync message.
1341         return;
1342     }
1343
1344     RELEASE_LOG(ProcessSuspension, "%p - WebProcess::processWillSuspendImminently()", this);
1345     DatabaseTracker::singleton().closeAllDatabases(CurrentQueryBehavior::Interrupt);
1346     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::No);
1347     handled = true;
1348 }
1349
1350 void WebProcess::prepareToSuspend()
1351 {
1352     RELEASE_LOG(ProcessSuspension, "%p - WebProcess::prepareToSuspend()", this);
1353     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::Yes);
1354 }
1355
1356 void WebProcess::cancelPrepareToSuspend()
1357 {
1358     RELEASE_LOG(ProcessSuspension, "%p - WebProcess::cancelPrepareToSuspend()", this);
1359     setAllLayerTreeStatesFrozen(false);
1360
1361     // If we've already finished cleaning up and sent ProcessReadyToSuspend, we
1362     // shouldn't send DidCancelProcessSuspension; the UI process strictly expects one or the other.
1363     if (!m_pagesMarkingLayersAsVolatile)
1364         return;
1365
1366     cancelMarkAllLayersVolatile();
1367
1368     RELEASE_LOG(ProcessSuspension, "%p - WebProcess::cancelPrepareToSuspend() Sending DidCancelProcessSuspension IPC message", this);
1369     parentProcessConnection()->send(Messages::WebProcessProxy::DidCancelProcessSuspension(), 0);
1370 }
1371
1372 void WebProcess::markAllLayersVolatile(std::function<void()> completionHandler)
1373 {
1374     RELEASE_LOG(ProcessSuspension, "%p - WebProcess::markAllLayersVolatile()", this);
1375     m_pagesMarkingLayersAsVolatile = m_pageMap.size();
1376     if (!m_pagesMarkingLayersAsVolatile) {
1377         completionHandler();
1378         return;
1379     }
1380     for (auto& page : m_pageMap.values()) {
1381         page->markLayersVolatile([this, completionHandler] {
1382             ASSERT(m_pagesMarkingLayersAsVolatile);
1383             if (!--m_pagesMarkingLayersAsVolatile)
1384                 completionHandler();
1385         });
1386     }
1387 }
1388
1389 void WebProcess::cancelMarkAllLayersVolatile()
1390 {
1391     if (!m_pagesMarkingLayersAsVolatile)
1392         return;
1393
1394     for (auto& page : m_pageMap.values())
1395         page->cancelMarkLayersVolatile();
1396     m_pagesMarkingLayersAsVolatile = 0;
1397 }
1398
1399 void WebProcess::setAllLayerTreeStatesFrozen(bool frozen)
1400 {
1401     for (auto& page : m_pageMap.values())
1402         page->setLayerTreeStateIsFrozen(frozen);
1403 }
1404     
1405 void WebProcess::processDidResume()
1406 {
1407     RELEASE_LOG(ProcessSuspension, "%p - WebProcess::processDidResume()", this);
1408
1409     cancelMarkAllLayersVolatile();
1410     setAllLayerTreeStatesFrozen(false);
1411 }
1412
1413 void WebProcess::pageDidEnterWindow(uint64_t pageID)
1414 {
1415     m_pagesInWindows.add(pageID);
1416     m_nonVisibleProcessCleanupTimer.stop();
1417 }
1418
1419 void WebProcess::pageWillLeaveWindow(uint64_t pageID)
1420 {
1421     m_pagesInWindows.remove(pageID);
1422
1423     if (m_pagesInWindows.isEmpty() && !m_nonVisibleProcessCleanupTimer.isActive())
1424         m_nonVisibleProcessCleanupTimer.startOneShot(nonVisibleProcessCleanupDelay);
1425 }
1426     
1427 void WebProcess::nonVisibleProcessCleanupTimerFired()
1428 {
1429     ASSERT(m_pagesInWindows.isEmpty());
1430     if (!m_pagesInWindows.isEmpty())
1431         return;
1432
1433 #if PLATFORM(COCOA)
1434     destroyRenderingResources();
1435 #endif
1436 }
1437
1438 void WebProcess::statisticsChangedTimerFired()
1439 {
1440     if (m_resourceLoadStatisticsStore->isEmpty())
1441         return;
1442
1443     parentProcessConnection()->send(Messages::WebResourceLoadStatisticsStore::ResourceLoadStatisticsUpdated(m_resourceLoadStatisticsStore->takeStatistics()), 0);
1444 }
1445
1446 void WebProcess::setResourceLoadStatisticsEnabled(bool enabled)
1447 {
1448     WebCore::Settings::setResourceLoadStatisticsEnabled(enabled);
1449 }
1450
1451 RefPtr<API::Object> WebProcess::transformHandlesToObjects(API::Object* object)
1452 {
1453     struct Transformer final : UserData::Transformer {
1454         Transformer(WebProcess& webProcess)
1455             : m_webProcess(webProcess)
1456         {
1457         }
1458
1459         bool shouldTransformObject(const API::Object& object) const override
1460         {
1461             switch (object.type()) {
1462             case API::Object::Type::FrameHandle:
1463                 return static_cast<const API::FrameHandle&>(object).isAutoconverting();
1464
1465             case API::Object::Type::PageHandle:
1466                 return static_cast<const API::PageHandle&>(object).isAutoconverting();
1467
1468             case API::Object::Type::PageGroupHandle:
1469 #if PLATFORM(COCOA)
1470             case API::Object::Type::ObjCObjectGraph:
1471 #endif
1472                 return true;
1473
1474             default:
1475                 return false;
1476             }
1477         }
1478
1479         RefPtr<API::Object> transformObject(API::Object& object) const override
1480         {
1481             switch (object.type()) {
1482             case API::Object::Type::FrameHandle:
1483                 return m_webProcess.webFrame(static_cast<const API::FrameHandle&>(object).frameID());
1484
1485             case API::Object::Type::PageGroupHandle:
1486                 return m_webProcess.webPageGroup(static_cast<const API::PageGroupHandle&>(object).webPageGroupData());
1487
1488             case API::Object::Type::PageHandle:
1489                 return m_webProcess.webPage(static_cast<const API::PageHandle&>(object).pageID());
1490
1491 #if PLATFORM(COCOA)
1492             case API::Object::Type::ObjCObjectGraph:
1493                 return m_webProcess.transformHandlesToObjects(static_cast<ObjCObjectGraph&>(object));
1494 #endif
1495             default:
1496                 return &object;
1497             }
1498         }
1499
1500         WebProcess& m_webProcess;
1501     };
1502
1503     return UserData::transform(object, Transformer(*this));
1504 }
1505
1506 RefPtr<API::Object> WebProcess::transformObjectsToHandles(API::Object* object)
1507 {
1508     struct Transformer final : UserData::Transformer {
1509         bool shouldTransformObject(const API::Object& object) const override
1510         {
1511             switch (object.type()) {
1512             case API::Object::Type::BundleFrame:
1513             case API::Object::Type::BundlePage:
1514             case API::Object::Type::BundlePageGroup:
1515 #if PLATFORM(COCOA)
1516             case API::Object::Type::ObjCObjectGraph:
1517 #endif
1518                 return true;
1519
1520             default:
1521                 return false;
1522             }
1523         }
1524
1525         RefPtr<API::Object> transformObject(API::Object& object) const override
1526         {
1527             switch (object.type()) {
1528             case API::Object::Type::BundleFrame:
1529                 return API::FrameHandle::createAutoconverting(static_cast<const WebFrame&>(object).frameID());
1530
1531             case API::Object::Type::BundlePage:
1532                 return API::PageHandle::createAutoconverting(static_cast<const WebPage&>(object).pageID());
1533
1534             case API::Object::Type::BundlePageGroup: {
1535                 WebPageGroupData pageGroupData;
1536                 pageGroupData.pageGroupID = static_cast<const WebPageGroupProxy&>(object).pageGroupID();
1537
1538                 return API::PageGroupHandle::create(WTFMove(pageGroupData));
1539             }
1540
1541 #if PLATFORM(COCOA)
1542             case API::Object::Type::ObjCObjectGraph:
1543                 return transformObjectsToHandles(static_cast<ObjCObjectGraph&>(object));
1544 #endif
1545
1546             default:
1547                 return &object;
1548             }
1549         }
1550     };
1551
1552     return UserData::transform(object, Transformer());
1553 }
1554
1555 void WebProcess::setMemoryCacheDisabled(bool disabled)
1556 {
1557     auto& memoryCache = MemoryCache::singleton();
1558     if (memoryCache.disabled() != disabled)
1559         memoryCache.setDisabled(disabled);
1560 }
1561
1562 #if ENABLE(SERVICE_CONTROLS)
1563 void WebProcess::setEnabledServices(bool hasImageServices, bool hasSelectionServices, bool hasRichContentServices)
1564 {
1565     m_hasImageServices = hasImageServices;
1566     m_hasSelectionServices = hasSelectionServices;
1567     m_hasRichContentServices = hasRichContentServices;
1568 }
1569 #endif
1570
1571 void WebProcess::ensureAutomationSessionProxy(const String& sessionIdentifier)
1572 {
1573     m_automationSessionProxy = std::make_unique<WebAutomationSessionProxy>(sessionIdentifier);
1574 }
1575
1576 void WebProcess::destroyAutomationSessionProxy()
1577 {
1578     m_automationSessionProxy = nullptr;
1579 }
1580
1581 void WebProcess::prefetchDNS(const String& hostname)
1582 {
1583     if (hostname.isEmpty())
1584         return;
1585
1586     if (m_dnsPrefetchedHosts.add(hostname).isNewEntry)
1587         networkConnection().connection().send(Messages::NetworkConnectionToWebProcess::PrefetchDNS(hostname), 0);
1588     // The DNS prefetched hosts cache is only to avoid asking for the same hosts too many times
1589     // in a very short period of time, producing a lot of IPC traffic. So we clear this cache after
1590     // some time of no DNS requests.
1591     m_dnsPrefetchHystereris.impulse();
1592 }
1593
1594 bool WebProcess::hasVisibleWebPage() const
1595 {
1596     for (auto& page : m_pageMap.values()) {
1597         if (page->isVisible())
1598             return true;
1599     }
1600     return false;
1601 }
1602
1603 #if USE(LIBWEBRTC)
1604 LibWebRTCNetwork& WebProcess::libWebRTCNetwork()
1605 {
1606     if (!m_libWebRTCNetwork)
1607         m_libWebRTCNetwork = std::make_unique<LibWebRTCNetwork>();
1608     return *m_libWebRTCNetwork;
1609 }
1610 #endif
1611
1612 } // namespace WebKit