blob: 29b8c8a1a9020d17e256e28e6c51e813e8c08fe2 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/renderer_host/render_message_filter.h"
#include <errno.h>
#include <string.h>
#include <map>
#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/debug/alias.h"
#include "base/macros.h"
#include "base/numerics/safe_math.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread.h"
#include "base/threading/worker_pool.h"
#include "build/build_config.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/cache_storage/cache_storage_cache.h"
#include "content/browser/cache_storage/cache_storage_cache_handle.h"
#include "content/browser/cache_storage/cache_storage_context_impl.h"
#include "content/browser/cache_storage/cache_storage_manager.h"
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
#include "content/browser/dom_storage/session_storage_namespace_impl.h"
#include "content/browser/download/download_stats.h"
#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/media/media_internals.h"
#include "content/browser/renderer_host/pepper/pepper_security_helper.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_widget_helper.h"
#include "content/browser/resource_context_impl.h"
#include "content/common/cache_storage/cache_storage_types.h"
#include "content/common/child_process_host_impl.h"
#include "content/common/child_process_messages.h"
#include "content/common/content_constants_internal.h"
#include "content/common/host_shared_bitmap_manager.h"
#include "content/common/render_process_messages.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_child_process_host.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/resource_context.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/context_menu_params.h"
#include "content/public/common/url_constants.h"
#include "gpu/ipc/client/gpu_memory_buffer_impl.h"
#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_platform_file.h"
#include "media/base/media_log_event.h"
#include "net/base/io_buffer.h"
#include "net/base/keygen_handler.h"
#include "net/base/mime_util.h"
#include "net/base/request_priority.h"
#include "net/http/http_cache.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "ppapi/shared_impl/file_type_conversion.h"
#include "url/gurl.h"
#if defined(OS_MACOSX)
#include "content/common/mac/font_descriptor.h"
#endif
#if defined(OS_WIN)
#include "content/common/font_cache_dispatcher_win.h"
#endif
#if defined(OS_POSIX)
#include "base/file_descriptor_posix.h"
#endif
#if defined(OS_ANDROID)
#include "content/browser/media/android/media_throttler.h"
#endif
#if defined(OS_MACOSX)
#include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
#endif
#if defined(OS_LINUX)
#include "base/linux_util.h"
#include "base/threading/platform_thread.h"
#endif
namespace content {
namespace {
const uint32_t kFilteredMessageClasses[] = {
ChildProcessMsgStart, RenderProcessMsgStart, ViewMsgStart,
};
#if defined(OS_MACOSX)
void ResizeHelperHandleMsgOnUIThread(int render_process_id,
const IPC::Message& message) {
RenderProcessHost* host = RenderProcessHost::FromID(render_process_id);
if (host)
host->OnMessageReceived(message);
}
void ResizeHelperPostMsgToUIThread(int render_process_id,
const IPC::Message& msg) {
ui::WindowResizeHelperMac::Get()->task_runner()->PostDelayedTask(
FROM_HERE,
base::Bind(ResizeHelperHandleMsgOnUIThread, render_process_id, msg),
base::TimeDelta());
}
#endif
void NoOpCacheStorageErrorCallback(
std::unique_ptr<CacheStorageCacheHandle> cache_handle,
CacheStorageError error) {}
} // namespace
RenderMessageFilter::RenderMessageFilter(
int render_process_id,
BrowserContext* browser_context,
net::URLRequestContextGetter* request_context,
RenderWidgetHelper* render_widget_helper,
MediaInternals* media_internals,
DOMStorageContextWrapper* dom_storage_context,
CacheStorageContextImpl* cache_storage_context)
: BrowserMessageFilter(kFilteredMessageClasses,
arraysize(kFilteredMessageClasses)),
BrowserAssociatedInterface<mojom::RenderMessageFilter>(this, this),
resource_dispatcher_host_(ResourceDispatcherHostImpl::Get()),
bitmap_manager_client_(HostSharedBitmapManager::current()),
request_context_(request_context),
resource_context_(browser_context->GetResourceContext()),
render_widget_helper_(render_widget_helper),
dom_storage_context_(dom_storage_context),
gpu_process_id_(0),
render_process_id_(render_process_id),
media_internals_(media_internals),
cache_storage_context_(cache_storage_context),
weak_ptr_factory_(this) {
DCHECK(request_context_.get());
if (render_widget_helper)
render_widget_helper_->Init(render_process_id_, resource_dispatcher_host_);
}
RenderMessageFilter::~RenderMessageFilter() {
// This function should be called on the IO thread.
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserGpuMemoryBufferManager* gpu_memory_buffer_manager =
BrowserGpuMemoryBufferManager::current();
if (gpu_memory_buffer_manager)
gpu_memory_buffer_manager->ProcessRemoved(PeerHandle(), render_process_id_);
HostDiscardableSharedMemoryManager::current()->ProcessRemoved(
render_process_id_);
}
bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(RenderMessageFilter, message)
IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWindow, OnCreateWindow)
IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWidget, OnCreateWidget)
IPC_MESSAGE_HANDLER(ViewHostMsg_CreateFullscreenWidget,
OnCreateFullscreenWidget)
#if defined(OS_MACOSX)
// On Mac, the IPCs ViewHostMsg_SwapCompositorFrame, ViewHostMsg_UpdateRect,
// and GpuCommandBufferMsg_SwapBuffersCompleted need to be handled in a
// nested message loop during resize.
IPC_MESSAGE_HANDLER_GENERIC(
ViewHostMsg_SwapCompositorFrame,
ResizeHelperPostMsgToUIThread(render_process_id_, message))
IPC_MESSAGE_HANDLER_GENERIC(
ViewHostMsg_UpdateRect,
ResizeHelperPostMsgToUIThread(render_process_id_, message))
IPC_MESSAGE_HANDLER_GENERIC(
ViewHostMsg_SetNeedsBeginFrames,
ResizeHelperPostMsgToUIThread(render_process_id_, message))
#endif
// NB: The SyncAllocateSharedMemory, SyncAllocateGpuMemoryBuffer, and
// DeletedGpuMemoryBuffer IPCs are handled here for renderer processes. For
// non-renderer child processes, they are handled in ChildProcessHostImpl.
IPC_MESSAGE_HANDLER_DELAY_REPLY(
ChildProcessHostMsg_SyncAllocateSharedMemory, OnAllocateSharedMemory)
IPC_MESSAGE_HANDLER_DELAY_REPLY(
ChildProcessHostMsg_SyncAllocateSharedBitmap, OnAllocateSharedBitmap)
IPC_MESSAGE_HANDLER_DELAY_REPLY(
ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer,
OnAllocateGpuMemoryBuffer)
IPC_MESSAGE_HANDLER_DELAY_REPLY(ChildProcessHostMsg_EstablishGpuChannel,
OnEstablishGpuChannel)
IPC_MESSAGE_HANDLER_DELAY_REPLY(ChildProcessHostMsg_HasGpuProcess,
OnHasGpuProcess)
IPC_MESSAGE_HANDLER(ChildProcessHostMsg_DeletedGpuMemoryBuffer,
OnDeletedGpuMemoryBuffer)
IPC_MESSAGE_HANDLER(ChildProcessHostMsg_AllocatedSharedBitmap,
OnAllocatedSharedBitmap)
IPC_MESSAGE_HANDLER(ChildProcessHostMsg_DeletedSharedBitmap,
OnDeletedSharedBitmap)
IPC_MESSAGE_HANDLER_DELAY_REPLY(
ChildProcessHostMsg_SyncAllocateLockedDiscardableSharedMemory,
OnAllocateLockedDiscardableSharedMemory)
IPC_MESSAGE_HANDLER(ChildProcessHostMsg_DeletedDiscardableSharedMemory,
OnDeletedDiscardableSharedMemory)
#if defined(OS_LINUX)
IPC_MESSAGE_HANDLER(ChildProcessHostMsg_SetThreadPriority,
OnSetThreadPriority)
#endif
IPC_MESSAGE_HANDLER_DELAY_REPLY(RenderProcessHostMsg_Keygen, OnKeygen)
IPC_MESSAGE_HANDLER(RenderProcessHostMsg_DidGenerateCacheableMetadata,
OnCacheableMetadataAvailable)
IPC_MESSAGE_HANDLER(
RenderProcessHostMsg_DidGenerateCacheableMetadataInCacheStorage,
OnCacheableMetadataAvailableForCacheStorage)
#if defined(OS_MACOSX)
IPC_MESSAGE_HANDLER_DELAY_REPLY(RenderProcessHostMsg_LoadFont, OnLoadFont)
#endif
IPC_MESSAGE_HANDLER(ViewHostMsg_MediaLogEvents, OnMediaLogEvents)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
void RenderMessageFilter::OnDestruct() const {
const_cast<RenderMessageFilter*>(this)->resource_context_ = nullptr;
BrowserThread::DeleteOnIOThread::Destruct(this);
}
void RenderMessageFilter::OverrideThreadForMessage(const IPC::Message& message,
BrowserThread::ID* thread) {
if (message.type() == ViewHostMsg_MediaLogEvents::ID)
*thread = BrowserThread::UI;
}
void RenderMessageFilter::OnCreateWindow(
const ViewHostMsg_CreateWindow_Params& params,
ViewHostMsg_CreateWindow_Reply* reply) {
bool no_javascript_access;
bool can_create_window =
GetContentClient()->browser()->CanCreateWindow(
params.opener_url,
params.opener_top_level_frame_url,
params.opener_security_origin,
params.window_container_type,
params.target_url,
params.referrer,
params.frame_name,
params.disposition,
params.features,
params.user_gesture,
params.opener_suppressed,
resource_context_,
render_process_id_,
params.opener_id,
params.opener_render_frame_id,
&no_javascript_access);
if (!can_create_window) {
reply->route_id = MSG_ROUTING_NONE;
reply->main_frame_route_id = MSG_ROUTING_NONE;
reply->main_frame_widget_route_id = MSG_ROUTING_NONE;
reply->cloned_session_storage_namespace_id = 0;
return;
}
// This will clone the sessionStorage for namespace_id_to_clone.
scoped_refptr<SessionStorageNamespaceImpl> cloned_namespace =
new SessionStorageNamespaceImpl(dom_storage_context_.get(),
params.session_storage_namespace_id);
reply->cloned_session_storage_namespace_id = cloned_namespace->id();
render_widget_helper_->CreateNewWindow(
params, no_javascript_access, PeerHandle(), &reply->route_id,
&reply->main_frame_route_id, &reply->main_frame_widget_route_id,
cloned_namespace.get());
}
void RenderMessageFilter::OnCreateWidget(int opener_id,
blink::WebPopupType popup_type,
int* route_id) {
render_widget_helper_->CreateNewWidget(opener_id, popup_type, route_id);
}
void RenderMessageFilter::OnCreateFullscreenWidget(int opener_id,
int* route_id) {
render_widget_helper_->CreateNewFullscreenWidget(opener_id, route_id);
}
void RenderMessageFilter::GenerateRoutingID(
const GenerateRoutingIDCallback& callback) {
callback.Run(render_widget_helper_->GetNextRoutingID());
}
#if defined(OS_MACOSX)
void RenderMessageFilter::OnLoadFont(const FontDescriptor& font,
IPC::Message* reply_msg) {
FontLoader::Result* result = new FontLoader::Result;
BrowserThread::PostTaskAndReply(
BrowserThread::FILE, FROM_HERE,
base::Bind(&FontLoader::LoadFont, font, result),
base::Bind(&RenderMessageFilter::SendLoadFontReply, this, reply_msg,
base::Owned(result)));
}
void RenderMessageFilter::SendLoadFontReply(IPC::Message* reply,
FontLoader::Result* result) {
base::SharedMemoryHandle handle;
if (result->font_data_size == 0 || result->font_id == 0) {
result->font_data_size = 0;
result->font_id = 0;
handle = base::SharedMemory::NULLHandle();
} else {
result->font_data.GiveToProcess(base::GetCurrentProcessHandle(), &handle);
}
RenderProcessHostMsg_LoadFont::WriteReplyParams(
reply, result->font_data_size, handle, result->font_id);
Send(reply);
}
#endif // defined(OS_MACOSX)
void RenderMessageFilter::AllocateSharedMemoryOnFileThread(
uint32_t buffer_size,
IPC::Message* reply_msg) {
base::SharedMemoryHandle handle;
ChildProcessHostImpl::AllocateSharedMemory(buffer_size, PeerHandle(),
&handle);
ChildProcessHostMsg_SyncAllocateSharedMemory::WriteReplyParams(reply_msg,
handle);
Send(reply_msg);
}
void RenderMessageFilter::OnAllocateSharedMemory(uint32_t buffer_size,
IPC::Message* reply_msg) {
BrowserThread::PostTask(
BrowserThread::FILE_USER_BLOCKING, FROM_HERE,
base::Bind(&RenderMessageFilter::AllocateSharedMemoryOnFileThread, this,
buffer_size, reply_msg));
}
void RenderMessageFilter::AllocateSharedBitmapOnFileThread(
uint32_t buffer_size,
const cc::SharedBitmapId& id,
IPC::Message* reply_msg) {
base::SharedMemoryHandle handle;
bitmap_manager_client_.AllocateSharedBitmapForChild(PeerHandle(), buffer_size,
id, &handle);
ChildProcessHostMsg_SyncAllocateSharedBitmap::WriteReplyParams(reply_msg,
handle);
Send(reply_msg);
}
void RenderMessageFilter::OnAllocateSharedBitmap(uint32_t buffer_size,
const cc::SharedBitmapId& id,
IPC::Message* reply_msg) {
BrowserThread::PostTask(
BrowserThread::FILE_USER_BLOCKING,
FROM_HERE,
base::Bind(&RenderMessageFilter::AllocateSharedBitmapOnFileThread,
this,
buffer_size,
id,
reply_msg));
}
void RenderMessageFilter::OnAllocatedSharedBitmap(
size_t buffer_size,
const base::SharedMemoryHandle& handle,
const cc::SharedBitmapId& id) {
bitmap_manager_client_.ChildAllocatedSharedBitmap(buffer_size, handle, id);
}
void RenderMessageFilter::OnDeletedSharedBitmap(const cc::SharedBitmapId& id) {
bitmap_manager_client_.ChildDeletedSharedBitmap(id);
}
void RenderMessageFilter::AllocateLockedDiscardableSharedMemoryOnFileThread(
uint32_t size,
DiscardableSharedMemoryId id,
IPC::Message* reply_msg) {
base::SharedMemoryHandle handle;
HostDiscardableSharedMemoryManager::current()
->AllocateLockedDiscardableSharedMemoryForChild(
PeerHandle(), render_process_id_, size, id, &handle);
ChildProcessHostMsg_SyncAllocateLockedDiscardableSharedMemory::
WriteReplyParams(reply_msg, handle);
Send(reply_msg);
}
void RenderMessageFilter::OnAllocateLockedDiscardableSharedMemory(
uint32_t size,
DiscardableSharedMemoryId id,
IPC::Message* reply_msg) {
BrowserThread::PostTask(
BrowserThread::FILE_USER_BLOCKING, FROM_HERE,
base::Bind(&RenderMessageFilter::
AllocateLockedDiscardableSharedMemoryOnFileThread,
this, size, id, reply_msg));
}
void RenderMessageFilter::DeletedDiscardableSharedMemoryOnFileThread(
DiscardableSharedMemoryId id) {
HostDiscardableSharedMemoryManager::current()
->ChildDeletedDiscardableSharedMemory(id, render_process_id_);
}
void RenderMessageFilter::OnDeletedDiscardableSharedMemory(
DiscardableSharedMemoryId id) {
BrowserThread::PostTask(
BrowserThread::FILE_USER_BLOCKING, FROM_HERE,
base::Bind(
&RenderMessageFilter::DeletedDiscardableSharedMemoryOnFileThread,
this, id));
}
#if defined(OS_LINUX)
void RenderMessageFilter::SetThreadPriorityOnFileThread(
base::PlatformThreadId ns_tid,
base::ThreadPriority priority) {
bool ns_pid_supported = false;
pid_t peer_tid = base::FindThreadID(peer_pid(), ns_tid, &ns_pid_supported);
if (peer_tid == -1) {
if (ns_pid_supported)
DLOG(WARNING) << "Could not find tid";
return;
}
if (peer_tid == peer_pid()) {
DLOG(WARNING) << "Changing priority of main thread is not allowed";
return;
}
base::PlatformThread::SetThreadPriority(peer_tid, priority);
}
void RenderMessageFilter::OnSetThreadPriority(base::PlatformThreadId ns_tid,
base::ThreadPriority priority) {
BrowserThread::PostTask(
BrowserThread::FILE_USER_BLOCKING, FROM_HERE,
base::Bind(&RenderMessageFilter::SetThreadPriorityOnFileThread, this,
ns_tid, priority));
}
#endif
void RenderMessageFilter::OnCacheableMetadataAvailable(
const GURL& url,
base::Time expected_response_time,
const std::vector<char>& data) {
net::HttpCache* cache = request_context_->GetURLRequestContext()->
http_transaction_factory()->GetCache();
if (!cache)
return;
// Use the same priority for the metadata write as for script
// resources (see defaultPriorityForResourceType() in WebKit's
// CachedResource.cpp). Note that WebURLRequest::PriorityMedium
// corresponds to net::LOW (see ConvertWebKitPriorityToNetPriority()
// in weburlloader_impl.cc).
const net::RequestPriority kPriority = net::LOW;
scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(data.size()));
if (!data.empty())
memcpy(buf->data(), &data.front(), data.size());
cache->WriteMetadata(url, kPriority, expected_response_time, buf.get(),
data.size());
}
void RenderMessageFilter::OnCacheableMetadataAvailableForCacheStorage(
const GURL& url,
base::Time expected_response_time,
const std::vector<char>& data,
const url::Origin& cache_storage_origin,
const std::string& cache_storage_cache_name) {
scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(data.size()));
if (!data.empty())
memcpy(buf->data(), &data.front(), data.size());
cache_storage_context_->cache_manager()->OpenCache(
GURL(cache_storage_origin.Serialize()), cache_storage_cache_name,
base::Bind(&RenderMessageFilter::OnCacheStorageOpenCallback,
weak_ptr_factory_.GetWeakPtr(), url, expected_response_time,
buf, data.size()));
}
void RenderMessageFilter::OnCacheStorageOpenCallback(
const GURL& url,
base::Time expected_response_time,
scoped_refptr<net::IOBuffer> buf,
int buf_len,
std::unique_ptr<CacheStorageCacheHandle> cache_handle,
CacheStorageError error) {
if (error != CACHE_STORAGE_OK || !cache_handle || !cache_handle->value())
return;
CacheStorageCache* cache = cache_handle->value();
if (!cache)
return;
cache->WriteSideData(base::Bind(&NoOpCacheStorageErrorCallback,
base::Passed(std::move(cache_handle))),
url, expected_response_time, buf, buf_len);
}
void RenderMessageFilter::OnKeygen(uint32_t key_size_index,
const std::string& challenge_string,
const GURL& url,
const GURL& top_origin,
IPC::Message* reply_msg) {
if (!resource_context_)
return;
// Map displayed strings indicating level of keysecurity in the <keygen>
// menu to the key size in bits. (See SSLKeyGeneratorChromium.cpp in WebCore.)
int key_size_in_bits;
switch (key_size_index) {
case 0:
key_size_in_bits = 2048;
break;
case 1:
key_size_in_bits = 1024;
break;
default:
DCHECK(false) << "Illegal key_size_index " << key_size_index;
RenderProcessHostMsg_Keygen::WriteReplyParams(reply_msg, std::string());
Send(reply_msg);
return;
}
if (!GetContentClient()->browser()->AllowKeygen(top_origin,
resource_context_)) {
RenderProcessHostMsg_Keygen::WriteReplyParams(reply_msg, std::string());
Send(reply_msg);
return;
}
resource_context_->CreateKeygenHandler(
key_size_in_bits,
challenge_string,
url,
base::Bind(
&RenderMessageFilter::PostKeygenToWorkerThread, this, reply_msg));
}
void RenderMessageFilter::PostKeygenToWorkerThread(
IPC::Message* reply_msg,
std::unique_ptr<net::KeygenHandler> keygen_handler) {
VLOG(1) << "Dispatching keygen task to worker pool.";
// Dispatch to worker pool, so we do not block the IO thread.
if (!base::WorkerPool::PostTask(
FROM_HERE,
base::Bind(&RenderMessageFilter::OnKeygenOnWorkerThread,
this,
base::Passed(&keygen_handler),
reply_msg),
true)) {
NOTREACHED() << "Failed to dispatch keygen task to worker pool";
RenderProcessHostMsg_Keygen::WriteReplyParams(reply_msg, std::string());
Send(reply_msg);
}
}
void RenderMessageFilter::OnKeygenOnWorkerThread(
std::unique_ptr<net::KeygenHandler> keygen_handler,
IPC::Message* reply_msg) {
DCHECK(reply_msg);
// Generate a signed public key and challenge, then send it back.
RenderProcessHostMsg_Keygen::WriteReplyParams(
reply_msg,
keygen_handler->GenKeyAndSignChallenge());
Send(reply_msg);
}
void RenderMessageFilter::OnMediaLogEvents(
const std::vector<media::MediaLogEvent>& events) {
// OnMediaLogEvents() is always dispatched to the UI thread for handling.
// See OverrideThreadForMessage().
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (media_internals_)
media_internals_->OnMediaEvents(render_process_id_, events);
}
void RenderMessageFilter::OnAllocateGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
uint32_t width,
uint32_t height,
gfx::BufferFormat format,
gfx::BufferUsage usage,
IPC::Message* reply) {
DCHECK(BrowserGpuMemoryBufferManager::current());
base::CheckedNumeric<int> size = width;
size *= height;
if (!size.IsValid()) {
GpuMemoryBufferAllocated(reply, gfx::GpuMemoryBufferHandle());
return;
}
BrowserGpuMemoryBufferManager::current()
->AllocateGpuMemoryBufferForChildProcess(
id, gfx::Size(width, height), format, usage, PeerHandle(),
render_process_id_,
base::Bind(&RenderMessageFilter::GpuMemoryBufferAllocated, this,
reply));
}
void RenderMessageFilter::GpuMemoryBufferAllocated(
IPC::Message* reply,
const gfx::GpuMemoryBufferHandle& handle) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer::WriteReplyParams(reply,
handle);
Send(reply);
}
void RenderMessageFilter::OnEstablishGpuChannel(
IPC::Message* reply_ptr) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
std::unique_ptr<IPC::Message> reply(reply_ptr);
GpuProcessHost* host = GpuProcessHost::FromID(gpu_process_id_);
if (!host) {
host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED);
if (!host) {
reply->set_reply_error();
Send(reply.release());
return;
}
gpu_process_id_ = host->host_id();
}
bool preempts = false;
bool allow_view_command_buffers = false;
bool allow_real_time_streams = false;
host->EstablishGpuChannel(
render_process_id_,
ChildProcessHostImpl::ChildProcessUniqueIdToTracingProcessId(
render_process_id_),
preempts, allow_view_command_buffers, allow_real_time_streams,
base::Bind(&RenderMessageFilter::EstablishChannelCallback,
weak_ptr_factory_.GetWeakPtr(), base::Passed(&reply)));
}
void RenderMessageFilter::OnHasGpuProcess(IPC::Message* reply_ptr) {
std::unique_ptr<IPC::Message> reply(reply_ptr);
GpuProcessHost::GetProcessHandles(
base::Bind(&RenderMessageFilter::GetGpuProcessHandlesCallback,
weak_ptr_factory_.GetWeakPtr(), base::Passed(&reply)));
}
void RenderMessageFilter::EstablishChannelCallback(
std::unique_ptr<IPC::Message> reply,
const IPC::ChannelHandle& channel,
const gpu::GPUInfo& gpu_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
ChildProcessHostMsg_EstablishGpuChannel::WriteReplyParams(
reply.get(), render_process_id_, channel, gpu_info);
Send(reply.release());
}
void RenderMessageFilter::GetGpuProcessHandlesCallback(
std::unique_ptr<IPC::Message> reply,
const std::list<base::ProcessHandle>& handles) {
bool has_gpu_process = handles.size() > 0;
ChildProcessHostMsg_HasGpuProcess::WriteReplyParams(reply.get(),
has_gpu_process);
Send(reply.release());
}
void RenderMessageFilter::OnDeletedGpuMemoryBuffer(
gfx::GpuMemoryBufferId id,
const gpu::SyncToken& sync_token) {
DCHECK(BrowserGpuMemoryBufferManager::current());
BrowserGpuMemoryBufferManager::current()->ChildProcessDeletedGpuMemoryBuffer(
id, PeerHandle(), render_process_id_, sync_token);
}
} // namespace content