2 * Copyright (C) 2009-2017 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "WebProcess.h"
29 #include "APIFrameHandle.h"
30 #include "APIPageGroupHandle.h"
31 #include "APIPageHandle.h"
32 #include "AuthenticationManager.h"
33 #include "ChildProcessMessages.h"
34 #include "DrawingArea.h"
35 #include "EventDispatcher.h"
36 #include "InjectedBundle.h"
37 #include "LibWebRTCNetwork.h"
39 #include "NetworkConnectionToWebProcessMessages.h"
40 #include "NetworkProcessConnection.h"
41 #include "NetworkSession.h"
42 #include "NetworkSessionCreationParameters.h"
43 #include "PluginProcessConnectionManager.h"
44 #include "ServiceWorkerContextManager.h"
45 #include "ServiceWorkerContextManagerMessages.h"
46 #include "SessionTracker.h"
47 #include "StatisticsData.h"
48 #include "StorageProcessMessages.h"
50 #include "WebAutomationSessionProxy.h"
51 #include "WebCacheStorageProvider.h"
52 #include "WebConnectionToUIProcess.h"
53 #include "WebCookieManager.h"
54 #include "WebCoreArgumentCoders.h"
56 #include "WebFrameNetworkingContext.h"
57 #include "WebGamepadProvider.h"
58 #include "WebGeolocationManager.h"
59 #include "WebLoaderStrategy.h"
60 #include "WebMediaKeyStorageManager.h"
61 #include "WebMemorySampler.h"
63 #include "WebPageGroupProxy.h"
64 #include "WebPlatformStrategies.h"
65 #include "WebPluginInfoProvider.h"
66 #include "WebProcessCreationParameters.h"
67 #include "WebProcessMessages.h"
68 #include "WebProcessPoolMessages.h"
69 #include "WebProcessProxyMessages.h"
70 #include "WebResourceLoadStatisticsStoreMessages.h"
71 #include "WebServiceWorkerProvider.h"
72 #include "WebSocketStream.h"
73 #include "WebToStorageProcessConnection.h"
74 #include "WebsiteData.h"
75 #include "WebsiteDataStoreParameters.h"
76 #include "WebsiteDataType.h"
77 #include <JavaScriptCore/JSLock.h>
78 #include <JavaScriptCore/MemoryStatistics.h>
79 #include <JavaScriptCore/WasmFaultSignalHandler.h>
80 #include <WebCore/AXObjectCache.h>
81 #include <WebCore/ApplicationCacheStorage.h>
82 #include <WebCore/AuthenticationChallenge.h>
83 #include <WebCore/CPUMonitor.h>
84 #include <WebCore/CommonVM.h>
85 #include <WebCore/CrossOriginPreflightResultCache.h>
86 #include <WebCore/DNS.h>
87 #include <WebCore/DOMWindow.h>
88 #include <WebCore/DatabaseManager.h>
89 #include <WebCore/DatabaseTracker.h>
90 #include <WebCore/DeprecatedGlobalSettings.h>
91 #include <WebCore/DiagnosticLoggingClient.h>
92 #include <WebCore/DiagnosticLoggingKeys.h>
93 #include <WebCore/FontCache.h>
94 #include <WebCore/FontCascade.h>
95 #include <WebCore/Frame.h>
96 #include <WebCore/FrameLoader.h>
97 #include <WebCore/GCController.h>
98 #include <WebCore/GlyphPage.h>
99 #include <WebCore/HTMLMediaElement.h>
100 #include <WebCore/JSDOMWindow.h>
101 #include <WebCore/MainFrame.h>
102 #include <WebCore/MemoryCache.h>
103 #include <WebCore/MemoryRelease.h>
104 #include <WebCore/NetworkStorageSession.h>
105 #include <WebCore/Page.h>
106 #include <WebCore/PageCache.h>
107 #include <WebCore/PageGroup.h>
108 #include <WebCore/PlatformMediaSessionManager.h>
109 #include <WebCore/ResourceHandle.h>
110 #include <WebCore/ResourceLoadObserver.h>
111 #include <WebCore/ResourceLoadStatistics.h>
112 #include <WebCore/RuntimeApplicationChecks.h>
113 #include <WebCore/SchemeRegistry.h>
114 #include <WebCore/SecurityOrigin.h>
115 #include <WebCore/ServiceWorkerContextData.h>
116 #include <WebCore/Settings.h>
117 #include <WebCore/URLParser.h>
118 #include <WebCore/UserGestureIndicator.h>
120 #include <wtf/CurrentTime.h>
121 #include <wtf/Language.h>
122 #include <wtf/RunLoop.h>
123 #include <wtf/text/StringHash.h>
125 #if PLATFORM(WAYLAND)
126 #include "WaylandCompositorDisplay.h"
130 #include "CookieStorageShim.h"
131 #include "ObjCObjectGraph.h"
132 #include "UserMediaCaptureManager.h"
135 #if ENABLE(SEC_ITEM_SHIM)
136 #include "SecItemShim.h"
139 #if ENABLE(NOTIFICATIONS)
140 #include "WebNotificationManager.h"
143 #if ENABLE(REMOTE_INSPECTOR)
144 #include <JavaScriptCore/RemoteInspector.h>
148 using namespace WebCore;
150 // This should be less than plugInAutoStartExpirationTimeThreshold in PlugInAutoStartProvider.
151 static const double plugInAutoStartExpirationTimeUpdateThreshold = 29 * 24 * 60 * 60;
153 // This should be greater than tileRevalidationTimeout in TileController.
154 static const Seconds nonVisibleProcessCleanupDelay { 10_s };
158 WebProcess& WebProcess::singleton()
160 static WebProcess& process = *new WebProcess;
164 WebProcess::WebProcess()
165 : m_eventDispatcher(EventDispatcher::create())
167 , m_viewUpdateDispatcher(ViewUpdateDispatcher::create())
169 , m_webInspectorInterruptDispatcher(WebInspectorInterruptDispatcher::create())
170 , m_webLoaderStrategy(*new WebLoaderStrategy)
171 , m_cacheStorageProvider(WebCacheStorageProvider::create())
172 , m_dnsPrefetchHystereris([this](PAL::HysteresisState state) { if (state == PAL::HysteresisState::Stopped) m_dnsPrefetchedHosts.clear(); })
173 #if ENABLE(NETSCAPE_PLUGIN_API)
174 , m_pluginProcessConnectionManager(PluginProcessConnectionManager::create())
176 , m_nonVisibleProcessCleanupTimer(*this, &WebProcess::nonVisibleProcessCleanupTimerFired)
178 , m_webSQLiteDatabaseTracker(*this)
181 // Initialize our platform strategies.
182 WebPlatformStrategies::initialize();
184 // FIXME: This should moved to where WebProcess::initialize is called,
185 // so that ports have a chance to customize, and ifdefs in this file are
187 addSupplement<WebGeolocationManager>();
188 addSupplement<WebCookieManager>();
189 addSupplement<AuthenticationManager>();
191 #if ENABLE(NOTIFICATIONS)
192 addSupplement<WebNotificationManager>();
195 #if ENABLE(LEGACY_ENCRYPTED_MEDIA)
196 addSupplement<WebMediaKeyStorageManager>();
199 #if PLATFORM(COCOA) && ENABLE(MEDIA_STREAM)
200 addSupplement<UserMediaCaptureManager>();
203 m_plugInAutoStartOriginHashes.add(PAL::SessionID::defaultSessionID(), HashMap<unsigned, double>());
205 ResourceLoadObserver::shared().setNotificationCallback([this] (Vector<ResourceLoadStatistics>&& statistics) {
206 ASSERT(!statistics.isEmpty());
207 parentProcessConnection()->send(Messages::WebResourceLoadStatisticsStore::ResourceLoadStatisticsUpdated(WTFMove(statistics)), 0);
210 Gigacage::disableDisablingPrimitiveGigacageIfShouldBeEnabled();
213 WebProcess::~WebProcess()
217 void WebProcess::initializeProcess(const ChildProcessInitializationParameters& parameters)
219 platformInitializeProcess(parameters);
222 void WebProcess::initializeConnection(IPC::Connection* connection)
224 ChildProcess::initializeConnection(connection);
226 #if !PLATFORM(GTK) && !PLATFORM(WPE)
227 connection->setShouldExitOnSyncMessageSendFailure(true);
230 #if HAVE(QOS_CLASSES)
231 connection->setShouldBoostMainThreadOnSyncMessage(true);
234 m_eventDispatcher->initializeConnection(connection);
236 m_viewUpdateDispatcher->initializeConnection(connection);
237 #endif // PLATFORM(IOS)
238 m_webInspectorInterruptDispatcher->initializeConnection(connection);
240 #if ENABLE(NETSCAPE_PLUGIN_API)
241 m_pluginProcessConnectionManager->initializeConnection(connection);
244 for (auto& supplement : m_supplements.values())
245 supplement->initializeConnection(connection);
247 m_webConnection = WebConnectionToUIProcess::create(this);
249 // In order to ensure that the asynchronous messages that are used for notifying the UI process
250 // about when WebFrame objects come and go are always delivered before the synchronous policy messages,
251 // use this flag to force synchronous messages to be treated as asynchronous messages in the UI process
252 // unless when doing so would lead to a deadlock.
253 connection->setOnlySendMessagesAsDispatchWhenWaitingForSyncReplyWhenProcessingSuchAMessage(true);
256 void WebProcess::initializeWebProcess(WebProcessCreationParameters&& parameters)
258 ASSERT(m_pageMap.isEmpty());
260 WebCore::setPresentingApplicationPID(parameters.presentingApplicationPID);
263 if (parameters.memoryPressureMonitorHandle.fileDescriptor() != -1)
264 MemoryPressureHandler::singleton().setMemoryPressureMonitorHandle(parameters.memoryPressureMonitorHandle.releaseFileDescriptor());
265 MemoryPressureHandler::ReliefLogger::setLoggingEnabled(parameters.shouldEnableMemoryPressureReliefLogging);
268 platformInitializeWebProcess(WTFMove(parameters));
270 #if USE(NETWORK_SESSION)
271 SessionTracker::setSession(PAL::SessionID::defaultSessionID(), NetworkSession::create({ }));
274 // Match the QoS of the UIProcess and the scrolling thread but use a slightly lower priority.
275 WTF::Thread::setCurrentThreadIsUserInteractive(-1);
277 m_suppressMemoryPressureHandler = parameters.shouldSuppressMemoryPressureHandler;
278 if (!m_suppressMemoryPressureHandler) {
279 auto& memoryPressureHandler = MemoryPressureHandler::singleton();
280 memoryPressureHandler.setLowMemoryHandler([] (Critical critical, Synchronous synchronous) {
281 WebCore::releaseMemory(critical, synchronous);
283 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
284 memoryPressureHandler.setShouldUsePeriodicMemoryMonitor(true);
285 memoryPressureHandler.setMemoryKillCallback([this] () {
286 WebCore::logMemoryStatisticsAtTimeOfDeath();
287 if (MemoryPressureHandler::singleton().processState() == WebsamProcessState::Active)
288 parentProcessConnection()->send(Messages::WebProcessProxy::DidExceedActiveMemoryLimit(), 0);
290 parentProcessConnection()->send(Messages::WebProcessProxy::DidExceedInactiveMemoryLimit(), 0);
292 memoryPressureHandler.setDidExceedInactiveLimitWhileActiveCallback([this] () {
293 parentProcessConnection()->send(Messages::WebProcessProxy::DidExceedInactiveMemoryLimitWhileActive(), 0);
296 memoryPressureHandler.setMemoryPressureStatusChangedCallback([this](bool isUnderMemoryPressure) {
297 if (parentProcessConnection())
298 parentProcessConnection()->send(Messages::WebProcessProxy::MemoryPressureStatusChanged(isUnderMemoryPressure), 0);
300 memoryPressureHandler.install();
303 for (size_t i = 0, size = parameters.additionalSandboxExtensionHandles.size(); i < size; ++i)
304 SandboxExtension::consumePermanently(parameters.additionalSandboxExtensionHandles[i]);
306 if (!parameters.injectedBundlePath.isEmpty())
307 m_injectedBundle = InjectedBundle::create(parameters, transformHandlesToObjects(parameters.initializationUserData.object()).get());
309 for (auto& supplement : m_supplements.values())
310 supplement->initialize(parameters);
312 auto& databaseManager = DatabaseManager::singleton();
313 databaseManager.initialize(parameters.webSQLDatabaseDirectory);
315 // FIXME: This should be constructed per data store, not per process.
316 m_applicationCacheStorage = ApplicationCacheStorage::create(parameters.applicationCacheDirectory, parameters.applicationCacheFlatFileSubdirectoryName);
318 m_applicationCacheStorage->setDefaultOriginQuota(25ULL * 1024 * 1024);
322 if (!parameters.mediaCacheDirectory.isEmpty())
323 WebCore::HTMLMediaElement::setMediaCacheDirectory(parameters.mediaCacheDirectory);
326 setCacheModel(static_cast<uint32_t>(parameters.cacheModel));
328 if (!parameters.languages.isEmpty())
329 overrideUserPreferredLanguages(parameters.languages);
331 m_textCheckerState = parameters.textCheckerState;
333 m_fullKeyboardAccessEnabled = parameters.fullKeyboardAccessEnabled;
335 for (auto& scheme : parameters.urlSchemesRegisteredAsEmptyDocument)
336 registerURLSchemeAsEmptyDocument(scheme);
338 for (auto& scheme : parameters.urlSchemesRegisteredAsSecure)
339 registerURLSchemeAsSecure(scheme);
341 for (auto& scheme : parameters.urlSchemesRegisteredAsBypassingContentSecurityPolicy)
342 registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
344 for (auto& scheme : parameters.urlSchemesForWhichDomainRelaxationIsForbidden)
345 setDomainRelaxationForbiddenForURLScheme(scheme);
347 for (auto& scheme : parameters.urlSchemesRegisteredAsLocal)
348 registerURLSchemeAsLocal(scheme);
350 for (auto& scheme : parameters.urlSchemesRegisteredAsNoAccess)
351 registerURLSchemeAsNoAccess(scheme);
353 for (auto& scheme : parameters.urlSchemesRegisteredAsDisplayIsolated)
354 registerURLSchemeAsDisplayIsolated(scheme);
356 for (auto& scheme : parameters.urlSchemesRegisteredAsCORSEnabled)
357 registerURLSchemeAsCORSEnabled(scheme);
359 for (auto& scheme : parameters.urlSchemesRegisteredAsAlwaysRevalidated)
360 registerURLSchemeAsAlwaysRevalidated(scheme);
362 for (auto& scheme : parameters.urlSchemesRegisteredAsCachePartitioned)
363 registerURLSchemeAsCachePartitioned(scheme);
365 setDefaultRequestTimeoutInterval(parameters.defaultRequestTimeoutInterval);
367 setResourceLoadStatisticsEnabled(parameters.resourceLoadStatisticsEnabled);
369 if (parameters.shouldAlwaysUseComplexTextCodePath)
370 setAlwaysUsesComplexTextCodePath(true);
372 if (parameters.shouldUseFontSmoothing)
373 setShouldUseFontSmoothing(true);
375 if (parameters.shouldUseTestingNetworkSession)
376 NetworkStorageSession::switchToNewTestingSession();
378 ensureNetworkProcessConnection();
381 CookieStorageShim::singleton().initialize();
383 setTerminationTimeout(parameters.terminationTimeout);
385 resetPlugInAutoStartOriginHashes(parameters.plugInAutoStartOriginHashes);
386 for (auto& origin : parameters.plugInAutoStartOrigins)
387 m_plugInAutoStartOrigins.add(origin);
389 setMemoryCacheDisabled(parameters.memoryCacheDisabled);
391 #if ENABLE(SERVICE_CONTROLS)
392 setEnabledServices(parameters.hasImageServices, parameters.hasSelectionServices, parameters.hasRichContentServices);
395 #if ENABLE(REMOTE_INSPECTOR) && PLATFORM(COCOA)
396 audit_token_t auditToken;
397 if (parentProcessConnection()->getAuditToken(auditToken)) {
398 RetainPtr<CFDataRef> auditData = adoptCF(CFDataCreate(nullptr, (const UInt8*)&auditToken, sizeof(auditToken)));
399 Inspector::RemoteInspector::singleton().setParentProcessInformation(WebCore::presentingApplicationPID(), auditData);
403 #if ENABLE(NETSCAPE_PLUGIN_API) && PLATFORM(MAC)
404 resetPluginLoadClientPolicies(parameters.pluginLoadClientPolicies);
408 GamepadProvider::singleton().setSharedProvider(WebGamepadProvider::singleton());
411 #if ENABLE(SERVICE_WORKER)
412 ServiceWorkerProvider::setSharedProvider(WebServiceWorkerProvider::singleton());
415 #if ENABLE(WEBASSEMBLY)
416 JSC::Wasm::enableFastMemory();
420 void WebProcess::ensureNetworkProcessConnection()
422 if (m_networkProcessConnection)
425 IPC::Attachment encodedConnectionIdentifier;
427 if (!parentProcessConnection()->sendSync(Messages::WebProcessProxy::GetNetworkProcessConnection(),
428 Messages::WebProcessProxy::GetNetworkProcessConnection::Reply(encodedConnectionIdentifier), 0))
431 #if USE(UNIX_DOMAIN_SOCKETS)
432 IPC::Connection::Identifier connectionIdentifier = encodedConnectionIdentifier.releaseFileDescriptor();
434 IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.port());
436 ASSERT_NOT_REACHED();
438 if (IPC::Connection::identifierIsNull(connectionIdentifier))
440 m_networkProcessConnection = NetworkProcessConnection::create(connectionIdentifier);
443 void WebProcess::registerURLSchemeAsEmptyDocument(const String& urlScheme)
445 SchemeRegistry::registerURLSchemeAsEmptyDocument(urlScheme);
448 void WebProcess::registerURLSchemeAsSecure(const String& urlScheme) const
450 SchemeRegistry::registerURLSchemeAsSecure(urlScheme);
453 void WebProcess::registerURLSchemeAsBypassingContentSecurityPolicy(const String& urlScheme) const
455 SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(urlScheme);
458 void WebProcess::setDomainRelaxationForbiddenForURLScheme(const String& urlScheme) const
460 SchemeRegistry::setDomainRelaxationForbiddenForURLScheme(true, urlScheme);
463 void WebProcess::registerURLSchemeAsLocal(const String& urlScheme) const
465 SchemeRegistry::registerURLSchemeAsLocal(urlScheme);
468 void WebProcess::registerURLSchemeAsNoAccess(const String& urlScheme) const
470 SchemeRegistry::registerURLSchemeAsNoAccess(urlScheme);
473 void WebProcess::registerURLSchemeAsDisplayIsolated(const String& urlScheme) const
475 SchemeRegistry::registerURLSchemeAsDisplayIsolated(urlScheme);
478 void WebProcess::registerURLSchemeAsCORSEnabled(const String& urlScheme) const
480 SchemeRegistry::registerURLSchemeAsCORSEnabled(urlScheme);
483 void WebProcess::registerURLSchemeAsAlwaysRevalidated(const String& urlScheme) const
485 SchemeRegistry::registerURLSchemeAsAlwaysRevalidated(urlScheme);
488 void WebProcess::registerURLSchemeAsCachePartitioned(const String& urlScheme) const
490 SchemeRegistry::registerURLSchemeAsCachePartitioned(urlScheme);
493 void WebProcess::setDefaultRequestTimeoutInterval(double timeoutInterval)
495 ResourceRequest::setDefaultTimeoutInterval(timeoutInterval);
498 void WebProcess::setAlwaysUsesComplexTextCodePath(bool alwaysUseComplexText)
500 WebCore::FontCascade::setCodePath(alwaysUseComplexText ? WebCore::FontCascade::Complex : WebCore::FontCascade::Auto);
503 void WebProcess::setShouldUseFontSmoothing(bool useFontSmoothing)
505 WebCore::FontCascade::setShouldUseSmoothing(useFontSmoothing);
508 void WebProcess::userPreferredLanguagesChanged(const Vector<String>& languages) const
510 overrideUserPreferredLanguages(languages);
513 void WebProcess::fullKeyboardAccessModeChanged(bool fullKeyboardAccessEnabled)
515 m_fullKeyboardAccessEnabled = fullKeyboardAccessEnabled;
518 void WebProcess::ensurePrivateBrowsingSession(PAL::SessionID sessionID)
520 WebFrameNetworkingContext::ensurePrivateBrowsingSession({ { }, { }, { }, { }, { }, { }, { sessionID, { }, { }, AllowsCellularAccess::Yes }});
523 void WebProcess::addWebsiteDataStore(WebsiteDataStoreParameters&& parameters)
525 WebFrameNetworkingContext::ensureWebsiteDataStoreSession(WTFMove(parameters));
528 void WebProcess::destroySession(PAL::SessionID sessionID)
530 SessionTracker::destroySession(sessionID);
533 void WebProcess::ensureLegacyPrivateBrowsingSessionInNetworkProcess()
535 networkConnection().connection().send(Messages::NetworkConnectionToWebProcess::EnsureLegacyPrivateBrowsingSession(), 0);
538 #if ENABLE(NETSCAPE_PLUGIN_API)
539 PluginProcessConnectionManager& WebProcess::pluginProcessConnectionManager()
541 return *m_pluginProcessConnectionManager;
545 void WebProcess::setCacheModel(uint32_t cm)
547 CacheModel cacheModel = static_cast<CacheModel>(cm);
549 if (m_hasSetCacheModel && (cacheModel == m_cacheModel))
552 m_hasSetCacheModel = true;
553 m_cacheModel = cacheModel;
555 unsigned cacheTotalCapacity = 0;
556 unsigned cacheMinDeadCapacity = 0;
557 unsigned cacheMaxDeadCapacity = 0;
558 Seconds deadDecodedDataDeletionInterval;
559 unsigned pageCacheSize = 0;
560 calculateMemoryCacheSizes(cacheModel, cacheTotalCapacity, cacheMinDeadCapacity, cacheMaxDeadCapacity, deadDecodedDataDeletionInterval, pageCacheSize);
562 auto& memoryCache = MemoryCache::singleton();
563 memoryCache.setCapacities(cacheMinDeadCapacity, cacheMaxDeadCapacity, cacheTotalCapacity);
564 memoryCache.setDeadDecodedDataDeletionInterval(deadDecodedDataDeletionInterval);
565 PageCache::singleton().setMaxSize(pageCacheSize);
567 platformSetCacheModel(cacheModel);
570 void WebProcess::clearCachedCredentials()
572 NetworkStorageSession::defaultStorageSession().credentialStorage().clearCredentials();
573 #if USE(NETWORK_SESSION)
574 if (auto* networkSession = SessionTracker::networkSession(PAL::SessionID::defaultSessionID()))
575 networkSession->clearCredentials();
577 ASSERT_NOT_REACHED();
581 WebPage* WebProcess::focusedWebPage() const
583 for (auto& page : m_pageMap.values()) {
584 if (page->windowAndWebPageAreFocused())
590 WebPage* WebProcess::webPage(uint64_t pageID) const
592 return m_pageMap.get(pageID);
595 void WebProcess::createWebPage(uint64_t pageID, WebPageCreationParameters&& parameters)
597 // It is necessary to check for page existence here since during a window.open() (or targeted
598 // link) the WebPage gets created both in the synchronous handler and through the normal way.
599 HashMap<uint64_t, RefPtr<WebPage>>::AddResult result = m_pageMap.add(pageID, nullptr);
600 if (result.isNewEntry) {
601 ASSERT(!result.iterator->value);
602 result.iterator->value = WebPage::create(pageID, WTFMove(parameters));
604 // Balanced by an enableTermination in removeWebPage.
605 disableTermination();
608 result.iterator->value->reinitializeWebPage(WTFMove(parameters));
610 ASSERT(result.iterator->value);
613 void WebProcess::removeWebPage(uint64_t pageID)
615 ASSERT(m_pageMap.contains(pageID));
617 pageWillLeaveWindow(pageID);
618 m_pageMap.remove(pageID);
624 bool WebProcess::shouldTerminate()
626 ASSERT(m_pageMap.isEmpty());
628 // FIXME: the ShouldTerminate message should also send termination parameters, such as any session cookies that need to be preserved.
629 bool shouldTerminate = false;
630 if (parentProcessConnection()->sendSync(Messages::WebProcessProxy::ShouldTerminate(), Messages::WebProcessProxy::ShouldTerminate::Reply(shouldTerminate), 0)
637 void WebProcess::terminate()
640 GCController::singleton().garbageCollectNow();
641 FontCache::singleton().invalidate();
642 MemoryCache::singleton().setDisabled(true);
645 m_webConnection->invalidate();
646 m_webConnection = nullptr;
650 ChildProcess::terminate();
653 void WebProcess::didReceiveSyncMessage(IPC::Connection& connection, IPC::Decoder& decoder, std::unique_ptr<IPC::Encoder>& replyEncoder)
655 if (messageReceiverMap().dispatchSyncMessage(connection, decoder, replyEncoder))
658 didReceiveSyncWebProcessMessage(connection, decoder, replyEncoder);
661 void WebProcess::didReceiveMessage(IPC::Connection& connection, IPC::Decoder& decoder)
663 if (messageReceiverMap().dispatchMessage(connection, decoder))
666 if (decoder.messageReceiverName() == Messages::WebProcess::messageReceiverName()) {
667 didReceiveWebProcessMessage(connection, decoder);
671 if (decoder.messageReceiverName() == Messages::ChildProcess::messageReceiverName()) {
672 ChildProcess::didReceiveMessage(connection, decoder);
676 #if ENABLE(SERVICE_WORKER)
677 if (decoder.messageReceiverName() == Messages::ServiceWorkerContextManager::messageReceiverName()) {
678 ASSERT(m_serviceWorkerManager);
679 if (m_serviceWorkerManager)
680 m_serviceWorkerManager->didReceiveMessage(connection, decoder);
685 LOG_ERROR("Unhandled web process message '%s:%s'", decoder.messageReceiverName().toString().data(), decoder.messageName().toString().data());
688 void WebProcess::didClose(IPC::Connection&)
691 for (auto& page : copyToVector(m_pageMap.values()))
694 GCController::singleton().garbageCollectSoon();
695 FontCache::singleton().invalidate();
696 MemoryCache::singleton().setDisabled(true);
700 // FIXME(146657): This explicit media stop command should not be necessary
701 if (auto* platformMediaSessionManager = PlatformMediaSessionManager::sharedManagerIfExists())
702 platformMediaSessionManager->stopAllMediaPlaybackForProcess();
705 // The UI process closed this connection, shut down.
709 WebFrame* WebProcess::webFrame(uint64_t frameID) const
711 return m_frameMap.get(frameID);
714 void WebProcess::addWebFrame(uint64_t frameID, WebFrame* frame)
716 m_frameMap.set(frameID, frame);
719 void WebProcess::removeWebFrame(uint64_t frameID)
721 m_frameMap.remove(frameID);
723 // We can end up here after our connection has closed when WebCore's frame life-support timer
724 // fires when the application is shutting down. There's no need (and no way) to update the UI
725 // process in this case.
726 if (!parentProcessConnection())
729 parentProcessConnection()->send(Messages::WebProcessProxy::DidDestroyFrame(frameID), 0);
732 WebPageGroupProxy* WebProcess::webPageGroup(PageGroup* pageGroup)
734 for (auto& page : m_pageGroupMap.values()) {
735 if (page->corePageGroup() == pageGroup)
742 WebPageGroupProxy* WebProcess::webPageGroup(uint64_t pageGroupID)
744 return m_pageGroupMap.get(pageGroupID);
747 WebPageGroupProxy* WebProcess::webPageGroup(const WebPageGroupData& pageGroupData)
749 auto result = m_pageGroupMap.add(pageGroupData.pageGroupID, nullptr);
750 if (result.isNewEntry) {
751 ASSERT(!result.iterator->value);
752 result.iterator->value = WebPageGroupProxy::create(pageGroupData);
755 return result.iterator->value.get();
758 static uint64_t nextUserGestureTokenIdentifier()
760 static uint64_t identifier = 1;
764 uint64_t WebProcess::userGestureTokenIdentifier(RefPtr<UserGestureToken> token)
766 if (!token || !token->processingUserGesture())
769 auto result = m_userGestureTokens.ensure(token.get(), [] { return nextUserGestureTokenIdentifier(); });
770 if (result.isNewEntry) {
771 result.iterator->key->addDestructionObserver([] (UserGestureToken& tokenBeingDestroyed) {
772 WebProcess::singleton().userGestureTokenDestroyed(tokenBeingDestroyed);
776 return result.iterator->value;
779 void WebProcess::userGestureTokenDestroyed(UserGestureToken& token)
781 auto identifier = m_userGestureTokens.take(&token);
782 parentProcessConnection()->send(Messages::WebProcessProxy::DidDestroyUserGestureToken(identifier), 0);
785 void WebProcess::clearResourceCaches(ResourceCachesToClear resourceCachesToClear)
787 // Toggling the cache model like this forces the cache to evict all its in-memory resources.
788 // FIXME: We need a better way to do this.
789 CacheModel cacheModel = m_cacheModel;
790 setCacheModel(CacheModelDocumentViewer);
791 setCacheModel(cacheModel);
793 MemoryCache::singleton().evictResources();
795 // Empty the cross-origin preflight cache.
796 CrossOriginPreflightResultCache::singleton().empty();
799 static inline void addCaseFoldedCharacters(StringHasher& hasher, const String& string)
801 if (string.isEmpty())
803 if (string.is8Bit()) {
804 hasher.addCharacters<LChar, ASCIICaseInsensitiveHash::foldCase<LChar>>(string.characters8(), string.length());
807 hasher.addCharacters<UChar, ASCIICaseInsensitiveHash::foldCase<UChar>>(string.characters16(), string.length());
810 static unsigned hashForPlugInOrigin(const String& pageOrigin, const String& pluginOrigin, const String& mimeType)
812 // We want to avoid concatenating the strings and then taking the hash, since that could lead to an expensive conversion.
813 // We also want to avoid using the hash() function in StringImpl or ASCIICaseInsensitiveHash because that masks out bits for the use of flags.
815 addCaseFoldedCharacters(hasher, pageOrigin);
816 hasher.addCharacter(0);
817 addCaseFoldedCharacters(hasher, pluginOrigin);
818 hasher.addCharacter(0);
819 addCaseFoldedCharacters(hasher, mimeType);
820 return hasher.hash();
823 bool WebProcess::isPlugInAutoStartOriginHash(unsigned plugInOriginHash, PAL::SessionID sessionID)
825 HashMap<PAL::SessionID, HashMap<unsigned, double>>::const_iterator sessionIterator = m_plugInAutoStartOriginHashes.find(sessionID);
826 HashMap<unsigned, double>::const_iterator it;
827 bool contains = false;
829 if (sessionIterator != m_plugInAutoStartOriginHashes.end()) {
830 it = sessionIterator->value.find(plugInOriginHash);
831 contains = it != sessionIterator->value.end();
834 sessionIterator = m_plugInAutoStartOriginHashes.find(PAL::SessionID::defaultSessionID());
835 it = sessionIterator->value.find(plugInOriginHash);
836 if (it == sessionIterator->value.end())
839 return currentTime() < it->value;
842 bool WebProcess::shouldPlugInAutoStartFromOrigin(WebPage& webPage, const String& pageOrigin, const String& pluginOrigin, const String& mimeType)
844 if (!pluginOrigin.isEmpty() && m_plugInAutoStartOrigins.contains(pluginOrigin))
847 #ifdef ENABLE_PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC
848 // 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).
849 if (webPage.matchesPrimaryPlugIn(pageOrigin, pluginOrigin, mimeType))
852 UNUSED_PARAM(webPage);
855 // Lastly check against the more explicit hash list.
856 return isPlugInAutoStartOriginHash(hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType), webPage.sessionID());
859 void WebProcess::plugInDidStartFromOrigin(const String& pageOrigin, const String& pluginOrigin, const String& mimeType, PAL::SessionID sessionID)
861 if (pageOrigin.isEmpty()) {
862 LOG(Plugins, "Not adding empty page origin");
866 unsigned plugInOriginHash = hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType);
867 if (isPlugInAutoStartOriginHash(plugInOriginHash, sessionID)) {
868 LOG(Plugins, "Hash %x already exists as auto-start origin (request for %s)", plugInOriginHash, pageOrigin.utf8().data());
872 // We might attempt to start another plugin before the didAddPlugInAutoStartOrigin message
873 // comes back from the parent process. Temporarily add this hash to the list with a thirty
874 // second timeout. That way, even if the parent decides not to add it, we'll only be
875 // incorrect for a little while.
876 m_plugInAutoStartOriginHashes.add(sessionID, HashMap<unsigned, double>()).iterator->value.set(plugInOriginHash, currentTime() + 30 * 1000);
878 parentProcessConnection()->send(Messages::WebProcessPool::AddPlugInAutoStartOriginHash(pageOrigin, plugInOriginHash, sessionID), 0);
881 void WebProcess::didAddPlugInAutoStartOriginHash(unsigned plugInOriginHash, double expirationTime, PAL::SessionID sessionID)
883 // When called, some web process (which also might be this one) added the origin for auto-starting,
884 // or received user interaction.
885 // Set the bit to avoid having redundantly call into the UI process upon user interaction.
886 m_plugInAutoStartOriginHashes.add(sessionID, HashMap<unsigned, double>()).iterator->value.set(plugInOriginHash, expirationTime);
889 void WebProcess::resetPlugInAutoStartOriginDefaultHashes(const HashMap<unsigned, double>& hashes)
891 m_plugInAutoStartOriginHashes.clear();
892 m_plugInAutoStartOriginHashes.add(PAL::SessionID::defaultSessionID(), HashMap<unsigned, double>()).iterator->value.swap(const_cast<HashMap<unsigned, double>&>(hashes));
895 void WebProcess::resetPlugInAutoStartOriginHashes(const HashMap<PAL::SessionID, HashMap<unsigned, double>>& hashes)
897 m_plugInAutoStartOriginHashes.swap(const_cast<HashMap<PAL::SessionID, HashMap<unsigned, double>>&>(hashes));
900 void WebProcess::plugInDidReceiveUserInteraction(const String& pageOrigin, const String& pluginOrigin, const String& mimeType, PAL::SessionID sessionID)
902 if (pageOrigin.isEmpty())
905 unsigned plugInOriginHash = hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType);
906 if (!plugInOriginHash)
909 HashMap<PAL::SessionID, HashMap<unsigned, double>>::const_iterator sessionIterator = m_plugInAutoStartOriginHashes.find(sessionID);
910 HashMap<unsigned, double>::const_iterator it;
911 bool contains = false;
912 if (sessionIterator != m_plugInAutoStartOriginHashes.end()) {
913 it = sessionIterator->value.find(plugInOriginHash);
914 contains = it != sessionIterator->value.end();
917 sessionIterator = m_plugInAutoStartOriginHashes.find(PAL::SessionID::defaultSessionID());
918 it = sessionIterator->value.find(plugInOriginHash);
919 if (it == sessionIterator->value.end())
923 if (it->value - currentTime() > plugInAutoStartExpirationTimeUpdateThreshold)
926 parentProcessConnection()->send(Messages::WebProcessPool::PlugInDidReceiveUserInteraction(plugInOriginHash, sessionID), 0);
929 void WebProcess::setPluginLoadClientPolicy(uint8_t policy, const String& host, const String& bundleIdentifier, const String& versionString)
931 #if ENABLE(NETSCAPE_PLUGIN_API) && PLATFORM(MAC)
932 WebPluginInfoProvider::singleton().setPluginLoadClientPolicy(static_cast<PluginLoadClientPolicy>(policy), host, bundleIdentifier, versionString);
936 void WebProcess::resetPluginLoadClientPolicies(const HashMap<WTF::String, HashMap<WTF::String, HashMap<WTF::String, uint8_t>>>& pluginLoadClientPolicies)
938 #if ENABLE(NETSCAPE_PLUGIN_API) && PLATFORM(MAC)
939 clearPluginClientPolicies();
941 for (auto& hostPair : pluginLoadClientPolicies) {
942 for (auto& bundleIdentifierPair : hostPair.value) {
943 for (auto& versionPair : bundleIdentifierPair.value)
944 WebPluginInfoProvider::singleton().setPluginLoadClientPolicy(static_cast<PluginLoadClientPolicy>(versionPair.value), hostPair.key, bundleIdentifierPair.key, versionPair.key);
950 void WebProcess::clearPluginClientPolicies()
952 #if ENABLE(NETSCAPE_PLUGIN_API) && PLATFORM(MAC)
953 WebPluginInfoProvider::singleton().clearPluginClientPolicies();
957 void WebProcess::refreshPlugins()
959 #if ENABLE(NETSCAPE_PLUGIN_API)
960 WebPluginInfoProvider::singleton().refresh(false);
964 static void fromCountedSetToHashMap(TypeCountSet* countedSet, HashMap<String, uint64_t>& map)
966 TypeCountSet::const_iterator end = countedSet->end();
967 for (TypeCountSet::const_iterator it = countedSet->begin(); it != end; ++it)
968 map.set(it->key, it->value);
971 static void getWebCoreMemoryCacheStatistics(Vector<HashMap<String, uint64_t>>& result)
973 String imagesString(ASCIILiteral("Images"));
974 String cssString(ASCIILiteral("CSS"));
975 String xslString(ASCIILiteral("XSL"));
976 String javaScriptString(ASCIILiteral("JavaScript"));
978 MemoryCache::Statistics memoryCacheStatistics = MemoryCache::singleton().getStatistics();
980 HashMap<String, uint64_t> counts;
981 counts.set(imagesString, memoryCacheStatistics.images.count);
982 counts.set(cssString, memoryCacheStatistics.cssStyleSheets.count);
983 counts.set(xslString, memoryCacheStatistics.xslStyleSheets.count);
984 counts.set(javaScriptString, memoryCacheStatistics.scripts.count);
985 result.append(counts);
987 HashMap<String, uint64_t> sizes;
988 sizes.set(imagesString, memoryCacheStatistics.images.size);
989 sizes.set(cssString, memoryCacheStatistics.cssStyleSheets.size);
990 sizes.set(xslString, memoryCacheStatistics.xslStyleSheets.size);
991 sizes.set(javaScriptString, memoryCacheStatistics.scripts.size);
992 result.append(sizes);
994 HashMap<String, uint64_t> liveSizes;
995 liveSizes.set(imagesString, memoryCacheStatistics.images.liveSize);
996 liveSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.liveSize);
997 liveSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.liveSize);
998 liveSizes.set(javaScriptString, memoryCacheStatistics.scripts.liveSize);
999 result.append(liveSizes);
1001 HashMap<String, uint64_t> decodedSizes;
1002 decodedSizes.set(imagesString, memoryCacheStatistics.images.decodedSize);
1003 decodedSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.decodedSize);
1004 decodedSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.decodedSize);
1005 decodedSizes.set(javaScriptString, memoryCacheStatistics.scripts.decodedSize);
1006 result.append(decodedSizes);
1009 void WebProcess::getWebCoreStatistics(uint64_t callbackID)
1011 StatisticsData data;
1013 // Gather JavaScript statistics.
1015 JSLockHolder lock(commonVM());
1016 data.statisticsNumbers.set(ASCIILiteral("JavaScriptObjectsCount"), commonVM().heap.objectCount());
1017 data.statisticsNumbers.set(ASCIILiteral("JavaScriptGlobalObjectsCount"), commonVM().heap.globalObjectCount());
1018 data.statisticsNumbers.set(ASCIILiteral("JavaScriptProtectedObjectsCount"), commonVM().heap.protectedObjectCount());
1019 data.statisticsNumbers.set(ASCIILiteral("JavaScriptProtectedGlobalObjectsCount"), commonVM().heap.protectedGlobalObjectCount());
1021 std::unique_ptr<TypeCountSet> protectedObjectTypeCounts(commonVM().heap.protectedObjectTypeCounts());
1022 fromCountedSetToHashMap(protectedObjectTypeCounts.get(), data.javaScriptProtectedObjectTypeCounts);
1024 std::unique_ptr<TypeCountSet> objectTypeCounts(commonVM().heap.objectTypeCounts());
1025 fromCountedSetToHashMap(objectTypeCounts.get(), data.javaScriptObjectTypeCounts);
1027 uint64_t javaScriptHeapSize = commonVM().heap.size();
1028 data.statisticsNumbers.set(ASCIILiteral("JavaScriptHeapSize"), javaScriptHeapSize);
1029 data.statisticsNumbers.set(ASCIILiteral("JavaScriptFreeSize"), commonVM().heap.capacity() - javaScriptHeapSize);
1032 WTF::FastMallocStatistics fastMallocStatistics = WTF::fastMallocStatistics();
1033 data.statisticsNumbers.set(ASCIILiteral("FastMallocReservedVMBytes"), fastMallocStatistics.reservedVMBytes);
1034 data.statisticsNumbers.set(ASCIILiteral("FastMallocCommittedVMBytes"), fastMallocStatistics.committedVMBytes);
1035 data.statisticsNumbers.set(ASCIILiteral("FastMallocFreeListBytes"), fastMallocStatistics.freeListBytes);
1037 // Gather font statistics.
1038 auto& fontCache = FontCache::singleton();
1039 data.statisticsNumbers.set(ASCIILiteral("CachedFontDataCount"), fontCache.fontCount());
1040 data.statisticsNumbers.set(ASCIILiteral("CachedFontDataInactiveCount"), fontCache.inactiveFontCount());
1042 // Gather glyph page statistics.
1043 data.statisticsNumbers.set(ASCIILiteral("GlyphPageCount"), GlyphPage::count());
1045 // Get WebCore memory cache statistics
1046 getWebCoreMemoryCacheStatistics(data.webCoreCacheStatistics);
1048 parentProcessConnection()->send(Messages::WebProcessPool::DidGetStatistics(data, callbackID), 0);
1051 void WebProcess::garbageCollectJavaScriptObjects()
1053 GCController::singleton().garbageCollectNow();
1056 void WebProcess::mainThreadPing()
1058 parentProcessConnection()->send(Messages::WebProcessProxy::DidReceiveMainThreadPing(), 0);
1061 void WebProcess::backgroundResponsivenessPing()
1063 parentProcessConnection()->send(Messages::WebProcessProxy::DidReceiveBackgroundResponsivenessPing(), 0);
1068 void WebProcess::setInitialGamepads(const Vector<WebKit::GamepadData>& gamepadDatas)
1070 WebGamepadProvider::singleton().setInitialGamepads(gamepadDatas);
1073 void WebProcess::gamepadConnected(const GamepadData& gamepadData)
1075 WebGamepadProvider::singleton().gamepadConnected(gamepadData);
1078 void WebProcess::gamepadDisconnected(unsigned index)
1080 WebGamepadProvider::singleton().gamepadDisconnected(index);
1085 void WebProcess::setJavaScriptGarbageCollectorTimerEnabled(bool flag)
1087 GCController::singleton().setJavaScriptGarbageCollectorTimerEnabled(flag);
1090 void WebProcess::handleInjectedBundleMessage(const String& messageName, const UserData& messageBody)
1092 InjectedBundle* injectedBundle = WebProcess::singleton().injectedBundle();
1093 if (!injectedBundle)
1096 injectedBundle->didReceiveMessage(messageName, transformHandlesToObjects(messageBody.object()).get());
1099 void WebProcess::setInjectedBundleParameter(const String& key, const IPC::DataReference& value)
1101 InjectedBundle* injectedBundle = WebProcess::singleton().injectedBundle();
1102 if (!injectedBundle)
1105 injectedBundle->setBundleParameter(key, value);
1108 void WebProcess::setInjectedBundleParameters(const IPC::DataReference& value)
1110 InjectedBundle* injectedBundle = WebProcess::singleton().injectedBundle();
1111 if (!injectedBundle)
1114 injectedBundle->setBundleParameters(value);
1117 NetworkProcessConnection& WebProcess::networkConnection()
1119 // If we've lost our connection to the network process (e.g. it crashed) try to re-establish it.
1120 if (!m_networkProcessConnection)
1121 ensureNetworkProcessConnection();
1123 // If we failed to re-establish it then we are beyond recovery and should crash.
1124 if (!m_networkProcessConnection)
1127 return *m_networkProcessConnection;
1130 void WebProcess::logDiagnosticMessageForNetworkProcessCrash()
1132 WebCore::Page* page = nullptr;
1134 if (auto* webPage = focusedWebPage())
1135 page = webPage->corePage();
1138 for (auto& webPage : m_pageMap.values()) {
1139 if (auto* corePage = webPage->corePage()) {
1147 page->diagnosticLoggingClient().logDiagnosticMessage(WebCore::DiagnosticLoggingKeys::internalErrorKey(), WebCore::DiagnosticLoggingKeys::networkProcessCrashedKey(), WebCore::ShouldSample::No);
1150 void WebProcess::networkProcessConnectionClosed(NetworkProcessConnection* connection)
1152 ASSERT(m_networkProcessConnection);
1153 ASSERT_UNUSED(connection, m_networkProcessConnection == connection);
1155 m_networkProcessConnection = nullptr;
1157 logDiagnosticMessageForNetworkProcessCrash();
1159 m_webLoaderStrategy.networkProcessCrashed();
1160 WebSocketStream::networkProcessCrashed();
1162 for (auto& page : m_pageMap.values())
1163 page->stopAllURLSchemeTasks();
1166 WebLoaderStrategy& WebProcess::webLoaderStrategy()
1168 return m_webLoaderStrategy;
1171 void WebProcess::webToStorageProcessConnectionClosed(WebToStorageProcessConnection* connection)
1173 ASSERT(m_webToStorageProcessConnection);
1174 ASSERT(m_webToStorageProcessConnection == connection);
1176 m_webToStorageProcessConnection = nullptr;
1179 WebToStorageProcessConnection* WebProcess::webToStorageProcessConnection()
1181 if (!m_webToStorageProcessConnection)
1182 ensureWebToStorageProcessConnection();
1184 return m_webToStorageProcessConnection.get();
1187 void WebProcess::ensureWebToStorageProcessConnection()
1189 if (m_webToStorageProcessConnection)
1192 IPC::Attachment encodedConnectionIdentifier;
1194 if (!parentProcessConnection()->sendSync(Messages::WebProcessProxy::GetStorageProcessConnection(), Messages::WebProcessProxy::GetStorageProcessConnection::Reply(encodedConnectionIdentifier), 0))
1197 #if USE(UNIX_DOMAIN_SOCKETS)
1198 IPC::Connection::Identifier connectionIdentifier = encodedConnectionIdentifier.releaseFileDescriptor();
1200 IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.port());
1202 IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.handle());
1204 ASSERT_NOT_REACHED();
1206 if (IPC::Connection::identifierIsNull(connectionIdentifier))
1208 m_webToStorageProcessConnection = WebToStorageProcessConnection::create(connectionIdentifier);
1211 void WebProcess::setEnhancedAccessibility(bool flag)
1213 WebCore::AXObjectCache::setEnhancedUserInterfaceAccessibility(flag);
1216 void WebProcess::startMemorySampler(const SandboxExtension::Handle& sampleLogFileHandle, const String& sampleLogFilePath, const double interval)
1218 #if ENABLE(MEMORY_SAMPLER)
1219 WebMemorySampler::singleton()->start(sampleLogFileHandle, sampleLogFilePath, interval);
1221 UNUSED_PARAM(sampleLogFileHandle);
1222 UNUSED_PARAM(sampleLogFilePath);
1223 UNUSED_PARAM(interval);
1227 void WebProcess::stopMemorySampler()
1229 #if ENABLE(MEMORY_SAMPLER)
1230 WebMemorySampler::singleton()->stop();
1234 void WebProcess::setTextCheckerState(const TextCheckerState& textCheckerState)
1236 bool continuousSpellCheckingTurnedOff = !textCheckerState.isContinuousSpellCheckingEnabled && m_textCheckerState.isContinuousSpellCheckingEnabled;
1237 bool grammarCheckingTurnedOff = !textCheckerState.isGrammarCheckingEnabled && m_textCheckerState.isGrammarCheckingEnabled;
1239 m_textCheckerState = textCheckerState;
1241 if (!continuousSpellCheckingTurnedOff && !grammarCheckingTurnedOff)
1244 for (auto& page : m_pageMap.values()) {
1245 if (continuousSpellCheckingTurnedOff)
1246 page->unmarkAllMisspellings();
1247 if (grammarCheckingTurnedOff)
1248 page->unmarkAllBadGrammar();
1252 void WebProcess::releasePageCache()
1254 PageCache::singleton().pruneToSizeNow(0, PruningReason::MemoryPressure);
1257 void WebProcess::fetchWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, WebsiteData& websiteData)
1259 if (websiteDataTypes.contains(WebsiteDataType::MemoryCache)) {
1260 for (auto& origin : MemoryCache::singleton().originsWithCache(sessionID))
1261 websiteData.entries.append(WebsiteData::Entry { SecurityOriginData::fromSecurityOrigin(*origin), WebsiteDataType::MemoryCache, 0 });
1264 if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
1265 if (NetworkStorageSession::storageSession(sessionID))
1266 websiteData.originsWithCredentials = NetworkStorageSession::storageSession(sessionID)->credentialStorage().originsWithCredentials();
1270 void WebProcess::deleteWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, std::chrono::system_clock::time_point modifiedSince)
1272 UNUSED_PARAM(modifiedSince);
1274 if (websiteDataTypes.contains(WebsiteDataType::MemoryCache)) {
1275 PageCache::singleton().pruneToSizeNow(0, PruningReason::None);
1276 MemoryCache::singleton().evictResources(sessionID);
1278 CrossOriginPreflightResultCache::singleton().empty();
1281 if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
1282 if (WebCore::NetworkStorageSession::storageSession(sessionID))
1283 NetworkStorageSession::storageSession(sessionID)->credentialStorage().clearCredentials();
1287 void WebProcess::deleteWebsiteDataForOrigins(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, const Vector<WebCore::SecurityOriginData>& originDatas)
1289 if (websiteDataTypes.contains(WebsiteDataType::MemoryCache)) {
1290 HashSet<RefPtr<SecurityOrigin>> origins;
1291 for (auto& originData : originDatas)
1292 origins.add(originData.securityOrigin());
1294 MemoryCache::singleton().removeResourcesWithOrigins(sessionID, origins);
1298 void WebProcess::setHiddenPageDOMTimerThrottlingIncreaseLimit(int milliseconds)
1300 for (auto& page : m_pageMap.values())
1301 page->setHiddenPageDOMTimerThrottlingIncreaseLimit(Seconds::fromMilliseconds(milliseconds));
1304 #if !PLATFORM(COCOA)
1305 void WebProcess::initializeProcessName(const ChildProcessInitializationParameters&)
1309 void WebProcess::initializeSandbox(const ChildProcessInitializationParameters&, SandboxInitializationParameters&)
1313 void WebProcess::platformInitializeProcess(const ChildProcessInitializationParameters&)
1317 void WebProcess::updateActivePages()
1321 void WebProcess::updateCPULimit()
1325 void WebProcess::updateCPUMonitorState(CPUMonitorUpdateReason)
1331 void WebProcess::pageActivityStateDidChange(uint64_t, WebCore::ActivityState::Flags changed)
1333 if (changed & WebCore::ActivityState::IsVisible)
1334 updateCPUMonitorState(CPUMonitorUpdateReason::VisibilityHasChanged);
1338 void WebProcess::resetAllGeolocationPermissions()
1340 for (auto& page : m_pageMap.values()) {
1341 if (Frame* mainFrame = page->mainFrame())
1342 mainFrame->resetAllGeolocationPermission();
1347 void WebProcess::actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend shouldAcknowledgeWhenReadyToSuspend)
1349 if (!m_suppressMemoryPressureHandler)
1350 MemoryPressureHandler::singleton().releaseMemory(Critical::Yes, Synchronous::Yes);
1352 setAllLayerTreeStatesFrozen(true);
1355 destroyRenderingResources();
1358 markAllLayersVolatile([this, shouldAcknowledgeWhenReadyToSuspend] {
1359 RELEASE_LOG(ProcessSuspension, "%p - WebProcess::markAllLayersVolatile() Successfuly marked all layers as volatile", this);
1361 if (shouldAcknowledgeWhenReadyToSuspend == ShouldAcknowledgeWhenReadyToSuspend::Yes) {
1362 RELEASE_LOG(ProcessSuspension, "%p - WebProcess::actualPrepareToSuspend() Sending ProcessReadyToSuspend IPC message", this);
1363 parentProcessConnection()->send(Messages::WebProcessProxy::ProcessReadyToSuspend(), 0);
1368 void WebProcess::processWillSuspendImminently(bool& handled)
1370 if (parentProcessConnection()->inSendSync()) {
1371 // Avoid reentrency bugs such as rdar://problem/21605505 by just bailing
1372 // if we get an incoming ProcessWillSuspendImminently message when waiting for a
1373 // reply to a sync message.
1374 // FIXME: ProcessWillSuspendImminently should not be a sync message.
1378 RELEASE_LOG(ProcessSuspension, "%p - WebProcess::processWillSuspendImminently()", this);
1379 DatabaseTracker::singleton().closeAllDatabases(CurrentQueryBehavior::Interrupt);
1380 actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::No);
1384 void WebProcess::prepareToSuspend()
1386 RELEASE_LOG(ProcessSuspension, "%p - WebProcess::prepareToSuspend()", this);
1387 actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::Yes);
1390 void WebProcess::cancelPrepareToSuspend()
1392 RELEASE_LOG(ProcessSuspension, "%p - WebProcess::cancelPrepareToSuspend()", this);
1393 setAllLayerTreeStatesFrozen(false);
1395 // If we've already finished cleaning up and sent ProcessReadyToSuspend, we
1396 // shouldn't send DidCancelProcessSuspension; the UI process strictly expects one or the other.
1397 if (!m_pageMarkingLayersAsVolatileCounter)
1400 cancelMarkAllLayersVolatile();
1402 RELEASE_LOG(ProcessSuspension, "%p - WebProcess::cancelPrepareToSuspend() Sending DidCancelProcessSuspension IPC message", this);
1403 parentProcessConnection()->send(Messages::WebProcessProxy::DidCancelProcessSuspension(), 0);
1406 void WebProcess::markAllLayersVolatile(WTF::Function<void()>&& completionHandler)
1408 RELEASE_LOG(ProcessSuspension, "%p - WebProcess::markAllLayersVolatile()", this);
1409 ASSERT(!m_pageMarkingLayersAsVolatileCounter);
1410 m_pageMarkingLayersAsVolatileCounter = std::make_unique<PageMarkingLayersAsVolatileCounter>([this, completionHandler = WTFMove(completionHandler)] (RefCounterEvent) {
1411 if (m_pageMarkingLayersAsVolatileCounter->value())
1414 completionHandler();
1415 m_pageMarkingLayersAsVolatileCounter = nullptr;
1417 auto token = m_pageMarkingLayersAsVolatileCounter->count();
1418 for (auto& page : m_pageMap.values())
1419 page->markLayersVolatile([token] { });
1422 void WebProcess::cancelMarkAllLayersVolatile()
1424 if (!m_pageMarkingLayersAsVolatileCounter)
1427 m_pageMarkingLayersAsVolatileCounter = nullptr;
1428 for (auto& page : m_pageMap.values())
1429 page->cancelMarkLayersVolatile();
1432 void WebProcess::setAllLayerTreeStatesFrozen(bool frozen)
1434 for (auto& page : m_pageMap.values())
1435 page->setLayerTreeStateIsFrozen(frozen);
1438 void WebProcess::processDidResume()
1440 RELEASE_LOG(ProcessSuspension, "%p - WebProcess::processDidResume()", this);
1442 cancelMarkAllLayersVolatile();
1443 setAllLayerTreeStatesFrozen(false);
1446 void WebProcess::pageDidEnterWindow(uint64_t pageID)
1448 m_pagesInWindows.add(pageID);
1449 m_nonVisibleProcessCleanupTimer.stop();
1452 void WebProcess::pageWillLeaveWindow(uint64_t pageID)
1454 m_pagesInWindows.remove(pageID);
1456 if (m_pagesInWindows.isEmpty() && !m_nonVisibleProcessCleanupTimer.isActive())
1457 m_nonVisibleProcessCleanupTimer.startOneShot(nonVisibleProcessCleanupDelay);
1460 void WebProcess::nonVisibleProcessCleanupTimerFired()
1462 ASSERT(m_pagesInWindows.isEmpty());
1463 if (!m_pagesInWindows.isEmpty())
1467 destroyRenderingResources();
1471 void WebProcess::setResourceLoadStatisticsEnabled(bool enabled)
1473 WebCore::DeprecatedGlobalSettings::setResourceLoadStatisticsEnabled(enabled);
1476 void WebProcess::clearResourceLoadStatistics()
1478 ResourceLoadObserver::shared().clearState();
1481 RefPtr<API::Object> WebProcess::transformHandlesToObjects(API::Object* object)
1483 struct Transformer final : UserData::Transformer {
1484 Transformer(WebProcess& webProcess)
1485 : m_webProcess(webProcess)
1489 bool shouldTransformObject(const API::Object& object) const override
1491 switch (object.type()) {
1492 case API::Object::Type::FrameHandle:
1493 return static_cast<const API::FrameHandle&>(object).isAutoconverting();
1495 case API::Object::Type::PageHandle:
1496 return static_cast<const API::PageHandle&>(object).isAutoconverting();
1498 case API::Object::Type::PageGroupHandle:
1500 case API::Object::Type::ObjCObjectGraph:
1509 RefPtr<API::Object> transformObject(API::Object& object) const override
1511 switch (object.type()) {
1512 case API::Object::Type::FrameHandle:
1513 return m_webProcess.webFrame(static_cast<const API::FrameHandle&>(object).frameID());
1515 case API::Object::Type::PageGroupHandle:
1516 return m_webProcess.webPageGroup(static_cast<const API::PageGroupHandle&>(object).webPageGroupData());
1518 case API::Object::Type::PageHandle:
1519 return m_webProcess.webPage(static_cast<const API::PageHandle&>(object).pageID());
1522 case API::Object::Type::ObjCObjectGraph:
1523 return m_webProcess.transformHandlesToObjects(static_cast<ObjCObjectGraph&>(object));
1530 WebProcess& m_webProcess;
1533 return UserData::transform(object, Transformer(*this));
1536 RefPtr<API::Object> WebProcess::transformObjectsToHandles(API::Object* object)
1538 struct Transformer final : UserData::Transformer {
1539 bool shouldTransformObject(const API::Object& object) const override
1541 switch (object.type()) {
1542 case API::Object::Type::BundleFrame:
1543 case API::Object::Type::BundlePage:
1544 case API::Object::Type::BundlePageGroup:
1546 case API::Object::Type::ObjCObjectGraph:
1555 RefPtr<API::Object> transformObject(API::Object& object) const override
1557 switch (object.type()) {
1558 case API::Object::Type::BundleFrame:
1559 return API::FrameHandle::createAutoconverting(static_cast<const WebFrame&>(object).frameID());
1561 case API::Object::Type::BundlePage:
1562 return API::PageHandle::createAutoconverting(static_cast<const WebPage&>(object).pageID());
1564 case API::Object::Type::BundlePageGroup: {
1565 WebPageGroupData pageGroupData;
1566 pageGroupData.pageGroupID = static_cast<const WebPageGroupProxy&>(object).pageGroupID();
1568 return API::PageGroupHandle::create(WTFMove(pageGroupData));
1572 case API::Object::Type::ObjCObjectGraph:
1573 return transformObjectsToHandles(static_cast<ObjCObjectGraph&>(object));
1582 return UserData::transform(object, Transformer());
1585 void WebProcess::setMemoryCacheDisabled(bool disabled)
1587 auto& memoryCache = MemoryCache::singleton();
1588 if (memoryCache.disabled() != disabled)
1589 memoryCache.setDisabled(disabled);
1592 #if ENABLE(SERVICE_CONTROLS)
1593 void WebProcess::setEnabledServices(bool hasImageServices, bool hasSelectionServices, bool hasRichContentServices)
1595 m_hasImageServices = hasImageServices;
1596 m_hasSelectionServices = hasSelectionServices;
1597 m_hasRichContentServices = hasRichContentServices;
1601 void WebProcess::ensureAutomationSessionProxy(const String& sessionIdentifier)
1603 m_automationSessionProxy = std::make_unique<WebAutomationSessionProxy>(sessionIdentifier);
1606 void WebProcess::destroyAutomationSessionProxy()
1608 m_automationSessionProxy = nullptr;
1611 void WebProcess::prefetchDNS(const String& hostname)
1613 if (hostname.isEmpty())
1616 if (m_dnsPrefetchedHosts.add(hostname).isNewEntry)
1617 networkConnection().connection().send(Messages::NetworkConnectionToWebProcess::PrefetchDNS(hostname), 0);
1618 // The DNS prefetched hosts cache is only to avoid asking for the same hosts too many times
1619 // in a very short period of time, producing a lot of IPC traffic. So we clear this cache after
1620 // some time of no DNS requests.
1621 m_dnsPrefetchHystereris.impulse();
1624 bool WebProcess::hasVisibleWebPage() const
1626 for (auto& page : m_pageMap.values()) {
1627 if (page->isVisible())
1634 LibWebRTCNetwork& WebProcess::libWebRTCNetwork()
1636 if (!m_libWebRTCNetwork)
1637 m_libWebRTCNetwork = std::make_unique<LibWebRTCNetwork>();
1638 return *m_libWebRTCNetwork;
1642 #if ENABLE(SERVICE_WORKER)
1643 void WebProcess::getWorkerContextConnection(uint64_t pageID, const WebPreferencesStore& store)
1645 ASSERT(!m_serviceWorkerManager);
1647 #if USE(UNIX_DOMAIN_SOCKETS)
1648 IPC::Connection::SocketPair socketPair = IPC::Connection::createPlatformConnection();
1649 IPC::Connection::Identifier connectionIdentifier(socketPair.server);
1650 IPC::Attachment connectionClientPort(socketPair.client);
1652 mach_port_t listeningPort;
1653 if (mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &listeningPort) != KERN_SUCCESS)
1656 if (mach_port_insert_right(mach_task_self(), listeningPort, listeningPort, MACH_MSG_TYPE_MAKE_SEND) != KERN_SUCCESS)
1659 IPC::Connection::Identifier connectionIdentifier(listeningPort);
1660 IPC::Attachment connectionClientPort(listeningPort, MACH_MSG_TYPE_MOVE_SEND);
1662 RELEASE_ASSERT_NOT_REACHED();
1665 auto workerContextConnection = IPC::Connection::createServerConnection(connectionIdentifier, *this);
1666 workerContextConnection->open();
1667 m_serviceWorkerManager = ServiceWorkerContextManager(WTFMove(workerContextConnection), pageID, store);
1668 WebProcess::singleton().parentProcessConnection()->send(Messages::WebProcessProxy::DidGetWorkerContextConnection(connectionClientPort), 0);
1672 } // namespace WebKit