Home | History | Annotate | Download | only in WebProcess
      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