a1b4e4eeee9859f357c5ef3988eeb7ab5857f2a5
[WebKit-https.git] / Source / WebKit2 / UIProcess / WebContext.cpp
1 /*
2  * Copyright (C) 2010, 2011 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 "WebContext.h"
28
29 #include "DownloadProxy.h"
30 #include "ImmutableArray.h"
31 #include "InjectedBundleMessageKinds.h"
32 #include "Logging.h"
33 #include "RunLoop.h"
34 #include "SandboxExtension.h"
35 #include "TextChecker.h"
36 #include "WKContextPrivate.h"
37 #include "WebApplicationCacheManagerProxy.h"
38 #include "WebContextMessageKinds.h"
39 #include "WebContextUserMessageCoders.h"
40 #include "WebCookieManagerProxy.h"
41 #include "WebCoreArgumentCoders.h"
42 #include "WebDatabaseManagerProxy.h"
43 #include "WebGeolocationManagerProxy.h"
44 #include "WebIconDatabase.h"
45 #include "WebKeyValueStorageManagerProxy.h"
46 #include "WebMediaCacheManagerProxy.h"
47 #include "WebPluginSiteDataManager.h"
48 #include "WebPageGroup.h"
49 #include "WebMemorySampler.h"
50 #include "WebProcessCreationParameters.h"
51 #include "WebProcessMessages.h"
52 #include "WebProcessProxy.h"
53 #include "WebResourceCacheManagerProxy.h"
54 #include <WebCore/Language.h>
55 #include <WebCore/LinkHash.h>
56 #include <WebCore/Logging.h>
57 #include <WebCore/ResourceRequest.h>
58 #include <runtime/InitializeThreading.h>
59 #include <wtf/CurrentTime.h>
60 #include <wtf/MainThread.h>
61
62 #ifndef NDEBUG
63 #include <wtf/RefCountedLeakCounter.h>
64 #endif
65
66 #define MESSAGE_CHECK(assertion) MESSAGE_CHECK_BASE(assertion, process()->connection())
67
68 using namespace WebCore;
69
70 namespace WebKit {
71
72 #ifndef NDEBUG
73 static WTF::RefCountedLeakCounter webContextCounter("WebContext");
74 #endif
75
76 WebContext* WebContext::sharedProcessContext()
77 {
78     JSC::initializeThreading();
79     WTF::initializeMainThread();
80     RunLoop::initializeMainRunLoop();
81     static WebContext* context = adoptRef(new WebContext(ProcessModelSharedSecondaryProcess, String())).leakRef();
82     return context;
83 }
84
85 WebContext* WebContext::sharedThreadContext()
86 {
87     RunLoop::initializeMainRunLoop();
88     static WebContext* context = adoptRef(new WebContext(ProcessModelSharedSecondaryThread, String())).leakRef();
89     return context;
90 }
91
92 PassRefPtr<WebContext> WebContext::create(const String& injectedBundlePath)
93 {
94     JSC::initializeThreading();
95     WTF::initializeMainThread();
96     RunLoop::initializeMainRunLoop();
97     return adoptRef(new WebContext(ProcessModelSecondaryProcess, injectedBundlePath));
98 }
99
100 static Vector<WebContext*>& contexts()
101 {
102     DEFINE_STATIC_LOCAL(Vector<WebContext*>, contexts, ());
103
104     return contexts;
105 }
106
107 const Vector<WebContext*>& WebContext::allContexts()
108 {
109     return contexts();
110 }
111
112 WebContext::WebContext(ProcessModel processModel, const String& injectedBundlePath)
113     : m_processModel(processModel)
114     , m_defaultPageGroup(WebPageGroup::create())
115     , m_injectedBundlePath(injectedBundlePath)
116     , m_visitedLinkProvider(this)
117     , m_alwaysUsesComplexTextCodePath(false)
118     , m_cacheModel(CacheModelDocumentViewer)
119     , m_memorySamplerEnabled(false)
120     , m_memorySamplerInterval(1400.0)
121     , m_applicationCacheManagerProxy(WebApplicationCacheManagerProxy::create(this))
122     , m_cookieManagerProxy(WebCookieManagerProxy::create(this))
123     , m_databaseManagerProxy(WebDatabaseManagerProxy::create(this))
124     , m_geolocationManagerProxy(WebGeolocationManagerProxy::create(this))
125     , m_iconDatabase(WebIconDatabase::create(this))
126     , m_keyValueStorageManagerProxy(WebKeyValueStorageManagerProxy::create(this))
127     , m_mediaCacheManagerProxy(WebMediaCacheManagerProxy::create(this))
128     , m_pluginSiteDataManager(WebPluginSiteDataManager::create(this))
129     , m_resourceCacheManagerProxy(WebResourceCacheManagerProxy::create(this))
130 #if PLATFORM(WIN)
131     , m_shouldPaintNativeControls(true)
132     , m_initialHTTPCookieAcceptPolicy(HTTPCookieAcceptPolicyAlways)
133 #endif
134     , m_processTerminationEnabled(true)
135 {
136 #if !LOG_DISABLED
137     WebKit::initializeLogChannelsIfNecessary();
138 #endif
139
140     contexts().append(this);
141
142     addLanguageChangeObserver(this, languageChanged);
143
144     WebCore::InitializeLoggingChannelsIfNecessary();
145
146 #ifndef NDEBUG
147     webContextCounter.increment();
148 #endif
149 }
150
151 WebContext::~WebContext()
152 {
153     ASSERT(contexts().find(this) != notFound);
154     contexts().remove(contexts().find(this));
155
156     removeLanguageChangeObserver(this);
157
158     m_applicationCacheManagerProxy->invalidate();
159     m_applicationCacheManagerProxy->clearContext();
160
161     m_cookieManagerProxy->invalidate();
162     m_cookieManagerProxy->clearContext();
163
164     m_databaseManagerProxy->invalidate();
165     m_databaseManagerProxy->clearContext();
166     
167     m_geolocationManagerProxy->invalidate();
168     m_geolocationManagerProxy->clearContext();
169
170     m_iconDatabase->invalidate();
171     m_iconDatabase->clearContext();
172     
173     m_keyValueStorageManagerProxy->invalidate();
174     m_keyValueStorageManagerProxy->clearContext();
175
176     m_mediaCacheManagerProxy->invalidate();
177     m_mediaCacheManagerProxy->clearContext();
178
179     m_pluginSiteDataManager->invalidate();
180     m_pluginSiteDataManager->clearContext();
181
182     m_resourceCacheManagerProxy->invalidate();
183     m_resourceCacheManagerProxy->clearContext();
184
185     platformInvalidateContext();
186     
187 #ifndef NDEBUG
188     webContextCounter.decrement();
189 #endif
190 }
191
192 void WebContext::initializeInjectedBundleClient(const WKContextInjectedBundleClient* client)
193 {
194     m_injectedBundleClient.initialize(client);
195 }
196
197 void WebContext::initializeHistoryClient(const WKContextHistoryClient* client)
198 {
199     m_historyClient.initialize(client);
200
201     sendToAllProcesses(Messages::WebProcess::SetShouldTrackVisitedLinks(m_historyClient.shouldTrackVisitedLinks()));
202 }
203
204 void WebContext::initializeDownloadClient(const WKContextDownloadClient* client)
205 {
206     m_downloadClient.initialize(client);
207 }
208     
209 void WebContext::languageChanged(void* context)
210 {
211     static_cast<WebContext*>(context)->languageChanged();
212 }
213
214 void WebContext::languageChanged()
215 {
216     sendToAllProcesses(Messages::WebProcess::LanguageChanged(defaultLanguage()));
217 }
218
219 void WebContext::ensureWebProcess()
220 {
221     if (m_process)
222         return;
223
224     m_process = WebProcessProxy::create(this);
225
226     WebProcessCreationParameters parameters;
227
228     if (!injectedBundlePath().isEmpty()) {
229         parameters.injectedBundlePath = injectedBundlePath();
230         SandboxExtension::createHandle(parameters.injectedBundlePath, SandboxExtension::ReadOnly, parameters.injectedBundlePathExtensionHandle);
231     }
232
233     parameters.shouldTrackVisitedLinks = m_historyClient.shouldTrackVisitedLinks();
234     parameters.cacheModel = m_cacheModel;
235     parameters.languageCode = defaultLanguage();
236     parameters.applicationCacheDirectory = applicationCacheDirectory();
237     parameters.databaseDirectory = databaseDirectory();
238     parameters.localStorageDirectory = localStorageDirectory();
239 #if PLATFORM(MAC)
240     parameters.presenterApplicationPid = getpid();
241 #endif
242
243     copyToVector(m_schemesToRegisterAsEmptyDocument, parameters.urlSchemesRegistererdAsEmptyDocument);
244     copyToVector(m_schemesToRegisterAsSecure, parameters.urlSchemesRegisteredAsSecure);
245     copyToVector(m_schemesToSetDomainRelaxationForbiddenFor, parameters.urlSchemesForWhichDomainRelaxationIsForbidden);
246
247     parameters.shouldAlwaysUseComplexTextCodePath = m_alwaysUsesComplexTextCodePath;
248     
249     parameters.iconDatabaseEnabled = !iconDatabasePath().isEmpty();
250
251     parameters.textCheckerState = TextChecker::state();
252
253     parameters.defaultRequestTimeoutInterval = WebURLRequest::defaultTimeoutInterval();
254
255     // Add any platform specific parameters
256     platformInitializeWebProcess(parameters);
257
258     m_process->send(Messages::WebProcess::InitializeWebProcess(parameters, WebContextUserMessageEncoder(m_injectedBundleInitializationUserData.get())), 0);
259
260     for (size_t i = 0; i != m_pendingMessagesToPostToInjectedBundle.size(); ++i) {
261         pair<String, RefPtr<APIObject> >& message = m_pendingMessagesToPostToInjectedBundle[i];
262         m_process->deprecatedSend(InjectedBundleMessage::PostMessage, 0, CoreIPC::In(message.first, WebContextUserMessageEncoder(message.second.get())));
263     }
264     m_pendingMessagesToPostToInjectedBundle.clear();
265 }
266
267 void WebContext::warmInitialProcess()  
268 {
269     ensureWebProcess();
270 }
271
272 void WebContext::enableProcessTermination()
273 {
274     m_processTerminationEnabled = true;
275     if (shouldTerminate(m_process.get()))
276         m_process->terminate();
277 }
278
279 bool WebContext::shouldTerminate(WebProcessProxy* process)
280 {
281     // FIXME: Once we support multiple processes per context, this assertion won't hold.
282     ASSERT(process == m_process);
283
284     if (!m_processTerminationEnabled)
285         return false;
286
287     if (!m_downloads.isEmpty())
288         return false;
289
290     if (!m_applicationCacheManagerProxy->shouldTerminate(process))
291         return false;
292     if (!m_cookieManagerProxy->shouldTerminate(process))
293         return false;
294     if (!m_databaseManagerProxy->shouldTerminate(process))
295         return false;
296     if (!m_keyValueStorageManagerProxy->shouldTerminate(process))
297         return false;
298     if (!m_mediaCacheManagerProxy->shouldTerminate(process))
299         return false;
300     if (!m_pluginSiteDataManager->shouldTerminate(process))
301         return false;
302     if (!m_resourceCacheManagerProxy->shouldTerminate(process))
303         return false;
304
305     return true;
306 }
307
308 void WebContext::processDidFinishLaunching(WebProcessProxy* process)
309 {
310     // FIXME: Once we support multiple processes per context, this assertion won't hold.
311     ASSERT_UNUSED(process, process == m_process);
312
313     m_visitedLinkProvider.processDidFinishLaunching();
314     
315     // Sometimes the memorySampler gets initialized after process initialization has happened but before the process has finished launching
316     // so check if it needs to be started here
317     if (m_memorySamplerEnabled) {
318         SandboxExtension::Handle sampleLogSandboxHandle;        
319         double now = WTF::currentTime();
320         String sampleLogFilePath = String::format("WebProcess%llu", static_cast<uint64_t>(now));
321         sampleLogFilePath = SandboxExtension::createHandleForTemporaryFile(sampleLogFilePath, SandboxExtension::WriteOnly, sampleLogSandboxHandle);
322         
323         m_process->send(Messages::WebProcess::StartMemorySampler(sampleLogSandboxHandle, sampleLogFilePath, m_memorySamplerInterval), 0);
324     }
325 }
326
327 void WebContext::disconnectProcess(WebProcessProxy* process)
328 {
329     // FIXME: Once we support multiple processes per context, this assertion won't hold.
330     ASSERT_UNUSED(process, process == m_process);
331
332     m_visitedLinkProvider.processDidClose();
333
334     // Invalidate all outstanding downloads.
335     for (HashMap<uint64_t, RefPtr<DownloadProxy> >::iterator::Values it = m_downloads.begin().values(), end = m_downloads.end().values(); it != end; ++it) {
336         (*it)->processDidClose();
337         (*it)->invalidate();
338     }
339
340     m_downloads.clear();
341
342     m_applicationCacheManagerProxy->invalidate();
343     m_cookieManagerProxy->invalidate();
344     m_databaseManagerProxy->invalidate();
345     m_geolocationManagerProxy->invalidate();
346     m_keyValueStorageManagerProxy->invalidate();
347     m_mediaCacheManagerProxy->invalidate();
348     m_resourceCacheManagerProxy->invalidate();
349
350     // When out of process plug-ins are enabled, we don't want to invalidate the plug-in site data
351     // manager just because the web process crashes since it's not involved.
352 #if !ENABLE(PLUGIN_PROCESS)
353     m_pluginSiteDataManager->invalidate();
354 #endif
355
356     // This can cause the web context to be destroyed.
357     m_process = 0;
358 }
359
360 PassRefPtr<WebPageProxy> WebContext::createWebPage(PageClient* pageClient, WebPageGroup* pageGroup)
361 {
362     ensureWebProcess();
363
364     if (!pageGroup)
365         pageGroup = m_defaultPageGroup.get();
366
367     return m_process->createWebPage(pageClient, this, pageGroup);
368 }
369
370 WebProcessProxy* WebContext::relaunchProcessIfNecessary()
371 {
372     ensureWebProcess();
373
374     ASSERT(m_process);
375     return m_process.get();
376 }
377
378 DownloadProxy* WebContext::download(WebPageProxy* initiatingPage, const ResourceRequest& request)
379 {
380     DownloadProxy* download = createDownloadProxy();
381     uint64_t initiatingPageID = initiatingPage ? initiatingPage->pageID() : 0;
382
383     process()->send(Messages::WebProcess::DownloadRequest(download->downloadID(), initiatingPageID, request), 0);
384     return download;
385 }
386
387 void WebContext::postMessageToInjectedBundle(const String& messageName, APIObject* messageBody)
388 {
389     if (!m_process || !m_process->canSendMessage()) {
390         m_pendingMessagesToPostToInjectedBundle.append(make_pair(messageName, messageBody));
391         return;
392     }
393
394     // FIXME: We should consider returning false from this function if the messageBody cannot
395     // be encoded.
396     m_process->deprecatedSend(InjectedBundleMessage::PostMessage, 0, CoreIPC::In(messageName, WebContextUserMessageEncoder(messageBody)));
397 }
398
399 // InjectedBundle client
400
401 void WebContext::didReceiveMessageFromInjectedBundle(const String& messageName, APIObject* messageBody)
402 {
403     m_injectedBundleClient.didReceiveMessageFromInjectedBundle(this, messageName, messageBody);
404 }
405
406 void WebContext::didReceiveSynchronousMessageFromInjectedBundle(const String& messageName, APIObject* messageBody, RefPtr<APIObject>& returnData)
407 {
408     m_injectedBundleClient.didReceiveSynchronousMessageFromInjectedBundle(this, messageName, messageBody, returnData);
409 }
410
411 // HistoryClient
412
413 void WebContext::didNavigateWithNavigationData(uint64_t pageID, const WebNavigationDataStore& store, uint64_t frameID) 
414 {
415     WebPageProxy* page = m_process->webPage(pageID);
416     if (!page)
417         return;
418     
419     WebFrameProxy* frame = m_process->webFrame(frameID);
420     MESSAGE_CHECK(frame);
421     MESSAGE_CHECK(frame->page() == page);
422     
423     m_historyClient.didNavigateWithNavigationData(this, page, store, frame);
424 }
425
426 void WebContext::didPerformClientRedirect(uint64_t pageID, const String& sourceURLString, const String& destinationURLString, uint64_t frameID)
427 {
428     WebPageProxy* page = m_process->webPage(pageID);
429     if (!page)
430         return;
431     
432     WebFrameProxy* frame = m_process->webFrame(frameID);
433     MESSAGE_CHECK(frame);
434     MESSAGE_CHECK(frame->page() == page);
435     
436     m_historyClient.didPerformClientRedirect(this, page, sourceURLString, destinationURLString, frame);
437 }
438
439 void WebContext::didPerformServerRedirect(uint64_t pageID, const String& sourceURLString, const String& destinationURLString, uint64_t frameID)
440 {
441     WebPageProxy* page = m_process->webPage(pageID);
442     if (!page)
443         return;
444     
445     WebFrameProxy* frame = m_process->webFrame(frameID);
446     MESSAGE_CHECK(frame);
447     MESSAGE_CHECK(frame->page() == page);
448     
449     m_historyClient.didPerformServerRedirect(this, page, sourceURLString, destinationURLString, frame);
450 }
451
452 void WebContext::didUpdateHistoryTitle(uint64_t pageID, const String& title, const String& url, uint64_t frameID)
453 {
454     WebPageProxy* page = m_process->webPage(pageID);
455     if (!page)
456         return;
457
458     WebFrameProxy* frame = m_process->webFrame(frameID);
459     MESSAGE_CHECK(frame);
460     MESSAGE_CHECK(frame->page() == page);
461
462     m_historyClient.didUpdateHistoryTitle(this, page, title, url, frame);
463 }
464
465 void WebContext::populateVisitedLinks()
466 {
467     m_historyClient.populateVisitedLinks(this);
468 }
469
470 WebContext::Statistics& WebContext::statistics()
471 {
472     static Statistics statistics = Statistics();
473
474     return statistics;
475 }
476
477 void WebContext::setAdditionalPluginsDirectory(const String& directory)
478 {
479     Vector<String> directories;
480     directories.append(directory);
481
482     m_pluginInfoStore.setAdditionalPluginsDirectories(directories);
483 }
484
485 void WebContext::setAlwaysUsesComplexTextCodePath(bool alwaysUseComplexText)
486 {
487     m_alwaysUsesComplexTextCodePath = alwaysUseComplexText;
488     sendToAllProcesses(Messages::WebProcess::SetAlwaysUsesComplexTextCodePath(alwaysUseComplexText));
489 }
490
491 void WebContext::registerURLSchemeAsEmptyDocument(const String& urlScheme)
492 {
493     m_schemesToRegisterAsEmptyDocument.add(urlScheme);
494     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsEmptyDocument(urlScheme));
495 }
496
497 void WebContext::registerURLSchemeAsSecure(const String& urlScheme)
498 {
499     m_schemesToRegisterAsSecure.add(urlScheme);
500     sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsSecure(urlScheme));
501 }
502
503 void WebContext::setDomainRelaxationForbiddenForURLScheme(const String& urlScheme)
504 {
505     m_schemesToSetDomainRelaxationForbiddenFor.add(urlScheme);
506     sendToAllProcesses(Messages::WebProcess::SetDomainRelaxationForbiddenForURLScheme(urlScheme));
507 }
508
509 void WebContext::setCacheModel(CacheModel cacheModel)
510 {
511     m_cacheModel = cacheModel;
512     sendToAllProcesses(Messages::WebProcess::SetCacheModel(static_cast<uint32_t>(m_cacheModel)));
513 }
514
515 void WebContext::setDefaultRequestTimeoutInterval(double timeoutInterval)
516 {
517     sendToAllProcesses(Messages::WebProcess::SetDefaultRequestTimeoutInterval(timeoutInterval));
518 }
519
520 void WebContext::addVisitedLink(const String& visitedURL)
521 {
522     if (visitedURL.isEmpty())
523         return;
524
525     LinkHash linkHash = visitedLinkHash(visitedURL.characters(), visitedURL.length());
526     addVisitedLinkHash(linkHash);
527 }
528
529 void WebContext::addVisitedLinkHash(LinkHash linkHash)
530 {
531     m_visitedLinkProvider.addVisitedLink(linkHash);
532 }
533
534 void WebContext::getPlugins(bool refresh, Vector<PluginInfo>& pluginInfos)
535 {
536     if (refresh)
537         m_pluginInfoStore.refresh();
538
539     Vector<PluginModuleInfo> plugins = m_pluginInfoStore.plugins();
540     for (size_t i = 0; i < plugins.size(); ++i)
541         pluginInfos.append(plugins[i].info);
542 }
543
544 void WebContext::getPluginPath(const String& mimeType, const String& urlString, String& pluginPath)
545 {
546     String newMimeType = mimeType.lower();
547
548     PluginModuleInfo plugin = pluginInfoStore().findPlugin(newMimeType, KURL(ParsedURLString, urlString));
549     if (!plugin.path)
550         return;
551
552     pluginPath = plugin.path;
553 }
554
555 #if !ENABLE(PLUGIN_PROCESS)
556 void WebContext::didGetSitesWithPluginData(const Vector<String>& sites, uint64_t callbackID)
557 {
558     m_pluginSiteDataManager->didGetSitesWithData(sites, callbackID);
559 }
560
561 void WebContext::didClearPluginSiteData(uint64_t callbackID)
562 {
563     m_pluginSiteDataManager->didClearSiteData(callbackID);
564 }
565 #endif
566
567 DownloadProxy* WebContext::createDownloadProxy()
568 {
569     RefPtr<DownloadProxy> downloadProxy = DownloadProxy::create(this);
570     m_downloads.set(downloadProxy->downloadID(), downloadProxy);
571     return downloadProxy.get();
572 }
573
574 void WebContext::downloadFinished(DownloadProxy* downloadProxy)
575 {
576     ASSERT(m_downloads.contains(downloadProxy->downloadID()));
577
578     downloadProxy->invalidate();
579     m_downloads.remove(downloadProxy->downloadID());
580 }
581
582 // FIXME: This is not the ideal place for this function.
583 HashSet<String, CaseFoldingHash> WebContext::pdfAndPostScriptMIMETypes()
584 {
585     HashSet<String, CaseFoldingHash> mimeTypes;
586
587     mimeTypes.add("application/pdf");
588     mimeTypes.add("application/postscript");
589     mimeTypes.add("text/pdf");
590     
591     return mimeTypes;
592 }
593
594 void WebContext::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments)
595 {
596     if (messageID.is<CoreIPC::MessageClassWebContext>()) {
597         didReceiveWebContextMessage(connection, messageID, arguments);
598         return;
599     }
600
601     if (messageID.is<CoreIPC::MessageClassDownloadProxy>()) {
602         if (DownloadProxy* downloadProxy = m_downloads.get(arguments->destinationID()).get())
603             downloadProxy->didReceiveDownloadProxyMessage(connection, messageID, arguments);
604         
605         return;
606     }
607
608     if (messageID.is<CoreIPC::MessageClassWebApplicationCacheManagerProxy>()) {
609         m_applicationCacheManagerProxy->didReceiveMessage(connection, messageID, arguments);
610         return;
611     }
612
613     if (messageID.is<CoreIPC::MessageClassWebCookieManagerProxy>()) {
614         m_cookieManagerProxy->didReceiveMessage(connection, messageID, arguments);
615         return;
616     }
617
618     if (messageID.is<CoreIPC::MessageClassWebDatabaseManagerProxy>()) {
619         m_databaseManagerProxy->didReceiveWebDatabaseManagerProxyMessage(connection, messageID, arguments);
620         return;
621     }
622
623     if (messageID.is<CoreIPC::MessageClassWebGeolocationManagerProxy>()) {
624         m_geolocationManagerProxy->didReceiveMessage(connection, messageID, arguments);
625         return;
626     }
627     
628     if (messageID.is<CoreIPC::MessageClassWebIconDatabase>()) {
629         m_iconDatabase->didReceiveMessage(connection, messageID, arguments);
630         return;
631     }
632
633     if (messageID.is<CoreIPC::MessageClassWebKeyValueStorageManagerProxy>()) {
634         m_keyValueStorageManagerProxy->didReceiveMessage(connection, messageID, arguments);
635         return;
636     }
637
638     if (messageID.is<CoreIPC::MessageClassWebMediaCacheManagerProxy>()) {
639         m_mediaCacheManagerProxy->didReceiveMessage(connection, messageID, arguments);
640         return;
641     }
642
643     if (messageID.is<CoreIPC::MessageClassWebResourceCacheManagerProxy>()) {
644         m_resourceCacheManagerProxy->didReceiveWebResourceCacheManagerProxyMessage(connection, messageID, arguments);
645         return;
646     }
647
648     switch (messageID.get<WebContextLegacyMessage::Kind>()) {
649         case WebContextLegacyMessage::PostMessage: {
650             String messageName;
651             RefPtr<APIObject> messageBody;
652             WebContextUserMessageDecoder messageDecoder(messageBody, this);
653             if (!arguments->decode(CoreIPC::Out(messageName, messageDecoder)))
654                 return;
655
656             didReceiveMessageFromInjectedBundle(messageName, messageBody.get());
657             return;
658         }
659         case WebContextLegacyMessage::PostSynchronousMessage:
660             ASSERT_NOT_REACHED();
661     }
662
663     ASSERT_NOT_REACHED();
664 }
665
666 void WebContext::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments, OwnPtr<CoreIPC::ArgumentEncoder>& reply)
667 {
668     if (messageID.is<CoreIPC::MessageClassWebContext>()) {
669         didReceiveSyncWebContextMessage(connection, messageID, arguments, reply);
670         return;
671     }
672
673     if (messageID.is<CoreIPC::MessageClassDownloadProxy>()) {
674         if (DownloadProxy* downloadProxy = m_downloads.get(arguments->destinationID()).get())
675             downloadProxy->didReceiveSyncDownloadProxyMessage(connection, messageID, arguments, reply);
676         return;
677     }
678     
679     if (messageID.is<CoreIPC::MessageClassWebIconDatabase>()) {
680         m_iconDatabase->didReceiveSyncMessage(connection, messageID, arguments, reply);
681         return;
682     }
683     
684     switch (messageID.get<WebContextLegacyMessage::Kind>()) {
685         case WebContextLegacyMessage::PostSynchronousMessage: {
686             // FIXME: We should probably encode something in the case that the arguments do not decode correctly.
687
688             String messageName;
689             RefPtr<APIObject> messageBody;
690             WebContextUserMessageDecoder messageDecoder(messageBody, this);
691             if (!arguments->decode(CoreIPC::Out(messageName, messageDecoder)))
692                 return;
693
694             RefPtr<APIObject> returnData;
695             didReceiveSynchronousMessageFromInjectedBundle(messageName, messageBody.get(), returnData);
696             reply->encode(CoreIPC::In(WebContextUserMessageEncoder(returnData.get())));
697             return;
698         }
699         case WebContextLegacyMessage::PostMessage:
700             ASSERT_NOT_REACHED();
701     }
702 }
703
704 void WebContext::setEnhancedAccessibility(bool flag)
705 {
706     sendToAllProcesses(Messages::WebProcess::SetEnhancedAccessibility(flag));
707 }
708     
709 void WebContext::startMemorySampler(const double interval)
710 {    
711     // For new WebProcesses we will also want to start the Memory Sampler
712     m_memorySamplerEnabled = true;
713     m_memorySamplerInterval = interval;
714     
715     // For UIProcess
716 #if ENABLE(MEMORY_SAMPLER)
717     WebMemorySampler::shared()->start(interval);
718 #endif
719     
720     // For WebProcess
721     SandboxExtension::Handle sampleLogSandboxHandle;    
722     double now = WTF::currentTime();
723     String sampleLogFilePath = String::format("WebProcess%llu", static_cast<uint64_t>(now));
724     sampleLogFilePath = SandboxExtension::createHandleForTemporaryFile(sampleLogFilePath, SandboxExtension::WriteOnly, sampleLogSandboxHandle);
725     
726     sendToAllProcesses(Messages::WebProcess::StartMemorySampler(sampleLogSandboxHandle, sampleLogFilePath, interval));
727 }
728
729 void WebContext::stopMemorySampler()
730 {    
731     // For WebProcess
732     m_memorySamplerEnabled = false;
733     
734     // For UIProcess
735 #if ENABLE(MEMORY_SAMPLER)
736     WebMemorySampler::shared()->stop();
737 #endif
738
739     sendToAllProcesses(Messages::WebProcess::StopMemorySampler());
740 }
741
742 String WebContext::databaseDirectory() const
743 {
744     if (!m_overrideDatabaseDirectory.isEmpty())
745         return m_overrideDatabaseDirectory;
746
747     return platformDefaultDatabaseDirectory();
748 }
749
750 void WebContext::setIconDatabasePath(const String& path)
751 {
752     m_overrideIconDatabasePath = path;
753     m_iconDatabase->setDatabasePath(path);
754 }
755
756 String WebContext::iconDatabasePath() const
757 {
758     if (!m_overrideIconDatabasePath.isEmpty())
759         return m_overrideIconDatabasePath;
760
761     return platformDefaultIconDatabasePath();
762 }
763
764 String WebContext::localStorageDirectory() const
765 {
766     if (!m_overrideLocalStorageDirectory.isEmpty())
767         return m_overrideLocalStorageDirectory;
768
769     return platformDefaultLocalStorageDirectory();
770 }
771
772 void WebContext::setHTTPPipeliningEnabled(bool enabled)
773 {
774 #if PLATFORM(MAC)
775     ResourceRequest::setHTTPPipeliningEnabled(enabled);
776 #endif
777 }
778
779 bool WebContext::httpPipeliningEnabled()
780 {
781 #if PLATFORM(MAC)
782     return ResourceRequest::httpPipeliningEnabled();
783 #else
784     return false;
785 #endif
786 }
787
788 } // namespace WebKit