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/gpu/client/gpu_memory_buffer_impl.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_monster.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/gpu/client/gpu_memory_buffer_impl_io_surface.h"
74 #include "content/common/mac/font_descriptor.h"
75 #include "ui/gl/io_surface_support_mac.h"
77 #include "gpu/GLES2/gl2extchromium.h"
78 #include "third_party/khronos/GLES2/gl2.h"
79 #include "third_party/khronos/GLES2/gl2ext.h"
82 #include "base/file_descriptor_posix.h"
85 #include "content/common/font_cache_dispatcher_win.h"
87 #if defined(OS_ANDROID)
88 #include "media/base/android/webaudio_media_codec_bridge.h"
91 using net::CookieStore;
96 #if defined(ENABLE_PLUGINS)
97 const int kPluginsRefreshThresholdInSeconds = 3;
100 // When two CPU usage queries arrive within this interval, we sample the CPU
101 // usage only once and send it as a response for both queries.
102 static const int64 kCPUUsageSampleIntervalMs = 900;
105 // On Windows, |g_color_profile| can run on an arbitrary background thread.
106 // We avoid races by using LazyInstance's constructor lock to initialize the
108 base::LazyInstance<gfx::ColorProfile>::Leaky g_color_profile =
109 LAZY_INSTANCE_INITIALIZER;
112 // Common functionality for converting a sync renderer message to a callback
113 // function in the browser. Derive from this, create it on the heap when
114 // issuing your callback. When done, write your reply parameters into
115 // reply_msg(), and then call SendReplyAndDeleteThis().
116 class RenderMessageCompletionCallback {
118 RenderMessageCompletionCallback(RenderMessageFilter* filter,
119 IPC::Message* reply_msg)
121 reply_msg_(reply_msg) {
124 virtual ~RenderMessageCompletionCallback() {
127 RenderMessageFilter* filter() { return filter_.get(); }
128 IPC::Message* reply_msg() { return reply_msg_; }
130 void SendReplyAndDeleteThis() {
131 filter_->Send(reply_msg_);
136 scoped_refptr<RenderMessageFilter> filter_;
137 IPC::Message* reply_msg_;
140 class OpenChannelToPpapiPluginCallback
141 : public RenderMessageCompletionCallback,
142 public PpapiPluginProcessHost::PluginClient {
144 OpenChannelToPpapiPluginCallback(RenderMessageFilter* filter,
145 ResourceContext* context,
146 IPC::Message* reply_msg)
147 : RenderMessageCompletionCallback(filter, reply_msg),
151 virtual void GetPpapiChannelInfo(base::ProcessHandle* renderer_handle,
152 int* renderer_id) OVERRIDE {
153 *renderer_handle = filter()->PeerHandle();
154 *renderer_id = filter()->render_process_id();
157 virtual void OnPpapiChannelOpened(const IPC::ChannelHandle& channel_handle,
158 base::ProcessId plugin_pid,
159 int plugin_child_id) OVERRIDE {
160 ViewHostMsg_OpenChannelToPepperPlugin::WriteReplyParams(
161 reply_msg(), channel_handle, plugin_pid, plugin_child_id);
162 SendReplyAndDeleteThis();
165 virtual bool OffTheRecord() OVERRIDE {
166 return filter()->OffTheRecord();
169 virtual ResourceContext* GetResourceContext() OVERRIDE {
174 ResourceContext* context_;
177 class OpenChannelToPpapiBrokerCallback
178 : public PpapiPluginProcessHost::BrokerClient {
180 OpenChannelToPpapiBrokerCallback(RenderMessageFilter* filter,
183 routing_id_(routing_id) {
186 virtual ~OpenChannelToPpapiBrokerCallback() {}
188 virtual void GetPpapiChannelInfo(base::ProcessHandle* renderer_handle,
189 int* renderer_id) OVERRIDE {
190 *renderer_handle = filter_->PeerHandle();
191 *renderer_id = filter_->render_process_id();
194 virtual void OnPpapiChannelOpened(const IPC::ChannelHandle& channel_handle,
195 base::ProcessId plugin_pid,
196 int /* plugin_child_id */) OVERRIDE {
197 filter_->Send(new ViewMsg_PpapiBrokerChannelCreated(routing_id_,
203 virtual bool OffTheRecord() OVERRIDE {
204 return filter_->OffTheRecord();
208 scoped_refptr<RenderMessageFilter> filter_;
212 #if defined(OS_MACOSX)
213 void AddBooleanValue(CFMutableDictionaryRef dictionary,
214 const CFStringRef key,
216 CFDictionaryAddValue(
217 dictionary, key, value ? kCFBooleanTrue : kCFBooleanFalse);
220 void AddIntegerValue(CFMutableDictionaryRef dictionary,
221 const CFStringRef key,
223 base::ScopedCFTypeRef<CFNumberRef> number(
224 CFNumberCreate(NULL, kCFNumberSInt32Type, &value));
225 CFDictionaryAddValue(dictionary, key, number.get());
231 class RenderMessageFilter::OpenChannelToNpapiPluginCallback
232 : public RenderMessageCompletionCallback,
233 public PluginProcessHost::Client {
235 OpenChannelToNpapiPluginCallback(RenderMessageFilter* filter,
236 ResourceContext* context,
237 IPC::Message* reply_msg)
238 : RenderMessageCompletionCallback(filter, reply_msg),
241 sent_plugin_channel_request_(false) {
244 virtual int ID() OVERRIDE {
245 return filter()->render_process_id();
248 virtual ResourceContext* GetResourceContext() OVERRIDE {
252 virtual bool OffTheRecord() OVERRIDE {
253 if (filter()->OffTheRecord())
255 if (GetContentClient()->browser()->AllowSaveLocalState(context_))
258 // For now, only disallow storing data for Flash <http://crbug.com/97319>.
259 for (size_t i = 0; i < info_.mime_types.size(); ++i) {
260 if (info_.mime_types[i].mime_type == kFlashPluginSwfMimeType)
266 virtual void SetPluginInfo(const WebPluginInfo& info) OVERRIDE {
270 virtual void OnFoundPluginProcessHost(PluginProcessHost* host) OVERRIDE {
275 virtual void OnSentPluginChannelRequest() OVERRIDE {
276 sent_plugin_channel_request_ = true;
279 virtual void OnChannelOpened(const IPC::ChannelHandle& handle) OVERRIDE {
280 WriteReplyAndDeleteThis(handle);
283 virtual void OnError() OVERRIDE {
284 WriteReplyAndDeleteThis(IPC::ChannelHandle());
287 PluginProcessHost* host() const {
291 bool sent_plugin_channel_request() const {
292 return sent_plugin_channel_request_;
300 void WriteReplyAndDeleteThis(const IPC::ChannelHandle& handle) {
301 FrameHostMsg_OpenChannelToPlugin::WriteReplyParams(reply_msg(),
303 filter()->OnCompletedOpenChannelToNpapiPlugin(this);
304 SendReplyAndDeleteThis();
307 ResourceContext* context_;
309 PluginProcessHost* host_;
310 bool sent_plugin_channel_request_;
313 RenderMessageFilter::RenderMessageFilter(
314 int render_process_id,
316 PluginServiceImpl* plugin_service,
317 BrowserContext* browser_context,
318 net::URLRequestContextGetter* request_context,
319 RenderWidgetHelper* render_widget_helper,
320 media::AudioManager* audio_manager,
321 MediaInternals* media_internals,
322 DOMStorageContextWrapper* dom_storage_context)
323 : resource_dispatcher_host_(ResourceDispatcherHostImpl::Get()),
324 plugin_service_(plugin_service),
325 profile_data_directory_(browser_context->GetPath()),
326 request_context_(request_context),
327 resource_context_(browser_context->GetResourceContext()),
328 render_widget_helper_(render_widget_helper),
329 incognito_(browser_context->IsOffTheRecord()),
330 dom_storage_context_(dom_storage_context),
331 render_process_id_(render_process_id),
334 audio_manager_(audio_manager),
335 media_internals_(media_internals) {
336 DCHECK(request_context_.get());
338 render_widget_helper_->Init(render_process_id_, resource_dispatcher_host_);
341 RenderMessageFilter::~RenderMessageFilter() {
342 // This function should be called on the IO thread.
343 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
344 DCHECK(plugin_host_clients_.empty());
347 void RenderMessageFilter::OnChannelClosing() {
348 #if defined(ENABLE_PLUGINS)
349 for (std::set<OpenChannelToNpapiPluginCallback*>::iterator it =
350 plugin_host_clients_.begin(); it != plugin_host_clients_.end(); ++it) {
351 OpenChannelToNpapiPluginCallback* client = *it;
352 if (client->host()) {
353 if (client->sent_plugin_channel_request()) {
354 client->host()->CancelSentRequest(client);
356 client->host()->CancelPendingRequest(client);
359 plugin_service_->CancelOpenChannelToNpapiPlugin(client);
363 #endif // defined(ENABLE_PLUGINS)
364 plugin_host_clients_.clear();
367 void RenderMessageFilter::OnChannelConnected(int32 peer_id) {
368 base::ProcessHandle handle = PeerHandle();
369 #if defined(OS_MACOSX)
370 process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(handle,
373 process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(handle));
375 cpu_usage_ = process_metrics_->GetCPUUsage(); // Initialize CPU usage counters
376 cpu_usage_sample_time_ = base::TimeTicks::Now();
379 bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message,
380 bool* message_was_ok) {
382 IPC_BEGIN_MESSAGE_MAP_EX(RenderMessageFilter, message, *message_was_ok)
384 IPC_MESSAGE_HANDLER(ViewHostMsg_PreCacheFontCharacters,
385 OnPreCacheFontCharacters)
387 IPC_MESSAGE_HANDLER(ViewHostMsg_GetProcessMemorySizes,
388 OnGetProcessMemorySizes)
389 IPC_MESSAGE_HANDLER(ViewHostMsg_GenerateRoutingID, OnGenerateRoutingID)
390 IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWindow, OnCreateWindow)
391 IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWidget, OnCreateWidget)
392 IPC_MESSAGE_HANDLER(ViewHostMsg_CreateFullscreenWidget,
393 OnCreateFullscreenWidget)
394 IPC_MESSAGE_HANDLER(ViewHostMsg_SetCookie, OnSetCookie)
395 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetCookies, OnGetCookies)
396 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetRawCookies, OnGetRawCookies)
397 IPC_MESSAGE_HANDLER(ViewHostMsg_DeleteCookie, OnDeleteCookie)
398 IPC_MESSAGE_HANDLER(ViewHostMsg_CookiesEnabled, OnCookiesEnabled)
399 #if defined(OS_MACOSX)
400 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_LoadFont, OnLoadFont)
402 IPC_MESSAGE_HANDLER(ViewHostMsg_DownloadUrl, OnDownloadUrl)
403 #if defined(ENABLE_PLUGINS)
404 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetPlugins, OnGetPlugins)
405 IPC_MESSAGE_HANDLER(FrameHostMsg_GetPluginInfo, OnGetPluginInfo)
406 IPC_MESSAGE_HANDLER_DELAY_REPLY(FrameHostMsg_OpenChannelToPlugin,
407 OnOpenChannelToPlugin)
408 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_OpenChannelToPepperPlugin,
409 OnOpenChannelToPepperPlugin)
410 IPC_MESSAGE_HANDLER(ViewHostMsg_DidCreateOutOfProcessPepperInstance,
411 OnDidCreateOutOfProcessPepperInstance)
412 IPC_MESSAGE_HANDLER(ViewHostMsg_DidDeleteOutOfProcessPepperInstance,
413 OnDidDeleteOutOfProcessPepperInstance)
414 IPC_MESSAGE_HANDLER(ViewHostMsg_OpenChannelToPpapiBroker,
415 OnOpenChannelToPpapiBroker)
417 IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_UpdateRect,
418 render_widget_helper_->DidReceiveBackingStoreMsg(message))
419 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateIsDelayed, OnUpdateIsDelayed)
420 IPC_MESSAGE_HANDLER(DesktopNotificationHostMsg_CheckPermission,
421 OnCheckNotificationPermission)
422 IPC_MESSAGE_HANDLER(ChildProcessHostMsg_SyncAllocateSharedMemory,
423 OnAllocateSharedMemory)
424 IPC_MESSAGE_HANDLER(ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer,
425 OnAllocateGpuMemoryBuffer)
426 #if defined(OS_POSIX) && !defined(TOOLKIT_GTK) && !defined(OS_ANDROID)
427 IPC_MESSAGE_HANDLER(ViewHostMsg_AllocTransportDIB, OnAllocTransportDIB)
428 IPC_MESSAGE_HANDLER(ViewHostMsg_FreeTransportDIB, OnFreeTransportDIB)
430 IPC_MESSAGE_HANDLER(ViewHostMsg_DidGenerateCacheableMetadata,
431 OnCacheableMetadataAvailable)
432 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_Keygen, OnKeygen)
433 IPC_MESSAGE_HANDLER(ViewHostMsg_GetCPUUsage, OnGetCPUUsage)
434 IPC_MESSAGE_HANDLER(ViewHostMsg_GetAudioHardwareConfig,
435 OnGetAudioHardwareConfig)
437 IPC_MESSAGE_HANDLER(ViewHostMsg_GetMonitorColorProfile,
438 OnGetMonitorColorProfile)
440 IPC_MESSAGE_HANDLER(ViewHostMsg_MediaLogEvents, OnMediaLogEvents)
441 IPC_MESSAGE_HANDLER(ViewHostMsg_Are3DAPIsBlocked, OnAre3DAPIsBlocked)
442 IPC_MESSAGE_HANDLER(ViewHostMsg_DidLose3DContext, OnDidLose3DContext)
443 #if defined(OS_ANDROID)
444 IPC_MESSAGE_HANDLER(ViewHostMsg_RunWebAudioMediaCodec, OnWebAudioMediaCodec)
446 IPC_MESSAGE_UNHANDLED(handled = false)
447 IPC_END_MESSAGE_MAP_EX()
452 void RenderMessageFilter::OnDestruct() const {
453 BrowserThread::DeleteOnIOThread::Destruct(this);
456 base::TaskRunner* RenderMessageFilter::OverrideTaskRunnerForMessage(
457 const IPC::Message& message) {
459 // Windows monitor profile must be read from a file.
460 if (message.type() == ViewHostMsg_GetMonitorColorProfile::ID)
461 return BrowserThread::GetBlockingPool();
463 #if defined(OS_MACOSX)
464 // OSX CoreAudio calls must all happen on the main thread.
465 if (message.type() == ViewHostMsg_GetAudioHardwareConfig::ID)
466 return audio_manager_->GetTaskRunner().get();
471 bool RenderMessageFilter::OffTheRecord() const {
475 void RenderMessageFilter::OnCreateWindow(
476 const ViewHostMsg_CreateWindow_Params& params,
478 int* main_frame_route_id,
480 int64* cloned_session_storage_namespace_id) {
481 bool no_javascript_access;
483 // Merge the additional features into the WebWindowFeatures struct before we
485 blink::WebVector<blink::WebString> additional_features(
486 params.additional_features.size());
488 for (size_t i = 0; i < params.additional_features.size(); ++i)
489 additional_features[i] = blink::WebString(params.additional_features[i]);
491 blink::WebWindowFeatures features = params.features;
492 features.additionalFeatures.swap(additional_features);
494 bool can_create_window =
495 GetContentClient()->browser()->CanCreateWindow(
497 params.opener_top_level_frame_url,
498 params.opener_security_origin,
499 params.window_container_type,
505 params.opener_suppressed,
510 &no_javascript_access);
512 if (!can_create_window) {
513 *route_id = MSG_ROUTING_NONE;
514 *main_frame_route_id = MSG_ROUTING_NONE;
519 // This will clone the sessionStorage for namespace_id_to_clone.
520 scoped_refptr<SessionStorageNamespaceImpl> cloned_namespace =
521 new SessionStorageNamespaceImpl(dom_storage_context_.get(),
522 params.session_storage_namespace_id);
523 *cloned_session_storage_namespace_id = cloned_namespace->id();
525 render_widget_helper_->CreateNewWindow(params,
526 no_javascript_access,
531 cloned_namespace.get());
534 void RenderMessageFilter::OnCreateWidget(int opener_id,
535 blink::WebPopupType popup_type,
538 render_widget_helper_->CreateNewWidget(
539 opener_id, popup_type, route_id, surface_id);
542 void RenderMessageFilter::OnCreateFullscreenWidget(int opener_id,
545 render_widget_helper_->CreateNewFullscreenWidget(
546 opener_id, route_id, surface_id);
549 void RenderMessageFilter::OnGetProcessMemorySizes(size_t* private_bytes,
550 size_t* shared_bytes) {
551 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
552 using base::ProcessMetrics;
553 #if !defined(OS_MACOSX) || defined(OS_IOS)
554 scoped_ptr<ProcessMetrics> metrics(ProcessMetrics::CreateProcessMetrics(
557 scoped_ptr<ProcessMetrics> metrics(ProcessMetrics::CreateProcessMetrics(
558 PeerHandle(), content::BrowserChildProcessHost::GetPortProvider()));
560 if (!metrics->GetMemoryBytes(private_bytes, shared_bytes)) {
566 void RenderMessageFilter::OnSetCookie(int render_frame_id,
568 const GURL& first_party_for_cookies,
569 const std::string& cookie) {
570 ChildProcessSecurityPolicyImpl* policy =
571 ChildProcessSecurityPolicyImpl::GetInstance();
572 if (!policy->CanAccessCookiesForOrigin(render_process_id_, url))
575 net::CookieOptions options;
576 if (GetContentClient()->browser()->AllowSetCookie(
577 url, first_party_for_cookies, cookie, resource_context_,
578 render_process_id_, render_frame_id, &options)) {
579 net::URLRequestContext* context = GetRequestContextForURL(url);
580 // Pass a null callback since we don't care about when the 'set' completes.
581 context->cookie_store()->SetCookieWithOptionsAsync(
582 url, cookie, options, net::CookieMonster::SetCookiesCallback());
586 void RenderMessageFilter::OnGetCookies(int render_frame_id,
588 const GURL& first_party_for_cookies,
589 IPC::Message* reply_msg) {
590 ChildProcessSecurityPolicyImpl* policy =
591 ChildProcessSecurityPolicyImpl::GetInstance();
592 if (!policy->CanAccessCookiesForOrigin(render_process_id_, url)) {
593 SendGetCookiesResponse(reply_msg, std::string());
597 // If we crash here, figure out what URL the renderer was requesting.
598 // http://crbug.com/99242
600 base::strlcpy(url_buf, url.spec().c_str(), arraysize(url_buf));
601 base::debug::Alias(url_buf);
603 net::URLRequestContext* context = GetRequestContextForURL(url);
604 net::CookieMonster* cookie_monster =
605 context->cookie_store()->GetCookieMonster();
606 cookie_monster->GetAllCookiesForURLAsync(
607 url, base::Bind(&RenderMessageFilter::CheckPolicyForCookies, this,
608 render_frame_id, url, first_party_for_cookies,
612 void RenderMessageFilter::OnGetRawCookies(
614 const GURL& first_party_for_cookies,
615 IPC::Message* reply_msg) {
616 ChildProcessSecurityPolicyImpl* policy =
617 ChildProcessSecurityPolicyImpl::GetInstance();
618 // Only return raw cookies to trusted renderers or if this request is
619 // not targeted to an an external host like ChromeFrame.
620 // TODO(ananta) We need to support retreiving raw cookies from external
622 if (!policy->CanReadRawCookies(render_process_id_) ||
623 !policy->CanAccessCookiesForOrigin(render_process_id_, url)) {
624 SendGetRawCookiesResponse(reply_msg, net::CookieList());
628 // We check policy here to avoid sending back cookies that would not normally
629 // be applied to outbound requests for the given URL. Since this cookie info
630 // is visible in the developer tools, it is helpful to make it match reality.
631 net::URLRequestContext* context = GetRequestContextForURL(url);
632 net::CookieMonster* cookie_monster =
633 context->cookie_store()->GetCookieMonster();
634 cookie_monster->GetAllCookiesForURLAsync(
635 url, base::Bind(&RenderMessageFilter::SendGetRawCookiesResponse,
639 void RenderMessageFilter::OnDeleteCookie(const GURL& url,
640 const std::string& cookie_name) {
641 ChildProcessSecurityPolicyImpl* policy =
642 ChildProcessSecurityPolicyImpl::GetInstance();
643 if (!policy->CanAccessCookiesForOrigin(render_process_id_, url))
646 net::URLRequestContext* context = GetRequestContextForURL(url);
647 context->cookie_store()->DeleteCookieAsync(url, cookie_name, base::Closure());
650 void RenderMessageFilter::OnCookiesEnabled(
652 const GURL& first_party_for_cookies,
653 bool* cookies_enabled) {
654 // TODO(ananta): If this render view is associated with an automation channel,
655 // aka ChromeFrame then we need to retrieve cookie settings from the external
657 *cookies_enabled = GetContentClient()->browser()->AllowGetCookie(
658 url, first_party_for_cookies, net::CookieList(), resource_context_,
659 render_process_id_, MSG_ROUTING_CONTROL);
662 #if defined(OS_MACOSX)
663 void RenderMessageFilter::OnLoadFont(const FontDescriptor& font,
664 IPC::Message* reply_msg) {
665 FontLoader::Result* result = new FontLoader::Result;
667 BrowserThread::PostTaskAndReply(
668 BrowserThread::FILE, FROM_HERE,
669 base::Bind(&FontLoader::LoadFont, font, result),
670 base::Bind(&RenderMessageFilter::SendLoadFontReply, this, reply_msg,
671 base::Owned(result)));
674 void RenderMessageFilter::SendLoadFontReply(IPC::Message* reply,
675 FontLoader::Result* result) {
676 base::SharedMemoryHandle handle;
677 if (result->font_data_size == 0 || result->font_id == 0) {
678 result->font_data_size = 0;
680 handle = base::SharedMemory::NULLHandle();
682 result->font_data.GiveToProcess(base::GetCurrentProcessHandle(), &handle);
684 ViewHostMsg_LoadFont::WriteReplyParams(
685 reply, result->font_data_size, handle, result->font_id);
690 #if defined(ENABLE_PLUGINS)
691 void RenderMessageFilter::OnGetPlugins(
693 IPC::Message* reply_msg) {
694 // Don't refresh if the specified threshold has not been passed. Note that
695 // this check is performed before off-loading to the file thread. The reason
696 // we do this is that some pages tend to request that the list of plugins be
697 // refreshed at an excessive rate. This instigates disk scanning, as the list
698 // is accumulated by doing multiple reads from disk. This effect is
699 // multiplied when we have several pages requesting this operation.
701 const base::TimeDelta threshold = base::TimeDelta::FromSeconds(
702 kPluginsRefreshThresholdInSeconds);
703 const base::TimeTicks now = base::TimeTicks::Now();
704 if (now - last_plugin_refresh_time_ >= threshold) {
705 // Only refresh if the threshold hasn't been exceeded yet.
706 PluginServiceImpl::GetInstance()->RefreshPlugins();
707 last_plugin_refresh_time_ = now;
711 PluginServiceImpl::GetInstance()->GetPlugins(
712 base::Bind(&RenderMessageFilter::GetPluginsCallback, this, reply_msg));
715 void RenderMessageFilter::GetPluginsCallback(
716 IPC::Message* reply_msg,
717 const std::vector<WebPluginInfo>& all_plugins) {
718 // Filter the plugin list.
719 PluginServiceFilter* filter = PluginServiceImpl::GetInstance()->GetFilter();
720 std::vector<WebPluginInfo> plugins;
722 int child_process_id = -1;
723 int routing_id = MSG_ROUTING_NONE;
724 for (size_t i = 0; i < all_plugins.size(); ++i) {
725 // Copy because the filter can mutate.
726 WebPluginInfo plugin(all_plugins[i]);
727 if (!filter || filter->IsPluginAvailable(child_process_id,
733 plugins.push_back(plugin);
737 ViewHostMsg_GetPlugins::WriteReplyParams(reply_msg, plugins);
741 void RenderMessageFilter::OnGetPluginInfo(
744 const GURL& page_url,
745 const std::string& mime_type,
748 std::string* actual_mime_type) {
749 bool allow_wildcard = true;
750 *found = plugin_service_->GetPluginInfo(
751 render_process_id_, render_frame_id, resource_context_,
752 url, page_url, mime_type, allow_wildcard,
753 NULL, info, actual_mime_type);
756 void RenderMessageFilter::OnOpenChannelToPlugin(int render_frame_id,
758 const GURL& policy_url,
759 const std::string& mime_type,
760 IPC::Message* reply_msg) {
761 OpenChannelToNpapiPluginCallback* client =
762 new OpenChannelToNpapiPluginCallback(this, resource_context_, reply_msg);
763 DCHECK(!ContainsKey(plugin_host_clients_, client));
764 plugin_host_clients_.insert(client);
765 plugin_service_->OpenChannelToNpapiPlugin(
766 render_process_id_, render_frame_id,
767 url, policy_url, mime_type, client);
770 void RenderMessageFilter::OnOpenChannelToPepperPlugin(
771 const base::FilePath& path,
772 IPC::Message* reply_msg) {
773 plugin_service_->OpenChannelToPpapiPlugin(
776 profile_data_directory_,
777 new OpenChannelToPpapiPluginCallback(this, resource_context_, reply_msg));
780 void RenderMessageFilter::OnDidCreateOutOfProcessPepperInstance(
783 PepperRendererInstanceData instance_data,
785 // It's important that we supply the render process ID ourselves based on the
786 // channel the message arrived on. We use the
787 // PP_Instance -> (process id, view id)
788 // mapping to decide how to handle messages received from the (untrusted)
789 // plugin, so an exploited renderer must not be able to insert fake mappings
790 // that may allow it access to other render processes.
791 DCHECK_EQ(0, instance_data.render_process_id);
792 instance_data.render_process_id = render_process_id_;
794 // We provide the BrowserPpapiHost to the embedder, so it's safe to cast.
795 BrowserPpapiHostImpl* host = static_cast<BrowserPpapiHostImpl*>(
796 GetContentClient()->browser()->GetExternalBrowserPpapiHost(
799 host->AddInstance(pp_instance, instance_data);
801 PpapiPluginProcessHost::DidCreateOutOfProcessInstance(
802 plugin_child_id, pp_instance, instance_data);
806 void RenderMessageFilter::OnDidDeleteOutOfProcessPepperInstance(
811 // We provide the BrowserPpapiHost to the embedder, so it's safe to cast.
812 BrowserPpapiHostImpl* host = static_cast<BrowserPpapiHostImpl*>(
813 GetContentClient()->browser()->GetExternalBrowserPpapiHost(
816 host->DeleteInstance(pp_instance);
818 PpapiPluginProcessHost::DidDeleteOutOfProcessInstance(
819 plugin_child_id, pp_instance);
823 void RenderMessageFilter::OnOpenChannelToPpapiBroker(
825 const base::FilePath& path) {
826 plugin_service_->OpenChannelToPpapiBroker(
829 new OpenChannelToPpapiBrokerCallback(this, routing_id));
831 #endif // defined(ENABLE_PLUGINS)
833 void RenderMessageFilter::OnGenerateRoutingID(int* route_id) {
834 *route_id = render_widget_helper_->GetNextRoutingID();
837 void RenderMessageFilter::OnGetCPUUsage(int* cpu_usage) {
838 base::TimeTicks now = base::TimeTicks::Now();
839 int64 since_last_sample_ms = (now - cpu_usage_sample_time_).InMilliseconds();
840 if (since_last_sample_ms > kCPUUsageSampleIntervalMs) {
841 cpu_usage_sample_time_ = now;
842 cpu_usage_ = static_cast<int>(process_metrics_->GetCPUUsage());
844 *cpu_usage = cpu_usage_;
847 void RenderMessageFilter::OnGetAudioHardwareConfig(
848 media::AudioParameters* input_params,
849 media::AudioParameters* output_params) {
850 DCHECK(input_params);
851 DCHECK(output_params);
852 *output_params = audio_manager_->GetDefaultOutputStreamParameters();
854 // TODO(henrika): add support for all available input devices.
855 *input_params = audio_manager_->GetInputStreamParameters(
856 media::AudioManagerBase::kDefaultDeviceId);
860 void RenderMessageFilter::OnGetMonitorColorProfile(std::vector<char>* profile) {
861 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
862 static bool enabled = false;
863 static bool checked = false;
866 const CommandLine& command = *CommandLine::ForCurrentProcess();
867 enabled = command.HasSwitch(switches::kEnableMonitorProfile);
871 *profile = g_color_profile.Get().profile();
875 void RenderMessageFilter::OnDownloadUrl(const IPC::Message& message,
877 const Referrer& referrer,
878 const base::string16& suggested_name) {
879 scoped_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo());
880 save_info->suggested_name = suggested_name;
881 scoped_ptr<net::URLRequest> request(
882 resource_context_->GetRequestContext()->CreateRequest(
883 url, net::DEFAULT_PRIORITY, NULL));
884 RecordDownloadSource(INITIATED_BY_RENDERER);
885 resource_dispatcher_host_->BeginDownload(
888 true, // is_content_initiated
891 message.routing_id(),
894 content::DownloadItem::kInvalidId,
895 ResourceDispatcherHostImpl::DownloadStartedCallback());
898 void RenderMessageFilter::OnCheckNotificationPermission(
899 const GURL& source_origin, int* result) {
900 #if defined(ENABLE_NOTIFICATIONS)
901 *result = GetContentClient()->browser()->
902 CheckDesktopNotificationPermission(source_origin, resource_context_,
905 *result = blink::WebNotificationPresenter::PermissionAllowed;
909 void RenderMessageFilter::OnAllocateSharedMemory(
911 base::SharedMemoryHandle* handle) {
912 ChildProcessHostImpl::AllocateSharedMemory(
913 buffer_size, PeerHandle(), handle);
916 net::URLRequestContext* RenderMessageFilter::GetRequestContextForURL(
918 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
920 net::URLRequestContext* context =
921 GetContentClient()->browser()->OverrideRequestContextForURL(
922 url, resource_context_);
924 context = request_context_->GetURLRequestContext();
929 #if defined(OS_POSIX) && !defined(TOOLKIT_GTK) && !defined(OS_ANDROID)
930 void RenderMessageFilter::OnAllocTransportDIB(
931 uint32 size, bool cache_in_browser, TransportDIB::Handle* handle) {
932 render_widget_helper_->AllocTransportDIB(size, cache_in_browser, handle);
935 void RenderMessageFilter::OnFreeTransportDIB(
936 TransportDIB::Id dib_id) {
937 render_widget_helper_->FreeTransportDIB(dib_id);
941 bool RenderMessageFilter::CheckPreparsedJsCachingEnabled() const {
942 static bool checked = false;
943 static bool result = false;
945 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
946 result = command_line.HasSwitch(switches::kEnablePreparsedJsCaching);
952 void RenderMessageFilter::OnCacheableMetadataAvailable(
954 double expected_response_time,
955 const std::vector<char>& data) {
956 if (!CheckPreparsedJsCachingEnabled())
959 net::HttpCache* cache = request_context_->GetURLRequestContext()->
960 http_transaction_factory()->GetCache();
963 // Use the same priority for the metadata write as for script
964 // resources (see defaultPriorityForResourceType() in WebKit's
965 // CachedResource.cpp). Note that WebURLRequest::PriorityMedium
966 // corresponds to net::LOW (see ConvertWebKitPriorityToNetPriority()
967 // in weburlloader_impl.cc).
968 const net::RequestPriority kPriority = net::LOW;
969 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(data.size()));
970 memcpy(buf->data(), &data.front(), data.size());
971 cache->WriteMetadata(url,
973 base::Time::FromDoubleT(expected_response_time),
978 void RenderMessageFilter::OnKeygen(uint32 key_size_index,
979 const std::string& challenge_string,
981 IPC::Message* reply_msg) {
982 // Map displayed strings indicating level of keysecurity in the <keygen>
983 // menu to the key size in bits. (See SSLKeyGeneratorChromium.cpp in WebCore.)
984 int key_size_in_bits;
985 switch (key_size_index) {
987 key_size_in_bits = 2048;
990 key_size_in_bits = 1024;
993 DCHECK(false) << "Illegal key_size_index " << key_size_index;
994 ViewHostMsg_Keygen::WriteReplyParams(reply_msg, std::string());
999 resource_context_->CreateKeygenHandler(
1004 &RenderMessageFilter::PostKeygenToWorkerThread, this, reply_msg));
1007 void RenderMessageFilter::PostKeygenToWorkerThread(
1008 IPC::Message* reply_msg,
1009 scoped_ptr<net::KeygenHandler> keygen_handler) {
1010 VLOG(1) << "Dispatching keygen task to worker pool.";
1011 // Dispatch to worker pool, so we do not block the IO thread.
1012 if (!base::WorkerPool::PostTask(
1014 base::Bind(&RenderMessageFilter::OnKeygenOnWorkerThread,
1016 base::Passed(&keygen_handler),
1019 NOTREACHED() << "Failed to dispatch keygen task to worker pool";
1020 ViewHostMsg_Keygen::WriteReplyParams(reply_msg, std::string());
1025 void RenderMessageFilter::OnKeygenOnWorkerThread(
1026 scoped_ptr<net::KeygenHandler> keygen_handler,
1027 IPC::Message* reply_msg) {
1030 // Generate a signed public key and challenge, then send it back.
1031 ViewHostMsg_Keygen::WriteReplyParams(
1033 keygen_handler->GenKeyAndSignChallenge());
1037 void RenderMessageFilter::OnMediaLogEvents(
1038 const std::vector<media::MediaLogEvent>& events) {
1039 if (media_internals_)
1040 media_internals_->OnMediaEvents(render_process_id_, events);
1043 void RenderMessageFilter::CheckPolicyForCookies(
1044 int render_frame_id,
1046 const GURL& first_party_for_cookies,
1047 IPC::Message* reply_msg,
1048 const net::CookieList& cookie_list) {
1049 net::URLRequestContext* context = GetRequestContextForURL(url);
1050 // Check the policy for get cookies, and pass cookie_list to the
1051 // TabSpecificContentSetting for logging purpose.
1052 if (GetContentClient()->browser()->AllowGetCookie(
1053 url, first_party_for_cookies, cookie_list, resource_context_,
1054 render_process_id_, render_frame_id)) {
1055 // Gets the cookies from cookie store if allowed.
1056 context->cookie_store()->GetCookiesWithOptionsAsync(
1057 url, net::CookieOptions(),
1058 base::Bind(&RenderMessageFilter::SendGetCookiesResponse,
1061 SendGetCookiesResponse(reply_msg, std::string());
1065 void RenderMessageFilter::SendGetCookiesResponse(IPC::Message* reply_msg,
1066 const std::string& cookies) {
1067 ViewHostMsg_GetCookies::WriteReplyParams(reply_msg, cookies);
1071 void RenderMessageFilter::SendGetRawCookiesResponse(
1072 IPC::Message* reply_msg,
1073 const net::CookieList& cookie_list) {
1074 std::vector<CookieData> cookies;
1075 for (size_t i = 0; i < cookie_list.size(); ++i)
1076 cookies.push_back(CookieData(cookie_list[i]));
1077 ViewHostMsg_GetRawCookies::WriteReplyParams(reply_msg, cookies);
1081 void RenderMessageFilter::OnCompletedOpenChannelToNpapiPlugin(
1082 OpenChannelToNpapiPluginCallback* client) {
1083 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1084 DCHECK(ContainsKey(plugin_host_clients_, client));
1085 plugin_host_clients_.erase(client);
1088 void RenderMessageFilter::OnUpdateIsDelayed(const IPC::Message& msg) {
1089 // When not in accelerated compositing mode, in certain cases (e.g. waiting
1090 // for a resize or if no backing store) the RenderWidgetHost is blocking the
1091 // UI thread for some time, waiting for an UpdateRect from the renderer. If we
1092 // are going to switch to accelerated compositing, the GPU process may need
1093 // round-trips to the UI thread before finishing the frame, causing deadlocks
1094 // if we delay the UpdateRect until we receive the OnSwapBuffersComplete. So
1095 // the renderer sent us this message, so that we can unblock the UI thread.
1096 // We will simply re-use the UpdateRect unblock mechanism, just with a
1097 // different message.
1098 render_widget_helper_->DidReceiveBackingStoreMsg(msg);
1101 void RenderMessageFilter::OnAre3DAPIsBlocked(int render_view_id,
1102 const GURL& top_origin_url,
1103 ThreeDAPIType requester,
1105 *blocked = GpuDataManagerImpl::GetInstance()->Are3DAPIsBlocked(
1106 top_origin_url, render_process_id_, render_view_id, requester);
1109 void RenderMessageFilter::OnDidLose3DContext(
1110 const GURL& top_origin_url,
1111 ThreeDAPIType /* unused */,
1112 int arb_robustness_status_code) {
1113 #if defined(OS_MACOSX)
1114 // TODO(kbr): this file indirectly includes npapi.h, which on Mac
1115 // OS pulls in the system OpenGL headers. For some
1116 // not-yet-investigated reason this breaks the build with the 10.6
1117 // SDK but not 10.7. For now work around this in a way compatible
1118 // with the Khronos headers.
1119 #ifndef GL_GUILTY_CONTEXT_RESET_ARB
1120 #define GL_GUILTY_CONTEXT_RESET_ARB 0x8253
1122 #ifndef GL_INNOCENT_CONTEXT_RESET_ARB
1123 #define GL_INNOCENT_CONTEXT_RESET_ARB 0x8254
1125 #ifndef GL_UNKNOWN_CONTEXT_RESET_ARB
1126 #define GL_UNKNOWN_CONTEXT_RESET_ARB 0x8255
1130 GpuDataManagerImpl::DomainGuilt guilt;
1131 switch (arb_robustness_status_code) {
1132 case GL_GUILTY_CONTEXT_RESET_ARB:
1133 guilt = GpuDataManagerImpl::DOMAIN_GUILT_KNOWN;
1135 case GL_UNKNOWN_CONTEXT_RESET_ARB:
1136 guilt = GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN;
1139 // Ignore lost contexts known to be innocent.
1143 GpuDataManagerImpl::GetInstance()->BlockDomainFrom3DAPIs(
1144 top_origin_url, guilt);
1148 void RenderMessageFilter::OnPreCacheFontCharacters(const LOGFONT& font,
1149 const base::string16& str) {
1150 // First, comments from FontCacheDispatcher::OnPreCacheFont do apply here too.
1151 // Except that for True Type fonts,
1152 // GetTextMetrics will not load the font in memory.
1153 // The only way windows seem to load properly, it is to create a similar
1154 // device (like the one in which we print), then do an ExtTextOut,
1155 // as we do in the printing thread, which is sandboxed.
1156 HDC hdc = CreateEnhMetaFile(NULL, NULL, NULL, NULL);
1157 HFONT font_handle = CreateFontIndirect(&font);
1158 DCHECK(NULL != font_handle);
1160 HGDIOBJ old_font = SelectObject(hdc, font_handle);
1161 DCHECK(NULL != old_font);
1163 ExtTextOut(hdc, 0, 0, ETO_GLYPH_INDEX, 0, str.c_str(), str.length(), NULL);
1165 SelectObject(hdc, old_font);
1166 DeleteObject(font_handle);
1168 HENHMETAFILE metafile = CloseEnhMetaFile(hdc);
1171 DeleteEnhMetaFile(metafile);
1176 #if defined(OS_ANDROID)
1177 void RenderMessageFilter::OnWebAudioMediaCodec(
1178 base::SharedMemoryHandle encoded_data_handle,
1179 base::FileDescriptor pcm_output,
1180 uint32_t data_size) {
1181 // Let a WorkerPool handle this request since the WebAudio
1182 // MediaCodec bridge is slow and can block while sending the data to
1184 base::WorkerPool::PostTask(
1186 base::Bind(&media::WebAudioMediaCodecBridge::RunWebAudioMediaCodec,
1187 encoded_data_handle, pcm_output, data_size),
1192 void RenderMessageFilter::OnAllocateGpuMemoryBuffer(
1195 uint32 internalformat,
1196 gfx::GpuMemoryBufferHandle* handle) {
1197 if (!GpuMemoryBufferImpl::IsFormatValid(internalformat)) {
1198 handle->type = gfx::EMPTY_BUFFER;
1202 #if defined(OS_MACOSX)
1203 if (GpuMemoryBufferImplIOSurface::IsFormatSupported(internalformat)) {
1204 IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize();
1205 if (io_surface_support) {
1206 base::ScopedCFTypeRef<CFMutableDictionaryRef> properties;
1208 CFDictionaryCreateMutable(kCFAllocatorDefault,
1210 &kCFTypeDictionaryKeyCallBacks,
1211 &kCFTypeDictionaryValueCallBacks));
1212 AddIntegerValue(properties,
1213 io_surface_support->GetKIOSurfaceWidth(),
1215 AddIntegerValue(properties,
1216 io_surface_support->GetKIOSurfaceHeight(),
1218 AddIntegerValue(properties,
1219 io_surface_support->GetKIOSurfaceBytesPerElement(),
1220 GpuMemoryBufferImpl::BytesPerPixel(internalformat));
1221 AddIntegerValue(properties,
1222 io_surface_support->GetKIOSurfacePixelFormat(),
1223 GpuMemoryBufferImplIOSurface::PixelFormat(
1225 // TODO(reveman): Remove this when using a mach_port_t to transfer
1226 // IOSurface to renderer process. crbug.com/323304
1227 AddBooleanValue(properties,
1228 io_surface_support->GetKIOSurfaceIsGlobal(),
1231 base::ScopedCFTypeRef<CFTypeRef> io_surface(
1232 io_surface_support->IOSurfaceCreate(properties));
1234 handle->type = gfx::IO_SURFACE_BUFFER;
1235 handle->io_surface_id = io_surface_support->IOSurfaceGetID(io_surface);
1237 // TODO(reveman): This makes the assumption that the renderer will
1238 // grab a reference to the surface before sending another message.
1240 last_io_surface_ = io_surface;
1247 uint64 stride = static_cast<uint64>(width) *
1248 GpuMemoryBufferImpl::BytesPerPixel(internalformat);
1249 if (stride > std::numeric_limits<uint32>::max()) {
1250 handle->type = gfx::EMPTY_BUFFER;
1254 uint64 buffer_size = stride * static_cast<uint64>(height);
1255 if (buffer_size > std::numeric_limits<size_t>::max()) {
1256 handle->type = gfx::EMPTY_BUFFER;
1260 // Fallback to fake GpuMemoryBuffer that is backed by shared memory and
1261 // requires an upload before it can be used as a texture.
1262 handle->type = gfx::SHARED_MEMORY_BUFFER;
1263 ChildProcessHostImpl::AllocateSharedMemory(
1264 static_cast<size_t>(buffer_size), PeerHandle(), &handle->handle);
1267 } // namespace content