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
226 if (!injectedBundlePath().isEmpty()) {
227 parameters.injectedBundlePath = injectedBundlePath();
228
229 SandboxExtension::createHandle(parameters.injectedBundlePath, SandboxExtension::ReadOnly, parameters.injectedBundlePathExtensionHandle);
230 }
231
232 parameters.shouldTrackVisitedLinks = m_historyClient.shouldTrackVisitedLinks();
233 parameters.cacheModel = m_cacheModel;
234 parameters.languageCode = defaultLanguage();
235 parameters.applicationCacheDirectory = applicationCacheDirectory();
236 parameters.databaseDirectory = databaseDirectory();
237 parameters.localStorageDirectory = localStorageDirectory();
238 #if PLATFORM(MAC)
239 parameters.presenterApplicationPid = getpid();
240 #endif
241
242 copyToVector(m_schemesToRegisterAsEmptyDocument, parameters.urlSchemesRegistererdAsEmptyDocument);
243 copyToVector(m_schemesToRegisterAsSecure, parameters.urlSchemesRegisteredAsSecure);
244 copyToVector(m_schemesToSetDomainRelaxationForbiddenFor, parameters.urlSchemesForWhichDomainRelaxationIsForbidden);
245
246 parameters.shouldAlwaysUseComplexTextCodePath = m_alwaysUsesComplexTextCodePath;
247
248 parameters.iconDatabaseEnabled = !iconDatabasePath().isEmpty();
249
250 parameters.textCheckerState = TextChecker::state();
251
252 parameters.defaultRequestTimeoutInterval = WebURLRequest::defaultTimeoutInterval();
253
254 // Add any platform specific parameters
255 platformInitializeWebProcess(parameters);
256
257 m_process->send(Messages::WebProcess::InitializeWebProcess(parameters, WebContextUserMessageEncoder(m_injectedBundleInitializationUserData.get())), 0);
258
259 for (size_t i = 0; i != m_pendingMessagesToPostToInjectedBundle.size(); ++i) {
260 pair<String, RefPtr<APIObject> >& message = m_pendingMessagesToPostToInjectedBundle[i];
261 m_process->deprecatedSend(InjectedBundleMessage::PostMessage, 0, CoreIPC::In(message.first, WebContextUserMessageEncoder(message.second.get())));
262 }
263 m_pendingMessagesToPostToInjectedBundle.clear();
264 }
265
enableProcessTermination()266 void WebContext::enableProcessTermination()
267 {
268 m_processTerminationEnabled = true;
269 if (shouldTerminate(m_process.get()))
270 m_process->terminate();
271 }
272
shouldTerminate(WebProcessProxy * process)273 bool WebContext::shouldTerminate(WebProcessProxy* process)
274 {
275 // FIXME: Once we support multiple processes per context, this assertion won't hold.
276 ASSERT(process == m_process);
277
278 if (!m_processTerminationEnabled)
279 return false;
280
281 if (!m_downloads.isEmpty())
282 return false;
283
284 if (!m_applicationCacheManagerProxy->shouldTerminate(process))
285 return false;
286 if (!m_cookieManagerProxy->shouldTerminate(process))
287 return false;
288 if (!m_databaseManagerProxy->shouldTerminate(process))
289 return false;
290 if (!m_keyValueStorageManagerProxy->shouldTerminate(process))
291 return false;
292 if (!m_mediaCacheManagerProxy->shouldTerminate(process))
293 return false;
294 if (!m_pluginSiteDataManager->shouldTerminate(process))
295 return false;
296 if (!m_resourceCacheManagerProxy->shouldTerminate(process))
297 return false;
298
299 return true;
300 }
301
processDidFinishLaunching(WebProcessProxy * process)302 void WebContext::processDidFinishLaunching(WebProcessProxy* process)
303 {
304 // FIXME: Once we support multiple processes per context, this assertion won't hold.
305 ASSERT_UNUSED(process, process == m_process);
306
307 m_visitedLinkProvider.processDidFinishLaunching();
308
309 // Sometimes the memorySampler gets initialized after process initialization has happened but before the process has finished launching
310 // so check if it needs to be started here
311 if (m_memorySamplerEnabled) {
312 SandboxExtension::Handle sampleLogSandboxHandle;
313 double now = WTF::currentTime();
314 String sampleLogFilePath = String::format("WebProcess%llu", static_cast<uint64_t>(now));
315 sampleLogFilePath = SandboxExtension::createHandleForTemporaryFile(sampleLogFilePath, SandboxExtension::WriteOnly, sampleLogSandboxHandle);
316
317 m_process->send(Messages::WebProcess::StartMemorySampler(sampleLogSandboxHandle, sampleLogFilePath, m_memorySamplerInterval), 0);
318 }
319 }
320
disconnectProcess(WebProcessProxy * process)321 void WebContext::disconnectProcess(WebProcessProxy* process)
322 {
323 // FIXME: Once we support multiple processes per context, this assertion won't hold.
324 ASSERT_UNUSED(process, process == m_process);
325
326 m_visitedLinkProvider.processDidClose();
327
328 // Invalidate all outstanding downloads.
329 for (HashMap<uint64_t, RefPtr<DownloadProxy> >::iterator::Values it = m_downloads.begin().values(), end = m_downloads.end().values(); it != end; ++it) {
330 (*it)->processDidClose();
331 (*it)->invalidate();
332 }
333
334 m_downloads.clear();
335
336 m_applicationCacheManagerProxy->invalidate();
337 m_cookieManagerProxy->invalidate();
338 m_databaseManagerProxy->invalidate();
339 m_geolocationManagerProxy->invalidate();
340 m_keyValueStorageManagerProxy->invalidate();
341 m_mediaCacheManagerProxy->invalidate();
342 m_resourceCacheManagerProxy->invalidate();
343
344 // When out of process plug-ins are enabled, we don't want to invalidate the plug-in site data
345 // manager just because the web process crashes since it's not involved.
346 #if !ENABLE(PLUGIN_PROCESS)
347 m_pluginSiteDataManager->invalidate();
348 #endif
349
350 // This can cause the web context to be destroyed.
351 m_process = 0;
352 }
353
createWebPage(PageClient * pageClient,WebPageGroup * pageGroup)354 PassRefPtr<WebPageProxy> WebContext::createWebPage(PageClient* pageClient, WebPageGroup* pageGroup)
355 {
356 ensureWebProcess();
357
358 if (!pageGroup)
359 pageGroup = m_defaultPageGroup.get();
360
361 return m_process->createWebPage(pageClient, this, pageGroup);
362 }
363
relaunchProcessIfNecessary()364 WebProcessProxy* WebContext::relaunchProcessIfNecessary()
365 {
366 ensureWebProcess();
367
368 ASSERT(m_process);
369 return m_process.get();
370 }
371
download(WebPageProxy * initiatingPage,const ResourceRequest & request)372 DownloadProxy* WebContext::download(WebPageProxy* initiatingPage, const ResourceRequest& request)
373 {
374 DownloadProxy* download = createDownloadProxy();
375 uint64_t initiatingPageID = initiatingPage ? initiatingPage->pageID() : 0;
376
377 process()->send(Messages::WebProcess::DownloadRequest(download->downloadID(), initiatingPageID, request), 0);
378 return download;
379 }
380
postMessageToInjectedBundle(const String & messageName,APIObject * messageBody)381 void WebContext::postMessageToInjectedBundle(const String& messageName, APIObject* messageBody)
382 {
383 if (!m_process || !m_process->canSendMessage()) {
384 m_pendingMessagesToPostToInjectedBundle.append(make_pair(messageName, messageBody));
385 return;
386 }
387
388 // FIXME: We should consider returning false from this function if the messageBody cannot
389 // be encoded.
390 m_process->deprecatedSend(InjectedBundleMessage::PostMessage, 0, CoreIPC::In(messageName, WebContextUserMessageEncoder(messageBody)));
391 }
392
393 // InjectedBundle client
394
didReceiveMessageFromInjectedBundle(const String & messageName,APIObject * messageBody)395 void WebContext::didReceiveMessageFromInjectedBundle(const String& messageName, APIObject* messageBody)
396 {
397 m_injectedBundleClient.didReceiveMessageFromInjectedBundle(this, messageName, messageBody);
398 }
399
didReceiveSynchronousMessageFromInjectedBundle(const String & messageName,APIObject * messageBody,RefPtr<APIObject> & returnData)400 void WebContext::didReceiveSynchronousMessageFromInjectedBundle(const String& messageName, APIObject* messageBody, RefPtr<APIObject>& returnData)
401 {
402 m_injectedBundleClient.didReceiveSynchronousMessageFromInjectedBundle(this, messageName, messageBody, returnData);
403 }
404
405 // HistoryClient
406
didNavigateWithNavigationData(uint64_t pageID,const WebNavigationDataStore & store,uint64_t frameID)407 void WebContext::didNavigateWithNavigationData(uint64_t pageID, const WebNavigationDataStore& store, uint64_t frameID)
408 {
409 WebFrameProxy* frame = m_process->webFrame(frameID);
410 MESSAGE_CHECK(frame);
411 if (!frame->page())
412 return;
413
414 m_historyClient.didNavigateWithNavigationData(this, frame->page(), store, frame);
415 }
416
didPerformClientRedirect(uint64_t pageID,const String & sourceURLString,const String & destinationURLString,uint64_t frameID)417 void WebContext::didPerformClientRedirect(uint64_t pageID, const String& sourceURLString, const String& destinationURLString, uint64_t frameID)
418 {
419 WebFrameProxy* frame = m_process->webFrame(frameID);
420 MESSAGE_CHECK(frame);
421 if (!frame->page())
422 return;
423
424 m_historyClient.didPerformClientRedirect(this, frame->page(), sourceURLString, destinationURLString, frame);
425 }
426
didPerformServerRedirect(uint64_t pageID,const String & sourceURLString,const String & destinationURLString,uint64_t frameID)427 void WebContext::didPerformServerRedirect(uint64_t pageID, const String& sourceURLString, const String& destinationURLString, uint64_t frameID)
428 {
429 WebFrameProxy* frame = m_process->webFrame(frameID);
430 MESSAGE_CHECK(frame);
431 if (!frame->page())
432 return;
433
434 m_historyClient.didPerformServerRedirect(this, frame->page(), sourceURLString, destinationURLString, frame);
435 }
436
didUpdateHistoryTitle(uint64_t pageID,const String & title,const String & url,uint64_t frameID)437 void WebContext::didUpdateHistoryTitle(uint64_t pageID, const String& title, const String& url, uint64_t frameID)
438 {
439 WebFrameProxy* frame = m_process->webFrame(frameID);
440 MESSAGE_CHECK(frame);
441 if (!frame->page())
442 return;
443
444 m_historyClient.didUpdateHistoryTitle(this, frame->page(), title, url, frame);
445 }
446
populateVisitedLinks()447 void WebContext::populateVisitedLinks()
448 {
449 m_historyClient.populateVisitedLinks(this);
450 }
451
statistics()452 WebContext::Statistics& WebContext::statistics()
453 {
454 static Statistics statistics = Statistics();
455
456 return statistics;
457 }
458
setAdditionalPluginsDirectory(const String & directory)459 void WebContext::setAdditionalPluginsDirectory(const String& directory)
460 {
461 Vector<String> directories;
462 directories.append(directory);
463
464 m_pluginInfoStore.setAdditionalPluginsDirectories(directories);
465 }
466
setAlwaysUsesComplexTextCodePath(bool alwaysUseComplexText)467 void WebContext::setAlwaysUsesComplexTextCodePath(bool alwaysUseComplexText)
468 {
469 m_alwaysUsesComplexTextCodePath = alwaysUseComplexText;
470 sendToAllProcesses(Messages::WebProcess::SetAlwaysUsesComplexTextCodePath(alwaysUseComplexText));
471 }
472
registerURLSchemeAsEmptyDocument(const String & urlScheme)473 void WebContext::registerURLSchemeAsEmptyDocument(const String& urlScheme)
474 {
475 m_schemesToRegisterAsEmptyDocument.add(urlScheme);
476 sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsEmptyDocument(urlScheme));
477 }
478
registerURLSchemeAsSecure(const String & urlScheme)479 void WebContext::registerURLSchemeAsSecure(const String& urlScheme)
480 {
481 m_schemesToRegisterAsSecure.add(urlScheme);
482 sendToAllProcesses(Messages::WebProcess::RegisterURLSchemeAsSecure(urlScheme));
483 }
484
setDomainRelaxationForbiddenForURLScheme(const String & urlScheme)485 void WebContext::setDomainRelaxationForbiddenForURLScheme(const String& urlScheme)
486 {
487 m_schemesToSetDomainRelaxationForbiddenFor.add(urlScheme);
488 sendToAllProcesses(Messages::WebProcess::SetDomainRelaxationForbiddenForURLScheme(urlScheme));
489 }
490
setCacheModel(CacheModel cacheModel)491 void WebContext::setCacheModel(CacheModel cacheModel)
492 {
493 m_cacheModel = cacheModel;
494 sendToAllProcesses(Messages::WebProcess::SetCacheModel(static_cast<uint32_t>(m_cacheModel)));
495 }
496
setDefaultRequestTimeoutInterval(double timeoutInterval)497 void WebContext::setDefaultRequestTimeoutInterval(double timeoutInterval)
498 {
499 sendToAllProcesses(Messages::WebProcess::SetDefaultRequestTimeoutInterval(timeoutInterval));
500 }
501
addVisitedLink(const String & visitedURL)502 void WebContext::addVisitedLink(const String& visitedURL)
503 {
504 if (visitedURL.isEmpty())
505 return;
506
507 LinkHash linkHash = visitedLinkHash(visitedURL.characters(), visitedURL.length());
508 addVisitedLinkHash(linkHash);
509 }
510
addVisitedLinkHash(LinkHash linkHash)511 void WebContext::addVisitedLinkHash(LinkHash linkHash)
512 {
513 m_visitedLinkProvider.addVisitedLink(linkHash);
514 }
515
getPlugins(bool refresh,Vector<PluginInfo> & plugins)516 void WebContext::getPlugins(bool refresh, Vector<PluginInfo>& plugins)
517 {
518 if (refresh)
519 pluginInfoStore()->refresh();
520 pluginInfoStore()->getPlugins(plugins);
521 }
522
getPluginPath(const String & mimeType,const String & urlString,String & pluginPath)523 void WebContext::getPluginPath(const String& mimeType, const String& urlString, String& pluginPath)
524 {
525 String newMimeType = mimeType.lower();
526
527 PluginInfoStore::Plugin plugin = pluginInfoStore()->findPlugin(newMimeType, KURL(ParsedURLString, urlString));
528 if (!plugin.path)
529 return;
530
531 pluginPath = plugin.path;
532 }
533
534 #if !ENABLE(PLUGIN_PROCESS)
didGetSitesWithPluginData(const Vector<String> & sites,uint64_t callbackID)535 void WebContext::didGetSitesWithPluginData(const Vector<String>& sites, uint64_t callbackID)
536 {
537 m_pluginSiteDataManager->didGetSitesWithData(sites, callbackID);
538 }
539
didClearPluginSiteData(uint64_t callbackID)540 void WebContext::didClearPluginSiteData(uint64_t callbackID)
541 {
542 m_pluginSiteDataManager->didClearSiteData(callbackID);
543 }
544 #endif
545
createDownloadProxy()546 DownloadProxy* WebContext::createDownloadProxy()
547 {
548 RefPtr<DownloadProxy> downloadProxy = DownloadProxy::create(this);
549 m_downloads.set(downloadProxy->downloadID(), downloadProxy);
550 return downloadProxy.get();
551 }
552
downloadFinished(DownloadProxy * downloadProxy)553 void WebContext::downloadFinished(DownloadProxy* downloadProxy)
554 {
555 ASSERT(m_downloads.contains(downloadProxy->downloadID()));
556
557 downloadProxy->invalidate();
558 m_downloads.remove(downloadProxy->downloadID());
559 }
560
561 // FIXME: This is not the ideal place for this function.
pdfAndPostScriptMIMETypes()562 HashSet<String, CaseFoldingHash> WebContext::pdfAndPostScriptMIMETypes()
563 {
564 HashSet<String, CaseFoldingHash> mimeTypes;
565
566 mimeTypes.add("application/pdf");
567 mimeTypes.add("application/postscript");
568 mimeTypes.add("text/pdf");
569
570 return mimeTypes;
571 }
572
didReceiveMessage(CoreIPC::Connection * connection,CoreIPC::MessageID messageID,CoreIPC::ArgumentDecoder * arguments)573 void WebContext::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments)
574 {
575 if (messageID.is<CoreIPC::MessageClassWebContext>()) {
576 didReceiveWebContextMessage(connection, messageID, arguments);
577 return;
578 }
579
580 if (messageID.is<CoreIPC::MessageClassDownloadProxy>()) {
581 if (DownloadProxy* downloadProxy = m_downloads.get(arguments->destinationID()).get())
582 downloadProxy->didReceiveDownloadProxyMessage(connection, messageID, arguments);
583
584 return;
585 }
586
587 if (messageID.is<CoreIPC::MessageClassWebApplicationCacheManagerProxy>()) {
588 m_applicationCacheManagerProxy->didReceiveMessage(connection, messageID, arguments);
589 return;
590 }
591
592 if (messageID.is<CoreIPC::MessageClassWebCookieManagerProxy>()) {
593 m_cookieManagerProxy->didReceiveMessage(connection, messageID, arguments);
594 return;
595 }
596
597 if (messageID.is<CoreIPC::MessageClassWebDatabaseManagerProxy>()) {
598 m_databaseManagerProxy->didReceiveWebDatabaseManagerProxyMessage(connection, messageID, arguments);
599 return;
600 }
601
602 if (messageID.is<CoreIPC::MessageClassWebGeolocationManagerProxy>()) {
603 m_geolocationManagerProxy->didReceiveMessage(connection, messageID, arguments);
604 return;
605 }
606
607 if (messageID.is<CoreIPC::MessageClassWebIconDatabase>()) {
608 m_iconDatabase->didReceiveMessage(connection, messageID, arguments);
609 return;
610 }
611
612 if (messageID.is<CoreIPC::MessageClassWebKeyValueStorageManagerProxy>()) {
613 m_keyValueStorageManagerProxy->didReceiveMessage(connection, messageID, arguments);
614 return;
615 }
616
617 if (messageID.is<CoreIPC::MessageClassWebMediaCacheManagerProxy>()) {
618 m_mediaCacheManagerProxy->didReceiveMessage(connection, messageID, arguments);
619 return;
620 }
621
622 if (messageID.is<CoreIPC::MessageClassWebResourceCacheManagerProxy>()) {
623 m_resourceCacheManagerProxy->didReceiveWebResourceCacheManagerProxyMessage(connection, messageID, arguments);
624 return;
625 }
626
627 switch (messageID.get<WebContextLegacyMessage::Kind>()) {
628 case WebContextLegacyMessage::PostMessage: {
629 String messageName;
630 RefPtr<APIObject> messageBody;
631 WebContextUserMessageDecoder messageDecoder(messageBody, this);
632 if (!arguments->decode(CoreIPC::Out(messageName, messageDecoder)))
633 return;
634
635 didReceiveMessageFromInjectedBundle(messageName, messageBody.get());
636 return;
637 }
638 case WebContextLegacyMessage::PostSynchronousMessage:
639 ASSERT_NOT_REACHED();
640 }
641
642 ASSERT_NOT_REACHED();
643 }
644
didReceiveSyncMessage(CoreIPC::Connection * connection,CoreIPC::MessageID messageID,CoreIPC::ArgumentDecoder * arguments,CoreIPC::ArgumentEncoder * reply)645 CoreIPC::SyncReplyMode WebContext::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments, CoreIPC::ArgumentEncoder* reply)
646 {
647 if (messageID.is<CoreIPC::MessageClassWebContext>())
648 return didReceiveSyncWebContextMessage(connection, messageID, arguments, reply);
649
650 if (messageID.is<CoreIPC::MessageClassDownloadProxy>()) {
651 if (DownloadProxy* downloadProxy = m_downloads.get(arguments->destinationID()).get())
652 return downloadProxy->didReceiveSyncDownloadProxyMessage(connection, messageID, arguments, reply);
653
654 return CoreIPC::AutomaticReply;
655 }
656
657 if (messageID.is<CoreIPC::MessageClassWebIconDatabase>())
658 return m_iconDatabase->didReceiveSyncMessage(connection, messageID, arguments, reply);
659
660 switch (messageID.get<WebContextLegacyMessage::Kind>()) {
661 case WebContextLegacyMessage::PostSynchronousMessage: {
662 // FIXME: We should probably encode something in the case that the arguments do not decode correctly.
663
664 String messageName;
665 RefPtr<APIObject> messageBody;
666 WebContextUserMessageDecoder messageDecoder(messageBody, this);
667 if (!arguments->decode(CoreIPC::Out(messageName, messageDecoder)))
668 return CoreIPC::AutomaticReply;
669
670 RefPtr<APIObject> returnData;
671 didReceiveSynchronousMessageFromInjectedBundle(messageName, messageBody.get(), returnData);
672 reply->encode(CoreIPC::In(WebContextUserMessageEncoder(returnData.get())));
673 return CoreIPC::AutomaticReply;
674 }
675 case WebContextLegacyMessage::PostMessage:
676 ASSERT_NOT_REACHED();
677 }
678
679 return CoreIPC::AutomaticReply;
680 }
681
setEnhancedAccessibility(bool flag)682 void WebContext::setEnhancedAccessibility(bool flag)
683 {
684 sendToAllProcesses(Messages::WebProcess::SetEnhancedAccessibility(flag));
685 }
686
startMemorySampler(const double interval)687 void WebContext::startMemorySampler(const double interval)
688 {
689 // For new WebProcesses we will also want to start the Memory Sampler
690 m_memorySamplerEnabled = true;
691 m_memorySamplerInterval = interval;
692
693 // For UIProcess
694 #if ENABLE(MEMORY_SAMPLER)
695 WebMemorySampler::shared()->start(interval);
696 #endif
697
698 // For WebProcess
699 SandboxExtension::Handle sampleLogSandboxHandle;
700 double now = WTF::currentTime();
701 String sampleLogFilePath = String::format("WebProcess%llu", static_cast<uint64_t>(now));
702 sampleLogFilePath = SandboxExtension::createHandleForTemporaryFile(sampleLogFilePath, SandboxExtension::WriteOnly, sampleLogSandboxHandle);
703
704 sendToAllProcesses(Messages::WebProcess::StartMemorySampler(sampleLogSandboxHandle, sampleLogFilePath, interval));
705 }
706
stopMemorySampler()707 void WebContext::stopMemorySampler()
708 {
709 // For WebProcess
710 m_memorySamplerEnabled = false;
711
712 // For UIProcess
713 #if ENABLE(MEMORY_SAMPLER)
714 WebMemorySampler::shared()->stop();
715 #endif
716
717 sendToAllProcesses(Messages::WebProcess::StopMemorySampler());
718 }
719
databaseDirectory() const720 String WebContext::databaseDirectory() const
721 {
722 if (!m_overrideDatabaseDirectory.isEmpty())
723 return m_overrideDatabaseDirectory;
724
725 return platformDefaultDatabaseDirectory();
726 }
727
setIconDatabasePath(const String & path)728 void WebContext::setIconDatabasePath(const String& path)
729 {
730 m_overrideIconDatabasePath = path;
731 m_iconDatabase->setDatabasePath(path);
732 }
733
iconDatabasePath() const734 String WebContext::iconDatabasePath() const
735 {
736 if (!m_overrideIconDatabasePath.isEmpty())
737 return m_overrideIconDatabasePath;
738
739 return platformDefaultIconDatabasePath();
740 }
741
localStorageDirectory() const742 String WebContext::localStorageDirectory() const
743 {
744 if (!m_overrideLocalStorageDirectory.isEmpty())
745 return m_overrideLocalStorageDirectory;
746
747 return platformDefaultLocalStorageDirectory();
748 }
749
setHTTPPipeliningEnabled(bool enabled)750 void WebContext::setHTTPPipeliningEnabled(bool enabled)
751 {
752 #if PLATFORM(MAC)
753 ResourceRequest::setHTTPPipeliningEnabled(enabled);
754 #endif
755 }
756
httpPipeliningEnabled()757 bool WebContext::httpPipeliningEnabled()
758 {
759 #if PLATFORM(MAC)
760 return ResourceRequest::httpPipeliningEnabled();
761 #else
762 return false;
763 #endif
764 }
765
766 } // namespace WebKit
767