2 * Copyright (C) 2009, 2010, 2012, 2014 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 "CustomProtocolManager.h"
35 #include "DrawingArea.h"
36 #include "EventDispatcher.h"
37 #include "InjectedBundle.h"
39 #include "NetworkConnectionToWebProcessMessages.h"
40 #include "NetworkProcessConnection.h"
41 #include "PluginProcessConnectionManager.h"
42 #include "SessionTracker.h"
43 #include "StatisticsData.h"
45 #include "WebConnectionToUIProcess.h"
46 #include "WebCookieManager.h"
47 #include "WebCoreArgumentCoders.h"
48 #include "WebDatabaseManager.h"
50 #include "WebFrameNetworkingContext.h"
51 #include "WebGeolocationManager.h"
52 #include "WebIconDatabaseProxy.h"
53 #include "WebMediaCacheManager.h"
54 #include "WebMediaKeyStorageManager.h"
55 #include "WebMemorySampler.h"
57 #include "WebPageGroupProxy.h"
58 #include "WebPageGroupProxyMessages.h"
59 #include "WebPlatformStrategies.h"
60 #include "WebProcessCreationParameters.h"
61 #include "WebProcessMessages.h"
62 #include "WebProcessPoolMessages.h"
63 #include "WebProcessProxyMessages.h"
64 #include "WebResourceLoadScheduler.h"
65 #include "WebsiteData.h"
66 #include "WebsiteDataTypes.h"
67 #include <JavaScriptCore/JSLock.h>
68 #include <JavaScriptCore/MemoryStatistics.h>
69 #include <WebCore/AXObjectCache.h>
70 #include <WebCore/ApplicationCacheStorage.h>
71 #include <WebCore/AuthenticationChallenge.h>
72 #include <WebCore/CrossOriginPreflightResultCache.h>
73 #include <WebCore/DNS.h>
74 #include <WebCore/FontCache.h>
75 #include <WebCore/FontCascade.h>
76 #include <WebCore/Frame.h>
77 #include <WebCore/FrameLoader.h>
78 #include <WebCore/GCController.h>
79 #include <WebCore/GlyphPage.h>
80 #include <WebCore/IconDatabase.h>
81 #include <WebCore/JSDOMWindow.h>
82 #include <WebCore/Language.h>
83 #include <WebCore/MainFrame.h>
84 #include <WebCore/MemoryCache.h>
85 #include <WebCore/MemoryPressureHandler.h>
86 #include <WebCore/Page.h>
87 #include <WebCore/PageCache.h>
88 #include <WebCore/PageGroup.h>
89 #include <WebCore/PlatformMediaSessionManager.h>
90 #include <WebCore/ResourceHandle.h>
91 #include <WebCore/RuntimeEnabledFeatures.h>
92 #include <WebCore/SchemeRegistry.h>
93 #include <WebCore/SecurityOrigin.h>
94 #include <WebCore/Settings.h>
96 #include <wtf/CurrentTime.h>
97 #include <wtf/HashCountedSet.h>
98 #include <wtf/PassRefPtr.h>
99 #include <wtf/RunLoop.h>
100 #include <wtf/text/StringHash.h>
103 #include "ObjCObjectGraph.h"
107 #include "CookieStorageShim.h"
110 #if ENABLE(SEC_ITEM_SHIM)
111 #include "SecItemShim.h"
114 #if ENABLE(DATABASE_PROCESS)
115 #include "WebToDatabaseProcessConnection.h"
118 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
119 #include "WebNotificationManager.h"
122 #if ENABLE(BATTERY_STATUS)
123 #include "WebBatteryManager.h"
126 #if ENABLE(REMOTE_INSPECTOR)
127 #include <JavaScriptCore/RemoteInspector.h>
131 using namespace WebCore;
133 // This should be less than plugInAutoStartExpirationTimeThreshold in PlugInAutoStartProvider.
134 static const double plugInAutoStartExpirationTimeUpdateThreshold = 29 * 24 * 60 * 60;
136 // This should be greater than tileRevalidationTimeout in TileController.
137 static const double nonVisibleProcessCleanupDelay = 10;
141 WebProcess& WebProcess::singleton()
143 static WebProcess& process = *new WebProcess;
147 WebProcess::WebProcess()
148 : m_eventDispatcher(EventDispatcher::create())
150 , m_viewUpdateDispatcher(ViewUpdateDispatcher::create())
152 , m_processSuspensionCleanupTimer(*this, &WebProcess::processSuspensionCleanupTimerFired)
153 , m_inDidClose(false)
154 , m_hasSetCacheModel(false)
155 , m_cacheModel(CacheModelDocumentViewer)
156 , m_fullKeyboardAccessEnabled(false)
157 , m_textCheckerState()
158 , m_iconDatabaseProxy(new WebIconDatabaseProxy(this))
159 , m_usesNetworkProcess(false)
160 , m_webResourceLoadScheduler(new WebResourceLoadScheduler)
161 , m_dnsPrefetchHystereris([this](HysteresisState state) { if (state == HysteresisState::Stopped) m_dnsPrefetchedHosts.clear(); })
162 #if ENABLE(NETSCAPE_PLUGIN_API)
163 , m_pluginProcessConnectionManager(PluginProcessConnectionManager::create())
165 #if ENABLE(SERVICE_CONTROLS)
166 , m_hasImageServices(false)
167 , m_hasSelectionServices(false)
168 , m_hasRichContentServices(false)
170 , m_nonVisibleProcessCleanupTimer(*this, &WebProcess::nonVisibleProcessCleanupTimerFired)
172 , m_webSQLiteDatabaseTracker(*this)
175 // Initialize our platform strategies.
176 WebPlatformStrategies::initialize();
178 // FIXME: This should moved to where WebProcess::initialize is called,
179 // so that ports have a chance to customize, and ifdefs in this file are
181 addSupplement<WebGeolocationManager>();
182 addSupplement<WebCookieManager>();
183 addSupplement<WebMediaCacheManager>();
184 addSupplement<AuthenticationManager>();
185 addSupplement<WebDatabaseManager>();
187 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
188 addSupplement<WebNotificationManager>();
190 addSupplement<CustomProtocolManager>();
191 #if ENABLE(BATTERY_STATUS)
192 addSupplement<WebBatteryManager>();
194 #if ENABLE(ENCRYPTED_MEDIA_V2)
195 addSupplement<WebMediaKeyStorageManager>();
197 m_plugInAutoStartOriginHashes.add(SessionID::defaultSessionID(), HashMap<unsigned, double>());
199 #if ENABLE(INDEXED_DATABASE)
200 RuntimeEnabledFeatures::sharedFeatures().setWebkitIndexedDBEnabled(true);
204 WebProcess::~WebProcess()
208 void WebProcess::initializeProcess(const ChildProcessInitializationParameters& parameters)
210 platformInitializeProcess(parameters);
213 void WebProcess::initializeConnection(IPC::Connection* connection)
215 ChildProcess::initializeConnection(connection);
217 connection->setShouldExitOnSyncMessageSendFailure(true);
219 #if HAVE(QOS_CLASSES)
220 connection->setShouldBoostMainThreadOnSyncMessage(true);
223 m_eventDispatcher->initializeConnection(connection);
225 m_viewUpdateDispatcher->initializeConnection(connection);
226 #endif // PLATFORM(IOS)
228 #if ENABLE(NETSCAPE_PLUGIN_API)
229 m_pluginProcessConnectionManager->initializeConnection(connection);
232 #if ENABLE(SEC_ITEM_SHIM)
233 SecItemShim::singleton().initializeConnection(connection);
236 for (auto& supplement : m_supplements.values())
237 supplement->initializeConnection(connection);
239 m_webConnection = WebConnectionToUIProcess::create(this);
241 // In order to ensure that the asynchronous messages that are used for notifying the UI process
242 // about when WebFrame objects come and go are always delivered before the synchronous policy messages,
243 // use this flag to force synchronous messages to be treated as asynchronous messages in the UI process
244 // unless when doing so would lead to a deadlock.
245 connection->setOnlySendMessagesAsDispatchWhenWaitingForSyncReplyWhenProcessingSuchAMessage(true);
248 void WebProcess::didCreateDownload()
250 disableTermination();
253 void WebProcess::didDestroyDownload()
258 IPC::Connection* WebProcess::downloadProxyConnection()
260 return parentProcessConnection();
263 AuthenticationManager& WebProcess::downloadsAuthenticationManager()
265 return *supplement<AuthenticationManager>();
268 void WebProcess::initializeWebProcess(WebProcessCreationParameters&& parameters)
270 ASSERT(m_pageMap.isEmpty());
272 m_usesNetworkProcess = parameters.usesNetworkProcess;
275 WebCore::MemoryPressureHandler::ReliefLogger::setLoggingEnabled(parameters.shouldEnableMemoryPressureReliefLogging);
278 platformInitializeWebProcess(WTF::move(parameters));
280 WTF::setCurrentThreadIsUserInitiated();
282 MemoryPressureHandler::singleton().install();
284 if (!parameters.injectedBundlePath.isEmpty())
285 m_injectedBundle = InjectedBundle::create(parameters, transformHandlesToObjects(parameters.initializationUserData.object()).get());
287 for (auto& supplement : m_supplements.values())
288 supplement->initialize(parameters);
290 #if ENABLE(ICONDATABASE)
291 m_iconDatabaseProxy->setEnabled(parameters.iconDatabaseEnabled);
294 if (!parameters.applicationCacheDirectory.isEmpty())
295 ApplicationCacheStorage::singleton().setCacheDirectory(parameters.applicationCacheDirectory);
297 setCacheModel(static_cast<uint32_t>(parameters.cacheModel));
299 if (!parameters.languages.isEmpty())
300 overrideUserPreferredLanguages(parameters.languages);
302 m_textCheckerState = parameters.textCheckerState;
304 m_fullKeyboardAccessEnabled = parameters.fullKeyboardAccessEnabled;
306 for (auto& scheme : parameters.urlSchemesRegisteredAsEmptyDocument)
307 registerURLSchemeAsEmptyDocument(scheme);
309 for (auto& scheme : parameters.urlSchemesRegisteredAsSecure)
310 registerURLSchemeAsSecure(scheme);
312 for (auto& scheme : parameters.urlSchemesRegisteredAsBypassingContentSecurityPolicy)
313 registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
315 for (auto& scheme : parameters.urlSchemesForWhichDomainRelaxationIsForbidden)
316 setDomainRelaxationForbiddenForURLScheme(scheme);
318 for (auto& scheme : parameters.urlSchemesRegisteredAsLocal)
319 registerURLSchemeAsLocal(scheme);
321 for (auto& scheme : parameters.urlSchemesRegisteredAsNoAccess)
322 registerURLSchemeAsNoAccess(scheme);
324 for (auto& scheme : parameters.urlSchemesRegisteredAsDisplayIsolated)
325 registerURLSchemeAsDisplayIsolated(scheme);
327 for (auto& scheme : parameters.urlSchemesRegisteredAsCORSEnabled)
328 registerURLSchemeAsCORSEnabled(scheme);
330 WebCore::Settings::setShouldRewriteConstAsVar(parameters.shouldRewriteConstAsVar);
332 #if ENABLE(CACHE_PARTITIONING)
333 for (auto& scheme : parameters.urlSchemesRegisteredAsCachePartitioned)
334 registerURLSchemeAsCachePartitioned(scheme);
337 setDefaultRequestTimeoutInterval(parameters.defaultRequestTimeoutInterval);
339 if (parameters.shouldAlwaysUseComplexTextCodePath)
340 setAlwaysUsesComplexTextCodePath(true);
342 if (parameters.shouldUseFontSmoothing)
343 setShouldUseFontSmoothing(true);
345 #if PLATFORM(COCOA) || USE(CFNETWORK)
346 SessionTracker::setIdentifierBase(parameters.uiProcessBundleIdentifier);
349 if (parameters.shouldUseTestingNetworkSession)
350 NetworkStorageSession::switchToNewTestingSession();
352 ensureNetworkProcessConnection();
355 if (usesNetworkProcess())
356 CookieStorageShim::singleton().initialize();
358 setTerminationTimeout(parameters.terminationTimeout);
360 resetPlugInAutoStartOriginHashes(parameters.plugInAutoStartOriginHashes);
361 for (auto& origin : parameters.plugInAutoStartOrigins)
362 m_plugInAutoStartOrigins.add(origin);
364 setMemoryCacheDisabled(parameters.memoryCacheDisabled);
366 #if ENABLE(SERVICE_CONTROLS)
367 setEnabledServices(parameters.hasImageServices, parameters.hasSelectionServices, parameters.hasRichContentServices);
370 #if ENABLE(REMOTE_INSPECTOR)
371 audit_token_t auditToken;
372 if (parentProcessConnection()->getAuditToken(auditToken)) {
373 RetainPtr<CFDataRef> auditData = adoptCF(CFDataCreate(nullptr, (const UInt8*)&auditToken, sizeof(auditToken)));
374 Inspector::RemoteInspector::singleton().setParentProcessInformation(presenterApplicationPid(), auditData);
378 #if ENABLE(NETSCAPE_PLUGIN_API) && PLATFORM(MAC)
379 for (auto hostIter = parameters.pluginLoadClientPolicies.begin(); hostIter != parameters.pluginLoadClientPolicies.end(); ++hostIter) {
380 for (auto bundleIdentifierIter = hostIter->value.begin(); bundleIdentifierIter != hostIter->value.end(); ++bundleIdentifierIter) {
381 for (auto versionIter = bundleIdentifierIter->value.begin(); versionIter != bundleIdentifierIter->value.end(); ++versionIter)
382 platformStrategies()->pluginStrategy()->setPluginLoadClientPolicy(static_cast<PluginLoadClientPolicy>(versionIter->value), hostIter->key, bundleIdentifierIter->key, versionIter->key);
388 void WebProcess::ensureNetworkProcessConnection()
390 if (!m_usesNetworkProcess)
393 if (m_networkProcessConnection)
396 IPC::Attachment encodedConnectionIdentifier;
398 if (!parentProcessConnection()->sendSync(Messages::WebProcessProxy::GetNetworkProcessConnection(),
399 Messages::WebProcessProxy::GetNetworkProcessConnection::Reply(encodedConnectionIdentifier), 0))
402 #if USE(UNIX_DOMAIN_SOCKETS)
403 IPC::Connection::Identifier connectionIdentifier = encodedConnectionIdentifier.releaseFileDescriptor();
405 IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.port());
407 ASSERT_NOT_REACHED();
409 if (IPC::Connection::identifierIsNull(connectionIdentifier))
411 m_networkProcessConnection = NetworkProcessConnection::create(connectionIdentifier);
414 void WebProcess::registerURLSchemeAsEmptyDocument(const String& urlScheme)
416 SchemeRegistry::registerURLSchemeAsEmptyDocument(urlScheme);
419 void WebProcess::registerURLSchemeAsSecure(const String& urlScheme) const
421 SchemeRegistry::registerURLSchemeAsSecure(urlScheme);
424 void WebProcess::registerURLSchemeAsBypassingContentSecurityPolicy(const String& urlScheme) const
426 SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(urlScheme);
429 void WebProcess::setDomainRelaxationForbiddenForURLScheme(const String& urlScheme) const
431 SchemeRegistry::setDomainRelaxationForbiddenForURLScheme(true, urlScheme);
434 void WebProcess::registerURLSchemeAsLocal(const String& urlScheme) const
436 SchemeRegistry::registerURLSchemeAsLocal(urlScheme);
439 void WebProcess::registerURLSchemeAsNoAccess(const String& urlScheme) const
441 SchemeRegistry::registerURLSchemeAsNoAccess(urlScheme);
444 void WebProcess::registerURLSchemeAsDisplayIsolated(const String& urlScheme) const
446 SchemeRegistry::registerURLSchemeAsDisplayIsolated(urlScheme);
449 void WebProcess::registerURLSchemeAsCORSEnabled(const String& urlScheme) const
451 SchemeRegistry::registerURLSchemeAsCORSEnabled(urlScheme);
454 #if ENABLE(CACHE_PARTITIONING)
455 void WebProcess::registerURLSchemeAsCachePartitioned(const String& urlScheme) const
457 SchemeRegistry::registerURLSchemeAsCachePartitioned(urlScheme);
461 void WebProcess::setDefaultRequestTimeoutInterval(double timeoutInterval)
463 ResourceRequest::setDefaultTimeoutInterval(timeoutInterval);
466 void WebProcess::setAlwaysUsesComplexTextCodePath(bool alwaysUseComplexText)
468 WebCore::FontCascade::setCodePath(alwaysUseComplexText ? WebCore::FontCascade::Complex : WebCore::FontCascade::Auto);
471 void WebProcess::setShouldUseFontSmoothing(bool useFontSmoothing)
473 WebCore::FontCascade::setShouldUseSmoothing(useFontSmoothing);
476 void WebProcess::userPreferredLanguagesChanged(const Vector<String>& languages) const
478 overrideUserPreferredLanguages(languages);
482 void WebProcess::fullKeyboardAccessModeChanged(bool fullKeyboardAccessEnabled)
484 m_fullKeyboardAccessEnabled = fullKeyboardAccessEnabled;
487 void WebProcess::ensurePrivateBrowsingSession(SessionID sessionID)
489 #if PLATFORM(COCOA) || USE(CFNETWORK) || USE(SOUP)
490 WebFrameNetworkingContext::ensurePrivateBrowsingSession(sessionID);
494 void WebProcess::destroyPrivateBrowsingSession(SessionID sessionID)
496 #if PLATFORM(COCOA) || USE(CFNETWORK) || USE(SOUP)
497 SessionTracker::destroySession(sessionID);
501 DownloadManager& WebProcess::downloadManager()
503 ASSERT(!usesNetworkProcess());
505 static NeverDestroyed<DownloadManager> downloadManager(this);
506 return downloadManager;
509 #if ENABLE(NETSCAPE_PLUGIN_API)
510 PluginProcessConnectionManager& WebProcess::pluginProcessConnectionManager()
512 return *m_pluginProcessConnectionManager;
516 void WebProcess::setCacheModel(uint32_t cm)
518 CacheModel cacheModel = static_cast<CacheModel>(cm);
520 if (!m_hasSetCacheModel || cacheModel != m_cacheModel) {
521 m_hasSetCacheModel = true;
522 m_cacheModel = cacheModel;
523 platformSetCacheModel(cacheModel);
527 WebPage* WebProcess::focusedWebPage() const
529 for (auto& page : m_pageMap.values()) {
530 if (page->windowAndWebPageAreFocused())
536 WebPage* WebProcess::webPage(uint64_t pageID) const
538 return m_pageMap.get(pageID);
541 void WebProcess::createWebPage(uint64_t pageID, const WebPageCreationParameters& parameters)
543 // It is necessary to check for page existence here since during a window.open() (or targeted
544 // link) the WebPage gets created both in the synchronous handler and through the normal way.
545 HashMap<uint64_t, RefPtr<WebPage>>::AddResult result = m_pageMap.add(pageID, nullptr);
546 if (result.isNewEntry) {
547 ASSERT(!result.iterator->value);
548 result.iterator->value = WebPage::create(pageID, parameters);
550 // Balanced by an enableTermination in removeWebPage.
551 disableTermination();
553 result.iterator->value->reinitializeWebPage(parameters);
555 ASSERT(result.iterator->value);
558 void WebProcess::removeWebPage(uint64_t pageID)
560 ASSERT(m_pageMap.contains(pageID));
562 pageWillLeaveWindow(pageID);
563 m_pageMap.remove(pageID);
568 bool WebProcess::shouldTerminate()
570 ASSERT(m_pageMap.isEmpty());
571 ASSERT(usesNetworkProcess() || !downloadManager().isDownloading());
573 // FIXME: the ShouldTerminate message should also send termination parameters, such as any session cookies that need to be preserved.
574 bool shouldTerminate = false;
575 if (parentProcessConnection()->sendSync(Messages::WebProcessProxy::ShouldTerminate(), Messages::WebProcessProxy::ShouldTerminate::Reply(shouldTerminate), 0)
582 void WebProcess::terminate()
585 GCController::singleton().garbageCollectNow();
586 FontCache::singleton().invalidate();
587 MemoryCache::singleton().setDisabled(true);
590 m_webConnection->invalidate();
591 m_webConnection = nullptr;
595 ChildProcess::terminate();
598 void WebProcess::didReceiveSyncMessage(IPC::Connection& connection, IPC::MessageDecoder& decoder, std::unique_ptr<IPC::MessageEncoder>& replyEncoder)
600 if (messageReceiverMap().dispatchSyncMessage(connection, decoder, replyEncoder))
603 didReceiveSyncWebProcessMessage(connection, decoder, replyEncoder);
606 void WebProcess::didReceiveMessage(IPC::Connection& connection, IPC::MessageDecoder& decoder)
608 if (messageReceiverMap().dispatchMessage(connection, decoder))
611 if (decoder.messageReceiverName() == Messages::WebProcess::messageReceiverName()) {
612 didReceiveWebProcessMessage(connection, decoder);
616 if (decoder.messageReceiverName() == Messages::WebPageGroupProxy::messageReceiverName()) {
617 uint64_t pageGroupID = decoder.destinationID();
621 WebPageGroupProxy* pageGroupProxy = webPageGroup(pageGroupID);
625 pageGroupProxy->didReceiveMessage(connection, decoder);
629 if (decoder.messageReceiverName() == Messages::ChildProcess::messageReceiverName()) {
630 ChildProcess::didReceiveMessage(connection, decoder);
634 LOG_ERROR("Unhandled web process message '%s:%s'", decoder.messageReceiverName().toString().data(), decoder.messageName().toString().data());
637 void WebProcess::didClose(IPC::Connection&)
642 // Close all the live pages.
643 Vector<RefPtr<WebPage>> pages;
644 copyValuesToVector(m_pageMap, pages);
645 for (auto& page : pages)
649 GCController::singleton().garbageCollectSoon();
650 FontCache::singleton().invalidate();
651 MemoryCache::singleton().setDisabled(true);
655 // FIXME(146657): This explicit media stop command should not be necessary
656 if (auto* platformMediaSessionManager = PlatformMediaSessionManager::sharedManagerIfExists())
657 platformMediaSessionManager->stopAllMediaPlaybackForProcess();
660 // The UI process closed this connection, shut down.
664 void WebProcess::didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference, IPC::StringReference)
666 // We received an invalid message, but since this is from the UI process (which we trust),
667 // we'll let it slide.
670 WebFrame* WebProcess::webFrame(uint64_t frameID) const
672 return m_frameMap.get(frameID);
675 void WebProcess::addWebFrame(uint64_t frameID, WebFrame* frame)
677 m_frameMap.set(frameID, frame);
680 void WebProcess::removeWebFrame(uint64_t frameID)
682 m_frameMap.remove(frameID);
684 // We can end up here after our connection has closed when WebCore's frame life-support timer
685 // fires when the application is shutting down. There's no need (and no way) to update the UI
686 // process in this case.
687 if (!parentProcessConnection())
690 parentProcessConnection()->send(Messages::WebProcessProxy::DidDestroyFrame(frameID), 0);
693 WebPageGroupProxy* WebProcess::webPageGroup(PageGroup* pageGroup)
695 for (auto& page : m_pageGroupMap.values()) {
696 if (page->corePageGroup() == pageGroup)
703 WebPageGroupProxy* WebProcess::webPageGroup(uint64_t pageGroupID)
705 return m_pageGroupMap.get(pageGroupID);
708 WebPageGroupProxy* WebProcess::webPageGroup(const WebPageGroupData& pageGroupData)
710 auto result = m_pageGroupMap.add(pageGroupData.pageGroupID, nullptr);
711 if (result.isNewEntry) {
712 ASSERT(!result.iterator->value);
713 result.iterator->value = WebPageGroupProxy::create(pageGroupData);
716 return result.iterator->value.get();
719 void WebProcess::clearResourceCaches(ResourceCachesToClear resourceCachesToClear)
721 platformClearResourceCaches(resourceCachesToClear);
723 // Toggling the cache model like this forces the cache to evict all its in-memory resources.
724 // FIXME: We need a better way to do this.
725 CacheModel cacheModel = m_cacheModel;
726 setCacheModel(CacheModelDocumentViewer);
727 setCacheModel(cacheModel);
729 MemoryCache::singleton().evictResources();
731 // Empty the cross-origin preflight cache.
732 CrossOriginPreflightResultCache::singleton().empty();
735 void WebProcess::clearApplicationCache()
737 // Empty the application cache.
738 ApplicationCacheStorage::singleton().empty();
741 static inline void addCaseFoldedCharacters(StringHasher& hasher, const String& string)
743 if (string.isEmpty())
745 if (string.is8Bit()) {
746 hasher.addCharacters<LChar, CaseFoldingHash::foldCase<LChar>>(string.characters8(), string.length());
749 hasher.addCharacters<UChar, CaseFoldingHash::foldCase<UChar>>(string.characters16(), string.length());
752 static unsigned hashForPlugInOrigin(const String& pageOrigin, const String& pluginOrigin, const String& mimeType)
754 // We want to avoid concatenating the strings and then taking the hash, since that could lead to an expensive conversion.
755 // We also want to avoid using the hash() function in StringImpl or CaseFoldingHash because that masks out bits for the use of flags.
757 addCaseFoldedCharacters(hasher, pageOrigin);
758 hasher.addCharacter(0);
759 addCaseFoldedCharacters(hasher, pluginOrigin);
760 hasher.addCharacter(0);
761 addCaseFoldedCharacters(hasher, mimeType);
762 return hasher.hash();
765 bool WebProcess::isPlugInAutoStartOriginHash(unsigned plugInOriginHash, SessionID sessionID)
767 HashMap<WebCore::SessionID, HashMap<unsigned, double>>::const_iterator sessionIterator = m_plugInAutoStartOriginHashes.find(sessionID);
768 HashMap<unsigned, double>::const_iterator it;
769 bool contains = false;
771 if (sessionIterator != m_plugInAutoStartOriginHashes.end()) {
772 it = sessionIterator->value.find(plugInOriginHash);
773 contains = it != sessionIterator->value.end();
776 sessionIterator = m_plugInAutoStartOriginHashes.find(SessionID::defaultSessionID());
777 it = sessionIterator->value.find(plugInOriginHash);
778 if (it == sessionIterator->value.end())
781 return currentTime() < it->value;
784 bool WebProcess::shouldPlugInAutoStartFromOrigin(WebPage& webPage, const String& pageOrigin, const String& pluginOrigin, const String& mimeType)
786 if (!pluginOrigin.isEmpty() && m_plugInAutoStartOrigins.contains(pluginOrigin))
789 #ifdef ENABLE_PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC
790 // 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).
791 if (webPage.matchesPrimaryPlugIn(pageOrigin, pluginOrigin, mimeType))
794 UNUSED_PARAM(webPage);
797 // Lastly check against the more explicit hash list.
798 return isPlugInAutoStartOriginHash(hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType), webPage.sessionID());
801 void WebProcess::plugInDidStartFromOrigin(const String& pageOrigin, const String& pluginOrigin, const String& mimeType, SessionID sessionID)
803 if (pageOrigin.isEmpty()) {
804 LOG(Plugins, "Not adding empty page origin");
808 unsigned plugInOriginHash = hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType);
809 if (isPlugInAutoStartOriginHash(plugInOriginHash, sessionID)) {
810 LOG(Plugins, "Hash %x already exists as auto-start origin (request for %s)", plugInOriginHash, pageOrigin.utf8().data());
814 // We might attempt to start another plugin before the didAddPlugInAutoStartOrigin message
815 // comes back from the parent process. Temporarily add this hash to the list with a thirty
816 // second timeout. That way, even if the parent decides not to add it, we'll only be
817 // incorrect for a little while.
818 m_plugInAutoStartOriginHashes.add(sessionID, HashMap<unsigned, double>()).iterator->value.set(plugInOriginHash, currentTime() + 30 * 1000);
820 parentProcessConnection()->send(Messages::WebProcessPool::AddPlugInAutoStartOriginHash(pageOrigin, plugInOriginHash, sessionID), 0);
823 void WebProcess::didAddPlugInAutoStartOriginHash(unsigned plugInOriginHash, double expirationTime, SessionID sessionID)
825 // When called, some web process (which also might be this one) added the origin for auto-starting,
826 // or received user interaction.
827 // Set the bit to avoid having redundantly call into the UI process upon user interaction.
828 m_plugInAutoStartOriginHashes.add(sessionID, HashMap<unsigned, double>()).iterator->value.set(plugInOriginHash, expirationTime);
831 void WebProcess::resetPlugInAutoStartOriginDefaultHashes(const HashMap<unsigned, double>& hashes)
833 m_plugInAutoStartOriginHashes.clear();
834 m_plugInAutoStartOriginHashes.add(SessionID::defaultSessionID(), HashMap<unsigned, double>()).iterator->value.swap(const_cast<HashMap<unsigned, double>&>(hashes));
837 void WebProcess::resetPlugInAutoStartOriginHashes(const HashMap<SessionID, HashMap<unsigned, double>>& hashes)
839 m_plugInAutoStartOriginHashes.swap(const_cast<HashMap<SessionID, HashMap<unsigned, double>>&>(hashes));
842 void WebProcess::plugInDidReceiveUserInteraction(const String& pageOrigin, const String& pluginOrigin, const String& mimeType, SessionID sessionID)
844 if (pageOrigin.isEmpty())
847 unsigned plugInOriginHash = hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType);
848 if (!plugInOriginHash)
851 HashMap<WebCore::SessionID, HashMap<unsigned, double>>::const_iterator sessionIterator = m_plugInAutoStartOriginHashes.find(sessionID);
852 HashMap<unsigned, double>::const_iterator it;
853 bool contains = false;
854 if (sessionIterator != m_plugInAutoStartOriginHashes.end()) {
855 it = sessionIterator->value.find(plugInOriginHash);
856 contains = it != sessionIterator->value.end();
859 sessionIterator = m_plugInAutoStartOriginHashes.find(SessionID::defaultSessionID());
860 it = sessionIterator->value.find(plugInOriginHash);
861 if (it == sessionIterator->value.end())
865 if (it->value - currentTime() > plugInAutoStartExpirationTimeUpdateThreshold)
868 parentProcessConnection()->send(Messages::WebProcessPool::PlugInDidReceiveUserInteraction(plugInOriginHash, sessionID), 0);
871 void WebProcess::setPluginLoadClientPolicy(uint8_t policy, const String& host, const String& bundleIdentifier, const String& versionString)
873 #if ENABLE(NETSCAPE_PLUGIN_API) && PLATFORM(MAC)
874 platformStrategies()->pluginStrategy()->setPluginLoadClientPolicy(static_cast<PluginLoadClientPolicy>(policy), host, bundleIdentifier, versionString);
878 void WebProcess::clearPluginClientPolicies()
880 #if ENABLE(NETSCAPE_PLUGIN_API) && PLATFORM(MAC)
881 platformStrategies()->pluginStrategy()->clearPluginClientPolicies();
885 static void fromCountedSetToHashMap(TypeCountSet* countedSet, HashMap<String, uint64_t>& map)
887 TypeCountSet::const_iterator end = countedSet->end();
888 for (TypeCountSet::const_iterator it = countedSet->begin(); it != end; ++it)
889 map.set(it->key, it->value);
892 static void getWebCoreMemoryCacheStatistics(Vector<HashMap<String, uint64_t>>& result)
894 String imagesString(ASCIILiteral("Images"));
895 String cssString(ASCIILiteral("CSS"));
896 String xslString(ASCIILiteral("XSL"));
897 String javaScriptString(ASCIILiteral("JavaScript"));
899 MemoryCache::Statistics memoryCacheStatistics = MemoryCache::singleton().getStatistics();
901 HashMap<String, uint64_t> counts;
902 counts.set(imagesString, memoryCacheStatistics.images.count);
903 counts.set(cssString, memoryCacheStatistics.cssStyleSheets.count);
904 counts.set(xslString, memoryCacheStatistics.xslStyleSheets.count);
905 counts.set(javaScriptString, memoryCacheStatistics.scripts.count);
906 result.append(counts);
908 HashMap<String, uint64_t> sizes;
909 sizes.set(imagesString, memoryCacheStatistics.images.size);
910 sizes.set(cssString, memoryCacheStatistics.cssStyleSheets.size);
911 sizes.set(xslString, memoryCacheStatistics.xslStyleSheets.size);
912 sizes.set(javaScriptString, memoryCacheStatistics.scripts.size);
913 result.append(sizes);
915 HashMap<String, uint64_t> liveSizes;
916 liveSizes.set(imagesString, memoryCacheStatistics.images.liveSize);
917 liveSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.liveSize);
918 liveSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.liveSize);
919 liveSizes.set(javaScriptString, memoryCacheStatistics.scripts.liveSize);
920 result.append(liveSizes);
922 HashMap<String, uint64_t> decodedSizes;
923 decodedSizes.set(imagesString, memoryCacheStatistics.images.decodedSize);
924 decodedSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.decodedSize);
925 decodedSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.decodedSize);
926 decodedSizes.set(javaScriptString, memoryCacheStatistics.scripts.decodedSize);
927 result.append(decodedSizes);
930 void WebProcess::getWebCoreStatistics(uint64_t callbackID)
934 // Gather JavaScript statistics.
936 JSLockHolder lock(JSDOMWindow::commonVM());
937 data.statisticsNumbers.set(ASCIILiteral("JavaScriptObjectsCount"), JSDOMWindow::commonVM().heap.objectCount());
938 data.statisticsNumbers.set(ASCIILiteral("JavaScriptGlobalObjectsCount"), JSDOMWindow::commonVM().heap.globalObjectCount());
939 data.statisticsNumbers.set(ASCIILiteral("JavaScriptProtectedObjectsCount"), JSDOMWindow::commonVM().heap.protectedObjectCount());
940 data.statisticsNumbers.set(ASCIILiteral("JavaScriptProtectedGlobalObjectsCount"), JSDOMWindow::commonVM().heap.protectedGlobalObjectCount());
942 std::unique_ptr<TypeCountSet> protectedObjectTypeCounts(JSDOMWindow::commonVM().heap.protectedObjectTypeCounts());
943 fromCountedSetToHashMap(protectedObjectTypeCounts.get(), data.javaScriptProtectedObjectTypeCounts);
945 std::unique_ptr<TypeCountSet> objectTypeCounts(JSDOMWindow::commonVM().heap.objectTypeCounts());
946 fromCountedSetToHashMap(objectTypeCounts.get(), data.javaScriptObjectTypeCounts);
948 uint64_t javaScriptHeapSize = JSDOMWindow::commonVM().heap.size();
949 data.statisticsNumbers.set(ASCIILiteral("JavaScriptHeapSize"), javaScriptHeapSize);
950 data.statisticsNumbers.set(ASCIILiteral("JavaScriptFreeSize"), JSDOMWindow::commonVM().heap.capacity() - javaScriptHeapSize);
953 WTF::FastMallocStatistics fastMallocStatistics = WTF::fastMallocStatistics();
954 data.statisticsNumbers.set(ASCIILiteral("FastMallocReservedVMBytes"), fastMallocStatistics.reservedVMBytes);
955 data.statisticsNumbers.set(ASCIILiteral("FastMallocCommittedVMBytes"), fastMallocStatistics.committedVMBytes);
956 data.statisticsNumbers.set(ASCIILiteral("FastMallocFreeListBytes"), fastMallocStatistics.freeListBytes);
958 // Gather icon statistics.
959 data.statisticsNumbers.set(ASCIILiteral("IconPageURLMappingCount"), iconDatabase().pageURLMappingCount());
960 data.statisticsNumbers.set(ASCIILiteral("IconRetainedPageURLCount"), iconDatabase().retainedPageURLCount());
961 data.statisticsNumbers.set(ASCIILiteral("IconRecordCount"), iconDatabase().iconRecordCount());
962 data.statisticsNumbers.set(ASCIILiteral("IconsWithDataCount"), iconDatabase().iconRecordCountWithData());
964 // Gather font statistics.
965 auto& fontCache = FontCache::singleton();
966 data.statisticsNumbers.set(ASCIILiteral("CachedFontDataCount"), fontCache.fontCount());
967 data.statisticsNumbers.set(ASCIILiteral("CachedFontDataInactiveCount"), fontCache.inactiveFontCount());
969 // Gather glyph page statistics.
970 data.statisticsNumbers.set(ASCIILiteral("GlyphPageCount"), GlyphPage::count());
972 // Get WebCore memory cache statistics
973 getWebCoreMemoryCacheStatistics(data.webCoreCacheStatistics);
975 parentProcessConnection()->send(Messages::WebProcessPool::DidGetStatistics(data, callbackID), 0);
978 void WebProcess::garbageCollectJavaScriptObjects()
980 GCController::singleton().garbageCollectNow();
983 void WebProcess::mainThreadPing()
985 parentProcessConnection()->send(Messages::WebProcessProxy::DidReceiveMainThreadPing(), 0);
988 void WebProcess::setJavaScriptGarbageCollectorTimerEnabled(bool flag)
990 GCController::singleton().setJavaScriptGarbageCollectorTimerEnabled(flag);
993 void WebProcess::handleInjectedBundleMessage(const String& messageName, const UserData& messageBody)
995 InjectedBundle* injectedBundle = WebProcess::singleton().injectedBundle();
999 injectedBundle->didReceiveMessage(messageName, transformHandlesToObjects(messageBody.object()).get());
1002 void WebProcess::setInjectedBundleParameter(const String& key, const IPC::DataReference& value)
1004 InjectedBundle* injectedBundle = WebProcess::singleton().injectedBundle();
1005 if (!injectedBundle)
1008 injectedBundle->setBundleParameter(key, value);
1011 void WebProcess::setInjectedBundleParameters(const IPC::DataReference& value)
1013 InjectedBundle* injectedBundle = WebProcess::singleton().injectedBundle();
1014 if (!injectedBundle)
1017 injectedBundle->setBundleParameters(value);
1020 bool WebProcess::usesNetworkProcess() const
1022 return m_usesNetworkProcess;
1025 NetworkProcessConnection* WebProcess::networkConnection()
1027 ASSERT(m_usesNetworkProcess);
1029 // If we've lost our connection to the network process (e.g. it crashed) try to re-establish it.
1030 if (!m_networkProcessConnection)
1031 ensureNetworkProcessConnection();
1033 // If we failed to re-establish it then we are beyond recovery and should crash.
1034 if (!m_networkProcessConnection)
1037 return m_networkProcessConnection.get();
1040 void WebProcess::networkProcessConnectionClosed(NetworkProcessConnection* connection)
1042 ASSERT(m_networkProcessConnection);
1043 ASSERT_UNUSED(connection, m_networkProcessConnection == connection);
1045 m_networkProcessConnection = nullptr;
1047 m_webResourceLoadScheduler->networkProcessCrashed();
1050 WebResourceLoadScheduler& WebProcess::webResourceLoadScheduler()
1052 return *m_webResourceLoadScheduler;
1055 #if ENABLE(DATABASE_PROCESS)
1056 void WebProcess::webToDatabaseProcessConnectionClosed(WebToDatabaseProcessConnection* connection)
1058 ASSERT(m_webToDatabaseProcessConnection);
1059 ASSERT(m_webToDatabaseProcessConnection == connection);
1061 m_webToDatabaseProcessConnection = nullptr;
1064 WebToDatabaseProcessConnection* WebProcess::webToDatabaseProcessConnection()
1066 if (!m_webToDatabaseProcessConnection)
1067 ensureWebToDatabaseProcessConnection();
1069 return m_webToDatabaseProcessConnection.get();
1072 void WebProcess::ensureWebToDatabaseProcessConnection()
1074 if (m_webToDatabaseProcessConnection)
1077 IPC::Attachment encodedConnectionIdentifier;
1079 if (!parentProcessConnection()->sendSync(Messages::WebProcessProxy::GetDatabaseProcessConnection(),
1080 Messages::WebProcessProxy::GetDatabaseProcessConnection::Reply(encodedConnectionIdentifier), 0))
1083 #if USE(UNIX_DOMAIN_SOCKETS)
1084 IPC::Connection::Identifier connectionIdentifier = encodedConnectionIdentifier.releaseFileDescriptor();
1086 IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.port());
1088 ASSERT_NOT_REACHED();
1090 if (IPC::Connection::identifierIsNull(connectionIdentifier))
1092 m_webToDatabaseProcessConnection = WebToDatabaseProcessConnection::create(connectionIdentifier);
1095 #endif // ENABLED(DATABASE_PROCESS)
1097 void WebProcess::downloadRequest(SessionID sessionID, uint64_t downloadID, uint64_t initiatingPageID, const ResourceRequest& request)
1099 WebPage* initiatingPage = initiatingPageID ? webPage(initiatingPageID) : 0;
1101 ResourceRequest requestWithOriginalURL = request;
1103 initiatingPage->mainFrame()->loader().setOriginalURLForDownloadRequest(requestWithOriginalURL);
1105 downloadManager().startDownload(sessionID, downloadID, requestWithOriginalURL);
1108 void WebProcess::resumeDownload(uint64_t downloadID, const IPC::DataReference& resumeData, const String& path, const WebKit::SandboxExtension::Handle& sandboxExtensionHandle)
1110 downloadManager().resumeDownload(downloadID, resumeData, path, sandboxExtensionHandle);
1113 void WebProcess::cancelDownload(uint64_t downloadID)
1115 downloadManager().cancelDownload(downloadID);
1118 void WebProcess::setEnhancedAccessibility(bool flag)
1120 WebCore::AXObjectCache::setEnhancedUserInterfaceAccessibility(flag);
1123 void WebProcess::startMemorySampler(const SandboxExtension::Handle& sampleLogFileHandle, const String& sampleLogFilePath, const double interval)
1125 #if ENABLE(MEMORY_SAMPLER)
1126 WebMemorySampler::singleton()->start(sampleLogFileHandle, sampleLogFilePath, interval);
1128 UNUSED_PARAM(sampleLogFileHandle);
1129 UNUSED_PARAM(sampleLogFilePath);
1130 UNUSED_PARAM(interval);
1134 void WebProcess::stopMemorySampler()
1136 #if ENABLE(MEMORY_SAMPLER)
1137 WebMemorySampler::singleton()->stop();
1141 void WebProcess::setTextCheckerState(const TextCheckerState& textCheckerState)
1143 bool continuousSpellCheckingTurnedOff = !textCheckerState.isContinuousSpellCheckingEnabled && m_textCheckerState.isContinuousSpellCheckingEnabled;
1144 bool grammarCheckingTurnedOff = !textCheckerState.isGrammarCheckingEnabled && m_textCheckerState.isGrammarCheckingEnabled;
1146 m_textCheckerState = textCheckerState;
1148 if (!continuousSpellCheckingTurnedOff && !grammarCheckingTurnedOff)
1151 for (auto& page : m_pageMap.values()) {
1152 if (continuousSpellCheckingTurnedOff)
1153 page->unmarkAllMisspellings();
1154 if (grammarCheckingTurnedOff)
1155 page->unmarkAllBadGrammar();
1159 void WebProcess::releasePageCache()
1161 PageCache::singleton().pruneToSizeNow(0, PruningReason::MemoryPressure);
1164 void WebProcess::fetchWebsiteData(SessionID sessionID, uint64_t websiteDataTypes, uint64_t callbackID)
1166 WebsiteData websiteData;
1168 if (websiteDataTypes & WebsiteDataTypeMemoryCache) {
1169 for (auto& origin : MemoryCache::singleton().originsWithCache(sessionID))
1170 websiteData.entries.append(WebsiteData::Entry { origin, WebsiteDataTypeMemoryCache });
1173 parentProcessConnection()->send(Messages::WebProcessProxy::DidFetchWebsiteData(callbackID, websiteData), 0);
1176 void WebProcess::deleteWebsiteData(SessionID sessionID, uint64_t websiteDataTypes, std::chrono::system_clock::time_point modifiedSince, uint64_t callbackID)
1178 UNUSED_PARAM(modifiedSince);
1180 if (websiteDataTypes & WebsiteDataTypeMemoryCache) {
1181 PageCache::singleton().pruneToSizeNow(0, PruningReason::None);
1182 MemoryCache::singleton().evictResources(sessionID);
1184 CrossOriginPreflightResultCache::singleton().empty();
1187 parentProcessConnection()->send(Messages::WebProcessProxy::DidDeleteWebsiteData(callbackID), 0);
1190 void WebProcess::deleteWebsiteDataForOrigins(WebCore::SessionID sessionID, uint64_t websiteDataTypes, const Vector<WebCore::SecurityOriginData>& originDatas, uint64_t callbackID)
1192 if (websiteDataTypes & WebsiteDataTypeMemoryCache) {
1193 HashSet<RefPtr<SecurityOrigin>> origins;
1194 for (auto& originData : originDatas)
1195 origins.add(originData.securityOrigin());
1197 MemoryCache::singleton().removeResourcesWithOrigins(sessionID, origins);
1200 parentProcessConnection()->send(Messages::WebProcessProxy::DidDeleteWebsiteDataForOrigins(callbackID), 0);
1203 #if !PLATFORM(COCOA)
1204 void WebProcess::initializeProcessName(const ChildProcessInitializationParameters&)
1208 void WebProcess::initializeSandbox(const ChildProcessInitializationParameters&, SandboxInitializationParameters&)
1212 void WebProcess::platformInitializeProcess(const ChildProcessInitializationParameters&)
1216 void WebProcess::updateActivePages()
1223 void WebProcess::resetAllGeolocationPermissions()
1225 for (auto& page : m_pageMap.values()) {
1226 if (Frame* mainFrame = page->mainFrame())
1227 mainFrame->resetAllGeolocationPermission();
1232 void WebProcess::actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend shouldAcknowledgeWhenReadyToSuspend)
1234 MemoryPressureHandler::singleton().releaseMemory(Critical::Yes, Synchronous::Yes);
1235 setAllLayerTreeStatesFrozen(true);
1237 if (markAllLayersVolatileIfPossible()) {
1238 if (shouldAcknowledgeWhenReadyToSuspend == ShouldAcknowledgeWhenReadyToSuspend::Yes)
1239 parentProcessConnection()->send(Messages::WebProcessProxy::ProcessReadyToSuspend(), 0);
1242 m_shouldAcknowledgeWhenReadyToSuspend = shouldAcknowledgeWhenReadyToSuspend;
1243 m_processSuspensionCleanupTimer.startRepeating(std::chrono::milliseconds(20));
1246 void WebProcess::processWillSuspendImminently(bool& handled)
1248 if (parentProcessConnection()->inSendSync()) {
1249 // Avoid reentrency bugs such as rdar://problem/21605505 by just bailing
1250 // if we get an incoming ProcessWillSuspendImminently message when waiting for a
1251 // reply to a sync message.
1252 // FIXME: ProcessWillSuspendImminently should not be a sync message.
1256 supplement<WebDatabaseManager>()->closeAllDatabases();
1257 actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::No);
1261 void WebProcess::prepareToSuspend()
1263 actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::Yes);
1266 void WebProcess::cancelPrepareToSuspend()
1268 setAllLayerTreeStatesFrozen(false);
1270 // If we've already finished cleaning up and sent ProcessReadyToSuspend, we
1271 // shouldn't send DidCancelProcessSuspension; the UI process strictly expects one or the other.
1272 if (!m_processSuspensionCleanupTimer.isActive())
1275 m_processSuspensionCleanupTimer.stop();
1276 parentProcessConnection()->send(Messages::WebProcessProxy::DidCancelProcessSuspension(), 0);
1279 bool WebProcess::markAllLayersVolatileIfPossible()
1281 bool successfullyMarkedAllLayersVolatile = true;
1282 for (auto& page : m_pageMap.values())
1283 successfullyMarkedAllLayersVolatile &= page->markLayersVolatileImmediatelyIfPossible();
1285 return successfullyMarkedAllLayersVolatile;
1288 void WebProcess::setAllLayerTreeStatesFrozen(bool frozen)
1290 for (auto& page : m_pageMap.values())
1291 page->setLayerTreeStateIsFrozen(frozen);
1294 void WebProcess::processSuspensionCleanupTimerFired()
1296 if (!markAllLayersVolatileIfPossible())
1298 m_processSuspensionCleanupTimer.stop();
1299 if (m_shouldAcknowledgeWhenReadyToSuspend == ShouldAcknowledgeWhenReadyToSuspend::Yes)
1300 parentProcessConnection()->send(Messages::WebProcessProxy::ProcessReadyToSuspend(), 0);
1303 void WebProcess::processDidResume()
1305 m_processSuspensionCleanupTimer.stop();
1306 setAllLayerTreeStatesFrozen(false);
1309 void WebProcess::pageDidEnterWindow(uint64_t pageID)
1311 m_pagesInWindows.add(pageID);
1312 m_nonVisibleProcessCleanupTimer.stop();
1315 void WebProcess::pageWillLeaveWindow(uint64_t pageID)
1317 m_pagesInWindows.remove(pageID);
1319 if (m_pagesInWindows.isEmpty() && !m_nonVisibleProcessCleanupTimer.isActive())
1320 m_nonVisibleProcessCleanupTimer.startOneShot(nonVisibleProcessCleanupDelay);
1323 void WebProcess::nonVisibleProcessCleanupTimerFired()
1325 ASSERT(m_pagesInWindows.isEmpty());
1326 if (!m_pagesInWindows.isEmpty())
1330 destroyRenderingResources();
1334 RefPtr<API::Object> WebProcess::transformHandlesToObjects(API::Object* object)
1336 struct Transformer final : UserData::Transformer {
1337 Transformer(WebProcess& webProcess)
1338 : m_webProcess(webProcess)
1342 virtual bool shouldTransformObject(const API::Object& object) const override
1344 switch (object.type()) {
1345 case API::Object::Type::FrameHandle:
1346 return static_cast<const API::FrameHandle&>(object).isAutoconverting();
1348 case API::Object::Type::PageHandle:
1349 return static_cast<const API::PageHandle&>(object).isAutoconverting();
1351 case API::Object::Type::PageGroupHandle:
1353 case API::Object::Type::ObjCObjectGraph:
1362 virtual RefPtr<API::Object> transformObject(API::Object& object) const override
1364 switch (object.type()) {
1365 case API::Object::Type::FrameHandle:
1366 return m_webProcess.webFrame(static_cast<const API::FrameHandle&>(object).frameID());
1368 case API::Object::Type::PageGroupHandle:
1369 return m_webProcess.webPageGroup(static_cast<const API::PageGroupHandle&>(object).webPageGroupData());
1371 case API::Object::Type::PageHandle:
1372 return m_webProcess.webPage(static_cast<const API::PageHandle&>(object).pageID());
1375 case API::Object::Type::ObjCObjectGraph:
1376 return m_webProcess.transformHandlesToObjects(static_cast<ObjCObjectGraph&>(object));
1383 WebProcess& m_webProcess;
1386 return UserData::transform(object, Transformer(*this));
1389 RefPtr<API::Object> WebProcess::transformObjectsToHandles(API::Object* object)
1391 struct Transformer final : UserData::Transformer {
1392 virtual bool shouldTransformObject(const API::Object& object) const override
1394 switch (object.type()) {
1395 case API::Object::Type::BundleFrame:
1396 case API::Object::Type::BundlePage:
1397 case API::Object::Type::BundlePageGroup:
1399 case API::Object::Type::ObjCObjectGraph:
1408 virtual RefPtr<API::Object> transformObject(API::Object& object) const override
1410 switch (object.type()) {
1411 case API::Object::Type::BundleFrame:
1412 return API::FrameHandle::createAutoconverting(static_cast<const WebFrame&>(object).frameID());
1414 case API::Object::Type::BundlePage:
1415 return API::PageHandle::createAutoconverting(static_cast<const WebPage&>(object).pageID());
1417 case API::Object::Type::BundlePageGroup: {
1418 WebPageGroupData pageGroupData;
1419 pageGroupData.pageGroupID = static_cast<const WebPageGroupProxy&>(object).pageGroupID();
1421 return API::PageGroupHandle::create(WTF::move(pageGroupData));
1425 case API::Object::Type::ObjCObjectGraph:
1426 return transformObjectsToHandles(static_cast<ObjCObjectGraph&>(object));
1435 return UserData::transform(object, Transformer());
1438 void WebProcess::setMemoryCacheDisabled(bool disabled)
1440 auto& memoryCache = MemoryCache::singleton();
1441 if (memoryCache.disabled() != disabled)
1442 memoryCache.setDisabled(disabled);
1445 #if ENABLE(SERVICE_CONTROLS)
1446 void WebProcess::setEnabledServices(bool hasImageServices, bool hasSelectionServices, bool hasRichContentServices)
1448 m_hasImageServices = hasImageServices;
1449 m_hasSelectionServices = hasSelectionServices;
1450 m_hasRichContentServices = hasRichContentServices;
1454 void WebProcess::prefetchDNS(const String& hostname)
1456 if (hostname.isEmpty())
1459 if (usesNetworkProcess()) {
1460 if (m_dnsPrefetchedHosts.add(hostname).isNewEntry)
1461 networkConnection()->connection()->send(Messages::NetworkConnectionToWebProcess::PrefetchDNS(hostname), 0);
1462 // The DNS prefetched hosts cache is only to avoid asking for the same hosts too many times
1463 // in a very short period of time, producing a lot of IPC traffic. So we clear this cache after
1464 // some time of no DNS requests.
1465 m_dnsPrefetchHystereris.impulse();
1468 WebCore::prefetchDNS(hostname);
1471 } // namespace WebKit