1 /* 2 * Copyright (C) 2009, 2010 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 "AuthenticationManager.h" 30 #include "DownloadManager.h" 31 #include "InjectedBundle.h" 32 #include "InjectedBundleMessageKinds.h" 33 #include "InjectedBundleUserMessageCoders.h" 34 #include "RunLoop.h" 35 #include "SandboxExtension.h" 36 #include "WebApplicationCacheManager.h" 37 #include "WebContextMessages.h" 38 #include "WebCookieManager.h" 39 #include "WebCoreArgumentCoders.h" 40 #include "WebDatabaseManager.h" 41 #include "WebFrame.h" 42 #include "WebGeolocationManagerMessages.h" 43 #include "WebKeyValueStorageManager.h" 44 #include "WebMediaCacheManager.h" 45 #include "WebMemorySampler.h" 46 #include "WebPage.h" 47 #include "WebPageCreationParameters.h" 48 #include "WebPlatformStrategies.h" 49 #include "WebPreferencesStore.h" 50 #include "WebProcessCreationParameters.h" 51 #include "WebProcessMessages.h" 52 #include "WebProcessProxyMessages.h" 53 #include "WebResourceCacheManager.h" 54 #include <WebCore/AXObjectCache.h> 55 #include <WebCore/ApplicationCacheStorage.h> 56 #include <WebCore/CrossOriginPreflightResultCache.h> 57 #include <WebCore/Font.h> 58 #include <WebCore/Language.h> 59 #include <WebCore/Logging.h> 60 #include <WebCore/MemoryCache.h> 61 #include <WebCore/Page.h> 62 #include <WebCore/PageCache.h> 63 #include <WebCore/PageGroup.h> 64 #include <WebCore/ResourceHandle.h> 65 #include <WebCore/SchemeRegistry.h> 66 #include <WebCore/SecurityOrigin.h> 67 #include <WebCore/Settings.h> 68 #include <WebCore/StorageTracker.h> 69 #include <wtf/PassRefPtr.h> 70 #include <wtf/RandomNumber.h> 71 72 #ifndef NDEBUG 73 #include <WebCore/GCController.h> 74 #endif 75 76 #if !OS(WINDOWS) 77 #include <unistd.h> 78 #endif 79 80 #if !ENABLE(PLUGIN_PROCESS) 81 #include "NetscapePluginModule.h" 82 #endif 83 84 using namespace WebCore; 85 86 namespace WebKit { 87 88 #if OS(WINDOWS) 89 static void sleep(unsigned seconds) 90 { 91 ::Sleep(seconds * 1000); 92 } 93 #endif 94 95 static void* randomCrashThread(void*) 96 { 97 // This delay was chosen semi-arbitrarily. We want the crash to happen somewhat quickly to 98 // enable useful stress testing, but not so quickly that the web process will always crash soon 99 // after launch. 100 static const unsigned maximumRandomCrashDelay = 180; 101 102 sleep(randomNumber() * maximumRandomCrashDelay); 103 CRASH(); 104 return 0; 105 } 106 107 static void startRandomCrashThreadIfRequested() 108 { 109 if (!getenv("WEBKIT2_CRASH_WEB_PROCESS_RANDOMLY")) 110 return; 111 createThread(randomCrashThread, 0, "WebKit2: Random Crash Thread"); 112 } 113 114 WebProcess& WebProcess::shared() 115 { 116 static WebProcess& process = *new WebProcess; 117 return process; 118 } 119 120 static const double shutdownTimeout = 60; 121 122 WebProcess::WebProcess() 123 : ChildProcess(shutdownTimeout) 124 , m_inDidClose(false) 125 , m_hasSetCacheModel(false) 126 , m_cacheModel(CacheModelDocumentViewer) 127 #if USE(ACCELERATED_COMPOSITING) && PLATFORM(MAC) 128 , m_compositingRenderServerPort(MACH_PORT_NULL) 129 #endif 130 #if PLATFORM(QT) 131 , m_networkAccessManager(0) 132 #endif 133 , m_textCheckerState() 134 , m_geolocationManager(this) 135 , m_iconDatabaseProxy(this) 136 { 137 #if USE(PLATFORM_STRATEGIES) 138 // Initialize our platform strategies. 139 WebPlatformStrategies::initialize(); 140 #endif // USE(PLATFORM_STRATEGIES) 141 142 WebCore::InitializeLoggingChannelsIfNecessary(); 143 } 144 145 void WebProcess::initialize(CoreIPC::Connection::Identifier serverIdentifier, RunLoop* runLoop) 146 { 147 ASSERT(!m_connection); 148 149 m_connection = CoreIPC::Connection::createClientConnection(serverIdentifier, this, runLoop); 150 m_connection->setDidCloseOnConnectionWorkQueueCallback(didCloseOnConnectionWorkQueue); 151 m_connection->setShouldExitOnSyncMessageSendFailure(true); 152 153 m_connection->open(); 154 155 m_runLoop = runLoop; 156 157 startRandomCrashThreadIfRequested(); 158 } 159 160 void WebProcess::initializeWebProcess(const WebProcessCreationParameters& parameters, CoreIPC::ArgumentDecoder* arguments) 161 { 162 ASSERT(m_pageMap.isEmpty()); 163 164 platformInitializeWebProcess(parameters, arguments); 165 166 RefPtr<APIObject> injectedBundleInitializationUserData; 167 InjectedBundleUserMessageDecoder messageDecoder(injectedBundleInitializationUserData); 168 if (!arguments->decode(messageDecoder)) 169 return; 170 171 if (!parameters.injectedBundlePath.isEmpty()) { 172 m_injectedBundle = InjectedBundle::create(parameters.injectedBundlePath); 173 m_injectedBundle->setSandboxExtension(SandboxExtension::create(parameters.injectedBundlePathExtensionHandle)); 174 175 if (!m_injectedBundle->load(injectedBundleInitializationUserData.get())) { 176 // Don't keep around the InjectedBundle reference if the load fails. 177 m_injectedBundle.clear(); 178 } 179 } 180 181 #if ENABLE(DATABASE) 182 // Make sure the WebDatabaseManager is initialized so that the Database directory is set. 183 WebDatabaseManager::initialize(parameters.databaseDirectory); 184 #endif 185 186 #if ENABLE(ICONDATABASE) 187 m_iconDatabaseProxy.setEnabled(parameters.iconDatabaseEnabled); 188 #endif 189 190 #if ENABLE(DOM_STORAGE) 191 StorageTracker::initializeTracker(parameters.localStorageDirectory); 192 m_localStorageDirectory = parameters.localStorageDirectory; 193 #endif 194 195 #if ENABLE(OFFLINE_WEB_APPLICATIONS) 196 if (!parameters.applicationCacheDirectory.isEmpty()) 197 cacheStorage().setCacheDirectory(parameters.applicationCacheDirectory); 198 #endif 199 200 setShouldTrackVisitedLinks(parameters.shouldTrackVisitedLinks); 201 setCacheModel(static_cast<uint32_t>(parameters.cacheModel)); 202 203 if (!parameters.languageCode.isEmpty()) 204 overrideDefaultLanguage(parameters.languageCode); 205 206 m_textCheckerState = parameters.textCheckerState; 207 208 for (size_t i = 0; i < parameters.urlSchemesRegistererdAsEmptyDocument.size(); ++i) 209 registerURLSchemeAsEmptyDocument(parameters.urlSchemesRegistererdAsEmptyDocument[i]); 210 211 for (size_t i = 0; i < parameters.urlSchemesRegisteredAsSecure.size(); ++i) 212 registerURLSchemeAsSecure(parameters.urlSchemesRegisteredAsSecure[i]); 213 214 for (size_t i = 0; i < parameters.urlSchemesForWhichDomainRelaxationIsForbidden.size(); ++i) 215 setDomainRelaxationForbiddenForURLScheme(parameters.urlSchemesForWhichDomainRelaxationIsForbidden[i]); 216 217 setDefaultRequestTimeoutInterval(parameters.defaultRequestTimeoutInterval); 218 219 for (size_t i = 0; i < parameters.mimeTypesWithCustomRepresentation.size(); ++i) 220 m_mimeTypesWithCustomRepresentations.add(parameters.mimeTypesWithCustomRepresentation[i]); 221 222 #if PLATFORM(MAC) 223 m_presenterApplicationPid = parameters.presenterApplicationPid; 224 #endif 225 226 if (parameters.shouldAlwaysUseComplexTextCodePath) 227 setAlwaysUsesComplexTextCodePath(true); 228 229 #if USE(CFURLSTORAGESESSIONS) 230 WebCore::ResourceHandle::setPrivateBrowsingStorageSessionIdentifierBase(parameters.uiProcessBundleIdentifier); 231 #endif 232 } 233 234 void WebProcess::setShouldTrackVisitedLinks(bool shouldTrackVisitedLinks) 235 { 236 PageGroup::setShouldTrackVisitedLinks(shouldTrackVisitedLinks); 237 } 238 239 void WebProcess::registerURLSchemeAsEmptyDocument(const String& urlScheme) 240 { 241 SchemeRegistry::registerURLSchemeAsEmptyDocument(urlScheme); 242 } 243 244 void WebProcess::registerURLSchemeAsSecure(const String& urlScheme) const 245 { 246 SchemeRegistry::registerURLSchemeAsSecure(urlScheme); 247 } 248 249 void WebProcess::setDomainRelaxationForbiddenForURLScheme(const String& urlScheme) const 250 { 251 SecurityOrigin::setDomainRelaxationForbiddenForURLScheme(true, urlScheme); 252 } 253 254 void WebProcess::setDefaultRequestTimeoutInterval(double timeoutInterval) 255 { 256 ResourceRequest::setDefaultTimeoutInterval(timeoutInterval); 257 } 258 259 void WebProcess::setAlwaysUsesComplexTextCodePath(bool alwaysUseComplexText) 260 { 261 WebCore::Font::setCodePath(alwaysUseComplexText ? WebCore::Font::Complex : WebCore::Font::Auto); 262 } 263 264 void WebProcess::languageChanged(const String& language) const 265 { 266 overrideDefaultLanguage(language); 267 } 268 269 void WebProcess::setVisitedLinkTable(const SharedMemory::Handle& handle) 270 { 271 RefPtr<SharedMemory> sharedMemory = SharedMemory::create(handle, SharedMemory::ReadOnly); 272 if (!sharedMemory) 273 return; 274 275 m_visitedLinkTable.setSharedMemory(sharedMemory.release()); 276 } 277 278 void WebProcess::visitedLinkStateChanged(const Vector<WebCore::LinkHash>& linkHashes) 279 { 280 // FIXME: We may want to track visited links per WebPageGroup rather than per WebContext. 281 for (size_t i = 0; i < linkHashes.size(); ++i) { 282 HashMap<uint64_t, RefPtr<WebPageGroupProxy> >::const_iterator it = m_pageGroupMap.begin(); 283 HashMap<uint64_t, RefPtr<WebPageGroupProxy> >::const_iterator end = m_pageGroupMap.end(); 284 for (; it != end; ++it) 285 Page::visitedStateChanged(PageGroup::pageGroup(it->second->identifier()), linkHashes[i]); 286 } 287 288 pageCache()->markPagesForVistedLinkStyleRecalc(); 289 } 290 291 void WebProcess::allVisitedLinkStateChanged() 292 { 293 // FIXME: We may want to track visited links per WebPageGroup rather than per WebContext. 294 HashMap<uint64_t, RefPtr<WebPageGroupProxy> >::const_iterator it = m_pageGroupMap.begin(); 295 HashMap<uint64_t, RefPtr<WebPageGroupProxy> >::const_iterator end = m_pageGroupMap.end(); 296 for (; it != end; ++it) 297 Page::allVisitedStateChanged(PageGroup::pageGroup(it->second->identifier())); 298 299 pageCache()->markPagesForVistedLinkStyleRecalc(); 300 } 301 302 bool WebProcess::isLinkVisited(LinkHash linkHash) const 303 { 304 return m_visitedLinkTable.isLinkVisited(linkHash); 305 } 306 307 void WebProcess::addVisitedLink(WebCore::LinkHash linkHash) 308 { 309 if (isLinkVisited(linkHash)) 310 return; 311 m_connection->send(Messages::WebContext::AddVisitedLinkHash(linkHash), 0); 312 } 313 314 #if !PLATFORM(MAC) 315 bool WebProcess::fullKeyboardAccessEnabled() 316 { 317 return false; 318 } 319 #endif 320 321 void WebProcess::setCacheModel(uint32_t cm) 322 { 323 CacheModel cacheModel = static_cast<CacheModel>(cm); 324 325 if (!m_hasSetCacheModel || cacheModel != m_cacheModel) { 326 m_hasSetCacheModel = true; 327 m_cacheModel = cacheModel; 328 platformSetCacheModel(cacheModel); 329 } 330 } 331 332 void WebProcess::calculateCacheSizes(CacheModel cacheModel, uint64_t memorySize, uint64_t diskFreeSize, 333 unsigned& cacheTotalCapacity, unsigned& cacheMinDeadCapacity, unsigned& cacheMaxDeadCapacity, double& deadDecodedDataDeletionInterval, 334 unsigned& pageCacheCapacity, unsigned long& urlCacheMemoryCapacity, unsigned long& urlCacheDiskCapacity) 335 { 336 switch (cacheModel) { 337 case CacheModelDocumentViewer: { 338 // Page cache capacity (in pages) 339 pageCacheCapacity = 0; 340 341 // Object cache capacities (in bytes) 342 if (memorySize >= 2048) 343 cacheTotalCapacity = 96 * 1024 * 1024; 344 else if (memorySize >= 1536) 345 cacheTotalCapacity = 64 * 1024 * 1024; 346 else if (memorySize >= 1024) 347 cacheTotalCapacity = 32 * 1024 * 1024; 348 else if (memorySize >= 512) 349 cacheTotalCapacity = 16 * 1024 * 1024; 350 351 cacheMinDeadCapacity = 0; 352 cacheMaxDeadCapacity = 0; 353 354 // Foundation memory cache capacity (in bytes) 355 urlCacheMemoryCapacity = 0; 356 357 // Foundation disk cache capacity (in bytes) 358 urlCacheDiskCapacity = 0; 359 360 break; 361 } 362 case CacheModelDocumentBrowser: { 363 // Page cache capacity (in pages) 364 if (memorySize >= 1024) 365 pageCacheCapacity = 3; 366 else if (memorySize >= 512) 367 pageCacheCapacity = 2; 368 else if (memorySize >= 256) 369 pageCacheCapacity = 1; 370 else 371 pageCacheCapacity = 0; 372 373 // Object cache capacities (in bytes) 374 if (memorySize >= 2048) 375 cacheTotalCapacity = 96 * 1024 * 1024; 376 else if (memorySize >= 1536) 377 cacheTotalCapacity = 64 * 1024 * 1024; 378 else if (memorySize >= 1024) 379 cacheTotalCapacity = 32 * 1024 * 1024; 380 else if (memorySize >= 512) 381 cacheTotalCapacity = 16 * 1024 * 1024; 382 383 cacheMinDeadCapacity = cacheTotalCapacity / 8; 384 cacheMaxDeadCapacity = cacheTotalCapacity / 4; 385 386 // Foundation memory cache capacity (in bytes) 387 if (memorySize >= 2048) 388 urlCacheMemoryCapacity = 4 * 1024 * 1024; 389 else if (memorySize >= 1024) 390 urlCacheMemoryCapacity = 2 * 1024 * 1024; 391 else if (memorySize >= 512) 392 urlCacheMemoryCapacity = 1 * 1024 * 1024; 393 else 394 urlCacheMemoryCapacity = 512 * 1024; 395 396 // Foundation disk cache capacity (in bytes) 397 if (diskFreeSize >= 16384) 398 urlCacheDiskCapacity = 50 * 1024 * 1024; 399 else if (diskFreeSize >= 8192) 400 urlCacheDiskCapacity = 40 * 1024 * 1024; 401 else if (diskFreeSize >= 4096) 402 urlCacheDiskCapacity = 30 * 1024 * 1024; 403 else 404 urlCacheDiskCapacity = 20 * 1024 * 1024; 405 406 break; 407 } 408 case CacheModelPrimaryWebBrowser: { 409 // Page cache capacity (in pages) 410 // (Research indicates that value / page drops substantially after 3 pages.) 411 if (memorySize >= 2048) 412 pageCacheCapacity = 5; 413 else if (memorySize >= 1024) 414 pageCacheCapacity = 4; 415 else if (memorySize >= 512) 416 pageCacheCapacity = 3; 417 else if (memorySize >= 256) 418 pageCacheCapacity = 2; 419 else 420 pageCacheCapacity = 1; 421 422 // Object cache capacities (in bytes) 423 // (Testing indicates that value / MB depends heavily on content and 424 // browsing pattern. Even growth above 128MB can have substantial 425 // value / MB for some content / browsing patterns.) 426 if (memorySize >= 2048) 427 cacheTotalCapacity = 128 * 1024 * 1024; 428 else if (memorySize >= 1536) 429 cacheTotalCapacity = 96 * 1024 * 1024; 430 else if (memorySize >= 1024) 431 cacheTotalCapacity = 64 * 1024 * 1024; 432 else if (memorySize >= 512) 433 cacheTotalCapacity = 32 * 1024 * 1024; 434 435 cacheMinDeadCapacity = cacheTotalCapacity / 4; 436 cacheMaxDeadCapacity = cacheTotalCapacity / 2; 437 438 // This code is here to avoid a PLT regression. We can remove it if we 439 // can prove that the overall system gain would justify the regression. 440 cacheMaxDeadCapacity = std::max(24u, cacheMaxDeadCapacity); 441 442 deadDecodedDataDeletionInterval = 60; 443 444 // Foundation memory cache capacity (in bytes) 445 // (These values are small because WebCore does most caching itself.) 446 if (memorySize >= 1024) 447 urlCacheMemoryCapacity = 4 * 1024 * 1024; 448 else if (memorySize >= 512) 449 urlCacheMemoryCapacity = 2 * 1024 * 1024; 450 else if (memorySize >= 256) 451 urlCacheMemoryCapacity = 1 * 1024 * 1024; 452 else 453 urlCacheMemoryCapacity = 512 * 1024; 454 455 // Foundation disk cache capacity (in bytes) 456 if (diskFreeSize >= 16384) 457 urlCacheDiskCapacity = 175 * 1024 * 1024; 458 else if (diskFreeSize >= 8192) 459 urlCacheDiskCapacity = 150 * 1024 * 1024; 460 else if (diskFreeSize >= 4096) 461 urlCacheDiskCapacity = 125 * 1024 * 1024; 462 else if (diskFreeSize >= 2048) 463 urlCacheDiskCapacity = 100 * 1024 * 1024; 464 else if (diskFreeSize >= 1024) 465 urlCacheDiskCapacity = 75 * 1024 * 1024; 466 else 467 urlCacheDiskCapacity = 50 * 1024 * 1024; 468 469 break; 470 } 471 default: 472 ASSERT_NOT_REACHED(); 473 }; 474 } 475 476 WebPage* WebProcess::focusedWebPage() const 477 { 478 HashMap<uint64_t, RefPtr<WebPage> >::const_iterator end = m_pageMap.end(); 479 for (HashMap<uint64_t, RefPtr<WebPage> >::const_iterator it = m_pageMap.begin(); it != end; ++it) { 480 WebPage* page = (*it).second.get(); 481 if (page->windowIsFocused()) 482 return page; 483 } 484 return 0; 485 } 486 487 WebPage* WebProcess::webPage(uint64_t pageID) const 488 { 489 return m_pageMap.get(pageID).get(); 490 } 491 492 void WebProcess::createWebPage(uint64_t pageID, const WebPageCreationParameters& parameters) 493 { 494 // It is necessary to check for page existence here since during a window.open() (or targeted 495 // link) the WebPage gets created both in the synchronous handler and through the normal way. 496 std::pair<HashMap<uint64_t, RefPtr<WebPage> >::iterator, bool> result = m_pageMap.add(pageID, 0); 497 if (result.second) { 498 ASSERT(!result.first->second); 499 result.first->second = WebPage::create(pageID, parameters); 500 501 // Balanced by an enableTermination in removeWebPage. 502 disableTermination(); 503 } 504 505 ASSERT(result.first->second); 506 } 507 508 void WebProcess::removeWebPage(uint64_t pageID) 509 { 510 ASSERT(m_pageMap.contains(pageID)); 511 512 m_pageMap.remove(pageID); 513 514 enableTermination(); 515 } 516 517 bool WebProcess::isSeparateProcess() const 518 { 519 // If we're running on the main run loop, we assume that we're in a separate process. 520 return m_runLoop == RunLoop::main(); 521 } 522 523 bool WebProcess::shouldTerminate() 524 { 525 // Keep running forever if we're running in the same process. 526 if (!isSeparateProcess()) 527 return false; 528 529 ASSERT(m_pageMap.isEmpty()); 530 ASSERT(!DownloadManager::shared().isDownloading()); 531 532 // FIXME: the ShouldTerminate message should also send termination parameters, such as any session cookies that need to be preserved. 533 bool shouldTerminate = false; 534 if (m_connection->sendSync(Messages::WebProcessProxy::ShouldTerminate(), Messages::WebProcessProxy::ShouldTerminate::Reply(shouldTerminate), 0) 535 && !shouldTerminate) 536 return false; 537 538 return true; 539 } 540 541 void WebProcess::terminate() 542 { 543 #ifndef NDEBUG 544 gcController().garbageCollectNow(); 545 memoryCache()->setDisabled(true); 546 #endif 547 548 // Invalidate our connection. 549 m_connection->invalidate(); 550 m_connection = nullptr; 551 552 platformTerminate(); 553 m_runLoop->stop(); 554 } 555 556 CoreIPC::SyncReplyMode WebProcess::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments, CoreIPC::ArgumentEncoder* reply) 557 { 558 uint64_t pageID = arguments->destinationID(); 559 if (!pageID) 560 return CoreIPC::AutomaticReply; 561 562 WebPage* page = webPage(pageID); 563 if (!page) 564 return CoreIPC::AutomaticReply; 565 566 page->didReceiveSyncMessage(connection, messageID, arguments, reply); 567 return CoreIPC::AutomaticReply; 568 } 569 570 void WebProcess::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments) 571 { 572 if (messageID.is<CoreIPC::MessageClassWebProcess>()) { 573 didReceiveWebProcessMessage(connection, messageID, arguments); 574 return; 575 } 576 577 if (messageID.is<CoreIPC::MessageClassAuthenticationManager>()) { 578 AuthenticationManager::shared().didReceiveMessage(connection, messageID, arguments); 579 return; 580 } 581 582 if (messageID.is<CoreIPC::MessageClassWebApplicationCacheManager>()) { 583 WebApplicationCacheManager::shared().didReceiveMessage(connection, messageID, arguments); 584 return; 585 } 586 587 if (messageID.is<CoreIPC::MessageClassWebCookieManager>()) { 588 WebCookieManager::shared().didReceiveMessage(connection, messageID, arguments); 589 return; 590 } 591 592 if (messageID.is<CoreIPC::MessageClassWebDatabaseManager>()) { 593 WebDatabaseManager::shared().didReceiveMessage(connection, messageID, arguments); 594 return; 595 } 596 597 if (messageID.is<CoreIPC::MessageClassWebGeolocationManager>()) { 598 m_geolocationManager.didReceiveMessage(connection, messageID, arguments); 599 return; 600 } 601 602 if (messageID.is<CoreIPC::MessageClassWebIconDatabaseProxy>()) { 603 m_iconDatabaseProxy.didReceiveMessage(connection, messageID, arguments); 604 return; 605 } 606 607 if (messageID.is<CoreIPC::MessageClassWebKeyValueStorageManager>()) { 608 WebKeyValueStorageManager::shared().didReceiveMessage(connection, messageID, arguments); 609 return; 610 } 611 612 if (messageID.is<CoreIPC::MessageClassWebMediaCacheManager>()) { 613 WebMediaCacheManager::shared().didReceiveMessage(connection, messageID, arguments); 614 return; 615 } 616 617 if (messageID.is<CoreIPC::MessageClassWebResourceCacheManager>()) { 618 WebResourceCacheManager::shared().didReceiveMessage(connection, messageID, arguments); 619 return; 620 } 621 622 if (messageID.is<CoreIPC::MessageClassInjectedBundle>()) { 623 if (!m_injectedBundle) 624 return; 625 m_injectedBundle->didReceiveMessage(connection, messageID, arguments); 626 return; 627 } 628 629 uint64_t pageID = arguments->destinationID(); 630 if (!pageID) 631 return; 632 633 WebPage* page = webPage(pageID); 634 if (!page) 635 return; 636 637 page->didReceiveMessage(connection, messageID, arguments); 638 } 639 640 void WebProcess::didClose(CoreIPC::Connection*) 641 { 642 // When running in the same process the connection will never be closed. 643 ASSERT(isSeparateProcess()); 644 645 #ifndef NDEBUG 646 m_inDidClose = true; 647 648 // Close all the live pages. 649 Vector<RefPtr<WebPage> > pages; 650 copyValuesToVector(m_pageMap, pages); 651 for (size_t i = 0; i < pages.size(); ++i) 652 pages[i]->close(); 653 pages.clear(); 654 655 gcController().garbageCollectNow(); 656 memoryCache()->setDisabled(true); 657 #endif 658 659 // The UI process closed this connection, shut down. 660 m_runLoop->stop(); 661 } 662 663 void WebProcess::didReceiveInvalidMessage(CoreIPC::Connection*, CoreIPC::MessageID) 664 { 665 // We received an invalid message, but since this is from the UI process (which we trust), 666 // we'll let it slide. 667 } 668 669 void WebProcess::syncMessageSendTimedOut(CoreIPC::Connection*) 670 { 671 } 672 673 WebFrame* WebProcess::webFrame(uint64_t frameID) const 674 { 675 return m_frameMap.get(frameID); 676 } 677 678 void WebProcess::addWebFrame(uint64_t frameID, WebFrame* frame) 679 { 680 m_frameMap.set(frameID, frame); 681 } 682 683 void WebProcess::removeWebFrame(uint64_t frameID) 684 { 685 m_frameMap.remove(frameID); 686 687 // We can end up here after our connection has closed when WebCore's frame life-support timer 688 // fires when the application is shutting down. There's no need (and no way) to update the UI 689 // process in this case. 690 if (!m_connection) 691 return; 692 693 m_connection->send(Messages::WebProcessProxy::DidDestroyFrame(frameID), 0); 694 } 695 696 WebPageGroupProxy* WebProcess::webPageGroup(uint64_t pageGroupID) 697 { 698 return m_pageGroupMap.get(pageGroupID).get(); 699 } 700 701 WebPageGroupProxy* WebProcess::webPageGroup(const WebPageGroupData& pageGroupData) 702 { 703 std::pair<HashMap<uint64_t, RefPtr<WebPageGroupProxy> >::iterator, bool> result = m_pageGroupMap.add(pageGroupData.pageGroupID, 0); 704 if (result.second) { 705 ASSERT(!result.first->second); 706 result.first->second = WebPageGroupProxy::create(pageGroupData); 707 } 708 709 return result.first->second.get(); 710 } 711 712 void WebProcess::clearResourceCaches(ResourceCachesToClear resourceCachesToClear) 713 { 714 platformClearResourceCaches(resourceCachesToClear); 715 716 // Toggling the cache model like this forces the cache to evict all its in-memory resources. 717 // FIXME: We need a better way to do this. 718 CacheModel cacheModel = m_cacheModel; 719 setCacheModel(CacheModelDocumentViewer); 720 setCacheModel(cacheModel); 721 722 memoryCache()->evictResources(); 723 724 // Empty the cross-origin preflight cache. 725 CrossOriginPreflightResultCache::shared().empty(); 726 } 727 728 void WebProcess::clearApplicationCache() 729 { 730 #if ENABLE(OFFLINE_WEB_APPLICATIONS) 731 // Empty the application cache. 732 cacheStorage().empty(); 733 #endif 734 } 735 736 #if !ENABLE(PLUGIN_PROCESS) 737 void WebProcess::getSitesWithPluginData(const Vector<String>& pluginPaths, uint64_t callbackID) 738 { 739 LocalTerminationDisabler terminationDisabler(*this); 740 741 HashSet<String> sitesSet; 742 743 for (size_t i = 0; i < pluginPaths.size(); ++i) { 744 RefPtr<NetscapePluginModule> netscapePluginModule = NetscapePluginModule::getOrCreate(pluginPaths[i]); 745 if (!netscapePluginModule) 746 continue; 747 748 Vector<String> sites = netscapePluginModule->sitesWithData(); 749 for (size_t i = 0; i < sites.size(); ++i) 750 sitesSet.add(sites[i]); 751 } 752 753 Vector<String> sites; 754 copyToVector(sitesSet, sites); 755 756 m_connection->send(Messages::WebContext::DidGetSitesWithPluginData(sites, callbackID), 0); 757 } 758 759 void WebProcess::clearPluginSiteData(const Vector<String>& pluginPaths, const Vector<String>& sites, uint64_t flags, uint64_t maxAgeInSeconds, uint64_t callbackID) 760 { 761 LocalTerminationDisabler terminationDisabler(*this); 762 763 for (size_t i = 0; i < pluginPaths.size(); ++i) { 764 RefPtr<NetscapePluginModule> netscapePluginModule = NetscapePluginModule::getOrCreate(pluginPaths[i]); 765 if (!netscapePluginModule) 766 continue; 767 768 if (sites.isEmpty()) { 769 // Clear everything. 770 netscapePluginModule->clearSiteData(String(), flags, maxAgeInSeconds); 771 continue; 772 } 773 774 for (size_t i = 0; i < sites.size(); ++i) 775 netscapePluginModule->clearSiteData(sites[i], flags, maxAgeInSeconds); 776 } 777 778 m_connection->send(Messages::WebContext::DidClearPluginSiteData(callbackID), 0); 779 } 780 #endif 781 782 void WebProcess::downloadRequest(uint64_t downloadID, uint64_t initiatingPageID, const ResourceRequest& request) 783 { 784 WebPage* initiatingPage = initiatingPageID ? webPage(initiatingPageID) : 0; 785 786 DownloadManager::shared().startDownload(downloadID, initiatingPage, request); 787 } 788 789 void WebProcess::cancelDownload(uint64_t downloadID) 790 { 791 DownloadManager::shared().cancelDownload(downloadID); 792 } 793 794 void WebProcess::setEnhancedAccessibility(bool flag) 795 { 796 WebCore::AXObjectCache::setEnhancedUserInterfaceAccessibility(flag); 797 } 798 799 void WebProcess::startMemorySampler(const SandboxExtension::Handle& sampleLogFileHandle, const String& sampleLogFilePath, const double interval) 800 { 801 #if ENABLE(MEMORY_SAMPLER) 802 WebMemorySampler::shared()->start(sampleLogFileHandle, sampleLogFilePath, interval); 803 #endif 804 } 805 806 void WebProcess::stopMemorySampler() 807 { 808 #if ENABLE(MEMORY_SAMPLER) 809 WebMemorySampler::shared()->stop(); 810 #endif 811 } 812 813 void WebProcess::setTextCheckerState(const TextCheckerState& textCheckerState) 814 { 815 bool continuousSpellCheckingTurnedOff = !textCheckerState.isContinuousSpellCheckingEnabled && m_textCheckerState.isContinuousSpellCheckingEnabled; 816 bool grammarCheckingTurnedOff = !textCheckerState.isGrammarCheckingEnabled && m_textCheckerState.isGrammarCheckingEnabled; 817 818 m_textCheckerState = textCheckerState; 819 820 if (!continuousSpellCheckingTurnedOff && !grammarCheckingTurnedOff) 821 return; 822 823 HashMap<uint64_t, RefPtr<WebPage> >::iterator end = m_pageMap.end(); 824 for (HashMap<uint64_t, RefPtr<WebPage> >::iterator it = m_pageMap.begin(); it != end; ++it) { 825 WebPage* page = (*it).second.get(); 826 if (continuousSpellCheckingTurnedOff) 827 page->unmarkAllMisspellings(); 828 if (grammarCheckingTurnedOff) 829 page->unmarkAllBadGrammar(); 830 } 831 } 832 833 } // namespace WebKit 834