diff options
Diffstat (limited to 'Source/WebKit2/WebProcess/WebProcess.cpp')
-rw-r--r-- | Source/WebKit2/WebProcess/WebProcess.cpp | 1169 |
1 files changed, 761 insertions, 408 deletions
diff --git a/Source/WebKit2/WebProcess/WebProcess.cpp b/Source/WebKit2/WebProcess/WebProcess.cpp index 70ea5fe13..cd5e9f4ba 100644 --- a/Source/WebKit2/WebProcess/WebProcess.cpp +++ b/Source/WebKit2/WebProcess/WebProcess.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, 2010, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2009-2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,87 +27,102 @@ #include "WebProcess.h" #include "APIFrameHandle.h" +#include "APIPageGroupHandle.h" +#include "APIPageHandle.h" #include "AuthenticationManager.h" +#include "ChildProcessMessages.h" +#include "DrawingArea.h" #include "EventDispatcher.h" #include "InjectedBundle.h" -#include "InjectedBundleUserMessageCoders.h" #include "Logging.h" +#include "NetworkConnectionToWebProcessMessages.h" +#include "NetworkProcessConnection.h" +#include "NetworkSession.h" #include "PluginProcessConnectionManager.h" #include "SessionTracker.h" #include "StatisticsData.h" #include "UserData.h" -#include "WebApplicationCacheManager.h" +#include "WebAutomationSessionProxy.h" #include "WebConnectionToUIProcess.h" -#include "WebContextMessages.h" #include "WebCookieManager.h" #include "WebCoreArgumentCoders.h" #include "WebFrame.h" #include "WebFrameNetworkingContext.h" +#include "WebGamepadProvider.h" #include "WebGeolocationManager.h" #include "WebIconDatabaseProxy.h" -#include "WebMediaCacheManager.h" +#include "WebLoaderStrategy.h" +#include "WebMediaKeyStorageManager.h" #include "WebMemorySampler.h" #include "WebPage.h" -#include "WebPageCreationParameters.h" -#include "WebPageGroupProxyMessages.h" +#include "WebPageGroupProxy.h" #include "WebPlatformStrategies.h" -#include "WebPreferencesStore.h" +#include "WebPluginInfoProvider.h" #include "WebProcessCreationParameters.h" #include "WebProcessMessages.h" +#include "WebProcessPoolMessages.h" #include "WebProcessProxyMessages.h" -#include "WebResourceCacheManager.h" +#include "WebResourceLoadStatisticsStoreMessages.h" +#include "WebsiteData.h" +#include "WebsiteDataType.h" #include <JavaScriptCore/JSLock.h> #include <JavaScriptCore/MemoryStatistics.h> #include <WebCore/AXObjectCache.h> #include <WebCore/ApplicationCacheStorage.h> #include <WebCore/AuthenticationChallenge.h> +#include <WebCore/CommonVM.h> #include <WebCore/CrossOriginPreflightResultCache.h> -#include <WebCore/Font.h> +#include <WebCore/DNS.h> +#include <WebCore/DatabaseManager.h> +#include <WebCore/DatabaseTracker.h> +#include <WebCore/DiagnosticLoggingClient.h> +#include <WebCore/DiagnosticLoggingKeys.h> #include <WebCore/FontCache.h> +#include <WebCore/FontCascade.h> #include <WebCore/Frame.h> #include <WebCore/FrameLoader.h> #include <WebCore/GCController.h> -#include <WebCore/GlyphPageTreeNode.h> +#include <WebCore/GlyphPage.h> +#include <WebCore/HTMLMediaElement.h> #include <WebCore/IconDatabase.h> #include <WebCore/JSDOMWindow.h> #include <WebCore/Language.h> +#include <WebCore/MainFrame.h> #include <WebCore/MemoryCache.h> -#include <WebCore/MemoryPressureHandler.h> +#include <WebCore/MemoryRelease.h> +#include <WebCore/NetworkStorageSession.h> #include <WebCore/Page.h> #include <WebCore/PageCache.h> #include <WebCore/PageGroup.h> +#include <WebCore/PlatformMediaSessionManager.h> #include <WebCore/ResourceHandle.h> +#include <WebCore/ResourceLoadObserver.h> +#include <WebCore/ResourceLoadStatistics.h> +#include <WebCore/ResourceLoadStatisticsStore.h> +#include <WebCore/RuntimeApplicationChecks.h> #include <WebCore/SchemeRegistry.h> #include <WebCore/SecurityOrigin.h> #include <WebCore/Settings.h> -#include <WebCore/StorageTracker.h> +#include <WebCore/URLParser.h> +#include <WebCore/UserGestureIndicator.h> #include <unistd.h> #include <wtf/CurrentTime.h> #include <wtf/HashCountedSet.h> -#include <wtf/PassRefPtr.h> #include <wtf/RunLoop.h> #include <wtf/text/StringHash.h> -#if ENABLE(NETWORK_INFO) -#include "WebNetworkInfoManager.h" -#include "WebNetworkInfoManagerMessages.h" +#if PLATFORM(COCOA) +#include "ObjCObjectGraph.h" #endif -#if ENABLE(NETWORK_PROCESS) -#if PLATFORM(MAC) +#if PLATFORM(COCOA) #include "CookieStorageShim.h" #endif -#include "NetworkProcessConnection.h" -#endif #if ENABLE(SEC_ITEM_SHIM) #include "SecItemShim.h" #endif -#if ENABLE(CUSTOM_PROTOCOLS) -#include "CustomProtocolManager.h" -#endif - #if ENABLE(DATABASE_PROCESS) #include "WebToDatabaseProcessConnection.h" #endif @@ -116,20 +131,8 @@ #include "WebNotificationManager.h" #endif -#if ENABLE(SQL_DATABASE) -#include "WebDatabaseManager.h" -#endif - -#if ENABLE(BATTERY_STATUS) -#include "WebBatteryManager.h" -#endif - -#if ENABLE(NETWORK_PROCESS) -#include "WebResourceLoadScheduler.h" -#endif - -#if USE(SOUP) && !ENABLE(CUSTOM_PROTOCOLS) -#include "WebSoupRequestManager.h" +#if ENABLE(REMOTE_INSPECTOR) +#include <JavaScriptCore/RemoteInspector.h> #endif using namespace JSC; @@ -143,7 +146,7 @@ static const double nonVisibleProcessCleanupDelay = 10; namespace WebKit { -WebProcess& WebProcess::shared() +WebProcess& WebProcess::singleton() { static WebProcess& process = *new WebProcess; return process; @@ -151,27 +154,21 @@ WebProcess& WebProcess::shared() WebProcess::WebProcess() : m_eventDispatcher(EventDispatcher::create()) - , m_inDidClose(false) - , m_shouldTrackVisitedLinks(true) - , m_hasSetCacheModel(false) - , m_cacheModel(CacheModelDocumentViewer) -#if USE(ACCELERATED_COMPOSITING) && PLATFORM(MAC) - , m_compositingRenderServerPort(MACH_PORT_NULL) -#endif -#if PLATFORM(MAC) - , m_clearResourceCachesDispatchGroup(0) -#endif - , m_fullKeyboardAccessEnabled(false) - , m_textCheckerState() - , m_iconDatabaseProxy(new WebIconDatabaseProxy(this)) -#if ENABLE(NETWORK_PROCESS) - , m_usesNetworkProcess(false) - , m_webResourceLoadScheduler(new WebResourceLoadScheduler) +#if PLATFORM(IOS) + , m_viewUpdateDispatcher(ViewUpdateDispatcher::create()) #endif + , m_iconDatabaseProxy(*new WebIconDatabaseProxy(*this)) + , m_webLoaderStrategy(*new WebLoaderStrategy) + , m_dnsPrefetchHystereris([this](HysteresisState state) { if (state == HysteresisState::Stopped) m_dnsPrefetchedHosts.clear(); }) #if ENABLE(NETSCAPE_PLUGIN_API) , m_pluginProcessConnectionManager(PluginProcessConnectionManager::create()) #endif - , m_nonVisibleProcessCleanupTimer(this, &WebProcess::nonVisibleProcessCleanupTimerFired) + , m_nonVisibleProcessCleanupTimer(*this, &WebProcess::nonVisibleProcessCleanupTimerFired) + , m_statisticsChangedTimer(*this, &WebProcess::statisticsChangedTimerFired) +#if PLATFORM(IOS) + , m_webSQLiteDatabaseTracker(*this) +#endif + , m_resourceLoadStatisticsStore(WebCore::ResourceLoadStatisticsStore::create()) { // Initialize our platform strategies. WebPlatformStrategies::initialize(); @@ -180,30 +177,29 @@ WebProcess::WebProcess() // so that ports have a chance to customize, and ifdefs in this file are // limited. addSupplement<WebGeolocationManager>(); - addSupplement<WebApplicationCacheManager>(); - addSupplement<WebResourceCacheManager>(); addSupplement<WebCookieManager>(); - addSupplement<WebMediaCacheManager>(); addSupplement<AuthenticationManager>(); - -#if ENABLE(SQL_DATABASE) - addSupplement<WebDatabaseManager>(); -#endif + #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS) addSupplement<WebNotificationManager>(); #endif -#if ENABLE(CUSTOM_PROTOCOLS) - addSupplement<CustomProtocolManager>(); -#endif -#if ENABLE(BATTERY_STATUS) - addSupplement<WebBatteryManager>(); -#endif -#if ENABLE(NETWORK_INFO) - addSupplement<WebNetworkInfoManager>(); -#endif -#if USE(SOUP) && !ENABLE(CUSTOM_PROTOCOLS) - addSupplement<WebSoupRequestManager>(); + +#if ENABLE(LEGACY_ENCRYPTED_MEDIA) + addSupplement<WebMediaKeyStorageManager>(); #endif + + m_plugInAutoStartOriginHashes.add(SessionID::defaultSessionID(), HashMap<unsigned, double>()); + + ResourceLoadObserver::sharedObserver().setStatisticsStore(m_resourceLoadStatisticsStore.copyRef()); + m_resourceLoadStatisticsStore->setNotificationCallback([this] { + if (m_statisticsChangedTimer.isActive()) + return; + m_statisticsChangedTimer.startOneShot(std::chrono::seconds(5)); + }); +} + +WebProcess::~WebProcess() +{ } void WebProcess::initializeProcess(const ChildProcessInitializationParameters& parameters) @@ -217,20 +213,21 @@ void WebProcess::initializeConnection(IPC::Connection* connection) connection->setShouldExitOnSyncMessageSendFailure(true); +#if HAVE(QOS_CLASSES) + connection->setShouldBoostMainThreadOnSyncMessage(true); +#endif + m_eventDispatcher->initializeConnection(connection); +#if PLATFORM(IOS) + m_viewUpdateDispatcher->initializeConnection(connection); +#endif // PLATFORM(IOS) #if ENABLE(NETSCAPE_PLUGIN_API) m_pluginProcessConnectionManager->initializeConnection(connection); #endif -#if ENABLE(SEC_ITEM_SHIM) - SecItemShim::shared().initializeConnection(connection); -#endif - - WebProcessSupplementMap::const_iterator it = m_supplements.begin(); - WebProcessSupplementMap::const_iterator end = m_supplements.end(); - for (; it != end; ++it) - it->value->initializeConnection(connection); + for (auto& supplement : m_supplements.values()) + supplement->initializeConnection(connection); m_webConnection = WebConnectionToUIProcess::create(this); @@ -241,62 +238,67 @@ void WebProcess::initializeConnection(IPC::Connection* connection) connection->setOnlySendMessagesAsDispatchWhenWaitingForSyncReplyWhenProcessingSuchAMessage(true); } -void WebProcess::didCreateDownload() -{ - disableTermination(); -} - -void WebProcess::didDestroyDownload() -{ - enableTermination(); -} - -IPC::Connection* WebProcess::downloadProxyConnection() -{ - return parentProcessConnection(); -} - -AuthenticationManager& WebProcess::downloadsAuthenticationManager() -{ - return *supplement<AuthenticationManager>(); -} - -void WebProcess::initializeWebProcess(const WebProcessCreationParameters& parameters, IPC::MessageDecoder& decoder) -{ +void WebProcess::initializeWebProcess(WebProcessCreationParameters&& parameters) +{ ASSERT(m_pageMap.isEmpty()); - platformInitializeWebProcess(parameters, decoder); - - memoryPressureHandler().install(); +#if OS(LINUX) + if (parameters.memoryPressureMonitorHandle.fileDescriptor() != -1) + MemoryPressureHandler::singleton().setMemoryPressureMonitorHandle(parameters.memoryPressureMonitorHandle.releaseFileDescriptor()); + MemoryPressureHandler::ReliefLogger::setLoggingEnabled(parameters.shouldEnableMemoryPressureReliefLogging); +#endif - RefPtr<API::Object> injectedBundleInitializationUserData; - InjectedBundleUserMessageDecoder messageDecoder(injectedBundleInitializationUserData); - if (!decoder.decode(messageDecoder)) - return; + platformInitializeWebProcess(WTFMove(parameters)); + + // Match the QoS of the UIProcess and the scrolling thread but use a slightly lower priority. + WTF::setCurrentThreadIsUserInteractive(-1); + + m_suppressMemoryPressureHandler = parameters.shouldSuppressMemoryPressureHandler; + if (!m_suppressMemoryPressureHandler) { + auto& memoryPressureHandler = MemoryPressureHandler::singleton(); + memoryPressureHandler.setLowMemoryHandler([] (Critical critical, Synchronous synchronous) { + WebCore::releaseMemory(critical, synchronous); + }); +#if PLATFORM(MAC) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 101200 + memoryPressureHandler.setShouldUsePeriodicMemoryMonitor(true); + memoryPressureHandler.setMemoryKillCallback([] () { + WebCore::didExceedMemoryLimitAndFailedToRecover(); + }); + memoryPressureHandler.setProcessIsEligibleForMemoryKillCallback([] () { + return WebCore::processIsEligibleForMemoryKill(); + }); +#endif + memoryPressureHandler.install(); + } - if (!parameters.injectedBundlePath.isEmpty()) { - m_injectedBundle = InjectedBundle::create(parameters.injectedBundlePath); - m_injectedBundle->setSandboxExtension(SandboxExtension::create(parameters.injectedBundlePathExtensionHandle)); + if (!parameters.injectedBundlePath.isEmpty()) + m_injectedBundle = InjectedBundle::create(parameters, transformHandlesToObjects(parameters.initializationUserData.object()).get()); - if (!m_injectedBundle->load(injectedBundleInitializationUserData.get())) { - // Don't keep around the InjectedBundle reference if the load fails. - m_injectedBundle.clear(); - } - } + for (auto& supplement : m_supplements.values()) + supplement->initialize(parameters); - WebProcessSupplementMap::const_iterator it = m_supplements.begin(); - WebProcessSupplementMap::const_iterator end = m_supplements.end(); - for (; it != end; ++it) - it->value->initialize(parameters); + auto& databaseManager = DatabaseManager::singleton(); + databaseManager.initialize(parameters.webSQLDatabaseDirectory); #if ENABLE(ICONDATABASE) - m_iconDatabaseProxy->setEnabled(parameters.iconDatabaseEnabled); + m_iconDatabaseProxy.setEnabled(parameters.iconDatabaseEnabled); #endif - if (!parameters.applicationCacheDirectory.isEmpty()) - cacheStorage().setCacheDirectory(parameters.applicationCacheDirectory); + // FIXME: This should be constructed per data store, not per process. + m_applicationCacheStorage = ApplicationCacheStorage::create(parameters.applicationCacheDirectory, parameters.applicationCacheFlatFileSubdirectoryName); +#if PLATFORM(IOS) + m_applicationCacheStorage->setDefaultOriginQuota(25ULL * 1024 * 1024); +#endif + +#if PLATFORM(WAYLAND) + m_waylandCompositorDisplayName = parameters.waylandCompositorDisplayName; +#endif + +#if ENABLE(VIDEO) + if (!parameters.mediaCacheDirectory.isEmpty()) + WebCore::HTMLMediaElement::setMediaCacheDirectory(parameters.mediaCacheDirectory); +#endif - setShouldTrackVisitedLinks(parameters.shouldTrackVisitedLinks); setCacheModel(static_cast<uint32_t>(parameters.cacheModel)); if (!parameters.languages.isEmpty()) @@ -306,66 +308,90 @@ void WebProcess::initializeWebProcess(const WebProcessCreationParameters& parame m_fullKeyboardAccessEnabled = parameters.fullKeyboardAccessEnabled; - for (size_t i = 0; i < parameters.urlSchemesRegistererdAsEmptyDocument.size(); ++i) - registerURLSchemeAsEmptyDocument(parameters.urlSchemesRegistererdAsEmptyDocument[i]); + for (auto& scheme : parameters.urlSchemesRegisteredAsEmptyDocument) + registerURLSchemeAsEmptyDocument(scheme); + + for (auto& scheme : parameters.urlSchemesRegisteredAsSecure) + registerURLSchemeAsSecure(scheme); - for (size_t i = 0; i < parameters.urlSchemesRegisteredAsSecure.size(); ++i) - registerURLSchemeAsSecure(parameters.urlSchemesRegisteredAsSecure[i]); + for (auto& scheme : parameters.urlSchemesRegisteredAsBypassingContentSecurityPolicy) + registerURLSchemeAsBypassingContentSecurityPolicy(scheme); - for (size_t i = 0; i < parameters.urlSchemesForWhichDomainRelaxationIsForbidden.size(); ++i) - setDomainRelaxationForbiddenForURLScheme(parameters.urlSchemesForWhichDomainRelaxationIsForbidden[i]); + for (auto& scheme : parameters.urlSchemesForWhichDomainRelaxationIsForbidden) + setDomainRelaxationForbiddenForURLScheme(scheme); - for (size_t i = 0; i < parameters.urlSchemesRegisteredAsLocal.size(); ++i) - registerURLSchemeAsLocal(parameters.urlSchemesRegisteredAsLocal[i]); + for (auto& scheme : parameters.urlSchemesRegisteredAsLocal) + registerURLSchemeAsLocal(scheme); - for (size_t i = 0; i < parameters.urlSchemesRegisteredAsNoAccess.size(); ++i) - registerURLSchemeAsNoAccess(parameters.urlSchemesRegisteredAsNoAccess[i]); + for (auto& scheme : parameters.urlSchemesRegisteredAsNoAccess) + registerURLSchemeAsNoAccess(scheme); - for (size_t i = 0; i < parameters.urlSchemesRegisteredAsDisplayIsolated.size(); ++i) - registerURLSchemeAsDisplayIsolated(parameters.urlSchemesRegisteredAsDisplayIsolated[i]); + for (auto& scheme : parameters.urlSchemesRegisteredAsDisplayIsolated) + registerURLSchemeAsDisplayIsolated(scheme); - for (size_t i = 0; i < parameters.urlSchemesRegisteredAsCORSEnabled.size(); ++i) - registerURLSchemeAsCORSEnabled(parameters.urlSchemesRegisteredAsCORSEnabled[i]); + for (auto& scheme : parameters.urlSchemesRegisteredAsCORSEnabled) + registerURLSchemeAsCORSEnabled(scheme); + + for (auto& scheme : parameters.urlSchemesRegisteredAsAlwaysRevalidated) + registerURLSchemeAsAlwaysRevalidated(scheme); + + for (auto& scheme : parameters.urlSchemesRegisteredAsCachePartitioned) + registerURLSchemeAsCachePartitioned(scheme); setDefaultRequestTimeoutInterval(parameters.defaultRequestTimeoutInterval); + setResourceLoadStatisticsEnabled(parameters.resourceLoadStatisticsEnabled); + if (parameters.shouldAlwaysUseComplexTextCodePath) setAlwaysUsesComplexTextCodePath(true); if (parameters.shouldUseFontSmoothing) setShouldUseFontSmoothing(true); -#if PLATFORM(MAC) || USE(CFNETWORK) - SessionTracker::setIdentifierBase(parameters.uiProcessBundleIdentifier); -#endif - if (parameters.shouldUseTestingNetworkSession) NetworkStorageSession::switchToNewTestingSession(); -#if ENABLE(NETWORK_PROCESS) - m_usesNetworkProcess = parameters.usesNetworkProcess; ensureNetworkProcessConnection(); -#if PLATFORM(MAC) - if (usesNetworkProcess()) - CookieStorageShim::shared().initialize(); -#endif +#if PLATFORM(COCOA) + CookieStorageShim::singleton().initialize(); #endif setTerminationTimeout(parameters.terminationTimeout); resetPlugInAutoStartOriginHashes(parameters.plugInAutoStartOriginHashes); - for (size_t i = 0; i < parameters.plugInAutoStartOrigins.size(); ++i) - m_plugInAutoStartOrigins.add(parameters.plugInAutoStartOrigins[i]); + for (auto& origin : parameters.plugInAutoStartOrigins) + m_plugInAutoStartOrigins.add(origin); setMemoryCacheDisabled(parameters.memoryCacheDisabled); + +#if ENABLE(SERVICE_CONTROLS) + setEnabledServices(parameters.hasImageServices, parameters.hasSelectionServices, parameters.hasRichContentServices); +#endif + +#if ENABLE(REMOTE_INSPECTOR) && PLATFORM(COCOA) + audit_token_t auditToken; + if (parentProcessConnection()->getAuditToken(auditToken)) { + RetainPtr<CFDataRef> auditData = adoptCF(CFDataCreate(nullptr, (const UInt8*)&auditToken, sizeof(auditToken))); + Inspector::RemoteInspector::singleton().setParentProcessInformation(presenterApplicationPid(), auditData); + } +#endif + +#if ENABLE(NETSCAPE_PLUGIN_API) && PLATFORM(MAC) + for (auto hostIter = parameters.pluginLoadClientPolicies.begin(); hostIter != parameters.pluginLoadClientPolicies.end(); ++hostIter) { + for (auto bundleIdentifierIter = hostIter->value.begin(); bundleIdentifierIter != hostIter->value.end(); ++bundleIdentifierIter) { + for (auto versionIter = bundleIdentifierIter->value.begin(); versionIter != bundleIdentifierIter->value.end(); ++versionIter) + WebPluginInfoProvider::singleton().setPluginLoadClientPolicy(static_cast<PluginLoadClientPolicy>(versionIter->value), hostIter->key, bundleIdentifierIter->key, versionIter->key); + } + } +#endif + +#if ENABLE(GAMEPAD) + GamepadProvider::singleton().setSharedProvider(WebGamepadProvider::singleton()); +#endif } -#if ENABLE(NETWORK_PROCESS) void WebProcess::ensureNetworkProcessConnection() { - if (!m_usesNetworkProcess) - return; - if (m_networkProcessConnection) return; @@ -375,10 +401,10 @@ void WebProcess::ensureNetworkProcessConnection() Messages::WebProcessProxy::GetNetworkProcessConnection::Reply(encodedConnectionIdentifier), 0)) return; -#if PLATFORM(MAC) - IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.port()); -#elif USE(UNIX_DOMAIN_SOCKETS) +#if USE(UNIX_DOMAIN_SOCKETS) IPC::Connection::Identifier connectionIdentifier = encodedConnectionIdentifier.releaseFileDescriptor(); +#elif OS(DARWIN) + IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.port()); #else ASSERT_NOT_REACHED(); #endif @@ -386,13 +412,6 @@ void WebProcess::ensureNetworkProcessConnection() return; m_networkProcessConnection = NetworkProcessConnection::create(connectionIdentifier); } -#endif // ENABLE(NETWORK_PROCESS) - -void WebProcess::setShouldTrackVisitedLinks(bool shouldTrackVisitedLinks) -{ - m_shouldTrackVisitedLinks = shouldTrackVisitedLinks; - PageGroup::setShouldTrackVisitedLinks(shouldTrackVisitedLinks); -} void WebProcess::registerURLSchemeAsEmptyDocument(const String& urlScheme) { @@ -404,6 +423,11 @@ void WebProcess::registerURLSchemeAsSecure(const String& urlScheme) const SchemeRegistry::registerURLSchemeAsSecure(urlScheme); } +void WebProcess::registerURLSchemeAsBypassingContentSecurityPolicy(const String& urlScheme) const +{ + SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(urlScheme); +} + void WebProcess::setDomainRelaxationForbiddenForURLScheme(const String& urlScheme) const { SchemeRegistry::setDomainRelaxationForbiddenForURLScheme(true, urlScheme); @@ -429,6 +453,16 @@ void WebProcess::registerURLSchemeAsCORSEnabled(const String& urlScheme) const SchemeRegistry::registerURLSchemeAsCORSEnabled(urlScheme); } +void WebProcess::registerURLSchemeAsAlwaysRevalidated(const String& urlScheme) const +{ + SchemeRegistry::registerURLSchemeAsAlwaysRevalidated(urlScheme); +} + +void WebProcess::registerURLSchemeAsCachePartitioned(const String& urlScheme) const +{ + SchemeRegistry::registerURLSchemeAsCachePartitioned(urlScheme); +} + void WebProcess::setDefaultRequestTimeoutInterval(double timeoutInterval) { ResourceRequest::setDefaultTimeoutInterval(timeoutInterval); @@ -436,12 +470,12 @@ void WebProcess::setDefaultRequestTimeoutInterval(double timeoutInterval) void WebProcess::setAlwaysUsesComplexTextCodePath(bool alwaysUseComplexText) { - WebCore::Font::setCodePath(alwaysUseComplexText ? WebCore::Font::Complex : WebCore::Font::Auto); + WebCore::FontCascade::setCodePath(alwaysUseComplexText ? WebCore::FontCascade::Complex : WebCore::FontCascade::Auto); } void WebProcess::setShouldUseFontSmoothing(bool useFontSmoothing) { - WebCore::Font::setShouldUseSmoothing(useFontSmoothing); + WebCore::FontCascade::setShouldUseSmoothing(useFontSmoothing); } void WebProcess::userPreferredLanguagesChanged(const Vector<String>& languages) const @@ -455,26 +489,19 @@ void WebProcess::fullKeyboardAccessModeChanged(bool fullKeyboardAccessEnabled) m_fullKeyboardAccessEnabled = fullKeyboardAccessEnabled; } -void WebProcess::ensurePrivateBrowsingSession(uint64_t sessionID) +void WebProcess::ensurePrivateBrowsingSession(SessionID sessionID) { -#if PLATFORM(MAC) || USE(CFNETWORK) || USE(SOUP) WebFrameNetworkingContext::ensurePrivateBrowsingSession(sessionID); -#endif } -void WebProcess::destroyPrivateBrowsingSession(uint64_t sessionID) +void WebProcess::destroyPrivateBrowsingSession(SessionID sessionID) { -#if PLATFORM(MAC) || USE(CFNETWORK) || USE(SOUP) SessionTracker::destroySession(sessionID); -#endif } -DownloadManager& WebProcess::downloadManager() +void WebProcess::ensureLegacyPrivateBrowsingSessionInNetworkProcess() { - ASSERT(!usesNetworkProcess()); - - static NeverDestroyed<DownloadManager> downloadManager(this); - return downloadManager; + networkConnection().connection().send(Messages::NetworkConnectionToWebProcess::EnsureLegacyPrivateBrowsingSession(), 0); } #if ENABLE(NETSCAPE_PLUGIN_API) @@ -484,69 +511,44 @@ PluginProcessConnectionManager& WebProcess::pluginProcessConnectionManager() } #endif -void WebProcess::setVisitedLinkTable(const SharedMemory::Handle& handle) -{ - RefPtr<SharedMemory> sharedMemory = SharedMemory::create(handle, SharedMemory::ReadOnly); - if (!sharedMemory) - return; - - m_visitedLinkTable.setSharedMemory(sharedMemory.release()); -} - -void WebProcess::visitedLinkStateChanged(const Vector<WebCore::LinkHash>& linkHashes) +void WebProcess::setCacheModel(uint32_t cm) { - // FIXME: We may want to track visited links per WebPageGroup rather than per WebContext. - for (size_t i = 0; i < linkHashes.size(); ++i) { - HashMap<uint64_t, RefPtr<WebPageGroupProxy>>::const_iterator it = m_pageGroupMap.begin(); - HashMap<uint64_t, RefPtr<WebPageGroupProxy>>::const_iterator end = m_pageGroupMap.end(); - for (; it != end; ++it) - Page::visitedStateChanged(PageGroup::pageGroup(it->value->identifier()), linkHashes[i]); - } + CacheModel cacheModel = static_cast<CacheModel>(cm); - pageCache()->markPagesForVistedLinkStyleRecalc(); -} + if (m_hasSetCacheModel && (cacheModel == m_cacheModel)) + return; -void WebProcess::allVisitedLinkStateChanged() -{ - // FIXME: We may want to track visited links per WebPageGroup rather than per WebContext. - HashMap<uint64_t, RefPtr<WebPageGroupProxy>>::const_iterator it = m_pageGroupMap.begin(); - HashMap<uint64_t, RefPtr<WebPageGroupProxy>>::const_iterator end = m_pageGroupMap.end(); - for (; it != end; ++it) - Page::allVisitedStateChanged(PageGroup::pageGroup(it->value->identifier())); + m_hasSetCacheModel = true; + m_cacheModel = cacheModel; - pageCache()->markPagesForVistedLinkStyleRecalc(); -} + unsigned cacheTotalCapacity = 0; + unsigned cacheMinDeadCapacity = 0; + unsigned cacheMaxDeadCapacity = 0; + auto deadDecodedDataDeletionInterval = std::chrono::seconds { 0 }; + unsigned pageCacheSize = 0; + calculateMemoryCacheSizes(cacheModel, cacheTotalCapacity, cacheMinDeadCapacity, cacheMaxDeadCapacity, deadDecodedDataDeletionInterval, pageCacheSize); -bool WebProcess::isLinkVisited(LinkHash linkHash) const -{ - return m_visitedLinkTable.isLinkVisited(linkHash); -} + auto& memoryCache = MemoryCache::singleton(); + memoryCache.setCapacities(cacheMinDeadCapacity, cacheMaxDeadCapacity, cacheTotalCapacity); + memoryCache.setDeadDecodedDataDeletionInterval(deadDecodedDataDeletionInterval); + PageCache::singleton().setMaxSize(pageCacheSize); -void WebProcess::addVisitedLink(WebCore::LinkHash linkHash) -{ - if (isLinkVisited(linkHash) || !m_shouldTrackVisitedLinks) - return; - parentProcessConnection()->send(Messages::WebContext::AddVisitedLinkHash(linkHash), 0); + platformSetCacheModel(cacheModel); } -void WebProcess::setCacheModel(uint32_t cm) +void WebProcess::clearCachedCredentials() { - CacheModel cacheModel = static_cast<CacheModel>(cm); - - if (!m_hasSetCacheModel || cacheModel != m_cacheModel) { - m_hasSetCacheModel = true; - m_cacheModel = cacheModel; - platformSetCacheModel(cacheModel); - } + NetworkStorageSession::defaultStorageSession().credentialStorage().clearCredentials(); +#if USE(NETWORK_SESSION) + NetworkSession::defaultSession().clearCredentials(); +#endif } WebPage* WebProcess::focusedWebPage() const { - HashMap<uint64_t, RefPtr<WebPage>>::const_iterator end = m_pageMap.end(); - for (HashMap<uint64_t, RefPtr<WebPage>>::const_iterator it = m_pageMap.begin(); it != end; ++it) { - WebPage* page = (*it).value.get(); + for (auto& page : m_pageMap.values()) { if (page->windowAndWebPageAreFocused()) - return page; + return page.get(); } return 0; } @@ -556,19 +558,19 @@ WebPage* WebProcess::webPage(uint64_t pageID) const return m_pageMap.get(pageID); } -void WebProcess::createWebPage(uint64_t pageID, const WebPageCreationParameters& parameters) +void WebProcess::createWebPage(uint64_t pageID, WebPageCreationParameters&& parameters) { // It is necessary to check for page existence here since during a window.open() (or targeted // link) the WebPage gets created both in the synchronous handler and through the normal way. HashMap<uint64_t, RefPtr<WebPage>>::AddResult result = m_pageMap.add(pageID, nullptr); if (result.isNewEntry) { ASSERT(!result.iterator->value); - result.iterator->value = WebPage::create(pageID, parameters); + result.iterator->value = WebPage::create(pageID, WTFMove(parameters)); // Balanced by an enableTermination in removeWebPage. disableTermination(); } else - result.iterator->value->reinitializeWebPage(parameters); + result.iterator->value->reinitializeWebPage(WTFMove(parameters)); ASSERT(result.iterator->value); } @@ -586,7 +588,6 @@ void WebProcess::removeWebPage(uint64_t pageID) bool WebProcess::shouldTerminate() { ASSERT(m_pageMap.isEmpty()); - ASSERT(usesNetworkProcess() || !downloadManager().isDownloading()); // FIXME: the ShouldTerminate message should also send termination parameters, such as any session cookies that need to be preserved. bool shouldTerminate = false; @@ -600,9 +601,9 @@ bool WebProcess::shouldTerminate() void WebProcess::terminate() { #ifndef NDEBUG - gcController().garbageCollectNow(); - fontCache()->invalidate(); - memoryCache()->setDisabled(true); + GCController::singleton().garbageCollectNow(); + FontCache::singleton().invalidate(); + MemoryCache::singleton().setDisabled(true); #endif m_webConnection->invalidate(); @@ -613,12 +614,15 @@ void WebProcess::terminate() ChildProcess::terminate(); } -void WebProcess::didReceiveSyncMessage(IPC::Connection* connection, IPC::MessageDecoder& decoder, std::unique_ptr<IPC::MessageEncoder>& replyEncoder) +void WebProcess::didReceiveSyncMessage(IPC::Connection& connection, IPC::Decoder& decoder, std::unique_ptr<IPC::Encoder>& replyEncoder) { - messageReceiverMap().dispatchSyncMessage(connection, decoder, replyEncoder); + if (messageReceiverMap().dispatchSyncMessage(connection, decoder, replyEncoder)) + return; + + didReceiveSyncWebProcessMessage(connection, decoder, replyEncoder); } -void WebProcess::didReceiveMessage(IPC::Connection* connection, IPC::MessageDecoder& decoder) +void WebProcess::didReceiveMessage(IPC::Connection& connection, IPC::Decoder& decoder) { if (messageReceiverMap().dispatchMessage(connection, decoder)) return; @@ -628,46 +632,39 @@ void WebProcess::didReceiveMessage(IPC::Connection* connection, IPC::MessageDeco return; } - if (decoder.messageReceiverName() == Messages::WebPageGroupProxy::messageReceiverName()) { - uint64_t pageGroupID = decoder.destinationID(); - if (!pageGroupID) - return; - - WebPageGroupProxy* pageGroupProxy = webPageGroup(pageGroupID); - if (!pageGroupProxy) - return; - - pageGroupProxy->didReceiveMessage(connection, decoder); + if (decoder.messageReceiverName() == Messages::ChildProcess::messageReceiverName()) { + ChildProcess::didReceiveMessage(connection, decoder); + return; } + + LOG_ERROR("Unhandled web process message '%s:%s'", decoder.messageReceiverName().toString().data(), decoder.messageName().toString().data()); } -void WebProcess::didClose(IPC::Connection*) +void WebProcess::didClose(IPC::Connection&) { #ifndef NDEBUG - m_inDidClose = true; - // Close all the live pages. Vector<RefPtr<WebPage>> pages; copyValuesToVector(m_pageMap, pages); - for (size_t i = 0; i < pages.size(); ++i) - pages[i]->close(); + for (auto& page : pages) + page->close(); pages.clear(); - gcController().garbageCollectSoon(); - fontCache()->invalidate(); - memoryCache()->setDisabled(true); -#endif + GCController::singleton().garbageCollectSoon(); + FontCache::singleton().invalidate(); + MemoryCache::singleton().setDisabled(true); +#endif + +#if ENABLE(VIDEO) + // FIXME(146657): This explicit media stop command should not be necessary + if (auto* platformMediaSessionManager = PlatformMediaSessionManager::sharedManagerIfExists()) + platformMediaSessionManager->stopAllMediaPlaybackForProcess(); +#endif // The UI process closed this connection, shut down. stopRunLoop(); } -void WebProcess::didReceiveInvalidMessage(IPC::Connection*, IPC::StringReference, IPC::StringReference) -{ - // We received an invalid message, but since this is from the UI process (which we trust), - // we'll let it slide. -} - WebFrame* WebProcess::webFrame(uint64_t frameID) const { return m_frameMap.get(frameID); @@ -693,9 +690,9 @@ void WebProcess::removeWebFrame(uint64_t frameID) WebPageGroupProxy* WebProcess::webPageGroup(PageGroup* pageGroup) { - for (HashMap<uint64_t, RefPtr<WebPageGroupProxy>>::const_iterator it = m_pageGroupMap.begin(), end = m_pageGroupMap.end(); it != end; ++it) { - if (it->value->corePageGroup() == pageGroup) - return it->value.get(); + for (auto& page : m_pageGroupMap.values()) { + if (page->corePageGroup() == pageGroup) + return page.get(); } return 0; @@ -717,26 +714,45 @@ WebPageGroupProxy* WebProcess::webPageGroup(const WebPageGroupData& pageGroupDat return result.iterator->value.get(); } -void WebProcess::clearResourceCaches(ResourceCachesToClear resourceCachesToClear) +static uint64_t nextUserGestureTokenIdentifier() +{ + static uint64_t identifier = 1; + return identifier++; +} + +uint64_t WebProcess::userGestureTokenIdentifier(RefPtr<UserGestureToken> token) +{ + if (!token || !token->processingUserGesture()) + return 0; + + auto result = m_userGestureTokens.ensure(token.get(), [] { return nextUserGestureTokenIdentifier(); }); + if (result.isNewEntry) { + result.iterator->key->addDestructionObserver([] (UserGestureToken& tokenBeingDestroyed) { + WebProcess::singleton().userGestureTokenDestroyed(tokenBeingDestroyed); + }); + } + + return result.iterator->value; +} + +void WebProcess::userGestureTokenDestroyed(UserGestureToken& token) { - platformClearResourceCaches(resourceCachesToClear); + auto identifier = m_userGestureTokens.take(&token); + parentProcessConnection()->send(Messages::WebProcessProxy::DidDestroyUserGestureToken(identifier), 0); +} +void WebProcess::clearResourceCaches(ResourceCachesToClear resourceCachesToClear) +{ // Toggling the cache model like this forces the cache to evict all its in-memory resources. // FIXME: We need a better way to do this. CacheModel cacheModel = m_cacheModel; setCacheModel(CacheModelDocumentViewer); setCacheModel(cacheModel); - memoryCache()->evictResources(); + MemoryCache::singleton().evictResources(); // Empty the cross-origin preflight cache. - CrossOriginPreflightResultCache::shared().empty(); -} - -void WebProcess::clearApplicationCache() -{ - // Empty the application cache. - cacheStorage().empty(); + CrossOriginPreflightResultCache::singleton().empty(); } static inline void addCaseFoldedCharacters(StringHasher& hasher, const String& string) @@ -744,16 +760,16 @@ static inline void addCaseFoldedCharacters(StringHasher& hasher, const String& s if (string.isEmpty()) return; if (string.is8Bit()) { - hasher.addCharacters<LChar, CaseFoldingHash::foldCase<LChar>>(string.characters8(), string.length()); + hasher.addCharacters<LChar, ASCIICaseInsensitiveHash::foldCase<LChar>>(string.characters8(), string.length()); return; } - hasher.addCharacters<UChar, CaseFoldingHash::foldCase<UChar>>(string.characters16(), string.length()); + hasher.addCharacters<UChar, ASCIICaseInsensitiveHash::foldCase<UChar>>(string.characters16(), string.length()); } static unsigned hashForPlugInOrigin(const String& pageOrigin, const String& pluginOrigin, const String& mimeType) { // We want to avoid concatenating the strings and then taking the hash, since that could lead to an expensive conversion. - // We also want to avoid using the hash() function in StringImpl or CaseFoldingHash because that masks out bits for the use of flags. + // We also want to avoid using the hash() function in StringImpl or ASCIICaseInsensitiveHash because that masks out bits for the use of flags. StringHasher hasher; addCaseFoldedCharacters(hasher, pageOrigin); hasher.addCharacter(0); @@ -763,32 +779,43 @@ static unsigned hashForPlugInOrigin(const String& pageOrigin, const String& plug return hasher.hash(); } -bool WebProcess::isPlugInAutoStartOriginHash(unsigned plugInOriginHash) +bool WebProcess::isPlugInAutoStartOriginHash(unsigned plugInOriginHash, SessionID sessionID) { - HashMap<unsigned, double>::const_iterator it = m_plugInAutoStartOriginHashes.find(plugInOriginHash); - if (it == m_plugInAutoStartOriginHashes.end()) - return false; + HashMap<WebCore::SessionID, HashMap<unsigned, double>>::const_iterator sessionIterator = m_plugInAutoStartOriginHashes.find(sessionID); + HashMap<unsigned, double>::const_iterator it; + bool contains = false; + + if (sessionIterator != m_plugInAutoStartOriginHashes.end()) { + it = sessionIterator->value.find(plugInOriginHash); + contains = it != sessionIterator->value.end(); + } + if (!contains) { + sessionIterator = m_plugInAutoStartOriginHashes.find(SessionID::defaultSessionID()); + it = sessionIterator->value.find(plugInOriginHash); + if (it == sessionIterator->value.end()) + return false; + } return currentTime() < it->value; } -bool WebProcess::shouldPlugInAutoStartFromOrigin(const WebPage* page, const String& pageOrigin, const String& pluginOrigin, const String& mimeType) +bool WebProcess::shouldPlugInAutoStartFromOrigin(WebPage& webPage, const String& pageOrigin, const String& pluginOrigin, const String& mimeType) { - if (m_plugInAutoStartOrigins.contains(pluginOrigin)) + if (!pluginOrigin.isEmpty() && m_plugInAutoStartOrigins.contains(pluginOrigin)) return true; #ifdef ENABLE_PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC // 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). - if (page && page->matchesPrimaryPlugIn(pageOrigin, pluginOrigin, mimeType)) + if (webPage.matchesPrimaryPlugIn(pageOrigin, pluginOrigin, mimeType)) return true; #else - UNUSED_PARAM(page); + UNUSED_PARAM(webPage); #endif // Lastly check against the more explicit hash list. - return isPlugInAutoStartOriginHash(hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType)); + return isPlugInAutoStartOriginHash(hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType), webPage.sessionID()); } -void WebProcess::plugInDidStartFromOrigin(const String& pageOrigin, const String& pluginOrigin, const String& mimeType) +void WebProcess::plugInDidStartFromOrigin(const String& pageOrigin, const String& pluginOrigin, const String& mimeType, SessionID sessionID) { if (pageOrigin.isEmpty()) { LOG(Plugins, "Not adding empty page origin"); @@ -796,7 +823,7 @@ void WebProcess::plugInDidStartFromOrigin(const String& pageOrigin, const String } unsigned plugInOriginHash = hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType); - if (isPlugInAutoStartOriginHash(plugInOriginHash)) { + if (isPlugInAutoStartOriginHash(plugInOriginHash, sessionID)) { LOG(Plugins, "Hash %x already exists as auto-start origin (request for %s)", plugInOriginHash, pageOrigin.utf8().data()); return; } @@ -805,25 +832,31 @@ void WebProcess::plugInDidStartFromOrigin(const String& pageOrigin, const String // comes back from the parent process. Temporarily add this hash to the list with a thirty // second timeout. That way, even if the parent decides not to add it, we'll only be // incorrect for a little while. - m_plugInAutoStartOriginHashes.set(plugInOriginHash, currentTime() + 30 * 1000); + m_plugInAutoStartOriginHashes.add(sessionID, HashMap<unsigned, double>()).iterator->value.set(plugInOriginHash, currentTime() + 30 * 1000); - parentProcessConnection()->send(Messages::WebContext::AddPlugInAutoStartOriginHash(pageOrigin, plugInOriginHash), 0); + parentProcessConnection()->send(Messages::WebProcessPool::AddPlugInAutoStartOriginHash(pageOrigin, plugInOriginHash, sessionID), 0); } -void WebProcess::didAddPlugInAutoStartOriginHash(unsigned plugInOriginHash, double expirationTime) +void WebProcess::didAddPlugInAutoStartOriginHash(unsigned plugInOriginHash, double expirationTime, SessionID sessionID) { // When called, some web process (which also might be this one) added the origin for auto-starting, // or received user interaction. // Set the bit to avoid having redundantly call into the UI process upon user interaction. - m_plugInAutoStartOriginHashes.set(plugInOriginHash, expirationTime); + m_plugInAutoStartOriginHashes.add(sessionID, HashMap<unsigned, double>()).iterator->value.set(plugInOriginHash, expirationTime); } -void WebProcess::resetPlugInAutoStartOriginHashes(const HashMap<unsigned, double>& hashes) +void WebProcess::resetPlugInAutoStartOriginDefaultHashes(const HashMap<unsigned, double>& hashes) { - m_plugInAutoStartOriginHashes.swap(const_cast<HashMap<unsigned, double>&>(hashes)); + m_plugInAutoStartOriginHashes.clear(); + m_plugInAutoStartOriginHashes.add(SessionID::defaultSessionID(), HashMap<unsigned, double>()).iterator->value.swap(const_cast<HashMap<unsigned, double>&>(hashes)); } -void WebProcess::plugInDidReceiveUserInteraction(const String& pageOrigin, const String& pluginOrigin, const String& mimeType) +void WebProcess::resetPlugInAutoStartOriginHashes(const HashMap<SessionID, HashMap<unsigned, double>>& hashes) +{ + m_plugInAutoStartOriginHashes.swap(const_cast<HashMap<SessionID, HashMap<unsigned, double>>&>(hashes)); +} + +void WebProcess::plugInDidReceiveUserInteraction(const String& pageOrigin, const String& pluginOrigin, const String& mimeType, SessionID sessionID) { if (pageOrigin.isEmpty()) return; @@ -832,13 +865,45 @@ void WebProcess::plugInDidReceiveUserInteraction(const String& pageOrigin, const if (!plugInOriginHash) return; - HashMap<unsigned, double>::iterator it = m_plugInAutoStartOriginHashes.find(plugInOriginHash); - if (it == m_plugInAutoStartOriginHashes.end()) - return; + HashMap<WebCore::SessionID, HashMap<unsigned, double>>::const_iterator sessionIterator = m_plugInAutoStartOriginHashes.find(sessionID); + HashMap<unsigned, double>::const_iterator it; + bool contains = false; + if (sessionIterator != m_plugInAutoStartOriginHashes.end()) { + it = sessionIterator->value.find(plugInOriginHash); + contains = it != sessionIterator->value.end(); + } + if (!contains) { + sessionIterator = m_plugInAutoStartOriginHashes.find(SessionID::defaultSessionID()); + it = sessionIterator->value.find(plugInOriginHash); + if (it == sessionIterator->value.end()) + return; + } + if (it->value - currentTime() > plugInAutoStartExpirationTimeUpdateThreshold) return; - parentProcessConnection()->send(Messages::WebContext::PlugInDidReceiveUserInteraction(plugInOriginHash), 0); + parentProcessConnection()->send(Messages::WebProcessPool::PlugInDidReceiveUserInteraction(plugInOriginHash, sessionID), 0); +} + +void WebProcess::setPluginLoadClientPolicy(uint8_t policy, const String& host, const String& bundleIdentifier, const String& versionString) +{ +#if ENABLE(NETSCAPE_PLUGIN_API) && PLATFORM(MAC) + WebPluginInfoProvider::singleton().setPluginLoadClientPolicy(static_cast<PluginLoadClientPolicy>(policy), host, bundleIdentifier, versionString); +#endif +} + +void WebProcess::clearPluginClientPolicies() +{ +#if ENABLE(NETSCAPE_PLUGIN_API) && PLATFORM(MAC) + WebPluginInfoProvider::singleton().clearPluginClientPolicies(); +#endif +} + +void WebProcess::refreshPlugins() +{ +#if ENABLE(NETSCAPE_PLUGIN_API) + WebPluginInfoProvider::singleton().refresh(false); +#endif } static void fromCountedSetToHashMap(TypeCountSet* countedSet, HashMap<String, uint64_t>& map) @@ -855,7 +920,7 @@ static void getWebCoreMemoryCacheStatistics(Vector<HashMap<String, uint64_t>>& r String xslString(ASCIILiteral("XSL")); String javaScriptString(ASCIILiteral("JavaScript")); - MemoryCache::Statistics memoryCacheStatistics = memoryCache()->getStatistics(); + MemoryCache::Statistics memoryCacheStatistics = MemoryCache::singleton().getStatistics(); HashMap<String, uint64_t> counts; counts.set(imagesString, memoryCacheStatistics.images.count); @@ -884,20 +949,6 @@ static void getWebCoreMemoryCacheStatistics(Vector<HashMap<String, uint64_t>>& r decodedSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.decodedSize); decodedSizes.set(javaScriptString, memoryCacheStatistics.scripts.decodedSize); result.append(decodedSizes); - - HashMap<String, uint64_t> purgeableSizes; - purgeableSizes.set(imagesString, memoryCacheStatistics.images.purgeableSize); - purgeableSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.purgeableSize); - purgeableSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.purgeableSize); - purgeableSizes.set(javaScriptString, memoryCacheStatistics.scripts.purgeableSize); - result.append(purgeableSizes); - - HashMap<String, uint64_t> purgedSizes; - purgedSizes.set(imagesString, memoryCacheStatistics.images.purgedSize); - purgedSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.purgedSize); - purgedSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.purgedSize); - purgedSizes.set(javaScriptString, memoryCacheStatistics.scripts.purgedSize); - result.append(purgedSizes); } void WebProcess::getWebCoreStatistics(uint64_t callbackID) @@ -906,21 +957,21 @@ void WebProcess::getWebCoreStatistics(uint64_t callbackID) // Gather JavaScript statistics. { - JSLockHolder lock(JSDOMWindow::commonVM()); - data.statisticsNumbers.set(ASCIILiteral("JavaScriptObjectsCount"), JSDOMWindow::commonVM()->heap.objectCount()); - data.statisticsNumbers.set(ASCIILiteral("JavaScriptGlobalObjectsCount"), JSDOMWindow::commonVM()->heap.globalObjectCount()); - data.statisticsNumbers.set(ASCIILiteral("JavaScriptProtectedObjectsCount"), JSDOMWindow::commonVM()->heap.protectedObjectCount()); - data.statisticsNumbers.set(ASCIILiteral("JavaScriptProtectedGlobalObjectsCount"), JSDOMWindow::commonVM()->heap.protectedGlobalObjectCount()); + JSLockHolder lock(commonVM()); + data.statisticsNumbers.set(ASCIILiteral("JavaScriptObjectsCount"), commonVM().heap.objectCount()); + data.statisticsNumbers.set(ASCIILiteral("JavaScriptGlobalObjectsCount"), commonVM().heap.globalObjectCount()); + data.statisticsNumbers.set(ASCIILiteral("JavaScriptProtectedObjectsCount"), commonVM().heap.protectedObjectCount()); + data.statisticsNumbers.set(ASCIILiteral("JavaScriptProtectedGlobalObjectsCount"), commonVM().heap.protectedGlobalObjectCount()); - OwnPtr<TypeCountSet> protectedObjectTypeCounts(JSDOMWindow::commonVM()->heap.protectedObjectTypeCounts()); + std::unique_ptr<TypeCountSet> protectedObjectTypeCounts(commonVM().heap.protectedObjectTypeCounts()); fromCountedSetToHashMap(protectedObjectTypeCounts.get(), data.javaScriptProtectedObjectTypeCounts); - OwnPtr<TypeCountSet> objectTypeCounts(JSDOMWindow::commonVM()->heap.objectTypeCounts()); + std::unique_ptr<TypeCountSet> objectTypeCounts(commonVM().heap.objectTypeCounts()); fromCountedSetToHashMap(objectTypeCounts.get(), data.javaScriptObjectTypeCounts); - uint64_t javaScriptHeapSize = JSDOMWindow::commonVM()->heap.size(); + uint64_t javaScriptHeapSize = commonVM().heap.size(); data.statisticsNumbers.set(ASCIILiteral("JavaScriptHeapSize"), javaScriptHeapSize); - data.statisticsNumbers.set(ASCIILiteral("JavaScriptFreeSize"), JSDOMWindow::commonVM()->heap.capacity() - javaScriptHeapSize); + data.statisticsNumbers.set(ASCIILiteral("JavaScriptFreeSize"), commonVM().heap.capacity() - javaScriptHeapSize); } WTF::FastMallocStatistics fastMallocStatistics = WTF::fastMallocStatistics(); @@ -935,62 +986,82 @@ void WebProcess::getWebCoreStatistics(uint64_t callbackID) data.statisticsNumbers.set(ASCIILiteral("IconsWithDataCount"), iconDatabase().iconRecordCountWithData()); // Gather font statistics. - data.statisticsNumbers.set(ASCIILiteral("CachedFontDataCount"), fontCache()->fontDataCount()); - data.statisticsNumbers.set(ASCIILiteral("CachedFontDataInactiveCount"), fontCache()->inactiveFontDataCount()); + auto& fontCache = FontCache::singleton(); + data.statisticsNumbers.set(ASCIILiteral("CachedFontDataCount"), fontCache.fontCount()); + data.statisticsNumbers.set(ASCIILiteral("CachedFontDataInactiveCount"), fontCache.inactiveFontCount()); // Gather glyph page statistics. - data.statisticsNumbers.set(ASCIILiteral("GlyphPageCount"), GlyphPageTreeNode::treeGlyphPageCount()); + data.statisticsNumbers.set(ASCIILiteral("GlyphPageCount"), GlyphPage::count()); // Get WebCore memory cache statistics getWebCoreMemoryCacheStatistics(data.webCoreCacheStatistics); - parentProcessConnection()->send(Messages::WebContext::DidGetStatistics(data, callbackID), 0); + parentProcessConnection()->send(Messages::WebProcessPool::DidGetStatistics(data, callbackID), 0); } void WebProcess::garbageCollectJavaScriptObjects() { - gcController().garbageCollectNow(); + GCController::singleton().garbageCollectNow(); +} + +void WebProcess::mainThreadPing() +{ + parentProcessConnection()->send(Messages::WebProcessProxy::DidReceiveMainThreadPing(), 0); +} + +#if ENABLE(GAMEPAD) + +void WebProcess::setInitialGamepads(const Vector<WebKit::GamepadData>& gamepadDatas) +{ + WebGamepadProvider::singleton().setInitialGamepads(gamepadDatas); +} + +void WebProcess::gamepadConnected(const GamepadData& gamepadData) +{ + WebGamepadProvider::singleton().gamepadConnected(gamepadData); } +void WebProcess::gamepadDisconnected(unsigned index) +{ + WebGamepadProvider::singleton().gamepadDisconnected(index); +} + +#endif + void WebProcess::setJavaScriptGarbageCollectorTimerEnabled(bool flag) { - gcController().setJavaScriptGarbageCollectorTimerEnabled(flag); + GCController::singleton().setJavaScriptGarbageCollectorTimerEnabled(flag); } -void WebProcess::postInjectedBundleMessage(const IPC::DataReference& messageData) +void WebProcess::handleInjectedBundleMessage(const String& messageName, const UserData& messageBody) { - InjectedBundle* injectedBundle = WebProcess::shared().injectedBundle(); + InjectedBundle* injectedBundle = WebProcess::singleton().injectedBundle(); if (!injectedBundle) return; - IPC::ArgumentDecoder decoder(messageData.data(), messageData.size()); - - String messageName; - if (!decoder.decode(messageName)) - return; + injectedBundle->didReceiveMessage(messageName, transformHandlesToObjects(messageBody.object()).get()); +} - RefPtr<API::Object> messageBody; - InjectedBundleUserMessageDecoder messageBodyDecoder(messageBody); - if (!decoder.decode(messageBodyDecoder)) +void WebProcess::setInjectedBundleParameter(const String& key, const IPC::DataReference& value) +{ + InjectedBundle* injectedBundle = WebProcess::singleton().injectedBundle(); + if (!injectedBundle) return; - injectedBundle->didReceiveMessage(messageName, messageBody.get()); + injectedBundle->setBundleParameter(key, value); } -bool WebProcess::usesNetworkProcess() const +void WebProcess::setInjectedBundleParameters(const IPC::DataReference& value) { -#if ENABLE(NETWORK_PROCESS) - return m_usesNetworkProcess; -#else - return false; -#endif + InjectedBundle* injectedBundle = WebProcess::singleton().injectedBundle(); + if (!injectedBundle) + return; + + injectedBundle->setBundleParameters(value); } -#if ENABLE(NETWORK_PROCESS) -NetworkProcessConnection* WebProcess::networkConnection() +NetworkProcessConnection& WebProcess::networkConnection() { - ASSERT(m_usesNetworkProcess); - // If we've lost our connection to the network process (e.g. it crashed) try to re-establish it. if (!m_networkProcessConnection) ensureNetworkProcessConnection(); @@ -999,24 +1070,45 @@ NetworkProcessConnection* WebProcess::networkConnection() if (!m_networkProcessConnection) CRASH(); - return m_networkProcessConnection.get(); + return *m_networkProcessConnection; +} + +void WebProcess::logDiagnosticMessageForNetworkProcessCrash() +{ + WebCore::Page* page = nullptr; + + if (auto* webPage = focusedWebPage()) + page = webPage->corePage(); + + if (!page) { + for (auto& webPage : m_pageMap.values()) { + if (auto* corePage = webPage->corePage()) { + page = corePage; + break; + } + } + } + + if (page) + page->diagnosticLoggingClient().logDiagnosticMessage(WebCore::DiagnosticLoggingKeys::internalErrorKey(), WebCore::DiagnosticLoggingKeys::networkProcessCrashedKey(), WebCore::ShouldSample::No); } void WebProcess::networkProcessConnectionClosed(NetworkProcessConnection* connection) { ASSERT(m_networkProcessConnection); - ASSERT(m_networkProcessConnection == connection); + ASSERT_UNUSED(connection, m_networkProcessConnection == connection); - m_networkProcessConnection = 0; - - m_webResourceLoadScheduler->networkProcessCrashed(); + m_networkProcessConnection = nullptr; + + logDiagnosticMessageForNetworkProcessCrash(); + + m_webLoaderStrategy.networkProcessCrashed(); } -WebResourceLoadScheduler& WebProcess::webResourceLoadScheduler() +WebLoaderStrategy& WebProcess::webLoaderStrategy() { - return *m_webResourceLoadScheduler; + return m_webLoaderStrategy; } -#endif // ENABLED(NETWORK_PROCESS) #if ENABLE(DATABASE_PROCESS) void WebProcess::webToDatabaseProcessConnectionClosed(WebToDatabaseProcessConnection* connection) @@ -1024,7 +1116,7 @@ void WebProcess::webToDatabaseProcessConnectionClosed(WebToDatabaseProcessConnec ASSERT(m_webToDatabaseProcessConnection); ASSERT(m_webToDatabaseProcessConnection == connection); - m_webToDatabaseProcessConnection = 0; + m_webToDatabaseProcessConnection = nullptr; } WebToDatabaseProcessConnection* WebProcess::webToDatabaseProcessConnection() @@ -1046,34 +1138,20 @@ void WebProcess::ensureWebToDatabaseProcessConnection() Messages::WebProcessProxy::GetDatabaseProcessConnection::Reply(encodedConnectionIdentifier), 0)) return; -#if PLATFORM(MAC) +#if USE(UNIX_DOMAIN_SOCKETS) + IPC::Connection::Identifier connectionIdentifier = encodedConnectionIdentifier.releaseFileDescriptor(); +#elif OS(DARWIN) IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.port()); - if (IPC::Connection::identifierIsNull(connectionIdentifier)) - return; #else ASSERT_NOT_REACHED(); #endif + if (IPC::Connection::identifierIsNull(connectionIdentifier)) + return; m_webToDatabaseProcessConnection = WebToDatabaseProcessConnection::create(connectionIdentifier); } #endif // ENABLED(DATABASE_PROCESS) -void WebProcess::downloadRequest(uint64_t downloadID, uint64_t initiatingPageID, const ResourceRequest& request) -{ - WebPage* initiatingPage = initiatingPageID ? webPage(initiatingPageID) : 0; - - ResourceRequest requestWithOriginalURL = request; - if (initiatingPage) - initiatingPage->mainFrame()->loader().setOriginalURLForDownloadRequest(requestWithOriginalURL); - - downloadManager().startDownload(downloadID, requestWithOriginalURL); -} - -void WebProcess::cancelDownload(uint64_t downloadID) -{ - downloadManager().cancelDownload(downloadID); -} - void WebProcess::setEnhancedAccessibility(bool flag) { WebCore::AXObjectCache::setEnhancedUserInterfaceAccessibility(flag); @@ -1082,7 +1160,7 @@ void WebProcess::setEnhancedAccessibility(bool flag) void WebProcess::startMemorySampler(const SandboxExtension::Handle& sampleLogFileHandle, const String& sampleLogFilePath, const double interval) { #if ENABLE(MEMORY_SAMPLER) - WebMemorySampler::shared()->start(sampleLogFileHandle, sampleLogFilePath, interval); + WebMemorySampler::singleton()->start(sampleLogFileHandle, sampleLogFilePath, interval); #else UNUSED_PARAM(sampleLogFileHandle); UNUSED_PARAM(sampleLogFilePath); @@ -1093,7 +1171,7 @@ void WebProcess::startMemorySampler(const SandboxExtension::Handle& sampleLogFil void WebProcess::stopMemorySampler() { #if ENABLE(MEMORY_SAMPLER) - WebMemorySampler::shared()->stop(); + WebMemorySampler::singleton()->stop(); #endif } @@ -1107,9 +1185,7 @@ void WebProcess::setTextCheckerState(const TextCheckerState& textCheckerState) if (!continuousSpellCheckingTurnedOff && !grammarCheckingTurnedOff) return; - HashMap<uint64_t, RefPtr<WebPage>>::iterator end = m_pageMap.end(); - for (HashMap<uint64_t, RefPtr<WebPage>>::iterator it = m_pageMap.begin(); it != end; ++it) { - WebPage* page = (*it).value.get(); + for (auto& page : m_pageMap.values()) { if (continuousSpellCheckingTurnedOff) page->unmarkAllMisspellings(); if (grammarCheckingTurnedOff) @@ -1119,12 +1195,47 @@ void WebProcess::setTextCheckerState(const TextCheckerState& textCheckerState) void WebProcess::releasePageCache() { - int savedPageCacheCapacity = pageCache()->capacity(); - pageCache()->setCapacity(0); - pageCache()->setCapacity(savedPageCacheCapacity); + PageCache::singleton().pruneToSizeNow(0, PruningReason::MemoryPressure); +} + +void WebProcess::fetchWebsiteData(WebCore::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, WebsiteData& websiteData) +{ + if (websiteDataTypes.contains(WebsiteDataType::MemoryCache)) { + for (auto& origin : MemoryCache::singleton().originsWithCache(sessionID)) + websiteData.entries.append(WebsiteData::Entry { SecurityOriginData::fromSecurityOrigin(*origin), WebsiteDataType::MemoryCache, 0 }); + } +} + +void WebProcess::deleteWebsiteData(SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, std::chrono::system_clock::time_point modifiedSince) +{ + UNUSED_PARAM(modifiedSince); + + if (websiteDataTypes.contains(WebsiteDataType::MemoryCache)) { + PageCache::singleton().pruneToSizeNow(0, PruningReason::None); + MemoryCache::singleton().evictResources(sessionID); + + CrossOriginPreflightResultCache::singleton().empty(); + } +} + +void WebProcess::deleteWebsiteDataForOrigins(WebCore::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, const Vector<WebCore::SecurityOriginData>& originDatas) +{ + if (websiteDataTypes.contains(WebsiteDataType::MemoryCache)) { + HashSet<RefPtr<SecurityOrigin>> origins; + for (auto& originData : originDatas) + origins.add(originData.securityOrigin()); + + MemoryCache::singleton().removeResourcesWithOrigins(sessionID, origins); + } } -#if !PLATFORM(MAC) +void WebProcess::setHiddenPageTimerThrottlingIncreaseLimit(int milliseconds) +{ + for (auto& page : m_pageMap.values()) + page->setHiddenPageTimerThrottlingIncreaseLimit(std::chrono::milliseconds(milliseconds)); +} + +#if !PLATFORM(COCOA) void WebProcess::initializeProcessName(const ChildProcessInitializationParameters&) { } @@ -1146,13 +1257,112 @@ void WebProcess::updateActivePages() #if PLATFORM(IOS) void WebProcess::resetAllGeolocationPermissions() { - for (auto it = m_pageMap.begin(), end = m_pageMap.end(); it != end; ++it) { - WebPage* page = (*it).value.get(); + for (auto& page : m_pageMap.values()) { if (Frame* mainFrame = page->mainFrame()) mainFrame->resetAllGeolocationPermission(); } } -#endif // PLATFORM(IOS) +#endif + +void WebProcess::actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend shouldAcknowledgeWhenReadyToSuspend) +{ + if (!m_suppressMemoryPressureHandler) + MemoryPressureHandler::singleton().releaseMemory(Critical::Yes, Synchronous::Yes); + + setAllLayerTreeStatesFrozen(true); + +#if PLATFORM(COCOA) + destroyRenderingResources(); +#endif + + markAllLayersVolatile([this, shouldAcknowledgeWhenReadyToSuspend] { + RELEASE_LOG(ProcessSuspension, "%p - WebProcess::markAllLayersVolatile() Successfuly marked all layers as volatile", this); + + if (shouldAcknowledgeWhenReadyToSuspend == ShouldAcknowledgeWhenReadyToSuspend::Yes) { + RELEASE_LOG(ProcessSuspension, "%p - WebProcess::actualPrepareToSuspend() Sending ProcessReadyToSuspend IPC message", this); + parentProcessConnection()->send(Messages::WebProcessProxy::ProcessReadyToSuspend(), 0); + } + }); +} + +void WebProcess::processWillSuspendImminently(bool& handled) +{ + if (parentProcessConnection()->inSendSync()) { + // Avoid reentrency bugs such as rdar://problem/21605505 by just bailing + // if we get an incoming ProcessWillSuspendImminently message when waiting for a + // reply to a sync message. + // FIXME: ProcessWillSuspendImminently should not be a sync message. + return; + } + + RELEASE_LOG(ProcessSuspension, "%p - WebProcess::processWillSuspendImminently()", this); + DatabaseTracker::singleton().closeAllDatabases(CurrentQueryBehavior::Interrupt); + actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::No); + handled = true; +} + +void WebProcess::prepareToSuspend() +{ + RELEASE_LOG(ProcessSuspension, "%p - WebProcess::prepareToSuspend()", this); + actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::Yes); +} + +void WebProcess::cancelPrepareToSuspend() +{ + RELEASE_LOG(ProcessSuspension, "%p - WebProcess::cancelPrepareToSuspend()", this); + setAllLayerTreeStatesFrozen(false); + + // If we've already finished cleaning up and sent ProcessReadyToSuspend, we + // shouldn't send DidCancelProcessSuspension; the UI process strictly expects one or the other. + if (!m_pagesMarkingLayersAsVolatile) + return; + + cancelMarkAllLayersVolatile(); + + RELEASE_LOG(ProcessSuspension, "%p - WebProcess::cancelPrepareToSuspend() Sending DidCancelProcessSuspension IPC message", this); + parentProcessConnection()->send(Messages::WebProcessProxy::DidCancelProcessSuspension(), 0); +} + +void WebProcess::markAllLayersVolatile(std::function<void()> completionHandler) +{ + RELEASE_LOG(ProcessSuspension, "%p - WebProcess::markAllLayersVolatile()", this); + m_pagesMarkingLayersAsVolatile = m_pageMap.size(); + if (!m_pagesMarkingLayersAsVolatile) { + completionHandler(); + return; + } + for (auto& page : m_pageMap.values()) { + page->markLayersVolatile([this, completionHandler] { + ASSERT(m_pagesMarkingLayersAsVolatile); + if (!--m_pagesMarkingLayersAsVolatile) + completionHandler(); + }); + } +} + +void WebProcess::cancelMarkAllLayersVolatile() +{ + if (!m_pagesMarkingLayersAsVolatile) + return; + + for (auto& page : m_pageMap.values()) + page->cancelMarkLayersVolatile(); + m_pagesMarkingLayersAsVolatile = 0; +} + +void WebProcess::setAllLayerTreeStatesFrozen(bool frozen) +{ + for (auto& page : m_pageMap.values()) + page->setLayerTreeStateIsFrozen(frozen); +} + +void WebProcess::processDidResume() +{ + RELEASE_LOG(ProcessSuspension, "%p - WebProcess::processDidResume()", this); + + cancelMarkAllLayersVolatile(); + setAllLayerTreeStatesFrozen(false); +} void WebProcess::pageDidEnterWindow(uint64_t pageID) { @@ -1168,37 +1378,180 @@ void WebProcess::pageWillLeaveWindow(uint64_t pageID) m_nonVisibleProcessCleanupTimer.startOneShot(nonVisibleProcessCleanupDelay); } -void WebProcess::nonVisibleProcessCleanupTimerFired(Timer<WebProcess>*) +void WebProcess::nonVisibleProcessCleanupTimerFired() { ASSERT(m_pagesInWindows.isEmpty()); if (!m_pagesInWindows.isEmpty()) return; -#if PLATFORM(MAC) - wkDestroyRenderingResources(); +#if PLATFORM(COCOA) + destroyRenderingResources(); #endif } -RefPtr<API::Object> WebProcess::apiObjectByConvertingFromHandles(API::Object* object) +void WebProcess::statisticsChangedTimerFired() { - return UserData::transform(object, [this](const API::Object& object) -> RefPtr<API::Object> { - switch (object.type()) { - case API::Object::Type::FrameHandle: { - auto& frameHandle = static_cast<const API::FrameHandle&>(object); + if (m_resourceLoadStatisticsStore->isEmpty()) + return; + + parentProcessConnection()->send(Messages::WebResourceLoadStatisticsStore::ResourceLoadStatisticsUpdated(m_resourceLoadStatisticsStore->takeStatistics()), 0); +} + +void WebProcess::setResourceLoadStatisticsEnabled(bool enabled) +{ + WebCore::Settings::setResourceLoadStatisticsEnabled(enabled); +} - return webFrame(frameHandle.frameID()); +RefPtr<API::Object> WebProcess::transformHandlesToObjects(API::Object* object) +{ + struct Transformer final : UserData::Transformer { + Transformer(WebProcess& webProcess) + : m_webProcess(webProcess) + { } - default: - return nullptr; + bool shouldTransformObject(const API::Object& object) const override + { + switch (object.type()) { + case API::Object::Type::FrameHandle: + return static_cast<const API::FrameHandle&>(object).isAutoconverting(); + + case API::Object::Type::PageHandle: + return static_cast<const API::PageHandle&>(object).isAutoconverting(); + + case API::Object::Type::PageGroupHandle: +#if PLATFORM(COCOA) + case API::Object::Type::ObjCObjectGraph: +#endif + return true; + + default: + return false; + } } - }); + + RefPtr<API::Object> transformObject(API::Object& object) const override + { + switch (object.type()) { + case API::Object::Type::FrameHandle: + return m_webProcess.webFrame(static_cast<const API::FrameHandle&>(object).frameID()); + + case API::Object::Type::PageGroupHandle: + return m_webProcess.webPageGroup(static_cast<const API::PageGroupHandle&>(object).webPageGroupData()); + + case API::Object::Type::PageHandle: + return m_webProcess.webPage(static_cast<const API::PageHandle&>(object).pageID()); + +#if PLATFORM(COCOA) + case API::Object::Type::ObjCObjectGraph: + return m_webProcess.transformHandlesToObjects(static_cast<ObjCObjectGraph&>(object)); +#endif + default: + return &object; + } + } + + WebProcess& m_webProcess; + }; + + return UserData::transform(object, Transformer(*this)); +} + +RefPtr<API::Object> WebProcess::transformObjectsToHandles(API::Object* object) +{ + struct Transformer final : UserData::Transformer { + bool shouldTransformObject(const API::Object& object) const override + { + switch (object.type()) { + case API::Object::Type::BundleFrame: + case API::Object::Type::BundlePage: + case API::Object::Type::BundlePageGroup: +#if PLATFORM(COCOA) + case API::Object::Type::ObjCObjectGraph: +#endif + return true; + + default: + return false; + } + } + + RefPtr<API::Object> transformObject(API::Object& object) const override + { + switch (object.type()) { + case API::Object::Type::BundleFrame: + return API::FrameHandle::createAutoconverting(static_cast<const WebFrame&>(object).frameID()); + + case API::Object::Type::BundlePage: + return API::PageHandle::createAutoconverting(static_cast<const WebPage&>(object).pageID()); + + case API::Object::Type::BundlePageGroup: { + WebPageGroupData pageGroupData; + pageGroupData.pageGroupID = static_cast<const WebPageGroupProxy&>(object).pageGroupID(); + + return API::PageGroupHandle::create(WTFMove(pageGroupData)); + } + +#if PLATFORM(COCOA) + case API::Object::Type::ObjCObjectGraph: + return transformObjectsToHandles(static_cast<ObjCObjectGraph&>(object)); +#endif + + default: + return &object; + } + } + }; + + return UserData::transform(object, Transformer()); } void WebProcess::setMemoryCacheDisabled(bool disabled) { - if (memoryCache()->disabled() != disabled) - memoryCache()->setDisabled(disabled); + auto& memoryCache = MemoryCache::singleton(); + if (memoryCache.disabled() != disabled) + memoryCache.setDisabled(disabled); +} + +#if ENABLE(SERVICE_CONTROLS) +void WebProcess::setEnabledServices(bool hasImageServices, bool hasSelectionServices, bool hasRichContentServices) +{ + m_hasImageServices = hasImageServices; + m_hasSelectionServices = hasSelectionServices; + m_hasRichContentServices = hasRichContentServices; } +#endif + +void WebProcess::ensureAutomationSessionProxy(const String& sessionIdentifier) +{ + m_automationSessionProxy = std::make_unique<WebAutomationSessionProxy>(sessionIdentifier); +} + +void WebProcess::destroyAutomationSessionProxy() +{ + m_automationSessionProxy = nullptr; +} + +void WebProcess::prefetchDNS(const String& hostname) +{ + if (hostname.isEmpty()) + return; + + if (m_dnsPrefetchedHosts.add(hostname).isNewEntry) + networkConnection().connection().send(Messages::NetworkConnectionToWebProcess::PrefetchDNS(hostname), 0); + // The DNS prefetched hosts cache is only to avoid asking for the same hosts too many times + // in a very short period of time, producing a lot of IPC traffic. So we clear this cache after + // some time of no DNS requests. + m_dnsPrefetchHystereris.impulse(); +} + +#if USE(LIBWEBRTC) +LibWebRTCNetwork& WebProcess::libWebRTCNetwork() +{ + if (!m_libWebRTCNetwork) + m_libWebRTCNetwork = std::make_unique<LibWebRTCNetwork>(); + return *m_libWebRTCNetwork; +} +#endif } // namespace WebKit |