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