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