1/* 2 * Copyright (C) 2009, 2010, 2012, 2014 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27#include "WebProcess.h" 28 29#include "APIFrameHandle.h" 30#include "AuthenticationManager.h" 31#include "DrawingArea.h" 32#include "EventDispatcher.h" 33#include "InjectedBundle.h" 34#include "InjectedBundleUserMessageCoders.h" 35#include "Logging.h" 36#include "PluginProcessConnectionManager.h" 37#include "SessionTracker.h" 38#include "StatisticsData.h" 39#include "UserData.h" 40#include "WebApplicationCacheManager.h" 41#include "WebConnectionToUIProcess.h" 42#include "WebContextMessages.h" 43#include "WebCookieManager.h" 44#include "WebCoreArgumentCoders.h" 45#include "WebFrame.h" 46#include "WebFrameNetworkingContext.h" 47#include "WebGeolocationManager.h" 48#include "WebIconDatabaseProxy.h" 49#include "WebMediaCacheManager.h" 50#include "WebMemorySampler.h" 51#include "WebPage.h" 52#include "WebPageCreationParameters.h" 53#include "WebPageGroupProxyMessages.h" 54#include "WebPlatformStrategies.h" 55#include "WebProcessCreationParameters.h" 56#include "WebProcessMessages.h" 57#include "WebProcessProxyMessages.h" 58#include "WebResourceCacheManager.h" 59#include <JavaScriptCore/JSLock.h> 60#include <JavaScriptCore/MemoryStatistics.h> 61#include <WebCore/AXObjectCache.h> 62#include <WebCore/ApplicationCacheStorage.h> 63#include <WebCore/AuthenticationChallenge.h> 64#include <WebCore/CrossOriginPreflightResultCache.h> 65#include <WebCore/Font.h> 66#include <WebCore/FontCache.h> 67#include <WebCore/Frame.h> 68#include <WebCore/FrameLoader.h> 69#include <WebCore/GCController.h> 70#include <WebCore/GlyphPageTreeNode.h> 71#include <WebCore/IconDatabase.h> 72#include <WebCore/JSDOMWindow.h> 73#include <WebCore/Language.h> 74#include <WebCore/MemoryCache.h> 75#include <WebCore/MemoryPressureHandler.h> 76#include <WebCore/Page.h> 77#include <WebCore/PageCache.h> 78#include <WebCore/PageGroup.h> 79#include <WebCore/ResourceHandle.h> 80#include <WebCore/SchemeRegistry.h> 81#include <WebCore/SecurityOrigin.h> 82#include <WebCore/Settings.h> 83#include <WebCore/StorageTracker.h> 84#include <unistd.h> 85#include <wtf/CurrentTime.h> 86#include <wtf/HashCountedSet.h> 87#include <wtf/PassRefPtr.h> 88#include <wtf/RunLoop.h> 89#include <wtf/text/StringHash.h> 90 91#if ENABLE(NETWORK_PROCESS) 92#if PLATFORM(COCOA) 93#include "CookieStorageShim.h" 94#endif 95#include "NetworkProcessConnection.h" 96#endif 97 98#if ENABLE(SEC_ITEM_SHIM) 99#include "SecItemShim.h" 100#endif 101 102#if ENABLE(CUSTOM_PROTOCOLS) 103#include "CustomProtocolManager.h" 104#endif 105 106#if ENABLE(DATABASE_PROCESS) 107#include "WebToDatabaseProcessConnection.h" 108#endif 109 110#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS) 111#include "WebNotificationManager.h" 112#endif 113 114#if ENABLE(SQL_DATABASE) 115#include "WebDatabaseManager.h" 116#endif 117 118#if ENABLE(BATTERY_STATUS) 119#include "WebBatteryManager.h" 120#endif 121 122#if ENABLE(NETWORK_PROCESS) 123#include "WebResourceLoadScheduler.h" 124#endif 125 126#if ENABLE(REMOTE_INSPECTOR) 127#include <JavaScriptCore/RemoteInspector.h> 128#endif 129 130#if USE(SOUP) && !ENABLE(CUSTOM_PROTOCOLS) 131#include "WebSoupRequestManager.h" 132#endif 133 134using namespace JSC; 135using namespace WebCore; 136 137// This should be less than plugInAutoStartExpirationTimeThreshold in PlugInAutoStartProvider. 138static const double plugInAutoStartExpirationTimeUpdateThreshold = 29 * 24 * 60 * 60; 139 140// This should be greater than tileRevalidationTimeout in TileController. 141static const double nonVisibleProcessCleanupDelay = 10; 142 143namespace WebKit { 144 145WebProcess& WebProcess::shared() 146{ 147 static WebProcess& process = *new WebProcess; 148 return process; 149} 150 151WebProcess::WebProcess() 152 : m_eventDispatcher(EventDispatcher::create()) 153#if PLATFORM(IOS) 154 , m_viewUpdateDispatcher(ViewUpdateDispatcher::create()) 155#endif 156 , m_processSuspensionCleanupTimer(this, &WebProcess::processSuspensionCleanupTimerFired) 157 , m_inDidClose(false) 158 , m_hasSetCacheModel(false) 159 , m_cacheModel(CacheModelDocumentViewer) 160#if PLATFORM(COCOA) 161 , m_compositingRenderServerPort(MACH_PORT_NULL) 162 , m_clearResourceCachesDispatchGroup(0) 163#endif 164 , m_fullKeyboardAccessEnabled(false) 165 , m_textCheckerState() 166 , m_iconDatabaseProxy(new WebIconDatabaseProxy(this)) 167#if ENABLE(NETWORK_PROCESS) 168 , m_usesNetworkProcess(false) 169 , m_webResourceLoadScheduler(new WebResourceLoadScheduler) 170#endif 171#if ENABLE(NETSCAPE_PLUGIN_API) 172 , m_pluginProcessConnectionManager(PluginProcessConnectionManager::create()) 173#endif 174#if ENABLE(SERVICE_CONTROLS) 175 , m_hasImageServices(false) 176 , m_hasSelectionServices(false) 177 , m_hasRichContentServices(false) 178#endif 179 , m_nonVisibleProcessCleanupTimer(this, &WebProcess::nonVisibleProcessCleanupTimerFired) 180{ 181 // Initialize our platform strategies. 182 WebPlatformStrategies::initialize(); 183 184 // FIXME: This should moved to where WebProcess::initialize is called, 185 // so that ports have a chance to customize, and ifdefs in this file are 186 // limited. 187 addSupplement<WebGeolocationManager>(); 188 addSupplement<WebApplicationCacheManager>(); 189 addSupplement<WebResourceCacheManager>(); 190 addSupplement<WebCookieManager>(); 191 addSupplement<WebMediaCacheManager>(); 192 addSupplement<AuthenticationManager>(); 193 194#if ENABLE(SQL_DATABASE) 195 addSupplement<WebDatabaseManager>(); 196#endif 197#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS) 198 addSupplement<WebNotificationManager>(); 199#endif 200#if ENABLE(CUSTOM_PROTOCOLS) 201 addSupplement<CustomProtocolManager>(); 202#endif 203#if ENABLE(BATTERY_STATUS) 204 addSupplement<WebBatteryManager>(); 205#endif 206#if USE(SOUP) && !ENABLE(CUSTOM_PROTOCOLS) 207 addSupplement<WebSoupRequestManager>(); 208#endif 209 m_plugInAutoStartOriginHashes.add(SessionID::defaultSessionID(), HashMap<unsigned, double>()); 210} 211 212void WebProcess::initializeProcess(const ChildProcessInitializationParameters& parameters) 213{ 214 platformInitializeProcess(parameters); 215} 216 217void WebProcess::initializeConnection(IPC::Connection* connection) 218{ 219 ChildProcess::initializeConnection(connection); 220 221 connection->setShouldExitOnSyncMessageSendFailure(true); 222 223 m_eventDispatcher->initializeConnection(connection); 224#if PLATFORM(IOS) 225 m_viewUpdateDispatcher->initializeConnection(connection); 226#endif // PLATFORM(IOS) 227 228#if ENABLE(NETSCAPE_PLUGIN_API) 229 m_pluginProcessConnectionManager->initializeConnection(connection); 230#endif 231 232#if ENABLE(SEC_ITEM_SHIM) 233 SecItemShim::shared().initializeConnection(connection); 234#endif 235 236 WebProcessSupplementMap::const_iterator it = m_supplements.begin(); 237 WebProcessSupplementMap::const_iterator end = m_supplements.end(); 238 for (; it != end; ++it) 239 it->value->initializeConnection(connection); 240 241 m_webConnection = WebConnectionToUIProcess::create(this); 242 243 // In order to ensure that the asynchronous messages that are used for notifying the UI process 244 // about when WebFrame objects come and go are always delivered before the synchronous policy messages, 245 // use this flag to force synchronous messages to be treated as asynchronous messages in the UI process 246 // unless when doing so would lead to a deadlock. 247 connection->setOnlySendMessagesAsDispatchWhenWaitingForSyncReplyWhenProcessingSuchAMessage(true); 248} 249 250void WebProcess::didCreateDownload() 251{ 252 disableTermination(); 253} 254 255void WebProcess::didDestroyDownload() 256{ 257 enableTermination(); 258} 259 260IPC::Connection* WebProcess::downloadProxyConnection() 261{ 262 return parentProcessConnection(); 263} 264 265AuthenticationManager& WebProcess::downloadsAuthenticationManager() 266{ 267 return *supplement<AuthenticationManager>(); 268} 269 270void WebProcess::initializeWebProcess(const WebProcessCreationParameters& parameters, IPC::MessageDecoder& decoder) 271{ 272 ASSERT(m_pageMap.isEmpty()); 273 274 platformInitializeWebProcess(parameters, decoder); 275 276 WTF::setCurrentThreadIsUserInitiated(); 277 278 memoryPressureHandler().install(); 279 280 RefPtr<API::Object> injectedBundleInitializationUserData; 281 InjectedBundleUserMessageDecoder messageDecoder(injectedBundleInitializationUserData); 282 if (!decoder.decode(messageDecoder)) 283 return; 284 285 if (!parameters.injectedBundlePath.isEmpty()) 286 m_injectedBundle = InjectedBundle::create(parameters, injectedBundleInitializationUserData.get()); 287 288 WebProcessSupplementMap::const_iterator it = m_supplements.begin(); 289 WebProcessSupplementMap::const_iterator end = m_supplements.end(); 290 for (; it != end; ++it) 291 it->value->initialize(parameters); 292 293#if ENABLE(ICONDATABASE) 294 m_iconDatabaseProxy->setEnabled(parameters.iconDatabaseEnabled); 295#endif 296 297 if (!parameters.applicationCacheDirectory.isEmpty()) 298 cacheStorage().setCacheDirectory(parameters.applicationCacheDirectory); 299 300 setCacheModel(static_cast<uint32_t>(parameters.cacheModel)); 301 302 if (!parameters.languages.isEmpty()) 303 overrideUserPreferredLanguages(parameters.languages); 304 305 m_textCheckerState = parameters.textCheckerState; 306 307 m_fullKeyboardAccessEnabled = parameters.fullKeyboardAccessEnabled; 308 309 for (size_t i = 0; i < parameters.urlSchemesRegistererdAsEmptyDocument.size(); ++i) 310 registerURLSchemeAsEmptyDocument(parameters.urlSchemesRegistererdAsEmptyDocument[i]); 311 312 for (size_t i = 0; i < parameters.urlSchemesRegisteredAsSecure.size(); ++i) 313 registerURLSchemeAsSecure(parameters.urlSchemesRegisteredAsSecure[i]); 314 315 for (size_t i = 0; i < parameters.urlSchemesForWhichDomainRelaxationIsForbidden.size(); ++i) 316 setDomainRelaxationForbiddenForURLScheme(parameters.urlSchemesForWhichDomainRelaxationIsForbidden[i]); 317 318 for (size_t i = 0; i < parameters.urlSchemesRegisteredAsLocal.size(); ++i) 319 registerURLSchemeAsLocal(parameters.urlSchemesRegisteredAsLocal[i]); 320 321 for (size_t i = 0; i < parameters.urlSchemesRegisteredAsNoAccess.size(); ++i) 322 registerURLSchemeAsNoAccess(parameters.urlSchemesRegisteredAsNoAccess[i]); 323 324 for (size_t i = 0; i < parameters.urlSchemesRegisteredAsDisplayIsolated.size(); ++i) 325 registerURLSchemeAsDisplayIsolated(parameters.urlSchemesRegisteredAsDisplayIsolated[i]); 326 327 for (size_t i = 0; i < parameters.urlSchemesRegisteredAsCORSEnabled.size(); ++i) 328 registerURLSchemeAsCORSEnabled(parameters.urlSchemesRegisteredAsCORSEnabled[i]); 329 330#if ENABLE(CACHE_PARTITIONING) 331 for (auto& scheme : parameters.urlSchemesRegisteredAsCachePartitioned) 332 registerURLSchemeAsCachePartitioned(scheme); 333#endif 334 335 setDefaultRequestTimeoutInterval(parameters.defaultRequestTimeoutInterval); 336 337 if (parameters.shouldAlwaysUseComplexTextCodePath) 338 setAlwaysUsesComplexTextCodePath(true); 339 340 if (parameters.shouldUseFontSmoothing) 341 setShouldUseFontSmoothing(true); 342 343#if PLATFORM(COCOA) || USE(CFNETWORK) 344 SessionTracker::setIdentifierBase(parameters.uiProcessBundleIdentifier); 345#endif 346 347 if (parameters.shouldUseTestingNetworkSession) 348 NetworkStorageSession::switchToNewTestingSession(); 349 350#if ENABLE(NETWORK_PROCESS) 351 m_usesNetworkProcess = parameters.usesNetworkProcess; 352 ensureNetworkProcessConnection(); 353 354#if PLATFORM(COCOA) 355 if (usesNetworkProcess()) 356 CookieStorageShim::shared().initialize(); 357#endif 358#endif 359 setTerminationTimeout(parameters.terminationTimeout); 360 361 resetPlugInAutoStartOriginHashes(parameters.plugInAutoStartOriginHashes); 362 for (size_t i = 0; i < parameters.plugInAutoStartOrigins.size(); ++i) 363 m_plugInAutoStartOrigins.add(parameters.plugInAutoStartOrigins[i]); 364 365 setMemoryCacheDisabled(parameters.memoryCacheDisabled); 366 367#if ENABLE(SERVICE_CONTROLS) 368 setEnabledServices(parameters.hasImageServices, parameters.hasSelectionServices, parameters.hasRichContentServices); 369#endif 370 371#if ENABLE(REMOTE_INSPECTOR) 372 audit_token_t auditToken; 373 if (parentProcessConnection()->getAuditToken(auditToken)) { 374 RetainPtr<CFDataRef> auditData = adoptCF(CFDataCreate(nullptr, (const UInt8*)&auditToken, sizeof(auditToken))); 375 Inspector::RemoteInspector::shared().setParentProcessInformation(presenterApplicationPid(), auditData); 376 } 377#endif 378} 379 380#if ENABLE(NETWORK_PROCESS) 381void WebProcess::ensureNetworkProcessConnection() 382{ 383 if (!m_usesNetworkProcess) 384 return; 385 386 if (m_networkProcessConnection) 387 return; 388 389 IPC::Attachment encodedConnectionIdentifier; 390 391 if (!parentProcessConnection()->sendSync(Messages::WebProcessProxy::GetNetworkProcessConnection(), 392 Messages::WebProcessProxy::GetNetworkProcessConnection::Reply(encodedConnectionIdentifier), 0)) 393 return; 394 395#if OS(DARWIN) 396 IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.port()); 397#elif USE(UNIX_DOMAIN_SOCKETS) 398 IPC::Connection::Identifier connectionIdentifier = encodedConnectionIdentifier.releaseFileDescriptor(); 399#else 400 ASSERT_NOT_REACHED(); 401#endif 402 if (IPC::Connection::identifierIsNull(connectionIdentifier)) 403 return; 404 m_networkProcessConnection = NetworkProcessConnection::create(connectionIdentifier); 405} 406#endif // ENABLE(NETWORK_PROCESS) 407 408void WebProcess::registerURLSchemeAsEmptyDocument(const String& urlScheme) 409{ 410 SchemeRegistry::registerURLSchemeAsEmptyDocument(urlScheme); 411} 412 413void WebProcess::registerURLSchemeAsSecure(const String& urlScheme) const 414{ 415 SchemeRegistry::registerURLSchemeAsSecure(urlScheme); 416} 417 418void WebProcess::setDomainRelaxationForbiddenForURLScheme(const String& urlScheme) const 419{ 420 SchemeRegistry::setDomainRelaxationForbiddenForURLScheme(true, urlScheme); 421} 422 423void WebProcess::registerURLSchemeAsLocal(const String& urlScheme) const 424{ 425 SchemeRegistry::registerURLSchemeAsLocal(urlScheme); 426} 427 428void WebProcess::registerURLSchemeAsNoAccess(const String& urlScheme) const 429{ 430 SchemeRegistry::registerURLSchemeAsNoAccess(urlScheme); 431} 432 433void WebProcess::registerURLSchemeAsDisplayIsolated(const String& urlScheme) const 434{ 435 SchemeRegistry::registerURLSchemeAsDisplayIsolated(urlScheme); 436} 437 438void WebProcess::registerURLSchemeAsCORSEnabled(const String& urlScheme) const 439{ 440 SchemeRegistry::registerURLSchemeAsCORSEnabled(urlScheme); 441} 442 443#if ENABLE(CACHE_PARTITIONING) 444void WebProcess::registerURLSchemeAsCachePartitioned(const String& urlScheme) const 445{ 446 SchemeRegistry::registerURLSchemeAsCachePartitioned(urlScheme); 447} 448#endif 449 450void WebProcess::setDefaultRequestTimeoutInterval(double timeoutInterval) 451{ 452 ResourceRequest::setDefaultTimeoutInterval(timeoutInterval); 453} 454 455void WebProcess::setAlwaysUsesComplexTextCodePath(bool alwaysUseComplexText) 456{ 457 WebCore::Font::setCodePath(alwaysUseComplexText ? WebCore::Font::Complex : WebCore::Font::Auto); 458} 459 460void WebProcess::setShouldUseFontSmoothing(bool useFontSmoothing) 461{ 462 WebCore::Font::setShouldUseSmoothing(useFontSmoothing); 463} 464 465void WebProcess::userPreferredLanguagesChanged(const Vector<String>& languages) const 466{ 467 overrideUserPreferredLanguages(languages); 468 languageDidChange(); 469} 470 471void WebProcess::fullKeyboardAccessModeChanged(bool fullKeyboardAccessEnabled) 472{ 473 m_fullKeyboardAccessEnabled = fullKeyboardAccessEnabled; 474} 475 476void WebProcess::ensurePrivateBrowsingSession(SessionID sessionID) 477{ 478#if PLATFORM(COCOA) || USE(CFNETWORK) || USE(SOUP) 479 WebFrameNetworkingContext::ensurePrivateBrowsingSession(sessionID); 480#endif 481} 482 483void WebProcess::destroyPrivateBrowsingSession(SessionID sessionID) 484{ 485#if PLATFORM(COCOA) || USE(CFNETWORK) || USE(SOUP) 486 SessionTracker::destroySession(sessionID); 487#endif 488} 489 490DownloadManager& WebProcess::downloadManager() 491{ 492 ASSERT(!usesNetworkProcess()); 493 494 static NeverDestroyed<DownloadManager> downloadManager(this); 495 return downloadManager; 496} 497 498#if ENABLE(NETSCAPE_PLUGIN_API) 499PluginProcessConnectionManager& WebProcess::pluginProcessConnectionManager() 500{ 501 return *m_pluginProcessConnectionManager; 502} 503#endif 504 505void WebProcess::setCacheModel(uint32_t cm) 506{ 507 CacheModel cacheModel = static_cast<CacheModel>(cm); 508 509 if (!m_hasSetCacheModel || cacheModel != m_cacheModel) { 510 m_hasSetCacheModel = true; 511 m_cacheModel = cacheModel; 512 platformSetCacheModel(cacheModel); 513 } 514} 515 516WebPage* WebProcess::focusedWebPage() const 517{ 518 HashMap<uint64_t, RefPtr<WebPage>>::const_iterator end = m_pageMap.end(); 519 for (HashMap<uint64_t, RefPtr<WebPage>>::const_iterator it = m_pageMap.begin(); it != end; ++it) { 520 WebPage* page = (*it).value.get(); 521 if (page->windowAndWebPageAreFocused()) 522 return page; 523 } 524 return 0; 525} 526 527WebPage* WebProcess::webPage(uint64_t pageID) const 528{ 529 return m_pageMap.get(pageID); 530} 531 532void WebProcess::createWebPage(uint64_t pageID, const WebPageCreationParameters& parameters) 533{ 534 // It is necessary to check for page existence here since during a window.open() (or targeted 535 // link) the WebPage gets created both in the synchronous handler and through the normal way. 536 HashMap<uint64_t, RefPtr<WebPage>>::AddResult result = m_pageMap.add(pageID, nullptr); 537 if (result.isNewEntry) { 538 ASSERT(!result.iterator->value); 539 result.iterator->value = WebPage::create(pageID, parameters); 540 541 // Balanced by an enableTermination in removeWebPage. 542 disableTermination(); 543 } else 544 result.iterator->value->reinitializeWebPage(parameters); 545 546 ASSERT(result.iterator->value); 547} 548 549void WebProcess::removeWebPage(uint64_t pageID) 550{ 551 ASSERT(m_pageMap.contains(pageID)); 552 553 pageWillLeaveWindow(pageID); 554 m_pageMap.remove(pageID); 555 556 enableTermination(); 557} 558 559bool WebProcess::shouldTerminate() 560{ 561 ASSERT(m_pageMap.isEmpty()); 562 ASSERT(usesNetworkProcess() || !downloadManager().isDownloading()); 563 564 // FIXME: the ShouldTerminate message should also send termination parameters, such as any session cookies that need to be preserved. 565 bool shouldTerminate = false; 566 if (parentProcessConnection()->sendSync(Messages::WebProcessProxy::ShouldTerminate(), Messages::WebProcessProxy::ShouldTerminate::Reply(shouldTerminate), 0) 567 && !shouldTerminate) 568 return false; 569 570 return true; 571} 572 573void WebProcess::terminate() 574{ 575#ifndef NDEBUG 576 gcController().garbageCollectNow(); 577 fontCache().invalidate(); 578 memoryCache()->setDisabled(true); 579#endif 580 581 m_webConnection->invalidate(); 582 m_webConnection = nullptr; 583 584 platformTerminate(); 585 586 ChildProcess::terminate(); 587} 588 589void WebProcess::didReceiveSyncMessage(IPC::Connection* connection, IPC::MessageDecoder& decoder, std::unique_ptr<IPC::MessageEncoder>& replyEncoder) 590{ 591 messageReceiverMap().dispatchSyncMessage(connection, decoder, replyEncoder); 592} 593 594void WebProcess::didReceiveMessage(IPC::Connection* connection, IPC::MessageDecoder& decoder) 595{ 596 if (messageReceiverMap().dispatchMessage(connection, decoder)) 597 return; 598 599 if (decoder.messageReceiverName() == Messages::WebProcess::messageReceiverName()) { 600 didReceiveWebProcessMessage(connection, decoder); 601 return; 602 } 603 604 if (decoder.messageReceiverName() == Messages::WebPageGroupProxy::messageReceiverName()) { 605 uint64_t pageGroupID = decoder.destinationID(); 606 if (!pageGroupID) 607 return; 608 609 WebPageGroupProxy* pageGroupProxy = webPageGroup(pageGroupID); 610 if (!pageGroupProxy) 611 return; 612 613 pageGroupProxy->didReceiveMessage(connection, decoder); 614 } 615} 616 617void WebProcess::didClose(IPC::Connection*) 618{ 619#ifndef NDEBUG 620 m_inDidClose = true; 621 622 // Close all the live pages. 623 Vector<RefPtr<WebPage>> pages; 624 copyValuesToVector(m_pageMap, pages); 625 for (size_t i = 0; i < pages.size(); ++i) 626 pages[i]->close(); 627 pages.clear(); 628 629 gcController().garbageCollectSoon(); 630 fontCache().invalidate(); 631 memoryCache()->setDisabled(true); 632#endif 633 634 // The UI process closed this connection, shut down. 635 stopRunLoop(); 636} 637 638void WebProcess::didReceiveInvalidMessage(IPC::Connection*, IPC::StringReference, IPC::StringReference) 639{ 640 // We received an invalid message, but since this is from the UI process (which we trust), 641 // we'll let it slide. 642} 643 644WebFrame* WebProcess::webFrame(uint64_t frameID) const 645{ 646 return m_frameMap.get(frameID); 647} 648 649void WebProcess::addWebFrame(uint64_t frameID, WebFrame* frame) 650{ 651 m_frameMap.set(frameID, frame); 652} 653 654void WebProcess::removeWebFrame(uint64_t frameID) 655{ 656 m_frameMap.remove(frameID); 657 658 // We can end up here after our connection has closed when WebCore's frame life-support timer 659 // fires when the application is shutting down. There's no need (and no way) to update the UI 660 // process in this case. 661 if (!parentProcessConnection()) 662 return; 663 664 parentProcessConnection()->send(Messages::WebProcessProxy::DidDestroyFrame(frameID), 0); 665} 666 667WebPageGroupProxy* WebProcess::webPageGroup(PageGroup* pageGroup) 668{ 669 for (HashMap<uint64_t, RefPtr<WebPageGroupProxy>>::const_iterator it = m_pageGroupMap.begin(), end = m_pageGroupMap.end(); it != end; ++it) { 670 if (it->value->corePageGroup() == pageGroup) 671 return it->value.get(); 672 } 673 674 return 0; 675} 676 677WebPageGroupProxy* WebProcess::webPageGroup(uint64_t pageGroupID) 678{ 679 return m_pageGroupMap.get(pageGroupID); 680} 681 682WebPageGroupProxy* WebProcess::webPageGroup(const WebPageGroupData& pageGroupData) 683{ 684 auto result = m_pageGroupMap.add(pageGroupData.pageGroupID, nullptr); 685 if (result.isNewEntry) { 686 ASSERT(!result.iterator->value); 687 result.iterator->value = WebPageGroupProxy::create(pageGroupData); 688 } 689 690 return result.iterator->value.get(); 691} 692 693void WebProcess::clearResourceCaches(ResourceCachesToClear resourceCachesToClear) 694{ 695 platformClearResourceCaches(resourceCachesToClear); 696 697 // Toggling the cache model like this forces the cache to evict all its in-memory resources. 698 // FIXME: We need a better way to do this. 699 CacheModel cacheModel = m_cacheModel; 700 setCacheModel(CacheModelDocumentViewer); 701 setCacheModel(cacheModel); 702 703 memoryCache()->evictResources(); 704 705 // Empty the cross-origin preflight cache. 706 CrossOriginPreflightResultCache::shared().empty(); 707} 708 709void WebProcess::clearApplicationCache() 710{ 711 // Empty the application cache. 712 cacheStorage().empty(); 713} 714 715static inline void addCaseFoldedCharacters(StringHasher& hasher, const String& string) 716{ 717 if (string.isEmpty()) 718 return; 719 if (string.is8Bit()) { 720 hasher.addCharacters<LChar, CaseFoldingHash::foldCase<LChar>>(string.characters8(), string.length()); 721 return; 722 } 723 hasher.addCharacters<UChar, CaseFoldingHash::foldCase<UChar>>(string.characters16(), string.length()); 724} 725 726static unsigned hashForPlugInOrigin(const String& pageOrigin, const String& pluginOrigin, const String& mimeType) 727{ 728 // We want to avoid concatenating the strings and then taking the hash, since that could lead to an expensive conversion. 729 // We also want to avoid using the hash() function in StringImpl or CaseFoldingHash because that masks out bits for the use of flags. 730 StringHasher hasher; 731 addCaseFoldedCharacters(hasher, pageOrigin); 732 hasher.addCharacter(0); 733 addCaseFoldedCharacters(hasher, pluginOrigin); 734 hasher.addCharacter(0); 735 addCaseFoldedCharacters(hasher, mimeType); 736 return hasher.hash(); 737} 738 739bool WebProcess::isPlugInAutoStartOriginHash(unsigned plugInOriginHash, SessionID sessionID) 740{ 741 HashMap<WebCore::SessionID, HashMap<unsigned, double>>::const_iterator sessionIterator = m_plugInAutoStartOriginHashes.find(sessionID); 742 HashMap<unsigned, double>::const_iterator it; 743 bool contains = false; 744 745 if (sessionIterator != m_plugInAutoStartOriginHashes.end()) { 746 it = sessionIterator->value.find(plugInOriginHash); 747 contains = it != sessionIterator->value.end(); 748 } 749 if (!contains) { 750 sessionIterator = m_plugInAutoStartOriginHashes.find(SessionID::defaultSessionID()); 751 it = sessionIterator->value.find(plugInOriginHash); 752 if (it == sessionIterator->value.end()) 753 return false; 754 } 755 return currentTime() < it->value; 756} 757 758bool WebProcess::shouldPlugInAutoStartFromOrigin(const WebPage* page, const String& pageOrigin, const String& pluginOrigin, const String& mimeType) 759{ 760 if (!pluginOrigin.isEmpty() && m_plugInAutoStartOrigins.contains(pluginOrigin)) 761 return true; 762 763#ifdef ENABLE_PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC 764 // 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). 765 if (page && page->matchesPrimaryPlugIn(pageOrigin, pluginOrigin, mimeType)) 766 return true; 767#else 768 UNUSED_PARAM(page); 769#endif 770 771 // Lastly check against the more explicit hash list. 772 return isPlugInAutoStartOriginHash(hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType), page->sessionID()); 773} 774 775void WebProcess::plugInDidStartFromOrigin(const String& pageOrigin, const String& pluginOrigin, const String& mimeType, SessionID sessionID) 776{ 777 if (pageOrigin.isEmpty()) { 778 LOG(Plugins, "Not adding empty page origin"); 779 return; 780 } 781 782 unsigned plugInOriginHash = hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType); 783 if (isPlugInAutoStartOriginHash(plugInOriginHash, sessionID)) { 784 LOG(Plugins, "Hash %x already exists as auto-start origin (request for %s)", plugInOriginHash, pageOrigin.utf8().data()); 785 return; 786 } 787 788 // We might attempt to start another plugin before the didAddPlugInAutoStartOrigin message 789 // comes back from the parent process. Temporarily add this hash to the list with a thirty 790 // second timeout. That way, even if the parent decides not to add it, we'll only be 791 // incorrect for a little while. 792 m_plugInAutoStartOriginHashes.add(sessionID, HashMap<unsigned, double>()).iterator->value.set(plugInOriginHash, currentTime() + 30 * 1000); 793 794 parentProcessConnection()->send(Messages::WebContext::AddPlugInAutoStartOriginHash(pageOrigin, plugInOriginHash, sessionID), 0); 795} 796 797void WebProcess::didAddPlugInAutoStartOriginHash(unsigned plugInOriginHash, double expirationTime, SessionID sessionID) 798{ 799 // When called, some web process (which also might be this one) added the origin for auto-starting, 800 // or received user interaction. 801 // Set the bit to avoid having redundantly call into the UI process upon user interaction. 802 m_plugInAutoStartOriginHashes.add(sessionID, HashMap<unsigned, double>()).iterator->value.set(plugInOriginHash, expirationTime); 803} 804 805void WebProcess::resetPlugInAutoStartOriginDefaultHashes(const HashMap<unsigned, double>& hashes) 806{ 807 m_plugInAutoStartOriginHashes.clear(); 808 m_plugInAutoStartOriginHashes.add(SessionID::defaultSessionID(), HashMap<unsigned, double>()).iterator->value.swap(const_cast<HashMap<unsigned, double>&>(hashes)); 809} 810 811void WebProcess::resetPlugInAutoStartOriginHashes(const HashMap<SessionID, HashMap<unsigned, double>>& hashes) 812{ 813 m_plugInAutoStartOriginHashes.swap(const_cast<HashMap<SessionID, HashMap<unsigned, double>>&>(hashes)); 814} 815 816void WebProcess::plugInDidReceiveUserInteraction(const String& pageOrigin, const String& pluginOrigin, const String& mimeType, SessionID sessionID) 817{ 818 if (pageOrigin.isEmpty()) 819 return; 820 821 unsigned plugInOriginHash = hashForPlugInOrigin(pageOrigin, pluginOrigin, mimeType); 822 if (!plugInOriginHash) 823 return; 824 825 HashMap<WebCore::SessionID, HashMap<unsigned, double>>::const_iterator sessionIterator = m_plugInAutoStartOriginHashes.find(sessionID); 826 HashMap<unsigned, double>::const_iterator it; 827 bool contains = false; 828 if (sessionIterator != m_plugInAutoStartOriginHashes.end()) { 829 it = sessionIterator->value.find(plugInOriginHash); 830 contains = it != sessionIterator->value.end(); 831 } 832 if (!contains) { 833 sessionIterator = m_plugInAutoStartOriginHashes.find(SessionID::defaultSessionID()); 834 it = sessionIterator->value.find(plugInOriginHash); 835 if (it == sessionIterator->value.end()) 836 return; 837 } 838 839 if (it->value - currentTime() > plugInAutoStartExpirationTimeUpdateThreshold) 840 return; 841 842 parentProcessConnection()->send(Messages::WebContext::PlugInDidReceiveUserInteraction(plugInOriginHash, sessionID), 0); 843} 844 845static void fromCountedSetToHashMap(TypeCountSet* countedSet, HashMap<String, uint64_t>& map) 846{ 847 TypeCountSet::const_iterator end = countedSet->end(); 848 for (TypeCountSet::const_iterator it = countedSet->begin(); it != end; ++it) 849 map.set(it->key, it->value); 850} 851 852static void getWebCoreMemoryCacheStatistics(Vector<HashMap<String, uint64_t>>& result) 853{ 854 String imagesString(ASCIILiteral("Images")); 855 String cssString(ASCIILiteral("CSS")); 856 String xslString(ASCIILiteral("XSL")); 857 String javaScriptString(ASCIILiteral("JavaScript")); 858 859 MemoryCache::Statistics memoryCacheStatistics = memoryCache()->getStatistics(); 860 861 HashMap<String, uint64_t> counts; 862 counts.set(imagesString, memoryCacheStatistics.images.count); 863 counts.set(cssString, memoryCacheStatistics.cssStyleSheets.count); 864 counts.set(xslString, memoryCacheStatistics.xslStyleSheets.count); 865 counts.set(javaScriptString, memoryCacheStatistics.scripts.count); 866 result.append(counts); 867 868 HashMap<String, uint64_t> sizes; 869 sizes.set(imagesString, memoryCacheStatistics.images.size); 870 sizes.set(cssString, memoryCacheStatistics.cssStyleSheets.size); 871 sizes.set(xslString, memoryCacheStatistics.xslStyleSheets.size); 872 sizes.set(javaScriptString, memoryCacheStatistics.scripts.size); 873 result.append(sizes); 874 875 HashMap<String, uint64_t> liveSizes; 876 liveSizes.set(imagesString, memoryCacheStatistics.images.liveSize); 877 liveSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.liveSize); 878 liveSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.liveSize); 879 liveSizes.set(javaScriptString, memoryCacheStatistics.scripts.liveSize); 880 result.append(liveSizes); 881 882 HashMap<String, uint64_t> decodedSizes; 883 decodedSizes.set(imagesString, memoryCacheStatistics.images.decodedSize); 884 decodedSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.decodedSize); 885 decodedSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.decodedSize); 886 decodedSizes.set(javaScriptString, memoryCacheStatistics.scripts.decodedSize); 887 result.append(decodedSizes); 888 889 HashMap<String, uint64_t> purgeableSizes; 890 purgeableSizes.set(imagesString, memoryCacheStatistics.images.purgeableSize); 891 purgeableSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.purgeableSize); 892 purgeableSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.purgeableSize); 893 purgeableSizes.set(javaScriptString, memoryCacheStatistics.scripts.purgeableSize); 894 result.append(purgeableSizes); 895 896 HashMap<String, uint64_t> purgedSizes; 897 purgedSizes.set(imagesString, memoryCacheStatistics.images.purgedSize); 898 purgedSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.purgedSize); 899 purgedSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.purgedSize); 900 purgedSizes.set(javaScriptString, memoryCacheStatistics.scripts.purgedSize); 901 result.append(purgedSizes); 902} 903 904void WebProcess::getWebCoreStatistics(uint64_t callbackID) 905{ 906 StatisticsData data; 907 908 // Gather JavaScript statistics. 909 { 910 JSLockHolder lock(JSDOMWindow::commonVM()); 911 data.statisticsNumbers.set(ASCIILiteral("JavaScriptObjectsCount"), JSDOMWindow::commonVM().heap.objectCount()); 912 data.statisticsNumbers.set(ASCIILiteral("JavaScriptGlobalObjectsCount"), JSDOMWindow::commonVM().heap.globalObjectCount()); 913 data.statisticsNumbers.set(ASCIILiteral("JavaScriptProtectedObjectsCount"), JSDOMWindow::commonVM().heap.protectedObjectCount()); 914 data.statisticsNumbers.set(ASCIILiteral("JavaScriptProtectedGlobalObjectsCount"), JSDOMWindow::commonVM().heap.protectedGlobalObjectCount()); 915 916 OwnPtr<TypeCountSet> protectedObjectTypeCounts(JSDOMWindow::commonVM().heap.protectedObjectTypeCounts()); 917 fromCountedSetToHashMap(protectedObjectTypeCounts.get(), data.javaScriptProtectedObjectTypeCounts); 918 919 OwnPtr<TypeCountSet> objectTypeCounts(JSDOMWindow::commonVM().heap.objectTypeCounts()); 920 fromCountedSetToHashMap(objectTypeCounts.get(), data.javaScriptObjectTypeCounts); 921 922 uint64_t javaScriptHeapSize = JSDOMWindow::commonVM().heap.size(); 923 data.statisticsNumbers.set(ASCIILiteral("JavaScriptHeapSize"), javaScriptHeapSize); 924 data.statisticsNumbers.set(ASCIILiteral("JavaScriptFreeSize"), JSDOMWindow::commonVM().heap.capacity() - javaScriptHeapSize); 925 } 926 927 WTF::FastMallocStatistics fastMallocStatistics = WTF::fastMallocStatistics(); 928 data.statisticsNumbers.set(ASCIILiteral("FastMallocReservedVMBytes"), fastMallocStatistics.reservedVMBytes); 929 data.statisticsNumbers.set(ASCIILiteral("FastMallocCommittedVMBytes"), fastMallocStatistics.committedVMBytes); 930 data.statisticsNumbers.set(ASCIILiteral("FastMallocFreeListBytes"), fastMallocStatistics.freeListBytes); 931 932 // Gather icon statistics. 933 data.statisticsNumbers.set(ASCIILiteral("IconPageURLMappingCount"), iconDatabase().pageURLMappingCount()); 934 data.statisticsNumbers.set(ASCIILiteral("IconRetainedPageURLCount"), iconDatabase().retainedPageURLCount()); 935 data.statisticsNumbers.set(ASCIILiteral("IconRecordCount"), iconDatabase().iconRecordCount()); 936 data.statisticsNumbers.set(ASCIILiteral("IconsWithDataCount"), iconDatabase().iconRecordCountWithData()); 937 938 // Gather font statistics. 939 data.statisticsNumbers.set(ASCIILiteral("CachedFontDataCount"), fontCache().fontDataCount()); 940 data.statisticsNumbers.set(ASCIILiteral("CachedFontDataInactiveCount"), fontCache().inactiveFontDataCount()); 941 942 // Gather glyph page statistics. 943 data.statisticsNumbers.set(ASCIILiteral("GlyphPageCount"), GlyphPageTreeNode::treeGlyphPageCount()); 944 945 // Get WebCore memory cache statistics 946 getWebCoreMemoryCacheStatistics(data.webCoreCacheStatistics); 947 948 parentProcessConnection()->send(Messages::WebContext::DidGetStatistics(data, callbackID), 0); 949} 950 951void WebProcess::garbageCollectJavaScriptObjects() 952{ 953 gcController().garbageCollectNow(); 954} 955 956void WebProcess::setJavaScriptGarbageCollectorTimerEnabled(bool flag) 957{ 958 gcController().setJavaScriptGarbageCollectorTimerEnabled(flag); 959} 960 961void WebProcess::postInjectedBundleMessage(const IPC::DataReference& messageData) 962{ 963 InjectedBundle* injectedBundle = WebProcess::shared().injectedBundle(); 964 if (!injectedBundle) 965 return; 966 967 IPC::ArgumentDecoder decoder(messageData.data(), messageData.size()); 968 969 String messageName; 970 if (!decoder.decode(messageName)) 971 return; 972 973 RefPtr<API::Object> messageBody; 974 InjectedBundleUserMessageDecoder messageBodyDecoder(messageBody); 975 if (!decoder.decode(messageBodyDecoder)) 976 return; 977 978 injectedBundle->didReceiveMessage(messageName, messageBody.get()); 979} 980 981void WebProcess::setInjectedBundleParameter(const String& key, const IPC::DataReference& value) 982{ 983 InjectedBundle* injectedBundle = WebProcess::shared().injectedBundle(); 984 if (!injectedBundle) 985 return; 986 987 injectedBundle->setBundleParameter(key, value); 988} 989 990bool WebProcess::usesNetworkProcess() const 991{ 992#if ENABLE(NETWORK_PROCESS) 993 return m_usesNetworkProcess; 994#else 995 return false; 996#endif 997} 998 999#if ENABLE(NETWORK_PROCESS) 1000NetworkProcessConnection* WebProcess::networkConnection() 1001{ 1002 ASSERT(m_usesNetworkProcess); 1003 1004 // If we've lost our connection to the network process (e.g. it crashed) try to re-establish it. 1005 if (!m_networkProcessConnection) 1006 ensureNetworkProcessConnection(); 1007 1008 // If we failed to re-establish it then we are beyond recovery and should crash. 1009 if (!m_networkProcessConnection) 1010 CRASH(); 1011 1012 return m_networkProcessConnection.get(); 1013} 1014 1015void WebProcess::networkProcessConnectionClosed(NetworkProcessConnection* connection) 1016{ 1017 ASSERT(m_networkProcessConnection); 1018 ASSERT_UNUSED(connection, m_networkProcessConnection == connection); 1019 1020 m_networkProcessConnection = 0; 1021 1022 m_webResourceLoadScheduler->networkProcessCrashed(); 1023} 1024 1025WebResourceLoadScheduler& WebProcess::webResourceLoadScheduler() 1026{ 1027 return *m_webResourceLoadScheduler; 1028} 1029#endif // ENABLED(NETWORK_PROCESS) 1030 1031#if ENABLE(DATABASE_PROCESS) 1032void WebProcess::webToDatabaseProcessConnectionClosed(WebToDatabaseProcessConnection* connection) 1033{ 1034 ASSERT(m_webToDatabaseProcessConnection); 1035 ASSERT(m_webToDatabaseProcessConnection == connection); 1036 1037 m_webToDatabaseProcessConnection = 0; 1038} 1039 1040WebToDatabaseProcessConnection* WebProcess::webToDatabaseProcessConnection() 1041{ 1042 if (!m_webToDatabaseProcessConnection) 1043 ensureWebToDatabaseProcessConnection(); 1044 1045 return m_webToDatabaseProcessConnection.get(); 1046} 1047 1048void WebProcess::ensureWebToDatabaseProcessConnection() 1049{ 1050 if (m_webToDatabaseProcessConnection) 1051 return; 1052 1053 IPC::Attachment encodedConnectionIdentifier; 1054 1055 if (!parentProcessConnection()->sendSync(Messages::WebProcessProxy::GetDatabaseProcessConnection(), 1056 Messages::WebProcessProxy::GetDatabaseProcessConnection::Reply(encodedConnectionIdentifier), 0)) 1057 return; 1058 1059#if OS(DARWIN) 1060 IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.port()); 1061 if (IPC::Connection::identifierIsNull(connectionIdentifier)) 1062 return; 1063#else 1064 ASSERT_NOT_REACHED(); 1065#endif 1066 m_webToDatabaseProcessConnection = WebToDatabaseProcessConnection::create(connectionIdentifier); 1067} 1068 1069#endif // ENABLED(DATABASE_PROCESS) 1070 1071void WebProcess::downloadRequest(uint64_t downloadID, uint64_t initiatingPageID, const ResourceRequest& request) 1072{ 1073 WebPage* initiatingPage = initiatingPageID ? webPage(initiatingPageID) : 0; 1074 1075 ResourceRequest requestWithOriginalURL = request; 1076 if (initiatingPage) 1077 initiatingPage->mainFrame()->loader().setOriginalURLForDownloadRequest(requestWithOriginalURL); 1078 1079 downloadManager().startDownload(downloadID, requestWithOriginalURL); 1080} 1081 1082void WebProcess::cancelDownload(uint64_t downloadID) 1083{ 1084 downloadManager().cancelDownload(downloadID); 1085} 1086 1087void WebProcess::setEnhancedAccessibility(bool flag) 1088{ 1089 WebCore::AXObjectCache::setEnhancedUserInterfaceAccessibility(flag); 1090} 1091 1092void WebProcess::startMemorySampler(const SandboxExtension::Handle& sampleLogFileHandle, const String& sampleLogFilePath, const double interval) 1093{ 1094#if ENABLE(MEMORY_SAMPLER) 1095 WebMemorySampler::shared()->start(sampleLogFileHandle, sampleLogFilePath, interval); 1096#else 1097 UNUSED_PARAM(sampleLogFileHandle); 1098 UNUSED_PARAM(sampleLogFilePath); 1099 UNUSED_PARAM(interval); 1100#endif 1101} 1102 1103void WebProcess::stopMemorySampler() 1104{ 1105#if ENABLE(MEMORY_SAMPLER) 1106 WebMemorySampler::shared()->stop(); 1107#endif 1108} 1109 1110void WebProcess::setTextCheckerState(const TextCheckerState& textCheckerState) 1111{ 1112 bool continuousSpellCheckingTurnedOff = !textCheckerState.isContinuousSpellCheckingEnabled && m_textCheckerState.isContinuousSpellCheckingEnabled; 1113 bool grammarCheckingTurnedOff = !textCheckerState.isGrammarCheckingEnabled && m_textCheckerState.isGrammarCheckingEnabled; 1114 1115 m_textCheckerState = textCheckerState; 1116 1117 if (!continuousSpellCheckingTurnedOff && !grammarCheckingTurnedOff) 1118 return; 1119 1120 HashMap<uint64_t, RefPtr<WebPage>>::iterator end = m_pageMap.end(); 1121 for (HashMap<uint64_t, RefPtr<WebPage>>::iterator it = m_pageMap.begin(); it != end; ++it) { 1122 WebPage* page = (*it).value.get(); 1123 if (continuousSpellCheckingTurnedOff) 1124 page->unmarkAllMisspellings(); 1125 if (grammarCheckingTurnedOff) 1126 page->unmarkAllBadGrammar(); 1127 } 1128} 1129 1130void WebProcess::releasePageCache() 1131{ 1132 int savedPageCacheCapacity = pageCache()->capacity(); 1133 pageCache()->setCapacity(0); 1134 pageCache()->setCapacity(savedPageCacheCapacity); 1135} 1136 1137#if !PLATFORM(COCOA) 1138void WebProcess::initializeProcessName(const ChildProcessInitializationParameters&) 1139{ 1140} 1141 1142void WebProcess::initializeSandbox(const ChildProcessInitializationParameters&, SandboxInitializationParameters&) 1143{ 1144} 1145 1146void WebProcess::platformInitializeProcess(const ChildProcessInitializationParameters&) 1147{ 1148} 1149 1150void WebProcess::updateActivePages() 1151{ 1152} 1153 1154#endif 1155 1156#if PLATFORM(IOS) 1157void WebProcess::resetAllGeolocationPermissions() 1158{ 1159 for (auto it = m_pageMap.begin(), end = m_pageMap.end(); it != end; ++it) { 1160 WebPage* page = (*it).value.get(); 1161 if (Frame* mainFrame = page->mainFrame()) 1162 mainFrame->resetAllGeolocationPermission(); 1163 } 1164} 1165#endif 1166 1167void WebProcess::processWillSuspend() 1168{ 1169 memoryPressureHandler().releaseMemory(true); 1170 1171 if (!markAllLayersVolatileIfPossible()) 1172 m_processSuspensionCleanupTimer.startRepeating(std::chrono::milliseconds(20)); 1173 else 1174 parentProcessConnection()->send(Messages::WebProcessProxy::ProcessReadyToSuspend(), 0); 1175} 1176 1177void WebProcess::cancelProcessWillSuspend() 1178{ 1179 // If we've already finished cleaning up and sent ProcessReadyToSuspend, we 1180 // shouldn't send DidCancelProcessSuspension; the UI process strictly expects one or the other. 1181 if (!m_processSuspensionCleanupTimer.isActive()) 1182 return; 1183 1184 m_processSuspensionCleanupTimer.stop(); 1185 parentProcessConnection()->send(Messages::WebProcessProxy::DidCancelProcessSuspension(), 0); 1186} 1187 1188bool WebProcess::markAllLayersVolatileIfPossible() 1189{ 1190 bool successfullyMarkedAllLayersVolatile = true; 1191 for (auto& page : m_pageMap.values()) { 1192 if (auto drawingArea = page->drawingArea()) 1193 successfullyMarkedAllLayersVolatile &= drawingArea->markLayersVolatileImmediatelyIfPossible(); 1194 } 1195 1196 return successfullyMarkedAllLayersVolatile; 1197} 1198 1199void WebProcess::processSuspensionCleanupTimerFired(Timer<WebProcess>* timer) 1200{ 1201 if (markAllLayersVolatileIfPossible()) { 1202 parentProcessConnection()->send(Messages::WebProcessProxy::ProcessReadyToSuspend(), 0); 1203 timer->stop(); 1204 } 1205} 1206 1207void WebProcess::pageDidEnterWindow(uint64_t pageID) 1208{ 1209 m_pagesInWindows.add(pageID); 1210 m_nonVisibleProcessCleanupTimer.stop(); 1211} 1212 1213void WebProcess::pageWillLeaveWindow(uint64_t pageID) 1214{ 1215 m_pagesInWindows.remove(pageID); 1216 1217 if (m_pagesInWindows.isEmpty() && !m_nonVisibleProcessCleanupTimer.isActive()) 1218 m_nonVisibleProcessCleanupTimer.startOneShot(nonVisibleProcessCleanupDelay); 1219} 1220 1221void WebProcess::nonVisibleProcessCleanupTimerFired(Timer<WebProcess>*) 1222{ 1223 ASSERT(m_pagesInWindows.isEmpty()); 1224 if (!m_pagesInWindows.isEmpty()) 1225 return; 1226 1227#if PLATFORM(COCOA) 1228 wkDestroyRenderingResources(); 1229#endif 1230} 1231 1232RefPtr<API::Object> WebProcess::apiObjectByConvertingFromHandles(API::Object* object) 1233{ 1234 return UserData::transform(object, [this](const API::Object& object) -> RefPtr<API::Object> { 1235 switch (object.type()) { 1236 case API::Object::Type::FrameHandle: { 1237 auto& frameHandle = static_cast<const API::FrameHandle&>(object); 1238 1239 return webFrame(frameHandle.frameID()); 1240 } 1241 1242 default: 1243 return nullptr; 1244 } 1245 }); 1246} 1247 1248void WebProcess::setMemoryCacheDisabled(bool disabled) 1249{ 1250 if (memoryCache()->disabled() != disabled) 1251 memoryCache()->setDisabled(disabled); 1252} 1253 1254#if ENABLE(SERVICE_CONTROLS) 1255void WebProcess::setEnabledServices(bool hasImageServices, bool hasSelectionServices, bool hasRichContentServices) 1256{ 1257 m_hasImageServices = hasImageServices; 1258 m_hasSelectionServices = hasSelectionServices; 1259 m_hasRichContentServices = hasRichContentServices; 1260} 1261#endif 1262 1263} // namespace WebKit 1264