1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/renderer_host/render_message_filter.h"
10 #include "base/bind_helpers.h"
11 #include "base/command_line.h"
12 #include "base/debug/alias.h"
13 #include "base/strings/sys_string_conversions.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/threading/thread.h"
16 #include "base/threading/worker_pool.h"
17 #include "content/browser/browser_main_loop.h"
18 #include "content/browser/child_process_security_policy_impl.h"
19 #include "content/browser/dom_storage/dom_storage_context_wrapper.h"
20 #include "content/browser/dom_storage/session_storage_namespace_impl.h"
21 #include "content/browser/download/download_stats.h"
22 #include "content/browser/gpu/gpu_data_manager_impl.h"
23 #include "content/browser/loader/resource_dispatcher_host_impl.h"
24 #include "content/browser/media/media_internals.h"
25 #include "content/browser/plugin_process_host.h"
26 #include "content/browser/plugin_service_impl.h"
27 #include "content/browser/ppapi_plugin_process_host.h"
28 #include "content/browser/renderer_host/pepper/pepper_security_helper.h"
29 #include "content/browser/renderer_host/render_process_host_impl.h"
30 #include "content/browser/renderer_host/render_view_host_delegate.h"
31 #include "content/browser/renderer_host/render_widget_helper.h"
32 #include "content/common/child_process_host_impl.h"
33 #include "content/common/child_process_messages.h"
34 #include "content/common/cookie_data.h"
35 #include "content/common/desktop_notification_messages.h"
36 #include "content/common/frame_messages.h"
37 #include "content/common/host_shared_bitmap_manager.h"
38 #include "content/common/media/media_param_traits.h"
39 #include "content/common/view_messages.h"
40 #include "content/public/browser/browser_child_process_host.h"
41 #include "content/public/browser/browser_context.h"
42 #include "content/public/browser/browser_thread.h"
43 #include "content/public/browser/content_browser_client.h"
44 #include "content/public/browser/download_save_info.h"
45 #include "content/public/browser/plugin_service_filter.h"
46 #include "content/public/browser/resource_context.h"
47 #include "content/public/browser/user_metrics.h"
48 #include "content/public/common/content_constants.h"
49 #include "content/public/common/content_switches.h"
50 #include "content/public/common/context_menu_params.h"
51 #include "content/public/common/url_constants.h"
52 #include "content/public/common/webplugininfo.h"
53 #include "ipc/ipc_channel_handle.h"
54 #include "ipc/ipc_platform_file.h"
55 #include "media/audio/audio_manager.h"
56 #include "media/audio/audio_manager_base.h"
57 #include "media/audio/audio_parameters.h"
58 #include "media/base/media_log_event.h"
59 #include "net/base/io_buffer.h"
60 #include "net/base/keygen_handler.h"
61 #include "net/base/mime_util.h"
62 #include "net/base/request_priority.h"
63 #include "net/cookies/canonical_cookie.h"
64 #include "net/cookies/cookie_store.h"
65 #include "net/http/http_cache.h"
66 #include "net/url_request/url_request_context.h"
67 #include "net/url_request/url_request_context_getter.h"
68 #include "ppapi/shared_impl/file_type_conversion.h"
69 #include "third_party/WebKit/public/web/WebNotificationPresenter.h"
70 #include "ui/gfx/color_profile.h"
72 #if defined(OS_MACOSX)
73 #include "content/common/mac/font_descriptor.h"
75 #include "gpu/GLES2/gl2extchromium.h"
76 #include "third_party/khronos/GLES2/gl2.h"
77 #include "third_party/khronos/GLES2/gl2ext.h"
80 #include "base/file_descriptor_posix.h"
83 #include "content/common/font_cache_dispatcher_win.h"
84 #include "content/common/sandbox_win.h"
86 #if defined(OS_ANDROID)
87 #include "media/base/android/webaudio_media_codec_bridge.h"
90 using net::CookieStore;
95 #if defined(ENABLE_PLUGINS)
96 const int kPluginsRefreshThresholdInSeconds = 3;
99 // When two CPU usage queries arrive within this interval, we sample the CPU
100 // usage only once and send it as a response for both queries.
101 static const int64 kCPUUsageSampleIntervalMs = 900;
103 const uint32 kFilteredMessageClasses[] = {
104 ChildProcessMsgStart,
105 DesktopNotificationMsgStart,
111 // On Windows, |g_color_profile| can run on an arbitrary background thread.
112 // We avoid races by using LazyInstance's constructor lock to initialize the
114 base::LazyInstance<gfx::ColorProfile>::Leaky g_color_profile =
115 LAZY_INSTANCE_INITIALIZER;
118 // Common functionality for converting a sync renderer message to a callback
119 // function in the browser. Derive from this, create it on the heap when
120 // issuing your callback. When done, write your reply parameters into
121 // reply_msg(), and then call SendReplyAndDeleteThis().
122 class RenderMessageCompletionCallback {
124 RenderMessageCompletionCallback(RenderMessageFilter* filter,
125 IPC::Message* reply_msg)
127 reply_msg_(reply_msg) {
130 virtual ~RenderMessageCompletionCallback() {
133 RenderMessageFilter* filter() { return filter_.get(); }
134 IPC::Message* reply_msg() { return reply_msg_; }
136 void SendReplyAndDeleteThis() {
137 filter_->Send(reply_msg_);
142 scoped_refptr<RenderMessageFilter> filter_;
143 IPC::Message* reply_msg_;
146 class OpenChannelToPpapiPluginCallback
147 : public RenderMessageCompletionCallback,
148 public PpapiPluginProcessHost::PluginClient {
150 OpenChannelToPpapiPluginCallback(RenderMessageFilter* filter,
151 ResourceContext* context,
152 IPC::Message* reply_msg)
153 : RenderMessageCompletionCallback(filter, reply_msg),
157 virtual void GetPpapiChannelInfo(base::ProcessHandle* renderer_handle,
158 int* renderer_id) OVERRIDE {
159 *renderer_handle = filter()->PeerHandle();
160 *renderer_id = filter()->render_process_id();
163 virtual void OnPpapiChannelOpened(const IPC::ChannelHandle& channel_handle,
164 base::ProcessId plugin_pid,
165 int plugin_child_id) OVERRIDE {
166 ViewHostMsg_OpenChannelToPepperPlugin::WriteReplyParams(
167 reply_msg(), channel_handle, plugin_pid, plugin_child_id);
168 SendReplyAndDeleteThis();
171 virtual bool OffTheRecord() OVERRIDE {
172 return filter()->OffTheRecord();
175 virtual ResourceContext* GetResourceContext() OVERRIDE {
180 ResourceContext* context_;
183 class OpenChannelToPpapiBrokerCallback
184 : public PpapiPluginProcessHost::BrokerClient {
186 OpenChannelToPpapiBrokerCallback(RenderMessageFilter* filter,
189 routing_id_(routing_id) {
192 virtual ~OpenChannelToPpapiBrokerCallback() {}
194 virtual void GetPpapiChannelInfo(base::ProcessHandle* renderer_handle,
195 int* renderer_id) OVERRIDE {
196 *renderer_handle = filter_->PeerHandle();
197 *renderer_id = filter_->render_process_id();
200 virtual void OnPpapiChannelOpened(const IPC::ChannelHandle& channel_handle,
201 base::ProcessId plugin_pid,
202 int /* plugin_child_id */) OVERRIDE {
203 filter_->Send(new ViewMsg_PpapiBrokerChannelCreated(routing_id_,
209 virtual bool OffTheRecord() OVERRIDE {
210 return filter_->OffTheRecord();
214 scoped_refptr<RenderMessageFilter> filter_;
220 class RenderMessageFilter::OpenChannelToNpapiPluginCallback
221 : public RenderMessageCompletionCallback,
222 public PluginProcessHost::Client {
224 OpenChannelToNpapiPluginCallback(RenderMessageFilter* filter,
225 ResourceContext* context,
226 IPC::Message* reply_msg)
227 : RenderMessageCompletionCallback(filter, reply_msg),
230 sent_plugin_channel_request_(false) {
233 virtual int ID() OVERRIDE {
234 return filter()->render_process_id();
237 virtual ResourceContext* GetResourceContext() OVERRIDE {
241 virtual bool OffTheRecord() OVERRIDE {
242 if (filter()->OffTheRecord())
244 if (GetContentClient()->browser()->AllowSaveLocalState(context_))
247 // For now, only disallow storing data for Flash <http://crbug.com/97319>.
248 for (size_t i = 0; i < info_.mime_types.size(); ++i) {
249 if (info_.mime_types[i].mime_type == kFlashPluginSwfMimeType)
255 virtual void SetPluginInfo(const WebPluginInfo& info) OVERRIDE {
259 virtual void OnFoundPluginProcessHost(PluginProcessHost* host) OVERRIDE {
264 virtual void OnSentPluginChannelRequest() OVERRIDE {
265 sent_plugin_channel_request_ = true;
268 virtual void OnChannelOpened(const IPC::ChannelHandle& handle) OVERRIDE {
269 WriteReplyAndDeleteThis(handle);
272 virtual void OnError() OVERRIDE {
273 WriteReplyAndDeleteThis(IPC::ChannelHandle());
276 PluginProcessHost* host() const {
280 bool sent_plugin_channel_request() const {
281 return sent_plugin_channel_request_;
289 void WriteReplyAndDeleteThis(const IPC::ChannelHandle& handle) {
290 FrameHostMsg_OpenChannelToPlugin::WriteReplyParams(reply_msg(),
292 filter()->OnCompletedOpenChannelToNpapiPlugin(this);
293 SendReplyAndDeleteThis();
296 ResourceContext* context_;
298 PluginProcessHost* host_;
299 bool sent_plugin_channel_request_;
302 RenderMessageFilter::RenderMessageFilter(
303 int render_process_id,
304 PluginServiceImpl* plugin_service,
305 BrowserContext* browser_context,
306 net::URLRequestContextGetter* request_context,
307 RenderWidgetHelper* render_widget_helper,
308 media::AudioManager* audio_manager,
309 MediaInternals* media_internals,
310 DOMStorageContextWrapper* dom_storage_context)
311 : BrowserMessageFilter(
312 kFilteredMessageClasses, arraysize(kFilteredMessageClasses)),
313 resource_dispatcher_host_(ResourceDispatcherHostImpl::Get()),
314 plugin_service_(plugin_service),
315 profile_data_directory_(browser_context->GetPath()),
316 request_context_(request_context),
317 resource_context_(browser_context->GetResourceContext()),
318 render_widget_helper_(render_widget_helper),
319 incognito_(browser_context->IsOffTheRecord()),
320 dom_storage_context_(dom_storage_context),
321 render_process_id_(render_process_id),
323 audio_manager_(audio_manager),
324 media_internals_(media_internals) {
325 DCHECK(request_context_.get());
327 render_widget_helper_->Init(render_process_id_, resource_dispatcher_host_);
330 RenderMessageFilter::~RenderMessageFilter() {
331 // This function should be called on the IO thread.
332 DCHECK_CURRENTLY_ON(BrowserThread::IO);
333 DCHECK(plugin_host_clients_.empty());
334 HostSharedBitmapManager::current()->ProcessRemoved(PeerHandle());
337 void RenderMessageFilter::OnChannelClosing() {
338 #if defined(ENABLE_PLUGINS)
339 for (std::set<OpenChannelToNpapiPluginCallback*>::iterator it =
340 plugin_host_clients_.begin(); it != plugin_host_clients_.end(); ++it) {
341 OpenChannelToNpapiPluginCallback* client = *it;
342 if (client->host()) {
343 if (client->sent_plugin_channel_request()) {
344 client->host()->CancelSentRequest(client);
346 client->host()->CancelPendingRequest(client);
349 plugin_service_->CancelOpenChannelToNpapiPlugin(client);
353 #endif // defined(ENABLE_PLUGINS)
354 plugin_host_clients_.clear();
357 void RenderMessageFilter::OnChannelConnected(int32 peer_id) {
358 base::ProcessHandle handle = PeerHandle();
359 #if defined(OS_MACOSX)
360 process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(handle,
363 process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(handle));
365 cpu_usage_ = process_metrics_->GetCPUUsage(); // Initialize CPU usage counters
366 cpu_usage_sample_time_ = base::TimeTicks::Now();
369 bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message) {
371 IPC_BEGIN_MESSAGE_MAP(RenderMessageFilter, message)
373 IPC_MESSAGE_HANDLER(ViewHostMsg_PreCacheFontCharacters,
374 OnPreCacheFontCharacters)
376 IPC_MESSAGE_HANDLER(ViewHostMsg_GetProcessMemorySizes,
377 OnGetProcessMemorySizes)
378 IPC_MESSAGE_HANDLER(ViewHostMsg_GenerateRoutingID, OnGenerateRoutingID)
379 IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWindow, OnCreateWindow)
380 IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWidget, OnCreateWidget)
381 IPC_MESSAGE_HANDLER(ViewHostMsg_CreateFullscreenWidget,
382 OnCreateFullscreenWidget)
383 IPC_MESSAGE_HANDLER(ViewHostMsg_SetCookie, OnSetCookie)
384 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetCookies, OnGetCookies)
385 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetRawCookies, OnGetRawCookies)
386 IPC_MESSAGE_HANDLER(ViewHostMsg_DeleteCookie, OnDeleteCookie)
387 IPC_MESSAGE_HANDLER(ViewHostMsg_CookiesEnabled, OnCookiesEnabled)
388 #if defined(OS_MACOSX)
389 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_LoadFont, OnLoadFont)
391 IPC_MESSAGE_HANDLER(ViewHostMsg_DownloadUrl, OnDownloadUrl)
392 #if defined(ENABLE_PLUGINS)
393 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetPlugins, OnGetPlugins)
394 IPC_MESSAGE_HANDLER(FrameHostMsg_GetPluginInfo, OnGetPluginInfo)
395 IPC_MESSAGE_HANDLER_DELAY_REPLY(FrameHostMsg_OpenChannelToPlugin,
396 OnOpenChannelToPlugin)
397 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_OpenChannelToPepperPlugin,
398 OnOpenChannelToPepperPlugin)
399 IPC_MESSAGE_HANDLER(ViewHostMsg_DidCreateOutOfProcessPepperInstance,
400 OnDidCreateOutOfProcessPepperInstance)
401 IPC_MESSAGE_HANDLER(ViewHostMsg_DidDeleteOutOfProcessPepperInstance,
402 OnDidDeleteOutOfProcessPepperInstance)
403 IPC_MESSAGE_HANDLER(ViewHostMsg_OpenChannelToPpapiBroker,
404 OnOpenChannelToPpapiBroker)
406 IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_SwapCompositorFrame,
407 render_widget_helper_->DidReceiveBackingStoreMsg(message))
408 IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_UpdateRect,
409 render_widget_helper_->DidReceiveBackingStoreMsg(message))
410 IPC_MESSAGE_HANDLER(DesktopNotificationHostMsg_CheckPermission,
411 OnCheckNotificationPermission)
412 IPC_MESSAGE_HANDLER(ChildProcessHostMsg_SyncAllocateSharedMemory,
413 OnAllocateSharedMemory)
414 IPC_MESSAGE_HANDLER_DELAY_REPLY(
415 ChildProcessHostMsg_SyncAllocateSharedBitmap, OnAllocateSharedBitmap)
416 IPC_MESSAGE_HANDLER(ChildProcessHostMsg_AllocatedSharedBitmap,
417 OnAllocatedSharedBitmap)
418 IPC_MESSAGE_HANDLER(ChildProcessHostMsg_DeletedSharedBitmap,
419 OnDeletedSharedBitmap)
420 #if defined(OS_POSIX) && !defined(OS_ANDROID)
421 IPC_MESSAGE_HANDLER(ViewHostMsg_AllocTransportDIB, OnAllocTransportDIB)
422 IPC_MESSAGE_HANDLER(ViewHostMsg_FreeTransportDIB, OnFreeTransportDIB)
424 IPC_MESSAGE_HANDLER(ViewHostMsg_DidGenerateCacheableMetadata,
425 OnCacheableMetadataAvailable)
426 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_Keygen, OnKeygen)
427 IPC_MESSAGE_HANDLER(ViewHostMsg_GetCPUUsage, OnGetCPUUsage)
428 IPC_MESSAGE_HANDLER(ViewHostMsg_GetAudioHardwareConfig,
429 OnGetAudioHardwareConfig)
431 IPC_MESSAGE_HANDLER(ViewHostMsg_GetMonitorColorProfile,
432 OnGetMonitorColorProfile)
434 IPC_MESSAGE_HANDLER(ViewHostMsg_MediaLogEvents, OnMediaLogEvents)
435 IPC_MESSAGE_HANDLER(ViewHostMsg_Are3DAPIsBlocked, OnAre3DAPIsBlocked)
436 IPC_MESSAGE_HANDLER(ViewHostMsg_DidLose3DContext, OnDidLose3DContext)
437 #if defined(OS_ANDROID)
438 IPC_MESSAGE_HANDLER(ViewHostMsg_RunWebAudioMediaCodec, OnWebAudioMediaCodec)
440 IPC_MESSAGE_UNHANDLED(handled = false)
441 IPC_END_MESSAGE_MAP()
446 void RenderMessageFilter::OnDestruct() const {
447 BrowserThread::DeleteOnIOThread::Destruct(this);
450 base::TaskRunner* RenderMessageFilter::OverrideTaskRunnerForMessage(
451 const IPC::Message& message) {
453 // Windows monitor profile must be read from a file.
454 if (message.type() == ViewHostMsg_GetMonitorColorProfile::ID)
455 return BrowserThread::GetBlockingPool();
457 // Always query audio device parameters on the audio thread.
458 if (message.type() == ViewHostMsg_GetAudioHardwareConfig::ID)
459 return audio_manager_->GetTaskRunner().get();
463 bool RenderMessageFilter::OffTheRecord() const {
467 void RenderMessageFilter::OnCreateWindow(
468 const ViewHostMsg_CreateWindow_Params& params,
470 int* main_frame_route_id,
472 int64* cloned_session_storage_namespace_id) {
473 bool no_javascript_access;
475 // Merge the additional features into the WebWindowFeatures struct before we
477 blink::WebVector<blink::WebString> additional_features(
478 params.additional_features.size());
480 for (size_t i = 0; i < params.additional_features.size(); ++i)
481 additional_features[i] = blink::WebString(params.additional_features[i]);
483 blink::WebWindowFeatures features = params.features;
484 features.additionalFeatures.swap(additional_features);
486 bool can_create_window =
487 GetContentClient()->browser()->CanCreateWindow(
489 params.opener_top_level_frame_url,
490 params.opener_security_origin,
491 params.window_container_type,
497 params.opener_suppressed,
501 &no_javascript_access);
503 if (!can_create_window) {
504 *route_id = MSG_ROUTING_NONE;
505 *main_frame_route_id = MSG_ROUTING_NONE;
510 // This will clone the sessionStorage for namespace_id_to_clone.
511 scoped_refptr<SessionStorageNamespaceImpl> cloned_namespace =
512 new SessionStorageNamespaceImpl(dom_storage_context_.get(),
513 params.session_storage_namespace_id);
514 *cloned_session_storage_namespace_id = cloned_namespace->id();
516 render_widget_helper_->CreateNewWindow(params,
517 no_javascript_access,
522 cloned_namespace.get());
525 void RenderMessageFilter::OnCreateWidget(int opener_id,
526 blink::WebPopupType popup_type,
529 render_widget_helper_->CreateNewWidget(
530 opener_id, popup_type, route_id, surface_id);
533 void RenderMessageFilter::OnCreateFullscreenWidget(int opener_id,
536 render_widget_helper_->CreateNewFullscreenWidget(
537 opener_id, route_id, surface_id);
540 void RenderMessageFilter::OnGetProcessMemorySizes(size_t* private_bytes,
541 size_t* shared_bytes) {
542 DCHECK_CURRENTLY_ON(BrowserThread::IO);
543 using base::ProcessMetrics;
544 #if !defined(OS_MACOSX) || defined(OS_IOS)
545 scoped_ptr<ProcessMetrics> metrics(ProcessMetrics::CreateProcessMetrics(
548 scoped_ptr<ProcessMetrics> metrics(ProcessMetrics::CreateProcessMetrics(
549 PeerHandle(), content::BrowserChildProcessHost::GetPortProvider()));
551 if (!metrics->GetMemoryBytes(private_bytes, shared_bytes)) {
557 void RenderMessageFilter::OnSetCookie(int render_frame_id,
559 const GURL& first_party_for_cookies,
560 const std::string& cookie) {
561 ChildProcessSecurityPolicyImpl* policy =
562 ChildProcessSecurityPolicyImpl::GetInstance();
563 if (!policy->CanAccessCookiesForOrigin(render_process_id_, url))
566 net::CookieOptions options;
567 if (GetContentClient()->browser()->AllowSetCookie(
568 url, first_party_for_cookies, cookie, resource_context_,
569 render_process_id_, render_frame_id, &options)) {
570 net::CookieStore* cookie_store = GetCookieStoreForURL(url);
571 // Pass a null callback since we don't care about when the 'set' completes.
572 cookie_store->SetCookieWithOptionsAsync(
573 url, cookie, options, net::CookieStore::SetCookiesCallback());
577 void RenderMessageFilter::OnGetCookies(int render_frame_id,
579 const GURL& first_party_for_cookies,
580 IPC::Message* reply_msg) {
581 ChildProcessSecurityPolicyImpl* policy =
582 ChildProcessSecurityPolicyImpl::GetInstance();
583 if (!policy->CanAccessCookiesForOrigin(render_process_id_, url)) {
584 SendGetCookiesResponse(reply_msg, std::string());
588 // If we crash here, figure out what URL the renderer was requesting.
589 // http://crbug.com/99242
591 base::strlcpy(url_buf, url.spec().c_str(), arraysize(url_buf));
592 base::debug::Alias(url_buf);
594 net::CookieStore* cookie_store = GetCookieStoreForURL(url);
595 cookie_store->GetAllCookiesForURLAsync(
596 url, base::Bind(&RenderMessageFilter::CheckPolicyForCookies, this,
597 render_frame_id, url, first_party_for_cookies,
601 void RenderMessageFilter::OnGetRawCookies(
603 const GURL& first_party_for_cookies,
604 IPC::Message* reply_msg) {
605 ChildProcessSecurityPolicyImpl* policy =
606 ChildProcessSecurityPolicyImpl::GetInstance();
607 // Only return raw cookies to trusted renderers or if this request is
608 // not targeted to an an external host like ChromeFrame.
609 // TODO(ananta) We need to support retreiving raw cookies from external
611 if (!policy->CanReadRawCookies(render_process_id_) ||
612 !policy->CanAccessCookiesForOrigin(render_process_id_, url)) {
613 SendGetRawCookiesResponse(reply_msg, net::CookieList());
617 // We check policy here to avoid sending back cookies that would not normally
618 // be applied to outbound requests for the given URL. Since this cookie info
619 // is visible in the developer tools, it is helpful to make it match reality.
620 net::CookieStore* cookie_store = GetCookieStoreForURL(url);
621 cookie_store->GetAllCookiesForURLAsync(
622 url, base::Bind(&RenderMessageFilter::SendGetRawCookiesResponse,
626 void RenderMessageFilter::OnDeleteCookie(const GURL& url,
627 const std::string& cookie_name) {
628 ChildProcessSecurityPolicyImpl* policy =
629 ChildProcessSecurityPolicyImpl::GetInstance();
630 if (!policy->CanAccessCookiesForOrigin(render_process_id_, url))
633 net::CookieStore* cookie_store = GetCookieStoreForURL(url);
634 cookie_store->DeleteCookieAsync(url, cookie_name, base::Closure());
637 void RenderMessageFilter::OnCookiesEnabled(
640 const GURL& first_party_for_cookies,
641 bool* cookies_enabled) {
642 // TODO(ananta): If this render view is associated with an automation channel,
643 // aka ChromeFrame then we need to retrieve cookie settings from the external
645 *cookies_enabled = GetContentClient()->browser()->AllowGetCookie(
646 url, first_party_for_cookies, net::CookieList(), resource_context_,
647 render_process_id_, render_frame_id);
650 #if defined(OS_MACOSX)
651 void RenderMessageFilter::OnLoadFont(const FontDescriptor& font,
652 IPC::Message* reply_msg) {
653 FontLoader::Result* result = new FontLoader::Result;
655 BrowserThread::PostTaskAndReply(
656 BrowserThread::FILE, FROM_HERE,
657 base::Bind(&FontLoader::LoadFont, font, result),
658 base::Bind(&RenderMessageFilter::SendLoadFontReply, this, reply_msg,
659 base::Owned(result)));
662 void RenderMessageFilter::SendLoadFontReply(IPC::Message* reply,
663 FontLoader::Result* result) {
664 base::SharedMemoryHandle handle;
665 if (result->font_data_size == 0 || result->font_id == 0) {
666 result->font_data_size = 0;
668 handle = base::SharedMemory::NULLHandle();
670 result->font_data.GiveToProcess(base::GetCurrentProcessHandle(), &handle);
672 ViewHostMsg_LoadFont::WriteReplyParams(
673 reply, result->font_data_size, handle, result->font_id);
678 #if defined(ENABLE_PLUGINS)
679 void RenderMessageFilter::OnGetPlugins(
681 IPC::Message* reply_msg) {
682 // Don't refresh if the specified threshold has not been passed. Note that
683 // this check is performed before off-loading to the file thread. The reason
684 // we do this is that some pages tend to request that the list of plugins be
685 // refreshed at an excessive rate. This instigates disk scanning, as the list
686 // is accumulated by doing multiple reads from disk. This effect is
687 // multiplied when we have several pages requesting this operation.
689 const base::TimeDelta threshold = base::TimeDelta::FromSeconds(
690 kPluginsRefreshThresholdInSeconds);
691 const base::TimeTicks now = base::TimeTicks::Now();
692 if (now - last_plugin_refresh_time_ >= threshold) {
693 // Only refresh if the threshold hasn't been exceeded yet.
694 PluginServiceImpl::GetInstance()->RefreshPlugins();
695 last_plugin_refresh_time_ = now;
699 PluginServiceImpl::GetInstance()->GetPlugins(
700 base::Bind(&RenderMessageFilter::GetPluginsCallback, this, reply_msg));
703 void RenderMessageFilter::GetPluginsCallback(
704 IPC::Message* reply_msg,
705 const std::vector<WebPluginInfo>& all_plugins) {
706 // Filter the plugin list.
707 PluginServiceFilter* filter = PluginServiceImpl::GetInstance()->GetFilter();
708 std::vector<WebPluginInfo> plugins;
710 int child_process_id = -1;
711 int routing_id = MSG_ROUTING_NONE;
712 for (size_t i = 0; i < all_plugins.size(); ++i) {
713 // Copy because the filter can mutate.
714 WebPluginInfo plugin(all_plugins[i]);
715 if (!filter || filter->IsPluginAvailable(child_process_id,
721 plugins.push_back(plugin);
725 ViewHostMsg_GetPlugins::WriteReplyParams(reply_msg, plugins);
729 void RenderMessageFilter::OnGetPluginInfo(
732 const GURL& page_url,
733 const std::string& mime_type,
736 std::string* actual_mime_type) {
737 bool allow_wildcard = true;
738 *found = plugin_service_->GetPluginInfo(
739 render_process_id_, render_frame_id, resource_context_,
740 url, page_url, mime_type, allow_wildcard,
741 NULL, info, actual_mime_type);
744 void RenderMessageFilter::OnOpenChannelToPlugin(int render_frame_id,
746 const GURL& policy_url,
747 const std::string& mime_type,
748 IPC::Message* reply_msg) {
749 OpenChannelToNpapiPluginCallback* client =
750 new OpenChannelToNpapiPluginCallback(this, resource_context_, reply_msg);
751 DCHECK(!ContainsKey(plugin_host_clients_, client));
752 plugin_host_clients_.insert(client);
753 plugin_service_->OpenChannelToNpapiPlugin(
754 render_process_id_, render_frame_id,
755 url, policy_url, mime_type, client);
758 void RenderMessageFilter::OnOpenChannelToPepperPlugin(
759 const base::FilePath& path,
760 IPC::Message* reply_msg) {
761 plugin_service_->OpenChannelToPpapiPlugin(
764 profile_data_directory_,
765 new OpenChannelToPpapiPluginCallback(this, resource_context_, reply_msg));
768 void RenderMessageFilter::OnDidCreateOutOfProcessPepperInstance(
771 PepperRendererInstanceData instance_data,
773 // It's important that we supply the render process ID ourselves based on the
774 // channel the message arrived on. We use the
775 // PP_Instance -> (process id, view id)
776 // mapping to decide how to handle messages received from the (untrusted)
777 // plugin, so an exploited renderer must not be able to insert fake mappings
778 // that may allow it access to other render processes.
779 DCHECK_EQ(0, instance_data.render_process_id);
780 instance_data.render_process_id = render_process_id_;
782 // We provide the BrowserPpapiHost to the embedder, so it's safe to cast.
783 BrowserPpapiHostImpl* host = static_cast<BrowserPpapiHostImpl*>(
784 GetContentClient()->browser()->GetExternalBrowserPpapiHost(
787 host->AddInstance(pp_instance, instance_data);
789 PpapiPluginProcessHost::DidCreateOutOfProcessInstance(
790 plugin_child_id, pp_instance, instance_data);
794 void RenderMessageFilter::OnDidDeleteOutOfProcessPepperInstance(
799 // We provide the BrowserPpapiHost to the embedder, so it's safe to cast.
800 BrowserPpapiHostImpl* host = static_cast<BrowserPpapiHostImpl*>(
801 GetContentClient()->browser()->GetExternalBrowserPpapiHost(
804 host->DeleteInstance(pp_instance);
806 PpapiPluginProcessHost::DidDeleteOutOfProcessInstance(
807 plugin_child_id, pp_instance);
811 void RenderMessageFilter::OnOpenChannelToPpapiBroker(
813 const base::FilePath& path) {
814 plugin_service_->OpenChannelToPpapiBroker(
817 new OpenChannelToPpapiBrokerCallback(this, routing_id));
819 #endif // defined(ENABLE_PLUGINS)
821 void RenderMessageFilter::OnGenerateRoutingID(int* route_id) {
822 *route_id = render_widget_helper_->GetNextRoutingID();
825 void RenderMessageFilter::OnGetCPUUsage(int* cpu_usage) {
826 base::TimeTicks now = base::TimeTicks::Now();
827 int64 since_last_sample_ms = (now - cpu_usage_sample_time_).InMilliseconds();
828 if (since_last_sample_ms > kCPUUsageSampleIntervalMs) {
829 cpu_usage_sample_time_ = now;
830 cpu_usage_ = static_cast<int>(process_metrics_->GetCPUUsage());
832 *cpu_usage = cpu_usage_;
835 void RenderMessageFilter::OnGetAudioHardwareConfig(
836 media::AudioParameters* input_params,
837 media::AudioParameters* output_params) {
838 DCHECK(input_params);
839 DCHECK(output_params);
840 *output_params = audio_manager_->GetDefaultOutputStreamParameters();
842 // TODO(henrika): add support for all available input devices.
843 *input_params = audio_manager_->GetInputStreamParameters(
844 media::AudioManagerBase::kDefaultDeviceId);
848 void RenderMessageFilter::OnGetMonitorColorProfile(std::vector<char>* profile) {
849 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
850 *profile = g_color_profile.Get().profile();
854 void RenderMessageFilter::OnDownloadUrl(int render_view_id,
856 const Referrer& referrer,
857 const base::string16& suggested_name,
858 const bool use_prompt) {
859 scoped_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo());
860 save_info->suggested_name = suggested_name;
861 save_info->prompt_for_save_location = use_prompt;
863 // There may be a special cookie store that we could use for this download,
864 // rather than the default one. Since this feature is generally only used for
865 // proper render views, and not downloads, we do not need to retrieve the
866 // special cookie store here, but just initialize the request to use the
867 // default cookie store.
868 // TODO(tburkard): retrieve the appropriate special cookie store, if this
869 // is ever to be used for downloads as well.
870 scoped_ptr<net::URLRequest> request(
871 resource_context_->GetRequestContext()->CreateRequest(
872 url, net::DEFAULT_PRIORITY, NULL, NULL));
873 RecordDownloadSource(INITIATED_BY_RENDERER);
874 resource_dispatcher_host_->BeginDownload(
877 true, // is_content_initiated
883 content::DownloadItem::kInvalidId,
884 ResourceDispatcherHostImpl::DownloadStartedCallback());
887 void RenderMessageFilter::OnCheckNotificationPermission(
888 const GURL& source_origin, int* result) {
889 #if defined(ENABLE_NOTIFICATIONS)
890 *result = GetContentClient()->browser()->
891 CheckDesktopNotificationPermission(source_origin, resource_context_,
894 *result = blink::WebNotificationPresenter::PermissionAllowed;
898 void RenderMessageFilter::OnAllocateSharedMemory(
900 base::SharedMemoryHandle* handle) {
901 ChildProcessHostImpl::AllocateSharedMemory(
902 buffer_size, PeerHandle(), handle);
905 void RenderMessageFilter::AllocateSharedBitmapOnFileThread(
907 const cc::SharedBitmapId& id,
908 IPC::Message* reply_msg) {
909 base::SharedMemoryHandle handle;
910 HostSharedBitmapManager::current()->AllocateSharedBitmapForChild(
911 PeerHandle(), buffer_size, id, &handle);
912 ChildProcessHostMsg_SyncAllocateSharedBitmap::WriteReplyParams(reply_msg,
917 void RenderMessageFilter::OnAllocateSharedBitmap(uint32 buffer_size,
918 const cc::SharedBitmapId& id,
919 IPC::Message* reply_msg) {
920 BrowserThread::PostTask(
921 BrowserThread::FILE_USER_BLOCKING,
923 base::Bind(&RenderMessageFilter::AllocateSharedBitmapOnFileThread,
930 void RenderMessageFilter::OnAllocatedSharedBitmap(
932 const base::SharedMemoryHandle& handle,
933 const cc::SharedBitmapId& id) {
934 HostSharedBitmapManager::current()->ChildAllocatedSharedBitmap(
935 buffer_size, handle, PeerHandle(), id);
938 void RenderMessageFilter::OnDeletedSharedBitmap(const cc::SharedBitmapId& id) {
939 HostSharedBitmapManager::current()->ChildDeletedSharedBitmap(id);
942 net::CookieStore* RenderMessageFilter::GetCookieStoreForURL(
944 DCHECK_CURRENTLY_ON(BrowserThread::IO);
946 net::URLRequestContext* context =
947 GetContentClient()->browser()->OverrideRequestContextForURL(
948 url, resource_context_);
950 // If we should use a special URLRequestContext rather than the default one,
951 // return the cookie store of that special URLRequestContext.
953 return context->cookie_store();
955 // Otherwise, if there is a special cookie store to be used for this process,
956 // return that cookie store.
957 net::CookieStore* cookie_store =
958 GetContentClient()->browser()->OverrideCookieStoreForRenderProcess(
963 // Otherwise, return the cookie store of the default request context used
964 // for this renderer.
965 return request_context_->GetURLRequestContext()->cookie_store();
968 #if defined(OS_POSIX) && !defined(OS_ANDROID)
969 void RenderMessageFilter::OnAllocTransportDIB(
970 uint32 size, bool cache_in_browser, TransportDIB::Handle* handle) {
971 render_widget_helper_->AllocTransportDIB(size, cache_in_browser, handle);
974 void RenderMessageFilter::OnFreeTransportDIB(
975 TransportDIB::Id dib_id) {
976 render_widget_helper_->FreeTransportDIB(dib_id);
980 bool RenderMessageFilter::CheckPreparsedJsCachingEnabled() const {
981 static bool checked = false;
982 static bool result = false;
984 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
985 result = command_line.HasSwitch(switches::kEnablePreparsedJsCaching);
991 void RenderMessageFilter::OnCacheableMetadataAvailable(
993 double expected_response_time,
994 const std::vector<char>& data) {
995 if (!CheckPreparsedJsCachingEnabled())
998 net::HttpCache* cache = request_context_->GetURLRequestContext()->
999 http_transaction_factory()->GetCache();
1002 // Use the same priority for the metadata write as for script
1003 // resources (see defaultPriorityForResourceType() in WebKit's
1004 // CachedResource.cpp). Note that WebURLRequest::PriorityMedium
1005 // corresponds to net::LOW (see ConvertWebKitPriorityToNetPriority()
1006 // in weburlloader_impl.cc).
1007 const net::RequestPriority kPriority = net::LOW;
1008 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(data.size()));
1009 memcpy(buf->data(), &data.front(), data.size());
1010 cache->WriteMetadata(url,
1012 base::Time::FromDoubleT(expected_response_time),
1017 void RenderMessageFilter::OnKeygen(uint32 key_size_index,
1018 const std::string& challenge_string,
1020 IPC::Message* reply_msg) {
1021 // Map displayed strings indicating level of keysecurity in the <keygen>
1022 // menu to the key size in bits. (See SSLKeyGeneratorChromium.cpp in WebCore.)
1023 int key_size_in_bits;
1024 switch (key_size_index) {
1026 key_size_in_bits = 2048;
1029 key_size_in_bits = 1024;
1032 DCHECK(false) << "Illegal key_size_index " << key_size_index;
1033 ViewHostMsg_Keygen::WriteReplyParams(reply_msg, std::string());
1038 resource_context_->CreateKeygenHandler(
1043 &RenderMessageFilter::PostKeygenToWorkerThread, this, reply_msg));
1046 void RenderMessageFilter::PostKeygenToWorkerThread(
1047 IPC::Message* reply_msg,
1048 scoped_ptr<net::KeygenHandler> keygen_handler) {
1049 VLOG(1) << "Dispatching keygen task to worker pool.";
1050 // Dispatch to worker pool, so we do not block the IO thread.
1051 if (!base::WorkerPool::PostTask(
1053 base::Bind(&RenderMessageFilter::OnKeygenOnWorkerThread,
1055 base::Passed(&keygen_handler),
1058 NOTREACHED() << "Failed to dispatch keygen task to worker pool";
1059 ViewHostMsg_Keygen::WriteReplyParams(reply_msg, std::string());
1064 void RenderMessageFilter::OnKeygenOnWorkerThread(
1065 scoped_ptr<net::KeygenHandler> keygen_handler,
1066 IPC::Message* reply_msg) {
1069 // Generate a signed public key and challenge, then send it back.
1070 ViewHostMsg_Keygen::WriteReplyParams(
1072 keygen_handler->GenKeyAndSignChallenge());
1076 void RenderMessageFilter::OnMediaLogEvents(
1077 const std::vector<media::MediaLogEvent>& events) {
1078 if (media_internals_)
1079 media_internals_->OnMediaEvents(render_process_id_, events);
1082 void RenderMessageFilter::CheckPolicyForCookies(
1083 int render_frame_id,
1085 const GURL& first_party_for_cookies,
1086 IPC::Message* reply_msg,
1087 const net::CookieList& cookie_list) {
1088 net::CookieStore* cookie_store = GetCookieStoreForURL(url);
1089 // Check the policy for get cookies, and pass cookie_list to the
1090 // TabSpecificContentSetting for logging purpose.
1091 if (GetContentClient()->browser()->AllowGetCookie(
1092 url, first_party_for_cookies, cookie_list, resource_context_,
1093 render_process_id_, render_frame_id)) {
1094 // Gets the cookies from cookie store if allowed.
1095 cookie_store->GetCookiesWithOptionsAsync(
1096 url, net::CookieOptions(),
1097 base::Bind(&RenderMessageFilter::SendGetCookiesResponse,
1100 SendGetCookiesResponse(reply_msg, std::string());
1104 void RenderMessageFilter::SendGetCookiesResponse(IPC::Message* reply_msg,
1105 const std::string& cookies) {
1106 ViewHostMsg_GetCookies::WriteReplyParams(reply_msg, cookies);
1110 void RenderMessageFilter::SendGetRawCookiesResponse(
1111 IPC::Message* reply_msg,
1112 const net::CookieList& cookie_list) {
1113 std::vector<CookieData> cookies;
1114 for (size_t i = 0; i < cookie_list.size(); ++i)
1115 cookies.push_back(CookieData(cookie_list[i]));
1116 ViewHostMsg_GetRawCookies::WriteReplyParams(reply_msg, cookies);
1120 void RenderMessageFilter::OnCompletedOpenChannelToNpapiPlugin(
1121 OpenChannelToNpapiPluginCallback* client) {
1122 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1123 DCHECK(ContainsKey(plugin_host_clients_, client));
1124 plugin_host_clients_.erase(client);
1127 void RenderMessageFilter::OnAre3DAPIsBlocked(int render_view_id,
1128 const GURL& top_origin_url,
1129 ThreeDAPIType requester,
1131 *blocked = GpuDataManagerImpl::GetInstance()->Are3DAPIsBlocked(
1132 top_origin_url, render_process_id_, render_view_id, requester);
1135 void RenderMessageFilter::OnDidLose3DContext(
1136 const GURL& top_origin_url,
1137 ThreeDAPIType /* unused */,
1138 int arb_robustness_status_code) {
1139 #if defined(OS_MACOSX)
1140 // TODO(kbr): this file indirectly includes npapi.h, which on Mac
1141 // OS pulls in the system OpenGL headers. For some
1142 // not-yet-investigated reason this breaks the build with the 10.6
1143 // SDK but not 10.7. For now work around this in a way compatible
1144 // with the Khronos headers.
1145 #ifndef GL_GUILTY_CONTEXT_RESET_ARB
1146 #define GL_GUILTY_CONTEXT_RESET_ARB 0x8253
1148 #ifndef GL_INNOCENT_CONTEXT_RESET_ARB
1149 #define GL_INNOCENT_CONTEXT_RESET_ARB 0x8254
1151 #ifndef GL_UNKNOWN_CONTEXT_RESET_ARB
1152 #define GL_UNKNOWN_CONTEXT_RESET_ARB 0x8255
1156 GpuDataManagerImpl::DomainGuilt guilt;
1157 switch (arb_robustness_status_code) {
1158 case GL_GUILTY_CONTEXT_RESET_ARB:
1159 guilt = GpuDataManagerImpl::DOMAIN_GUILT_KNOWN;
1161 case GL_UNKNOWN_CONTEXT_RESET_ARB:
1162 guilt = GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN;
1165 // Ignore lost contexts known to be innocent.
1169 GpuDataManagerImpl::GetInstance()->BlockDomainFrom3DAPIs(
1170 top_origin_url, guilt);
1174 void RenderMessageFilter::OnPreCacheFontCharacters(const LOGFONT& font,
1175 const base::string16& str) {
1176 // TODO(scottmg): pdf/ppapi still require the renderer to be able to precache
1177 // GDI fonts (http://crbug.com/383227), even when using DirectWrite.
1178 // Eventually this shouldn't be added and should be moved to
1179 // FontCacheDispatcher too. http://crbug.com/356346.
1181 // First, comments from FontCacheDispatcher::OnPreCacheFont do apply here too.
1182 // Except that for True Type fonts,
1183 // GetTextMetrics will not load the font in memory.
1184 // The only way windows seem to load properly, it is to create a similar
1185 // device (like the one in which we print), then do an ExtTextOut,
1186 // as we do in the printing thread, which is sandboxed.
1187 HDC hdc = CreateEnhMetaFile(NULL, NULL, NULL, NULL);
1188 HFONT font_handle = CreateFontIndirect(&font);
1189 DCHECK(NULL != font_handle);
1191 HGDIOBJ old_font = SelectObject(hdc, font_handle);
1192 DCHECK(NULL != old_font);
1194 ExtTextOut(hdc, 0, 0, ETO_GLYPH_INDEX, 0, str.c_str(), str.length(), NULL);
1196 SelectObject(hdc, old_font);
1197 DeleteObject(font_handle);
1199 HENHMETAFILE metafile = CloseEnhMetaFile(hdc);
1202 DeleteEnhMetaFile(metafile);
1207 #if defined(OS_ANDROID)
1208 void RenderMessageFilter::OnWebAudioMediaCodec(
1209 base::SharedMemoryHandle encoded_data_handle,
1210 base::FileDescriptor pcm_output,
1211 uint32_t data_size) {
1212 // Let a WorkerPool handle this request since the WebAudio
1213 // MediaCodec bridge is slow and can block while sending the data to
1215 base::WorkerPool::PostTask(
1217 base::Bind(&media::WebAudioMediaCodecBridge::RunWebAudioMediaCodec,
1218 encoded_data_handle, pcm_output, data_size),
1223 } // namespace content