diff options
author | eroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-13 20:17:49 +0000 |
---|---|---|
committer | eroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-13 20:17:49 +0000 |
commit | 2a9ee22f1e672099f70d59594258f093f5520a16 (patch) | |
tree | bcf1c08958b7850141e376fce82fbe9807648a82 | |
parent | 92922a8e913115ad091c367e5ec3acde7f26fa81 (diff) | |
download | chromium_src-2a9ee22f1e672099f70d59594258f093f5520a16.zip chromium_src-2a9ee22f1e672099f70d59594258f093f5520a16.tar.gz chromium_src-2a9ee22f1e672099f70d59594258f093f5520a16.tar.bz2 |
Revert 132218 - Convert plugin and GPU process to brokered handle duplication.
(Seems to be responsible for VMTest failure on ChromiumOS).
BUG=119250
Review URL: https://chromiumcodereview.appspot.com/9958034
TBR=jschuh@chromium.org
Review URL: https://chromiumcodereview.appspot.com/10081018
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@132254 0039d316-1c4b-4281-b951-d872f2087c98
27 files changed, 248 insertions, 143 deletions
diff --git a/chrome/common/chrome_content_client.cc b/chrome/common/chrome_content_client.cc index cbb47dd..b713f82 100644 --- a/chrome/common/chrome_content_client.cc +++ b/chrome/common/chrome_content_client.cc @@ -402,15 +402,6 @@ bool ChromeContentClient::SandboxPlugin(CommandLine* command_line, return false; } - // Add policy for the plugin proxy window pump event - // used by WebPluginDelegateProxy::HandleInputEvent(). - if (policy->AddRule(sandbox::TargetPolicy::SUBSYS_HANDLES, - sandbox::TargetPolicy::HANDLES_DUP_ANY, - L"Event") != sandbox::SBOX_ALL_OK) { - NOTREACHED(); - return false; - } - // Add the policy for the pipes. if (policy->AddRule(sandbox::TargetPolicy::SUBSYS_NAMED_PIPES, sandbox::TargetPolicy::NAMEDPIPES_ALLOW_ANY, diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.cc b/content/browser/gpu/browser_gpu_channel_host_factory.cc index 35a5172..81b0a74 100644 --- a/content/browser/gpu/browser_gpu_channel_host_factory.cc +++ b/content/browser/gpu/browser_gpu_channel_host_factory.cc @@ -153,8 +153,10 @@ void BrowserGpuChannelHostFactory::EstablishGpuChannelOnIO( void BrowserGpuChannelHostFactory::GpuChannelEstablishedOnIO( EstablishRequest* request, const IPC::ChannelHandle& channel_handle, + base::ProcessHandle gpu_process_handle, const GPUInfo& gpu_info) { request->channel_handle = channel_handle; + request->gpu_process_handle = gpu_process_handle; request->gpu_info = gpu_info; request->event.Signal(); } @@ -189,12 +191,26 @@ GpuChannelHost* BrowserGpuChannelHostFactory::EstablishGpuChannelSync( request.gpu_process_handle == base::kNullProcessHandle) return NULL; + base::ProcessHandle browser_process_for_gpu; +#if defined(OS_WIN) + // Create a process handle that the GPU process can use to access our handles. + DuplicateHandle(base::GetCurrentProcessHandle(), + base::GetCurrentProcessHandle(), + request.gpu_process_handle, + &browser_process_for_gpu, + PROCESS_DUP_HANDLE, + FALSE, + 0); +#else + browser_process_for_gpu = base::GetCurrentProcessHandle(); +#endif + gpu_channel_ = new GpuChannelHost(this, gpu_host_id_, gpu_client_id_); gpu_channel_->set_gpu_info(request.gpu_info); content::GetContentClient()->SetGpuInfo(request.gpu_info); // Connect to the GPU process if a channel name was received. - gpu_channel_->Connect(request.channel_handle); + gpu_channel_->Connect(request.channel_handle, browser_process_for_gpu); return gpu_channel_.get(); } diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.h b/content/browser/gpu/browser_gpu_channel_host_factory.h index 2c58b99..cfb4e6a 100644 --- a/content/browser/gpu/browser_gpu_channel_host_factory.h +++ b/content/browser/gpu/browser_gpu_channel_host_factory.h @@ -65,6 +65,7 @@ class BrowserGpuChannelHostFactory : public GpuChannelHostFactory { static void GpuChannelEstablishedOnIO( EstablishRequest* request, const IPC::ChannelHandle& channel_handle, + base::ProcessHandle gpu_process_handle, const GPUInfo& gpu_info); int gpu_client_id_; diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc index 2546131..c4d4e4c 100644 --- a/content/browser/gpu/gpu_process_host.cc +++ b/content/browser/gpu/gpu_process_host.cc @@ -267,6 +267,7 @@ GpuProcessHost* GpuProcessHost::FromID(int host_id) { GpuProcessHost::GpuProcessHost(int host_id, GpuProcessKind kind) : host_id_(host_id), + gpu_process_(base::kNullProcessHandle), in_process_(false), software_rendering_(false), kind_(kind), @@ -337,6 +338,11 @@ GpuProcessHost::~GpuProcessHost() { content::RESULT_CODE_LAST_CODE); } +#if defined(OS_WIN) + if (gpu_process_) + CloseHandle(gpu_process_); +#endif + // In case we never started, clean up. while (!queued_messages_.empty()) { delete queued_messages_.front(); @@ -492,6 +498,10 @@ void GpuProcessHost::CreateViewCommandBuffer( void GpuProcessHost::OnChannelEstablished( const IPC::ChannelHandle& channel_handle) { + // The GPU process should have launched at this point and this object should + // have been notified of its process handle. + DCHECK(gpu_process_); + EstablishChannelCallback callback = channel_requests_.front(); channel_requests_.pop(); @@ -511,7 +521,7 @@ void GpuProcessHost::OnChannelEstablished( return; } - callback.Run(channel_handle, + callback.Run(channel_handle, gpu_process_, GpuDataManagerImpl::GetInstance()->GetGPUInfo()); } @@ -613,6 +623,25 @@ void GpuProcessHost::OnAcceleratedSurfaceRelease( #endif // OS_WIN && !USE_AURA void GpuProcessHost::OnProcessLaunched() { + // Send the GPU process handle to the UI thread before it has to + // respond to any requests to establish a GPU channel. The response + // to such requests require that the GPU process handle be known. + + base::ProcessHandle child_handle = in_process_ ? + base::GetCurrentProcessHandle() : process_->GetData().handle; + +#if defined(OS_WIN) + DuplicateHandle(base::GetCurrentProcessHandle(), + child_handle, + base::GetCurrentProcessHandle(), + &gpu_process_, + PROCESS_DUP_HANDLE, + FALSE, + 0); +#else + gpu_process_ = child_handle; +#endif + UMA_HISTOGRAM_TIMES("GPU.GPUProcessLaunchTime", base::TimeTicks::Now() - init_start_time_); } @@ -745,7 +774,7 @@ void GpuProcessHost::EstablishChannelError( const IPC::ChannelHandle& channel_handle, base::ProcessHandle renderer_process_for_gpu, const content::GPUInfo& gpu_info) { - callback.Run(channel_handle, gpu_info); + callback.Run(channel_handle, renderer_process_for_gpu, gpu_info); } void GpuProcessHost::CreateCommandBufferError( diff --git a/content/browser/gpu/gpu_process_host.h b/content/browser/gpu/gpu_process_host.h index f101c6c..ae8d98b 100644 --- a/content/browser/gpu/gpu_process_host.h +++ b/content/browser/gpu/gpu_process_host.h @@ -41,6 +41,7 @@ class GpuProcessHost : public content::BrowserChildProcessHostDelegate, }; typedef base::Callback<void(const IPC::ChannelHandle&, + base::ProcessHandle, const content::GPUInfo&)> EstablishChannelCallback; @@ -164,6 +165,9 @@ class GpuProcessHost : public content::BrowserChildProcessHostDelegate, // Qeueud messages to send when the process launches. std::queue<IPC::Message*> queued_messages_; + // The handle for the GPU process or null if it is not known to be launched. + base::ProcessHandle gpu_process_; + // Whether we are running a GPU thread inside the browser process instead // of a separate GPU process. bool in_process_; diff --git a/content/browser/renderer_host/gpu_message_filter.cc b/content/browser/renderer_host/gpu_message_filter.cc index 75ad4fa..d563a91 100644 --- a/content/browser/renderer_host/gpu_message_filter.cc +++ b/content/browser/renderer_host/gpu_message_filter.cc @@ -173,11 +173,31 @@ void GpuMessageFilter::OnCreateViewCommandBuffer( void GpuMessageFilter::EstablishChannelCallback( IPC::Message* reply, const IPC::ChannelHandle& channel, + base::ProcessHandle gpu_process_for_browser, const content::GPUInfo& gpu_info) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + base::ProcessHandle renderer_process_for_gpu; + if (gpu_process_for_browser != 0) { +#if defined(OS_WIN) + // Create a process handle that the renderer process can give to the GPU + // process to give it access to its handles. + DuplicateHandle(base::GetCurrentProcessHandle(), + peer_handle(), + gpu_process_for_browser, + &renderer_process_for_gpu, + PROCESS_DUP_HANDLE, + FALSE, + 0); +#else + renderer_process_for_gpu = peer_handle(); +#endif + } else { + renderer_process_for_gpu = 0; + } + GpuHostMsg_EstablishGpuChannel::WriteReplyParams( - reply, render_process_id_, channel, gpu_info); + reply, render_process_id_, channel, renderer_process_for_gpu, gpu_info); Send(reply); } diff --git a/content/browser/renderer_host/gpu_message_filter.h b/content/browser/renderer_host/gpu_message_filter.h index e7a73f1..aafeeca 100644 --- a/content/browser/renderer_host/gpu_message_filter.h +++ b/content/browser/renderer_host/gpu_message_filter.h @@ -58,6 +58,7 @@ class GpuMessageFilter : public content::BrowserMessageFilter, // Helper callbacks for the message handlers. void EstablishChannelCallback(IPC::Message* reply, const IPC::ChannelHandle& channel, + base::ProcessHandle gpu_process_for_browser, const content::GPUInfo& gpu_info); void CreateCommandBufferCallback(IPC::Message* reply, int32 route_id); diff --git a/content/common/gpu/client/command_buffer_proxy_impl.cc b/content/common/gpu/client/command_buffer_proxy_impl.cc index 1bb1887..1a23eac 100644 --- a/content/common/gpu/client/command_buffer_proxy_impl.cc +++ b/content/common/gpu/client/command_buffer_proxy_impl.cc @@ -20,10 +20,6 @@ #include "gpu/command_buffer/common/command_buffer_shared.h" #include "ui/gfx/size.h" -#if defined(OS_WIN) -#include "content/common/sandbox_policy.h" -#endif - using gpu::Buffer; CommandBufferProxyImpl::CommandBufferProxyImpl( @@ -238,13 +234,7 @@ int32 CommandBufferProxyImpl::CreateTransferBuffer( return -1; base::SharedMemoryHandle handle = shm->handle(); -#if defined(OS_WIN) - // Windows needs to explicitly duplicate the handle out to another process. - if (!sandbox::BrokerDuplicateHandle(handle, channel_->gpu_pid(), - &handle, FILE_MAP_WRITE, 0)) { - return -1; - } -#elif defined(OS_POSIX) +#if defined(OS_POSIX) DCHECK(!handle.auto_close); #endif @@ -267,20 +257,10 @@ int32 CommandBufferProxyImpl::RegisterTransferBuffer( if (last_state_.error != gpu::error::kNoError) return -1; - // Returns FileDescriptor with auto_close off. - base::SharedMemoryHandle handle = shared_memory->handle(); -#if defined(OS_WIN) - // Windows needs to explicitly duplicate the handle out to another process. - if (!sandbox::BrokerDuplicateHandle(handle, channel_->gpu_pid(), - &handle, FILE_MAP_WRITE, 0)) { - return -1; - } -#endif - int32 id; if (!Send(new GpuCommandBufferMsg_RegisterTransferBuffer( route_id_, - handle, + shared_memory->handle(), // Returns FileDescriptor with auto_close off. size, id_request, &id))) { diff --git a/content/common/gpu/client/gpu_channel_host.cc b/content/common/gpu/client/gpu_channel_host.cc index cda0468..988feae 100644 --- a/content/common/gpu/client/gpu_channel_host.cc +++ b/content/common/gpu/client/gpu_channel_host.cc @@ -93,10 +93,10 @@ void GpuChannelHost::MessageFilter::OnChannelError() { } GpuChannelHost::GpuChannelHost( - GpuChannelHostFactory* factory, int gpu_host_id, int client_id) + GpuChannelHostFactory* factory, int gpu_process_id, int client_id) : factory_(factory), + gpu_process_id_(gpu_process_id), client_id_(client_id), - gpu_host_id_(gpu_host_id), state_(kUnconnected) { } @@ -104,7 +104,8 @@ GpuChannelHost::~GpuChannelHost() { } void GpuChannelHost::Connect( - const IPC::ChannelHandle& channel_handle) { + const IPC::ChannelHandle& channel_handle, + base::ProcessHandle client_process_for_gpu) { DCHECK(factory_->IsMainThread()); // Open a channel to the GPU process. We pass NULL as the main listener here // since we need to filter everything to route it to the right thread. @@ -129,6 +130,10 @@ void GpuChannelHost::Connect( // and receives the hello message from the GPU process. The messages get // cached. state_ = kConnected; + + // Notify the GPU process of our process handle. This gives it the ability + // to map client handles into the GPU process. + Send(new GpuChannelMsg_Initialize(client_process_for_gpu)); } void GpuChannelHost::set_gpu_info(const content::GPUInfo& gpu_info) { diff --git a/content/common/gpu/client/gpu_channel_host.h b/content/common/gpu/client/gpu_channel_host.h index b82efe9..0a88845 100644 --- a/content/common/gpu/client/gpu_channel_host.h +++ b/content/common/gpu/client/gpu_channel_host.h @@ -13,7 +13,6 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" -#include "base/process.h" #include "base/process_util.h" #include "base/synchronization/lock.h" #include "content/common/content_export.h" @@ -84,12 +83,13 @@ class GpuChannelHost : public IPC::Message::Sender, // Called on the render thread GpuChannelHost(GpuChannelHostFactory* factory, - int gpu_host_id, + int gpu_process_id, int client_id); virtual ~GpuChannelHost(); // Connect to GPU process channel. - void Connect(const IPC::ChannelHandle& channel_handle); + void Connect(const IPC::ChannelHandle& channel_handle, + base::ProcessHandle client_process_for_gpu); State state() const { return state_; } @@ -152,8 +152,7 @@ class GpuChannelHost : public IPC::Message::Sender, void ForciblyCloseChannel(); GpuChannelHostFactory* factory() const { return factory_; } - int gpu_host_id() const { return gpu_host_id_; } - base::ProcessId gpu_pid() const { return channel_->peer_pid(); } + int gpu_process_id() const { return gpu_process_id_; } int client_id() const { return client_id_; } private: @@ -181,8 +180,8 @@ class GpuChannelHost : public IPC::Message::Sender, }; GpuChannelHostFactory* factory_; + int gpu_process_id_; int client_id_; - int gpu_host_id_; State state_; diff --git a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc index aa9c645..32e4c2d 100644 --- a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc +++ b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc @@ -484,7 +484,7 @@ void WebGraphicsContext3DCommandBufferImpl::Destroy() { } int WebGraphicsContext3DCommandBufferImpl::GetGPUProcessID() { - return host_ ? host_->gpu_host_id() : 0; + return host_ ? host_->gpu_process_id() : 0; } int WebGraphicsContext3DCommandBufferImpl::GetChannelID() { diff --git a/content/common/gpu/gpu_channel.cc b/content/common/gpu/gpu_channel.cc index 96c3553..5568b17 100644 --- a/content/common/gpu/gpu_channel.cc +++ b/content/common/gpu/gpu_channel.cc @@ -40,6 +40,8 @@ GpuChannel::GpuChannel(GpuChannelManager* gpu_channel_manager, bool software) : gpu_channel_manager_(gpu_channel_manager), client_id_(client_id), + renderer_process_(base::kNullProcessHandle), + renderer_pid_(base::kNullProcessId), share_group_(share_group ? share_group : new gfx::GLShareGroup), watchdog_(watchdog), software_(software), @@ -60,6 +62,10 @@ GpuChannel::GpuChannel(GpuChannelManager* gpu_channel_manager, } GpuChannel::~GpuChannel() { +#if defined(OS_WIN) + if (renderer_process_) + CloseHandle(renderer_process_); +#endif } bool GpuChannel::OnMessageReceived(const IPC::Message& message) { @@ -107,6 +113,10 @@ void GpuChannel::OnChannelError() { gpu_channel_manager_->RemoveChannel(client_id_); } +void GpuChannel::OnChannelConnected(int32 peer_pid) { + renderer_pid_ = peer_pid; +} + bool GpuChannel::Send(IPC::Message* message) { // The GPU process must never send a synchronous IPC message to the renderer // process. This could result in deadlock. @@ -201,6 +211,7 @@ bool GpuChannel::OnControlMessageReceived(const IPC::Message& msg) { // here. This is so the reply can be delayed if the scheduler is unscheduled. bool handled = true; IPC_BEGIN_MESSAGE_MAP(GpuChannel, msg) + IPC_MESSAGE_HANDLER(GpuChannelMsg_Initialize, OnInitialize) IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuChannelMsg_CreateOffscreenCommandBuffer, OnCreateOffscreenCommandBuffer) IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuChannelMsg_DestroyCommandBuffer, @@ -301,6 +312,15 @@ bool GpuChannel::ShouldPreferDiscreteGpu() const { return num_contexts_preferring_discrete_gpu_ > 0; } +void GpuChannel::OnInitialize(base::ProcessHandle renderer_process) { + // Initialize should only happen once. + DCHECK(!renderer_process_); + + // Verify that the renderer has passed its own process handle. + if (base::GetProcId(renderer_process) == renderer_pid_) + renderer_process_ = renderer_process; +} + void GpuChannel::OnCreateOffscreenCommandBuffer( const gfx::Size& size, const GPUCreateCommandBufferConfig& init_params, diff --git a/content/common/gpu/gpu_channel.h b/content/common/gpu/gpu_channel.h index d9c5192..a92ed87 100644 --- a/content/common/gpu/gpu_channel.h +++ b/content/common/gpu/gpu_channel.h @@ -62,11 +62,14 @@ class GpuChannel : public IPC::Channel::Listener, int TakeRendererFileDescriptor(); #endif // defined(OS_POSIX) - base::ProcessId renderer_pid() const { return channel_->peer_pid(); } + base::ProcessHandle renderer_process() const { + return renderer_process_; + } // IPC::Channel::Listener implementation: virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE; virtual void OnChannelError() OVERRIDE; + virtual void OnChannelConnected(int32 peer_pid) OVERRIDE; // IPC::Message::Sender implementation: virtual bool Send(IPC::Message* msg) OVERRIDE; @@ -116,6 +119,7 @@ class GpuChannel : public IPC::Channel::Listener, void ScheduleDelayedWork(GpuCommandBufferStub *stub, int64 delay); // Message handlers. + void OnInitialize(base::ProcessHandle renderer_process); void OnCreateOffscreenCommandBuffer( const gfx::Size& size, const GPUCreateCommandBufferConfig& init_params, @@ -145,6 +149,12 @@ class GpuChannel : public IPC::Channel::Listener, // Uniquely identifies the channel within this GPU process. std::string channel_id_; + // Handle to the renderer process that is on the other side of the channel. + base::ProcessHandle renderer_process_; + + // The process id of the renderer process. + base::ProcessId renderer_pid_; + // Used to implement message routing functionality to CommandBuffer objects MessageRouter router_; diff --git a/content/common/gpu/gpu_command_buffer_stub.cc b/content/common/gpu/gpu_command_buffer_stub.cc index 1f22bce..047fb95 100644 --- a/content/common/gpu/gpu_command_buffer_stub.cc +++ b/content/common/gpu/gpu_command_buffer_stub.cc @@ -23,10 +23,6 @@ #include "ui/gfx/gl/gl_bindings.h" #include "ui/gfx/gl/gl_switches.h" -#if defined(OS_WIN) -#include "content/common/sandbox_policy.h" -#endif - GpuCommandBufferStub::SurfaceState::SurfaceState(int32 surface_id, bool visible, base::TimeTicks last_used_time) @@ -471,7 +467,17 @@ void GpuCommandBufferStub::OnRegisterTransferBuffer( size_t size, int32 id_request, IPC::Message* reply_message) { +#if defined(OS_WIN) + // Windows dups the shared memory handle it receives into the current process + // and closes it when this variable goes out of scope. + base::SharedMemory shared_memory(transfer_buffer, + false, + channel_->renderer_process()); +#else + // POSIX receives a dup of the shared memory handle and closes the dup when + // this variable goes out of scope. base::SharedMemory shared_memory(transfer_buffer, false); +#endif if (command_buffer_.get()) { int32 id = command_buffer_->RegisterTransferBuffer(&shared_memory, @@ -500,22 +506,20 @@ void GpuCommandBufferStub::OnDestroyTransferBuffer( void GpuCommandBufferStub::OnGetTransferBuffer( int32 id, IPC::Message* reply_message) { + // Fail if the renderer process has not provided its process handle. + if (!channel_->renderer_process()) + return; + if (command_buffer_.get()) { base::SharedMemoryHandle transfer_buffer = base::SharedMemoryHandle(); uint32 size = 0; gpu::Buffer buffer = command_buffer_->GetTransferBuffer(id); if (buffer.shared_memory) { -#if defined(OS_WIN) - transfer_buffer = NULL; - sandbox::BrokerDuplicateHandle(buffer.shared_memory->handle(), - channel_->renderer_pid(), &transfer_buffer, FILE_MAP_READ | - FILE_MAP_WRITE, 0); - CHECK(transfer_buffer != NULL); -#else - buffer.shared_memory->ShareToProcess(channel_->renderer_pid(), + // Assume service is responsible for duplicating the handle to the calling + // process. + buffer.shared_memory->ShareToProcess(channel_->renderer_process(), &transfer_buffer); -#endif size = buffer.size; } @@ -553,7 +557,8 @@ void GpuCommandBufferStub::OnCreateVideoDecoder( new GpuVideoDecodeAccelerator(this, decoder_route_id, this); video_decoders_.AddWithID(decoder, decoder_route_id); channel_->AddRoute(decoder_route_id, decoder); - decoder->Initialize(profile, reply_message); + decoder->Initialize(profile, reply_message, + channel_->renderer_process()); } void GpuCommandBufferStub::OnDestroyVideoDecoder(int decoder_route_id) { diff --git a/content/common/gpu/gpu_messages.h b/content/common/gpu/gpu_messages.h index d76491a..bd6ce94 100644 --- a/content/common/gpu/gpu_messages.h +++ b/content/common/gpu/gpu_messages.h @@ -216,10 +216,11 @@ IPC_MESSAGE_CONTROL0(GpuMsg_Hang) // A renderer sends this when it wants to create a connection to the GPU // process. The browser will create the GPU process if necessary, and will // return a handle to the channel via a GpuChannelEstablished message. -IPC_SYNC_MESSAGE_CONTROL1_3(GpuHostMsg_EstablishGpuChannel, +IPC_SYNC_MESSAGE_CONTROL1_4(GpuHostMsg_EstablishGpuChannel, content::CauseForGpuLaunch, int /* client id */, IPC::ChannelHandle /* handle to channel */, + base::ProcessHandle /* renderer_process_for_gpu */, content::GPUInfo /* stats about GPU process*/) // A renderer sends this to the browser process when it wants to @@ -291,6 +292,13 @@ IPC_MESSAGE_CONTROL1(GpuHostMsg_AcceleratedSurfaceSuspend, // GPU Channel Messages // These are messages from a renderer process to the GPU process. +// Initialize a channel between a renderer process and a GPU process. The +// renderer passes its process handle to the GPU process, which gives gives the +// GPU process the ability to map handles from the renderer process. This must +// be the first message sent on a newly connected channel. +IPC_MESSAGE_CONTROL1(GpuChannelMsg_Initialize, + base::ProcessHandle /* renderer_process_for_gpu */) + // Tells the GPU process to create a new command buffer that renders to an // offscreen frame buffer. IPC_SYNC_MESSAGE_CONTROL2_1(GpuChannelMsg_CreateOffscreenCommandBuffer, diff --git a/content/common/gpu/media/dxva_video_decode_accelerator.cc b/content/common/gpu/media/dxva_video_decode_accelerator.cc index 05afbad..10f5237 100644 --- a/content/common/gpu/media/dxva_video_decode_accelerator.cc +++ b/content/common/gpu/media/dxva_video_decode_accelerator.cc @@ -142,9 +142,20 @@ static IMFSample* CreateInputSample(const uint8* stream, int size, static IMFSample* CreateSampleFromInputBuffer( const media::BitstreamBuffer& bitstream_buffer, + base::ProcessHandle renderer_process, DWORD stream_size, DWORD alignment) { - base::SharedMemory shm(bitstream_buffer.handle(), true); + HANDLE shared_memory_handle = NULL; + RETURN_ON_FAILURE(::DuplicateHandle(renderer_process, + bitstream_buffer.handle(), + base::GetCurrentProcessHandle(), + &shared_memory_handle, + 0, + FALSE, + DUPLICATE_SAME_ACCESS), + "Duplicate handle failed", NULL); + + base::SharedMemory shm(shared_memory_handle, true); RETURN_ON_FAILURE(shm.Map(bitstream_buffer.size()), "Failed in base::SharedMemory::Map", NULL); @@ -494,11 +505,13 @@ bool DXVAVideoDecodeAccelerator::CreateD3DDevManager() { } DXVAVideoDecodeAccelerator::DXVAVideoDecodeAccelerator( - media::VideoDecodeAccelerator::Client* client) + media::VideoDecodeAccelerator::Client* client, + base::ProcessHandle renderer_process) : client_(client), egl_config_(NULL), state_(kUninitialized), pictures_requested_(false), + renderer_process_(renderer_process), last_input_buffer_id_(-1), inputs_before_decode_(0) { memset(&input_stream_info_, 0, sizeof(input_stream_info_)); @@ -547,6 +560,7 @@ void DXVAVideoDecodeAccelerator::Decode( base::win::ScopedComPtr<IMFSample> sample; sample.Attach(CreateSampleFromInputBuffer(bitstream_buffer, + renderer_process_, input_stream_info_.cbSize, input_stream_info_.cbAlignment)); RETURN_AND_NOTIFY_ON_FAILURE(sample, "Failed to create input sample", diff --git a/content/common/gpu/media/dxva_video_decode_accelerator.h b/content/common/gpu/media/dxva_video_decode_accelerator.h index 876ea4b..9c7469e 100644 --- a/content/common/gpu/media/dxva_video_decode_accelerator.h +++ b/content/common/gpu/media/dxva_video_decode_accelerator.h @@ -39,8 +39,9 @@ class CONTENT_EXPORT DXVAVideoDecodeAccelerator }; // Does not take ownership of |client| which must outlive |*this|. - explicit DXVAVideoDecodeAccelerator( - media::VideoDecodeAccelerator::Client* client); + DXVAVideoDecodeAccelerator( + media::VideoDecodeAccelerator::Client* client, + base::ProcessHandle renderer_process); virtual ~DXVAVideoDecodeAccelerator(); // media::VideoDecodeAccelerator implementation. @@ -186,6 +187,9 @@ class CONTENT_EXPORT DXVAVideoDecodeAccelerator // Contains the id of the last input buffer received from the client. int32 last_input_buffer_id_; + // Handle to the renderer process. + base::ProcessHandle renderer_process_; + // Ideally the reset token would be a stack variable which is used while // creating the device manager. However it seems that the device manager // holds onto the token and attempts to access it if the underlying device diff --git a/content/common/gpu/media/gpu_video_decode_accelerator.cc b/content/common/gpu/media/gpu_video_decode_accelerator.cc index 0ef9d87..224ba3a 100644 --- a/content/common/gpu/media/gpu_video_decode_accelerator.cc +++ b/content/common/gpu/media/gpu_video_decode_accelerator.cc @@ -116,7 +116,8 @@ void GpuVideoDecodeAccelerator::NotifyError( void GpuVideoDecodeAccelerator::Initialize( const media::VideoCodecProfile profile, - IPC::Message* init_done_msg) { + IPC::Message* init_done_msg, + base::ProcessHandle renderer_process) { DCHECK(!video_decode_accelerator_.get()); DCHECK(!init_done_msg_); DCHECK(init_done_msg); @@ -132,7 +133,7 @@ void GpuVideoDecodeAccelerator::Initialize( } DLOG(INFO) << "Initializing DXVA HW decoder for windows."; DXVAVideoDecodeAccelerator* video_decoder = - new DXVAVideoDecodeAccelerator(this); + new DXVAVideoDecodeAccelerator(this, renderer_process); #else // OS_WIN OmxVideoDecodeAccelerator* video_decoder = new OmxVideoDecodeAccelerator(this); diff --git a/content/common/gpu/media/gpu_video_decode_accelerator.h b/content/common/gpu/media/gpu_video_decode_accelerator.h index 2d2e559..430dda8 100644 --- a/content/common/gpu/media/gpu_video_decode_accelerator.h +++ b/content/common/gpu/media/gpu_video_decode_accelerator.h @@ -47,7 +47,8 @@ class GpuVideoDecodeAccelerator // The renderer process handle is valid as long as we have a channel between // GPU process and the renderer. void Initialize(const media::VideoCodecProfile profile, - IPC::Message* init_done_msg); + IPC::Message* init_done_msg, + base::ProcessHandle renderer_process); private: diff --git a/content/common/gpu/media/video_decode_accelerator_unittest.cc b/content/common/gpu/media/video_decode_accelerator_unittest.cc index 9dc6325..da73e34 100644 --- a/content/common/gpu/media/video_decode_accelerator_unittest.cc +++ b/content/common/gpu/media/video_decode_accelerator_unittest.cc @@ -655,7 +655,7 @@ void EglRenderingVDAClient::CreateDecoder() { CHECK(decoder_deleted()); #if defined(OS_WIN) scoped_refptr<DXVAVideoDecodeAccelerator> decoder = - new DXVAVideoDecodeAccelerator(this); + new DXVAVideoDecodeAccelerator(this, base::GetCurrentProcessHandle()); #else // OS_WIN scoped_refptr<OmxVideoDecodeAccelerator> decoder = new OmxVideoDecodeAccelerator(this); diff --git a/content/common/np_channel_base.h b/content/common/np_channel_base.h index 8bacac3..c931949 100644 --- a/content/common/np_channel_base.h +++ b/content/common/np_channel_base.h @@ -12,7 +12,6 @@ #include "base/hash_tables.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" -#include "base/process.h" #include "content/common/message_router.h" #include "content/common/npobject_base.h" #include "ipc/ipc_channel_handle.h" @@ -76,7 +75,7 @@ class NPChannelBase : public IPC::Channel::Listener, // IPC::Message::Sender implementation: virtual bool Send(IPC::Message* msg) OVERRIDE; - base::ProcessId peer_pid() { return channel_->peer_pid(); } + int peer_pid() { return peer_pid_; } IPC::ChannelHandle channel_handle() const { return channel_handle_; } // Returns the number of open NPObject channels in this process. diff --git a/content/common/sandbox_policy.cc b/content/common/sandbox_policy.cc index dc07070..11e8602 100644 --- a/content/common/sandbox_policy.cc +++ b/content/common/sandbox_policy.cc @@ -374,33 +374,21 @@ bool AddPolicyForGPU(CommandLine* cmd_line, sandbox::TargetPolicy* policy) { if (result != sandbox::SBOX_ALL_OK) return false; - // GPU needs to copy sections to renderers. - result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_HANDLES, - sandbox::TargetPolicy::HANDLES_DUP_ANY, - L"Section"); - if (result != sandbox::SBOX_ALL_OK) - return false; - AddGenericDllEvictionPolicy(policy); #endif return true; } bool AddPolicyForRenderer(sandbox::TargetPolicy* policy) { - // Renderers need to copy sections for plugin DIBs and GPU. + // Renderers need to copy sections for plugin DIBs. sandbox::ResultCode result; result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_HANDLES, sandbox::TargetPolicy::HANDLES_DUP_ANY, L"Section"); - if (result != sandbox::SBOX_ALL_OK) - return false; - - // Renderers need to share events with plugins. - result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_HANDLES, - sandbox::TargetPolicy::HANDLES_DUP_ANY, - L"Event"); - if (result != sandbox::SBOX_ALL_OK) + if (result != sandbox::SBOX_ALL_OK) { + NOTREACHED(); return false; + } policy->SetJobLevel(sandbox::JOB_LOCKDOWN, 0); @@ -463,33 +451,30 @@ bool BrokerDuplicateHandle(HANDLE source_handle, HANDLE* target_handle, DWORD desired_access, DWORD options) { - // If our process is the target just duplicate the handle. - if (::GetCurrentProcessId() == target_process_id) { - return !!::DuplicateHandle(::GetCurrentProcess(), source_handle, - ::GetCurrentProcess(), target_handle, - desired_access, FALSE, options); - - } + // Just use DuplicateHandle() if we aren't in the sandbox. + if (!g_target_services) { + base::win::ScopedHandle target_process(::OpenProcess(PROCESS_DUP_HANDLE, + FALSE, + target_process_id)); + if (!target_process.IsValid()) + return false; + + if (!::DuplicateHandle(::GetCurrentProcess(), source_handle, + target_process, target_handle, + desired_access, FALSE, + options)) { + return false; + } - // Try the broker next - if (g_target_services && - g_target_services->DuplicateHandle(source_handle, target_process_id, - target_handle, desired_access, - options) == SBOX_ALL_OK) { return true; } - // Finally, see if we already have access to the process. - base::win::ScopedHandle target_process; - target_process.Set(::OpenProcess(PROCESS_DUP_HANDLE, FALSE, - target_process_id)); - if (target_process.IsValid()) { - return !!::DuplicateHandle(::GetCurrentProcess(), source_handle, - target_process, target_handle, - desired_access, FALSE, options); - } - - return false; + ResultCode result = g_target_services->DuplicateHandle(source_handle, + target_process_id, + target_handle, + desired_access, + options); + return SBOX_ALL_OK == result; } @@ -588,7 +573,6 @@ base::ProcessHandle StartProcessWithAccess(CommandLine* cmd_line, policy->Release(); base::ProcessHandle process = 0; base::LaunchProcess(*cmd_line, base::LaunchOptions(), &process); - g_broker_services->AddTargetPeer(process); return process; } diff --git a/content/plugin/plugin_channel.cc b/content/plugin/plugin_channel.cc index 3f544da..dd60b67 100644 --- a/content/plugin/plugin_channel.cc +++ b/content/plugin/plugin_channel.cc @@ -161,7 +161,8 @@ void PluginChannel::NotifyRenderersOfPendingShutdown() { } PluginChannel::PluginChannel() - : renderer_id_(-1), + : renderer_handle_(0), + renderer_id_(-1), in_send_(0), incognito_(false), filter_(new MessageFilter()) { @@ -172,6 +173,9 @@ PluginChannel::PluginChannel() } PluginChannel::~PluginChannel() { + if (renderer_handle_) + base::CloseProcessHandle(renderer_handle_); + MessageLoop::current()->PostDelayedTask( FROM_HERE, base::Bind(&PluginReleaseCallback), @@ -281,7 +285,18 @@ base::WaitableEvent* PluginChannel::GetModalDialogEvent( return filter_->GetModalDialogEvent(containing_window); } +void PluginChannel::OnChannelConnected(int32 peer_pid) { + base::ProcessHandle handle; + if (!base::OpenProcessHandle(peer_pid, &handle)) { + NOTREACHED(); + } + renderer_handle_ = handle; + NPChannelBase::OnChannelConnected(peer_pid); +} + void PluginChannel::OnChannelError() { + base::CloseProcessHandle(renderer_handle_); + renderer_handle_ = 0; NPChannelBase::OnChannelError(); CleanUp(); } diff --git a/content/plugin/plugin_channel.h b/content/plugin/plugin_channel.h index 7be4d91..b83b133 100644 --- a/content/plugin/plugin_channel.h +++ b/content/plugin/plugin_channel.h @@ -1,4 +1,4 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -36,6 +36,7 @@ class PluginChannel : public NPChannelBase { virtual bool Send(IPC::Message* msg) OVERRIDE; virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + base::ProcessHandle renderer_handle() const { return renderer_handle_; } int renderer_id() { return renderer_id_; } virtual int GenerateRouteID() OVERRIDE; @@ -58,6 +59,7 @@ class PluginChannel : public NPChannelBase { protected: // IPC::Channel::Listener implementation: + virtual void OnChannelConnected(int32 peer_pid) OVERRIDE; virtual void OnChannelError() OVERRIDE; virtual void CleanUp() OVERRIDE; @@ -86,6 +88,9 @@ class PluginChannel : public NPChannelBase { std::vector<scoped_refptr<WebPluginDelegateStub> > plugin_stubs_; + // Handle to the renderer process who is on the other side of the channel. + base::ProcessHandle renderer_handle_; + // The id of the renderer who is on the other side of the channel. int renderer_id_; diff --git a/content/plugin/webplugin_proxy.cc b/content/plugin/webplugin_proxy.cc index 704058d..919f847 100644 --- a/content/plugin/webplugin_proxy.cc +++ b/content/plugin/webplugin_proxy.cc @@ -35,10 +35,6 @@ #include "ui/base/x/x11_util_internal.h" #endif -#if defined(OS_WIN) -#include "content/common/sandbox_policy.h" -#endif - using WebKit::WebBindings; using webkit::npapi::WebPluginResourceClient; @@ -133,9 +129,10 @@ void WebPluginProxy::WillDestroyWindow(gfx::PluginWindowHandle window) { #if defined(OS_WIN) void WebPluginProxy::SetWindowlessPumpEvent(HANDLE pump_messages_event) { HANDLE pump_messages_event_for_renderer = NULL; - sandbox::BrokerDuplicateHandle(pump_messages_event, channel_->peer_pid(), - &pump_messages_event_for_renderer, - SYNCHRONIZE | EVENT_MODIFY_STATE, 0); + DuplicateHandle(GetCurrentProcess(), pump_messages_event, + channel_->renderer_handle(), + &pump_messages_event_for_renderer, + 0, FALSE, DUPLICATE_SAME_ACCESS); DCHECK(pump_messages_event_for_renderer != NULL); Send(new PluginHostMsg_SetWindowlessPumpEvent( route_id_, pump_messages_event_for_renderer)); @@ -473,17 +470,25 @@ void WebPluginProxy::CreateCanvasFromHandle( const TransportDIB::Handle& dib_handle, const gfx::Rect& window_rect, scoped_ptr<skia::PlatformCanvas>* canvas_out) { + // Create a canvas that will reference the shared bits. We have to handle + // errors here since we're mapping a large amount of memory that may not fit + // in our address space, or go wrong in some other way. + HANDLE section; + DuplicateHandle(channel_->renderer_handle(), dib_handle, GetCurrentProcess(), + §ion, + STANDARD_RIGHTS_REQUIRED | FILE_MAP_READ | FILE_MAP_WRITE, + FALSE, 0); scoped_ptr<skia::PlatformCanvas> canvas(new skia::PlatformCanvas); if (!canvas->initialize( window_rect.width(), window_rect.height(), true, - dib_handle)) { + section)) { canvas_out->reset(); } canvas_out->reset(canvas.release()); // The canvas does not own the section so we need to close it now. - CloseHandle(dib_handle); + CloseHandle(section); } void WebPluginProxy::SetWindowlessBuffers( diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index f565201..a047050 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc @@ -909,15 +909,18 @@ GpuChannelHost* RenderThreadImpl::EstablishGpuChannelSync( // Ask the browser for the channel name. int client_id = 0; IPC::ChannelHandle channel_handle; + base::ProcessHandle renderer_process_for_gpu; content::GPUInfo gpu_info; if (!Send(new GpuHostMsg_EstablishGpuChannel(cause_for_gpu_launch, &client_id, &channel_handle, + &renderer_process_for_gpu, &gpu_info)) || + channel_handle.name.empty() || #if defined(OS_POSIX) channel_handle.socket.fd == -1 || #endif - channel_handle.name.empty()) { + renderer_process_for_gpu == base::kNullProcessHandle) { // Otherwise cancel the connection. gpu_channel_ = NULL; return NULL; @@ -928,7 +931,7 @@ GpuChannelHost* RenderThreadImpl::EstablishGpuChannelSync( content::GetContentClient()->SetGpuInfo(gpu_info); // Connect to the GPU process if a channel name was received. - gpu_channel_->Connect(channel_handle); + gpu_channel_->Connect(channel_handle, renderer_process_for_gpu); return GetGpuChannel(); } diff --git a/content/renderer/webplugin_delegate_proxy.cc b/content/renderer/webplugin_delegate_proxy.cc index b6ff543..5bc6084 100644 --- a/content/renderer/webplugin_delegate_proxy.cc +++ b/content/renderer/webplugin_delegate_proxy.cc @@ -18,7 +18,6 @@ #include "base/logging.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" -#include "base/process.h" #include "base/string_split.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" @@ -61,10 +60,6 @@ #include "base/mac/mac_util.h" #endif -#if defined(OS_WIN) -#include "content/common/sandbox_policy.h" -#endif - using WebKit::WebBindings; using WebKit::WebCursorInfo; using WebKit::WebDragData; @@ -489,8 +484,7 @@ void WebPluginDelegateProxy::OnChannelError() { static void CopyTransportDIBHandleForMessage( const TransportDIB::Handle& handle_in, - TransportDIB::Handle* handle_out, - base::ProcessId peer_pid) { + TransportDIB::Handle* handle_out) { #if defined(OS_MACOSX) // On Mac, TransportDIB::Handle is typedef'ed to FileDescriptor, and // FileDescriptor message fields needs to remain valid until the message is @@ -500,12 +494,6 @@ static void CopyTransportDIBHandleForMessage( return; } handle_out->auto_close = true; -#elif defined(OS_WIN) - // On Windows we need to duplicate the handle for the plugin process. - *handle_out = NULL; - sandbox::BrokerDuplicateHandle(handle_in, peer_pid, handle_out, - FILE_MAP_READ | FILE_MAP_WRITE, 0); - CHECK(*handle_out != NULL); #else // Don't need to do anything special for other platforms. *handle_out = handle_in; @@ -532,18 +520,15 @@ void WebPluginDelegateProxy::SendUpdateGeometry( { if (transport_stores_[0].dib.get()) CopyTransportDIBHandleForMessage(transport_stores_[0].dib->handle(), - ¶m.windowless_buffer0, - channel_host_->peer_pid()); + ¶m.windowless_buffer0); if (transport_stores_[1].dib.get()) CopyTransportDIBHandleForMessage(transport_stores_[1].dib->handle(), - ¶m.windowless_buffer1, - channel_host_->peer_pid()); + ¶m.windowless_buffer1); if (background_store_.dib.get()) CopyTransportDIBHandleForMessage(background_store_.dib->handle(), - ¶m.background_buffer, - channel_host_->peer_pid()); + ¶m.background_buffer); } IPC::Message* msg; |