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