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