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/numerics/safe_math.h"
14 #include "base/strings/sys_string_conversions.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "base/threading/thread.h"
17 #include "base/threading/worker_pool.h"
18 #include "content/browser/browser_main_loop.h"
19 #include "content/browser/child_process_security_policy_impl.h"
20 #include "content/browser/dom_storage/dom_storage_context_wrapper.h"
21 #include "content/browser/dom_storage/session_storage_namespace_impl.h"
22 #include "content/browser/download/download_stats.h"
23 #include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
24 #include "content/browser/gpu/gpu_data_manager_impl.h"
25 #include "content/browser/loader/resource_dispatcher_host_impl.h"
26 #include "content/browser/media/media_internals.h"
27 #include "content/browser/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/browser/renderer_host/render_widget_resize_helper.h"
33 #include "content/browser/transition_request_manager.h"
34 #include "content/common/child_process_host_impl.h"
35 #include "content/common/child_process_messages.h"
36 #include "content/common/content_constants_internal.h"
37 #include "content/common/cookie_data.h"
38 #include "content/common/desktop_notification_messages.h"
39 #include "content/common/frame_messages.h"
40 #include "content/common/gpu/client/gpu_memory_buffer_impl.h"
41 #include "content/common/host_discardable_shared_memory_manager.h"
42 #include "content/common/host_shared_bitmap_manager.h"
43 #include "content/common/media/media_param_traits.h"
44 #include "content/common/view_messages.h"
45 #include "content/public/browser/browser_child_process_host.h"
46 #include "content/public/browser/browser_context.h"
47 #include "content/public/browser/browser_thread.h"
48 #include "content/public/browser/content_browser_client.h"
49 #include "content/public/browser/download_save_info.h"
50 #include "content/public/browser/plugin_service_filter.h"
51 #include "content/public/browser/resource_context.h"
52 #include "content/public/browser/user_metrics.h"
53 #include "content/public/common/content_constants.h"
54 #include "content/public/common/content_switches.h"
55 #include "content/public/common/context_menu_params.h"
56 #include "content/public/common/url_constants.h"
57 #include "content/public/common/webplugininfo.h"
58 #include "ipc/ipc_channel_handle.h"
59 #include "ipc/ipc_platform_file.h"
60 #include "media/audio/audio_manager.h"
61 #include "media/audio/audio_manager_base.h"
62 #include "media/audio/audio_parameters.h"
63 #include "media/base/media_log_event.h"
64 #include "net/base/io_buffer.h"
65 #include "net/base/keygen_handler.h"
66 #include "net/base/mime_util.h"
67 #include "net/base/request_priority.h"
68 #include "net/cookies/canonical_cookie.h"
69 #include "net/cookies/cookie_store.h"
70 #include "net/http/http_cache.h"
71 #include "net/url_request/url_request_context.h"
72 #include "net/url_request/url_request_context_getter.h"
73 #include "ppapi/shared_impl/file_type_conversion.h"
74 #include "third_party/WebKit/public/web/WebNotificationPresenter.h"
75 #include "ui/gfx/color_profile.h"
77 #if defined(OS_MACOSX)
78 #include "content/common/mac/font_descriptor.h"
80 #include "gpu/GLES2/gl2extchromium.h"
81 #include "third_party/khronos/GLES2/gl2.h"
82 #include "third_party/khronos/GLES2/gl2ext.h"
85 #include "base/file_descriptor_posix.h"
88 #include "content/common/font_cache_dispatcher_win.h"
89 #include "content/common/sandbox_win.h"
91 #if defined(OS_ANDROID)
92 #include "media/base/android/webaudio_media_codec_bridge.h"
95 #if defined(ENABLE_PLUGINS)
96 #include "content/browser/plugin_service_impl.h"
97 #include "content/browser/ppapi_plugin_process_host.h"
100 using net::CookieStore;
105 #if defined(ENABLE_PLUGINS)
106 const int kPluginsRefreshThresholdInSeconds = 3;
109 const uint32 kFilteredMessageClasses[] = {
110 ChildProcessMsgStart,
111 DesktopNotificationMsgStart,
117 // On Windows, |g_color_profile| can run on an arbitrary background thread.
118 // We avoid races by using LazyInstance's constructor lock to initialize the
120 base::LazyInstance<gfx::ColorProfile>::Leaky g_color_profile =
121 LAZY_INSTANCE_INITIALIZER;
124 // Common functionality for converting a sync renderer message to a callback
125 // function in the browser. Derive from this, create it on the heap when
126 // issuing your callback. When done, write your reply parameters into
127 // reply_msg(), and then call SendReplyAndDeleteThis().
128 class RenderMessageCompletionCallback {
130 RenderMessageCompletionCallback(RenderMessageFilter* filter,
131 IPC::Message* reply_msg)
133 reply_msg_(reply_msg) {
136 virtual ~RenderMessageCompletionCallback() {
139 RenderMessageFilter* filter() { return filter_.get(); }
140 IPC::Message* reply_msg() { return reply_msg_; }
142 void SendReplyAndDeleteThis() {
143 filter_->Send(reply_msg_);
148 scoped_refptr<RenderMessageFilter> filter_;
149 IPC::Message* reply_msg_;
152 #if defined(ENABLE_PLUGINS)
153 class OpenChannelToPpapiPluginCallback
154 : public RenderMessageCompletionCallback,
155 public PpapiPluginProcessHost::PluginClient {
157 OpenChannelToPpapiPluginCallback(RenderMessageFilter* filter,
158 ResourceContext* context,
159 IPC::Message* reply_msg)
160 : RenderMessageCompletionCallback(filter, reply_msg),
164 void GetPpapiChannelInfo(base::ProcessHandle* renderer_handle,
165 int* renderer_id) override {
166 *renderer_handle = filter()->PeerHandle();
167 *renderer_id = filter()->render_process_id();
170 void OnPpapiChannelOpened(const IPC::ChannelHandle& channel_handle,
171 base::ProcessId plugin_pid,
172 int plugin_child_id) override {
173 ViewHostMsg_OpenChannelToPepperPlugin::WriteReplyParams(
174 reply_msg(), channel_handle, plugin_pid, plugin_child_id);
175 SendReplyAndDeleteThis();
178 bool OffTheRecord() override { return filter()->OffTheRecord(); }
180 ResourceContext* GetResourceContext() override { return context_; }
183 ResourceContext* context_;
186 class OpenChannelToPpapiBrokerCallback
187 : public PpapiPluginProcessHost::BrokerClient {
189 OpenChannelToPpapiBrokerCallback(RenderMessageFilter* filter,
192 routing_id_(routing_id) {
195 ~OpenChannelToPpapiBrokerCallback() override {}
197 void GetPpapiChannelInfo(base::ProcessHandle* renderer_handle,
198 int* renderer_id) override {
199 *renderer_handle = filter_->PeerHandle();
200 *renderer_id = filter_->render_process_id();
203 void OnPpapiChannelOpened(const IPC::ChannelHandle& channel_handle,
204 base::ProcessId plugin_pid,
205 int /* plugin_child_id */) override {
206 filter_->Send(new ViewMsg_PpapiBrokerChannelCreated(routing_id_,
212 bool OffTheRecord() override { return filter_->OffTheRecord(); }
215 scoped_refptr<RenderMessageFilter> filter_;
218 #endif // defined(ENABLE_PLUGINS)
222 class RenderMessageFilter::OpenChannelToNpapiPluginCallback
223 : public RenderMessageCompletionCallback,
224 public PluginProcessHost::Client {
226 OpenChannelToNpapiPluginCallback(RenderMessageFilter* filter,
227 ResourceContext* context,
228 IPC::Message* reply_msg)
229 : RenderMessageCompletionCallback(filter, reply_msg),
232 sent_plugin_channel_request_(false) {
235 int ID() override { return filter()->render_process_id(); }
237 ResourceContext* GetResourceContext() override { return context_; }
239 bool OffTheRecord() override {
240 if (filter()->OffTheRecord())
242 if (GetContentClient()->browser()->AllowSaveLocalState(context_))
245 // For now, only disallow storing data for Flash <http://crbug.com/97319>.
246 for (size_t i = 0; i < info_.mime_types.size(); ++i) {
247 if (info_.mime_types[i].mime_type == kFlashPluginSwfMimeType)
253 void SetPluginInfo(const WebPluginInfo& info) override { info_ = info; }
255 void OnFoundPluginProcessHost(PluginProcessHost* host) override {
260 void OnSentPluginChannelRequest() override {
261 sent_plugin_channel_request_ = true;
264 void OnChannelOpened(const IPC::ChannelHandle& handle) override {
265 WriteReplyAndDeleteThis(handle);
268 void OnError() override { WriteReplyAndDeleteThis(IPC::ChannelHandle()); }
270 PluginProcessHost* host() const {
274 bool sent_plugin_channel_request() const {
275 return sent_plugin_channel_request_;
283 void WriteReplyAndDeleteThis(const IPC::ChannelHandle& handle) {
284 FrameHostMsg_OpenChannelToPlugin::WriteReplyParams(reply_msg(),
286 filter()->OnCompletedOpenChannelToNpapiPlugin(this);
287 SendReplyAndDeleteThis();
290 ResourceContext* context_;
292 PluginProcessHost* host_;
293 bool sent_plugin_channel_request_;
296 RenderMessageFilter::RenderMessageFilter(
297 int render_process_id,
298 PluginServiceImpl* plugin_service,
299 BrowserContext* browser_context,
300 net::URLRequestContextGetter* request_context,
301 RenderWidgetHelper* render_widget_helper,
302 media::AudioManager* audio_manager,
303 MediaInternals* media_internals,
304 DOMStorageContextWrapper* dom_storage_context)
305 : BrowserMessageFilter(
306 kFilteredMessageClasses, arraysize(kFilteredMessageClasses)),
307 resource_dispatcher_host_(ResourceDispatcherHostImpl::Get()),
308 plugin_service_(plugin_service),
309 profile_data_directory_(browser_context->GetPath()),
310 request_context_(request_context),
311 resource_context_(browser_context->GetResourceContext()),
312 render_widget_helper_(render_widget_helper),
313 incognito_(browser_context->IsOffTheRecord()),
314 dom_storage_context_(dom_storage_context),
315 render_process_id_(render_process_id),
316 audio_manager_(audio_manager),
317 media_internals_(media_internals) {
318 DCHECK(request_context_.get());
320 if (render_widget_helper)
321 render_widget_helper_->Init(render_process_id_, resource_dispatcher_host_);
324 RenderMessageFilter::~RenderMessageFilter() {
325 // This function should be called on the IO thread.
326 DCHECK_CURRENTLY_ON(BrowserThread::IO);
327 DCHECK(plugin_host_clients_.empty());
328 HostSharedBitmapManager::current()->ProcessRemoved(PeerHandle());
329 BrowserGpuMemoryBufferManager* gpu_memory_buffer_manager =
330 BrowserGpuMemoryBufferManager::current();
331 if (gpu_memory_buffer_manager)
332 gpu_memory_buffer_manager->ProcessRemoved(PeerHandle(), render_process_id_);
333 HostDiscardableSharedMemoryManager::current()->ProcessRemoved(PeerHandle());
336 void RenderMessageFilter::OnChannelClosing() {
337 #if defined(ENABLE_PLUGINS)
338 for (std::set<OpenChannelToNpapiPluginCallback*>::iterator it =
339 plugin_host_clients_.begin(); it != plugin_host_clients_.end(); ++it) {
340 OpenChannelToNpapiPluginCallback* client = *it;
341 if (client->host()) {
342 if (client->sent_plugin_channel_request()) {
343 client->host()->CancelSentRequest(client);
345 client->host()->CancelPendingRequest(client);
348 plugin_service_->CancelOpenChannelToNpapiPlugin(client);
352 #endif // defined(ENABLE_PLUGINS)
353 plugin_host_clients_.clear();
356 bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message) {
358 IPC_BEGIN_MESSAGE_MAP(RenderMessageFilter, message)
360 IPC_MESSAGE_HANDLER(ViewHostMsg_PreCacheFontCharacters,
361 OnPreCacheFontCharacters)
363 IPC_MESSAGE_HANDLER(ViewHostMsg_GetProcessMemorySizes,
364 OnGetProcessMemorySizes)
365 IPC_MESSAGE_HANDLER(ViewHostMsg_GenerateRoutingID, OnGenerateRoutingID)
366 IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWindow, OnCreateWindow)
367 IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWidget, OnCreateWidget)
368 IPC_MESSAGE_HANDLER(ViewHostMsg_CreateFullscreenWidget,
369 OnCreateFullscreenWidget)
370 IPC_MESSAGE_HANDLER(ViewHostMsg_SetCookie, OnSetCookie)
371 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetCookies, OnGetCookies)
372 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetRawCookies, OnGetRawCookies)
373 IPC_MESSAGE_HANDLER(ViewHostMsg_DeleteCookie, OnDeleteCookie)
374 IPC_MESSAGE_HANDLER(ViewHostMsg_CookiesEnabled, OnCookiesEnabled)
375 #if defined(OS_MACOSX)
376 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_LoadFont, OnLoadFont)
378 IPC_MESSAGE_HANDLER(ViewHostMsg_DownloadUrl, OnDownloadUrl)
379 IPC_MESSAGE_HANDLER(ViewHostMsg_SaveImageFromDataURL,
380 OnSaveImageFromDataURL)
381 #if defined(ENABLE_PLUGINS)
382 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetPlugins, OnGetPlugins)
383 IPC_MESSAGE_HANDLER(FrameHostMsg_GetPluginInfo, OnGetPluginInfo)
384 IPC_MESSAGE_HANDLER_DELAY_REPLY(FrameHostMsg_OpenChannelToPlugin,
385 OnOpenChannelToPlugin)
386 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_OpenChannelToPepperPlugin,
387 OnOpenChannelToPepperPlugin)
388 IPC_MESSAGE_HANDLER(ViewHostMsg_DidCreateOutOfProcessPepperInstance,
389 OnDidCreateOutOfProcessPepperInstance)
390 IPC_MESSAGE_HANDLER(ViewHostMsg_DidDeleteOutOfProcessPepperInstance,
391 OnDidDeleteOutOfProcessPepperInstance)
392 IPC_MESSAGE_HANDLER(ViewHostMsg_OpenChannelToPpapiBroker,
393 OnOpenChannelToPpapiBroker)
395 #if defined(OS_MACOSX)
396 IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_SwapCompositorFrame,
397 RenderWidgetResizeHelper::Get()->PostRendererProcessMsg(
398 render_process_id_, message))
399 IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_UpdateRect,
400 RenderWidgetResizeHelper::Get()->PostRendererProcessMsg(
401 render_process_id_, message))
403 IPC_MESSAGE_HANDLER(DesktopNotificationHostMsg_CheckPermission,
404 OnCheckNotificationPermission)
405 IPC_MESSAGE_HANDLER(ChildProcessHostMsg_SyncAllocateSharedMemory,
406 OnAllocateSharedMemory)
407 IPC_MESSAGE_HANDLER_DELAY_REPLY(
408 ChildProcessHostMsg_SyncAllocateSharedBitmap, OnAllocateSharedBitmap)
409 IPC_MESSAGE_HANDLER_DELAY_REPLY(
410 ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer,
411 OnAllocateGpuMemoryBuffer)
412 IPC_MESSAGE_HANDLER(ChildProcessHostMsg_DeletedGpuMemoryBuffer,
413 OnDeletedGpuMemoryBuffer)
414 IPC_MESSAGE_HANDLER(ChildProcessHostMsg_AllocatedSharedBitmap,
415 OnAllocatedSharedBitmap)
416 IPC_MESSAGE_HANDLER(ChildProcessHostMsg_DeletedSharedBitmap,
417 OnDeletedSharedBitmap)
419 ChildProcessHostMsg_SyncAllocateLockedDiscardableSharedMemory,
420 OnAllocateLockedDiscardableSharedMemory)
421 #if defined(OS_POSIX) && !defined(OS_ANDROID)
422 IPC_MESSAGE_HANDLER(ViewHostMsg_AllocTransportDIB, OnAllocTransportDIB)
423 IPC_MESSAGE_HANDLER(ViewHostMsg_FreeTransportDIB, OnFreeTransportDIB)
425 IPC_MESSAGE_HANDLER(ViewHostMsg_DidGenerateCacheableMetadata,
426 OnCacheableMetadataAvailable)
427 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_Keygen, OnKeygen)
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_HANDLER(FrameHostMsg_AddNavigationTransitionData,
441 OnAddNavigationTransitionData)
442 IPC_MESSAGE_UNHANDLED(handled = false)
443 IPC_END_MESSAGE_MAP()
448 void RenderMessageFilter::OnDestruct() const {
449 BrowserThread::DeleteOnIOThread::Destruct(this);
452 base::TaskRunner* RenderMessageFilter::OverrideTaskRunnerForMessage(
453 const IPC::Message& message) {
455 // Windows monitor profile must be read from a file.
456 if (message.type() == ViewHostMsg_GetMonitorColorProfile::ID)
457 return BrowserThread::GetBlockingPool();
459 // Always query audio device parameters on the audio thread.
460 if (message.type() == ViewHostMsg_GetAudioHardwareConfig::ID)
461 return audio_manager_->GetTaskRunner().get();
465 bool RenderMessageFilter::OffTheRecord() const {
469 void RenderMessageFilter::OnCreateWindow(
470 const ViewHostMsg_CreateWindow_Params& params,
472 int* main_frame_route_id,
474 int64* cloned_session_storage_namespace_id) {
475 bool no_javascript_access;
477 // Merge the additional features into the WebWindowFeatures struct before we
479 blink::WebVector<blink::WebString> additional_features(
480 params.additional_features.size());
482 for (size_t i = 0; i < params.additional_features.size(); ++i)
483 additional_features[i] = blink::WebString(params.additional_features[i]);
485 blink::WebWindowFeatures features = params.features;
486 features.additionalFeatures.swap(additional_features);
488 bool can_create_window =
489 GetContentClient()->browser()->CanCreateWindow(
491 params.opener_top_level_frame_url,
492 params.opener_security_origin,
493 params.window_container_type,
499 params.opener_suppressed,
503 &no_javascript_access);
505 if (!can_create_window) {
506 *route_id = MSG_ROUTING_NONE;
507 *main_frame_route_id = MSG_ROUTING_NONE;
509 *cloned_session_storage_namespace_id = 0;
513 // This will clone the sessionStorage for namespace_id_to_clone.
514 scoped_refptr<SessionStorageNamespaceImpl> cloned_namespace =
515 new SessionStorageNamespaceImpl(dom_storage_context_.get(),
516 params.session_storage_namespace_id);
517 *cloned_session_storage_namespace_id = cloned_namespace->id();
519 render_widget_helper_->CreateNewWindow(params,
520 no_javascript_access,
525 cloned_namespace.get());
528 void RenderMessageFilter::OnCreateWidget(int opener_id,
529 blink::WebPopupType popup_type,
532 render_widget_helper_->CreateNewWidget(
533 opener_id, popup_type, route_id, surface_id);
536 void RenderMessageFilter::OnCreateFullscreenWidget(int opener_id,
539 render_widget_helper_->CreateNewFullscreenWidget(
540 opener_id, route_id, surface_id);
543 void RenderMessageFilter::OnGetProcessMemorySizes(size_t* private_bytes,
544 size_t* shared_bytes) {
545 DCHECK_CURRENTLY_ON(BrowserThread::IO);
546 using base::ProcessMetrics;
547 #if !defined(OS_MACOSX) || defined(OS_IOS)
548 scoped_ptr<ProcessMetrics> metrics(ProcessMetrics::CreateProcessMetrics(
551 scoped_ptr<ProcessMetrics> metrics(ProcessMetrics::CreateProcessMetrics(
552 PeerHandle(), BrowserChildProcessHost::GetPortProvider()));
554 if (!metrics->GetMemoryBytes(private_bytes, shared_bytes)) {
560 void RenderMessageFilter::OnSetCookie(int render_frame_id,
562 const GURL& first_party_for_cookies,
563 const std::string& cookie) {
564 ChildProcessSecurityPolicyImpl* policy =
565 ChildProcessSecurityPolicyImpl::GetInstance();
566 if (!policy->CanAccessCookiesForOrigin(render_process_id_, url))
569 net::CookieOptions options;
570 if (GetContentClient()->browser()->AllowSetCookie(
571 url, first_party_for_cookies, cookie, resource_context_,
572 render_process_id_, render_frame_id, &options)) {
573 net::CookieStore* cookie_store = GetCookieStoreForURL(url);
574 // Pass a null callback since we don't care about when the 'set' completes.
575 cookie_store->SetCookieWithOptionsAsync(
576 url, cookie, options, net::CookieStore::SetCookiesCallback());
580 void RenderMessageFilter::OnGetCookies(int render_frame_id,
582 const GURL& first_party_for_cookies,
583 IPC::Message* reply_msg) {
584 ChildProcessSecurityPolicyImpl* policy =
585 ChildProcessSecurityPolicyImpl::GetInstance();
586 if (!policy->CanAccessCookiesForOrigin(render_process_id_, url)) {
587 SendGetCookiesResponse(reply_msg, std::string());
591 // If we crash here, figure out what URL the renderer was requesting.
592 // http://crbug.com/99242
594 base::strlcpy(url_buf, url.spec().c_str(), arraysize(url_buf));
595 base::debug::Alias(url_buf);
597 net::CookieStore* cookie_store = GetCookieStoreForURL(url);
598 cookie_store->GetAllCookiesForURLAsync(
599 url, base::Bind(&RenderMessageFilter::CheckPolicyForCookies, this,
600 render_frame_id, url, first_party_for_cookies,
604 void RenderMessageFilter::OnGetRawCookies(
606 const GURL& first_party_for_cookies,
607 IPC::Message* reply_msg) {
608 ChildProcessSecurityPolicyImpl* policy =
609 ChildProcessSecurityPolicyImpl::GetInstance();
610 // Only return raw cookies to trusted renderers or if this request is
611 // not targeted to an an external host like ChromeFrame.
612 // TODO(ananta) We need to support retreiving raw cookies from external
614 if (!policy->CanReadRawCookies(render_process_id_) ||
615 !policy->CanAccessCookiesForOrigin(render_process_id_, url)) {
616 SendGetRawCookiesResponse(reply_msg, net::CookieList());
620 // We check policy here to avoid sending back cookies that would not normally
621 // be applied to outbound requests for the given URL. Since this cookie info
622 // is visible in the developer tools, it is helpful to make it match reality.
623 net::CookieStore* cookie_store = GetCookieStoreForURL(url);
624 cookie_store->GetAllCookiesForURLAsync(
625 url, base::Bind(&RenderMessageFilter::SendGetRawCookiesResponse,
629 void RenderMessageFilter::OnDeleteCookie(const GURL& url,
630 const std::string& cookie_name) {
631 ChildProcessSecurityPolicyImpl* policy =
632 ChildProcessSecurityPolicyImpl::GetInstance();
633 if (!policy->CanAccessCookiesForOrigin(render_process_id_, url))
636 net::CookieStore* cookie_store = GetCookieStoreForURL(url);
637 cookie_store->DeleteCookieAsync(url, cookie_name, base::Closure());
640 void RenderMessageFilter::OnCookiesEnabled(
643 const GURL& first_party_for_cookies,
644 bool* cookies_enabled) {
645 // TODO(ananta): If this render view is associated with an automation channel,
646 // aka ChromeFrame then we need to retrieve cookie settings from the external
648 *cookies_enabled = GetContentClient()->browser()->AllowGetCookie(
649 url, first_party_for_cookies, net::CookieList(), resource_context_,
650 render_process_id_, render_frame_id);
653 #if defined(OS_MACOSX)
654 void RenderMessageFilter::OnLoadFont(const FontDescriptor& font,
655 IPC::Message* reply_msg) {
656 FontLoader::Result* result = new FontLoader::Result;
658 BrowserThread::PostTaskAndReply(
659 BrowserThread::FILE, FROM_HERE,
660 base::Bind(&FontLoader::LoadFont, font, result),
661 base::Bind(&RenderMessageFilter::SendLoadFontReply, this, reply_msg,
662 base::Owned(result)));
665 void RenderMessageFilter::SendLoadFontReply(IPC::Message* reply,
666 FontLoader::Result* result) {
667 base::SharedMemoryHandle handle;
668 if (result->font_data_size == 0 || result->font_id == 0) {
669 result->font_data_size = 0;
671 handle = base::SharedMemory::NULLHandle();
673 result->font_data.GiveToProcess(base::GetCurrentProcessHandle(), &handle);
675 ViewHostMsg_LoadFont::WriteReplyParams(
676 reply, result->font_data_size, handle, result->font_id);
681 #if defined(ENABLE_PLUGINS)
682 void RenderMessageFilter::OnGetPlugins(
684 IPC::Message* reply_msg) {
685 // Don't refresh if the specified threshold has not been passed. Note that
686 // this check is performed before off-loading to the file thread. The reason
687 // we do this is that some pages tend to request that the list of plugins be
688 // refreshed at an excessive rate. This instigates disk scanning, as the list
689 // is accumulated by doing multiple reads from disk. This effect is
690 // multiplied when we have several pages requesting this operation.
692 const base::TimeDelta threshold = base::TimeDelta::FromSeconds(
693 kPluginsRefreshThresholdInSeconds);
694 const base::TimeTicks now = base::TimeTicks::Now();
695 if (now - last_plugin_refresh_time_ >= threshold) {
696 // Only refresh if the threshold hasn't been exceeded yet.
697 PluginServiceImpl::GetInstance()->RefreshPlugins();
698 last_plugin_refresh_time_ = now;
702 PluginServiceImpl::GetInstance()->GetPlugins(
703 base::Bind(&RenderMessageFilter::GetPluginsCallback, this, reply_msg));
706 void RenderMessageFilter::GetPluginsCallback(
707 IPC::Message* reply_msg,
708 const std::vector<WebPluginInfo>& all_plugins) {
709 // Filter the plugin list.
710 PluginServiceFilter* filter = PluginServiceImpl::GetInstance()->GetFilter();
711 std::vector<WebPluginInfo> plugins;
713 int child_process_id = -1;
714 int routing_id = MSG_ROUTING_NONE;
715 for (size_t i = 0; i < all_plugins.size(); ++i) {
716 // Copy because the filter can mutate.
717 WebPluginInfo plugin(all_plugins[i]);
718 if (!filter || filter->IsPluginAvailable(child_process_id,
724 plugins.push_back(plugin);
728 ViewHostMsg_GetPlugins::WriteReplyParams(reply_msg, plugins);
732 void RenderMessageFilter::OnGetPluginInfo(
735 const GURL& page_url,
736 const std::string& mime_type,
739 std::string* actual_mime_type) {
740 bool allow_wildcard = true;
741 *found = plugin_service_->GetPluginInfo(
742 render_process_id_, render_frame_id, resource_context_,
743 url, page_url, mime_type, allow_wildcard,
744 NULL, info, actual_mime_type);
747 void RenderMessageFilter::OnOpenChannelToPlugin(int render_frame_id,
749 const GURL& policy_url,
750 const std::string& mime_type,
751 IPC::Message* reply_msg) {
752 OpenChannelToNpapiPluginCallback* client =
753 new OpenChannelToNpapiPluginCallback(this, resource_context_, reply_msg);
754 DCHECK(!ContainsKey(plugin_host_clients_, client));
755 plugin_host_clients_.insert(client);
756 plugin_service_->OpenChannelToNpapiPlugin(
757 render_process_id_, render_frame_id,
758 url, policy_url, mime_type, client);
761 void RenderMessageFilter::OnOpenChannelToPepperPlugin(
762 const base::FilePath& path,
763 IPC::Message* reply_msg) {
764 plugin_service_->OpenChannelToPpapiPlugin(
767 profile_data_directory_,
768 new OpenChannelToPpapiPluginCallback(this, resource_context_, reply_msg));
771 void RenderMessageFilter::OnDidCreateOutOfProcessPepperInstance(
774 PepperRendererInstanceData instance_data,
776 // It's important that we supply the render process ID ourselves based on the
777 // channel the message arrived on. We use the
778 // PP_Instance -> (process id, view id)
779 // mapping to decide how to handle messages received from the (untrusted)
780 // plugin, so an exploited renderer must not be able to insert fake mappings
781 // that may allow it access to other render processes.
782 DCHECK_EQ(0, instance_data.render_process_id);
783 instance_data.render_process_id = render_process_id_;
785 // We provide the BrowserPpapiHost to the embedder, so it's safe to cast.
786 BrowserPpapiHostImpl* host = static_cast<BrowserPpapiHostImpl*>(
787 GetContentClient()->browser()->GetExternalBrowserPpapiHost(
790 host->AddInstance(pp_instance, instance_data);
792 PpapiPluginProcessHost::DidCreateOutOfProcessInstance(
793 plugin_child_id, pp_instance, instance_data);
797 void RenderMessageFilter::OnDidDeleteOutOfProcessPepperInstance(
802 // We provide the BrowserPpapiHost to the embedder, so it's safe to cast.
803 BrowserPpapiHostImpl* host = static_cast<BrowserPpapiHostImpl*>(
804 GetContentClient()->browser()->GetExternalBrowserPpapiHost(
807 host->DeleteInstance(pp_instance);
809 PpapiPluginProcessHost::DidDeleteOutOfProcessInstance(
810 plugin_child_id, pp_instance);
814 void RenderMessageFilter::OnOpenChannelToPpapiBroker(
816 const base::FilePath& path) {
817 plugin_service_->OpenChannelToPpapiBroker(
820 new OpenChannelToPpapiBrokerCallback(this, routing_id));
822 #endif // defined(ENABLE_PLUGINS)
824 void RenderMessageFilter::OnGenerateRoutingID(int* route_id) {
825 *route_id = render_widget_helper_->GetNextRoutingID();
828 void RenderMessageFilter::OnGetAudioHardwareConfig(
829 media::AudioParameters* input_params,
830 media::AudioParameters* output_params) {
831 DCHECK(input_params);
832 DCHECK(output_params);
833 *output_params = audio_manager_->GetDefaultOutputStreamParameters();
835 // TODO(henrika): add support for all available input devices.
836 *input_params = audio_manager_->GetInputStreamParameters(
837 media::AudioManagerBase::kDefaultDeviceId);
841 void RenderMessageFilter::OnGetMonitorColorProfile(std::vector<char>* profile) {
842 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
843 *profile = g_color_profile.Get().profile();
847 void RenderMessageFilter::DownloadUrl(int render_view_id,
849 const Referrer& referrer,
850 const base::string16& suggested_name,
851 const bool use_prompt) const {
852 scoped_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo());
853 save_info->suggested_name = suggested_name;
854 save_info->prompt_for_save_location = use_prompt;
856 // There may be a special cookie store that we could use for this download,
857 // rather than the default one. Since this feature is generally only used for
858 // proper render views, and not downloads, we do not need to retrieve the
859 // special cookie store here, but just initialize the request to use the
860 // default cookie store.
861 // TODO(tburkard): retrieve the appropriate special cookie store, if this
862 // is ever to be used for downloads as well.
864 scoped_ptr<net::URLRequest> request(
865 resource_context_->GetRequestContext()->CreateRequest(
866 url, net::DEFAULT_PRIORITY, NULL, NULL));
867 RecordDownloadSource(INITIATED_BY_RENDERER);
868 resource_dispatcher_host_->BeginDownload(
871 true, // is_content_initiated
877 DownloadItem::kInvalidId,
878 ResourceDispatcherHostImpl::DownloadStartedCallback());
881 void RenderMessageFilter::OnDownloadUrl(int render_view_id,
883 const Referrer& referrer,
884 const base::string16& suggested_name) {
885 DownloadUrl(render_view_id, url, referrer, suggested_name, false);
888 void RenderMessageFilter::OnSaveImageFromDataURL(int render_view_id,
889 const std::string& url_str) {
890 // Please refer to RenderViewImpl::saveImageFromDataURL().
891 if (url_str.length() >= kMaxLengthOfDataURLString)
894 GURL data_url(url_str);
895 if (!data_url.SchemeIs(url::kDataScheme))
898 DownloadUrl(render_view_id, data_url, Referrer(), base::string16(), true);
901 void RenderMessageFilter::OnCheckNotificationPermission(
902 const GURL& source_origin, int* result) {
903 #if defined(ENABLE_NOTIFICATIONS)
904 *result = GetContentClient()->browser()->
905 CheckDesktopNotificationPermission(source_origin, resource_context_,
908 *result = blink::WebNotificationPresenter::PermissionAllowed;
912 void RenderMessageFilter::OnAllocateSharedMemory(
914 base::SharedMemoryHandle* handle) {
915 ChildProcessHostImpl::AllocateSharedMemory(
916 buffer_size, PeerHandle(), handle);
919 void RenderMessageFilter::AllocateSharedBitmapOnFileThread(
921 const cc::SharedBitmapId& id,
922 IPC::Message* reply_msg) {
923 base::SharedMemoryHandle handle;
924 HostSharedBitmapManager::current()->AllocateSharedBitmapForChild(
925 PeerHandle(), buffer_size, id, &handle);
926 ChildProcessHostMsg_SyncAllocateSharedBitmap::WriteReplyParams(reply_msg,
931 void RenderMessageFilter::OnAllocateSharedBitmap(uint32 buffer_size,
932 const cc::SharedBitmapId& id,
933 IPC::Message* reply_msg) {
934 BrowserThread::PostTask(
935 BrowserThread::FILE_USER_BLOCKING,
937 base::Bind(&RenderMessageFilter::AllocateSharedBitmapOnFileThread,
944 void RenderMessageFilter::OnAllocatedSharedBitmap(
946 const base::SharedMemoryHandle& handle,
947 const cc::SharedBitmapId& id) {
948 HostSharedBitmapManager::current()->ChildAllocatedSharedBitmap(
949 buffer_size, handle, PeerHandle(), id);
952 void RenderMessageFilter::OnDeletedSharedBitmap(const cc::SharedBitmapId& id) {
953 HostSharedBitmapManager::current()->ChildDeletedSharedBitmap(id);
956 void RenderMessageFilter::OnAllocateLockedDiscardableSharedMemory(
958 base::SharedMemoryHandle* handle) {
959 HostDiscardableSharedMemoryManager::current()
960 ->AllocateLockedDiscardableSharedMemoryForChild(
961 PeerHandle(), size, handle);
964 net::CookieStore* RenderMessageFilter::GetCookieStoreForURL(
966 DCHECK_CURRENTLY_ON(BrowserThread::IO);
968 net::URLRequestContext* context =
969 GetContentClient()->browser()->OverrideRequestContextForURL(
970 url, resource_context_);
972 // If we should use a special URLRequestContext rather than the default one,
973 // return the cookie store of that special URLRequestContext.
975 return context->cookie_store();
977 // Otherwise, if there is a special cookie store to be used for this process,
978 // return that cookie store.
979 net::CookieStore* cookie_store =
980 GetContentClient()->browser()->OverrideCookieStoreForRenderProcess(
985 // Otherwise, return the cookie store of the default request context used
986 // for this renderer.
987 return request_context_->GetURLRequestContext()->cookie_store();
990 #if defined(OS_POSIX) && !defined(OS_ANDROID)
991 void RenderMessageFilter::OnAllocTransportDIB(
992 uint32 size, bool cache_in_browser, TransportDIB::Handle* handle) {
993 render_widget_helper_->AllocTransportDIB(size, cache_in_browser, handle);
996 void RenderMessageFilter::OnFreeTransportDIB(
997 TransportDIB::Id dib_id) {
998 render_widget_helper_->FreeTransportDIB(dib_id);
1002 void RenderMessageFilter::OnCacheableMetadataAvailable(
1004 double expected_response_time,
1005 const std::vector<char>& data) {
1006 net::HttpCache* cache = request_context_->GetURLRequestContext()->
1007 http_transaction_factory()->GetCache();
1010 // Use the same priority for the metadata write as for script
1011 // resources (see defaultPriorityForResourceType() in WebKit's
1012 // CachedResource.cpp). Note that WebURLRequest::PriorityMedium
1013 // corresponds to net::LOW (see ConvertWebKitPriorityToNetPriority()
1014 // in weburlloader_impl.cc).
1015 const net::RequestPriority kPriority = net::LOW;
1016 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(data.size()));
1017 memcpy(buf->data(), &data.front(), data.size());
1018 cache->WriteMetadata(url,
1020 base::Time::FromDoubleT(expected_response_time),
1025 void RenderMessageFilter::OnKeygen(uint32 key_size_index,
1026 const std::string& challenge_string,
1028 IPC::Message* reply_msg) {
1029 // Map displayed strings indicating level of keysecurity in the <keygen>
1030 // menu to the key size in bits. (See SSLKeyGeneratorChromium.cpp in WebCore.)
1031 int key_size_in_bits;
1032 switch (key_size_index) {
1034 key_size_in_bits = 2048;
1037 key_size_in_bits = 1024;
1040 DCHECK(false) << "Illegal key_size_index " << key_size_index;
1041 ViewHostMsg_Keygen::WriteReplyParams(reply_msg, std::string());
1046 resource_context_->CreateKeygenHandler(
1051 &RenderMessageFilter::PostKeygenToWorkerThread, this, reply_msg));
1054 void RenderMessageFilter::PostKeygenToWorkerThread(
1055 IPC::Message* reply_msg,
1056 scoped_ptr<net::KeygenHandler> keygen_handler) {
1057 VLOG(1) << "Dispatching keygen task to worker pool.";
1058 // Dispatch to worker pool, so we do not block the IO thread.
1059 if (!base::WorkerPool::PostTask(
1061 base::Bind(&RenderMessageFilter::OnKeygenOnWorkerThread,
1063 base::Passed(&keygen_handler),
1066 NOTREACHED() << "Failed to dispatch keygen task to worker pool";
1067 ViewHostMsg_Keygen::WriteReplyParams(reply_msg, std::string());
1072 void RenderMessageFilter::OnKeygenOnWorkerThread(
1073 scoped_ptr<net::KeygenHandler> keygen_handler,
1074 IPC::Message* reply_msg) {
1077 // Generate a signed public key and challenge, then send it back.
1078 ViewHostMsg_Keygen::WriteReplyParams(
1080 keygen_handler->GenKeyAndSignChallenge());
1084 void RenderMessageFilter::OnMediaLogEvents(
1085 const std::vector<media::MediaLogEvent>& events) {
1086 if (media_internals_)
1087 media_internals_->OnMediaEvents(render_process_id_, events);
1090 void RenderMessageFilter::CheckPolicyForCookies(
1091 int render_frame_id,
1093 const GURL& first_party_for_cookies,
1094 IPC::Message* reply_msg,
1095 const net::CookieList& cookie_list) {
1096 net::CookieStore* cookie_store = GetCookieStoreForURL(url);
1097 // Check the policy for get cookies, and pass cookie_list to the
1098 // TabSpecificContentSetting for logging purpose.
1099 if (GetContentClient()->browser()->AllowGetCookie(
1100 url, first_party_for_cookies, cookie_list, resource_context_,
1101 render_process_id_, render_frame_id)) {
1102 // Gets the cookies from cookie store if allowed.
1103 cookie_store->GetCookiesWithOptionsAsync(
1104 url, net::CookieOptions(),
1105 base::Bind(&RenderMessageFilter::SendGetCookiesResponse,
1108 SendGetCookiesResponse(reply_msg, std::string());
1112 void RenderMessageFilter::SendGetCookiesResponse(IPC::Message* reply_msg,
1113 const std::string& cookies) {
1114 ViewHostMsg_GetCookies::WriteReplyParams(reply_msg, cookies);
1118 void RenderMessageFilter::SendGetRawCookiesResponse(
1119 IPC::Message* reply_msg,
1120 const net::CookieList& cookie_list) {
1121 std::vector<CookieData> cookies;
1122 for (size_t i = 0; i < cookie_list.size(); ++i)
1123 cookies.push_back(CookieData(cookie_list[i]));
1124 ViewHostMsg_GetRawCookies::WriteReplyParams(reply_msg, cookies);
1128 void RenderMessageFilter::OnCompletedOpenChannelToNpapiPlugin(
1129 OpenChannelToNpapiPluginCallback* client) {
1130 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1131 DCHECK(ContainsKey(plugin_host_clients_, client));
1132 plugin_host_clients_.erase(client);
1135 void RenderMessageFilter::OnAre3DAPIsBlocked(int render_view_id,
1136 const GURL& top_origin_url,
1137 ThreeDAPIType requester,
1139 *blocked = GpuDataManagerImpl::GetInstance()->Are3DAPIsBlocked(
1140 top_origin_url, render_process_id_, render_view_id, requester);
1143 void RenderMessageFilter::OnDidLose3DContext(
1144 const GURL& top_origin_url,
1145 ThreeDAPIType /* unused */,
1146 int arb_robustness_status_code) {
1147 #if defined(OS_MACOSX)
1148 // TODO(kbr): this file indirectly includes npapi.h, which on Mac
1149 // OS pulls in the system OpenGL headers. For some
1150 // not-yet-investigated reason this breaks the build with the 10.6
1151 // SDK but not 10.7. For now work around this in a way compatible
1152 // with the Khronos headers.
1153 #ifndef GL_GUILTY_CONTEXT_RESET_ARB
1154 #define GL_GUILTY_CONTEXT_RESET_ARB 0x8253
1156 #ifndef GL_INNOCENT_CONTEXT_RESET_ARB
1157 #define GL_INNOCENT_CONTEXT_RESET_ARB 0x8254
1159 #ifndef GL_UNKNOWN_CONTEXT_RESET_ARB
1160 #define GL_UNKNOWN_CONTEXT_RESET_ARB 0x8255
1164 GpuDataManagerImpl::DomainGuilt guilt;
1165 switch (arb_robustness_status_code) {
1166 case GL_GUILTY_CONTEXT_RESET_ARB:
1167 guilt = GpuDataManagerImpl::DOMAIN_GUILT_KNOWN;
1169 case GL_UNKNOWN_CONTEXT_RESET_ARB:
1170 guilt = GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN;
1173 // Ignore lost contexts known to be innocent.
1177 GpuDataManagerImpl::GetInstance()->BlockDomainFrom3DAPIs(
1178 top_origin_url, guilt);
1182 void RenderMessageFilter::OnPreCacheFontCharacters(const LOGFONT& font,
1183 const base::string16& str) {
1184 // TODO(scottmg): pdf/ppapi still require the renderer to be able to precache
1185 // GDI fonts (http://crbug.com/383227), even when using DirectWrite.
1186 // Eventually this shouldn't be added and should be moved to
1187 // FontCacheDispatcher too. http://crbug.com/356346.
1189 // First, comments from FontCacheDispatcher::OnPreCacheFont do apply here too.
1190 // Except that for True Type fonts,
1191 // GetTextMetrics will not load the font in memory.
1192 // The only way windows seem to load properly, it is to create a similar
1193 // device (like the one in which we print), then do an ExtTextOut,
1194 // as we do in the printing thread, which is sandboxed.
1195 HDC hdc = CreateEnhMetaFile(NULL, NULL, NULL, NULL);
1196 HFONT font_handle = CreateFontIndirect(&font);
1197 DCHECK(NULL != font_handle);
1199 HGDIOBJ old_font = SelectObject(hdc, font_handle);
1200 DCHECK(NULL != old_font);
1202 ExtTextOut(hdc, 0, 0, ETO_GLYPH_INDEX, 0, str.c_str(), str.length(), NULL);
1204 SelectObject(hdc, old_font);
1205 DeleteObject(font_handle);
1207 HENHMETAFILE metafile = CloseEnhMetaFile(hdc);
1210 DeleteEnhMetaFile(metafile);
1215 #if defined(OS_ANDROID)
1216 void RenderMessageFilter::OnWebAudioMediaCodec(
1217 base::SharedMemoryHandle encoded_data_handle,
1218 base::FileDescriptor pcm_output,
1219 uint32_t data_size) {
1220 // Let a WorkerPool handle this request since the WebAudio
1221 // MediaCodec bridge is slow and can block while sending the data to
1223 base::WorkerPool::PostTask(
1225 base::Bind(&media::WebAudioMediaCodecBridge::RunWebAudioMediaCodec,
1226 encoded_data_handle, pcm_output, data_size),
1231 void RenderMessageFilter::OnAddNavigationTransitionData(
1232 FrameHostMsg_AddNavigationTransitionData_Params params) {
1233 if (params.elements.size() > TransitionRequestManager::kMaxNumOfElements)
1235 TransitionRequestManager::GetInstance()->AddPendingTransitionRequestData(
1237 params.render_frame_id,
1238 params.allowed_destination_host_pattern,
1244 void RenderMessageFilter::OnAllocateGpuMemoryBuffer(
1247 gfx::GpuMemoryBuffer::Format format,
1248 gfx::GpuMemoryBuffer::Usage usage,
1249 IPC::Message* reply) {
1250 DCHECK(BrowserGpuMemoryBufferManager::current());
1252 base::CheckedNumeric<int> size = width;
1254 if (!size.IsValid()) {
1255 GpuMemoryBufferAllocated(reply, gfx::GpuMemoryBufferHandle());
1259 BrowserGpuMemoryBufferManager::current()
1260 ->AllocateGpuMemoryBufferForChildProcess(
1261 gfx::Size(width, height),
1267 &RenderMessageFilter::GpuMemoryBufferAllocated, this, reply));
1270 void RenderMessageFilter::GpuMemoryBufferAllocated(
1271 IPC::Message* reply,
1272 const gfx::GpuMemoryBufferHandle& handle) {
1273 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1274 ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer::WriteReplyParams(reply,
1279 void RenderMessageFilter::OnDeletedGpuMemoryBuffer(
1280 gfx::GpuMemoryBufferId id,
1281 uint32 sync_point) {
1282 DCHECK(BrowserGpuMemoryBufferManager::current());
1284 BrowserGpuMemoryBufferManager::current()->ChildProcessDeletedGpuMemoryBuffer(
1285 id, PeerHandle(), render_process_id_, sync_point);
1288 } // namespace content