diff options
24 files changed, 377 insertions, 240 deletions
diff --git a/chrome/browser/child_process_host.cc b/chrome/browser/child_process_host.cc index d9f5218..a9dcbd7 100644 --- a/chrome/browser/child_process_host.cc +++ b/chrome/browser/child_process_host.cc @@ -80,7 +80,8 @@ ChildProcessHost::ChildProcessHost( ChildProcessHost::~ChildProcessHost() { Singleton<ChildProcessList>::get()->remove(this); - resource_dispatcher_host_->CancelRequestsForProcess(id()); + if (resource_dispatcher_host_) + resource_dispatcher_host_->CancelRequestsForProcess(id()); } // static @@ -217,8 +218,11 @@ void ChildProcessHost::ListenerHook::OnMessageReceived( #endif bool msg_is_ok = true; - bool handled = host_->resource_dispatcher_host_->OnMessageReceived( - msg, host_, &msg_is_ok); + bool handled = false; + + if (host_->resource_dispatcher_host_) + host_->resource_dispatcher_host_->OnMessageReceived( + msg, host_, &msg_is_ok); if (!handled) { if (msg.type() == PluginProcessHostMsg_ShutdownRequest::ID) { diff --git a/chrome/browser/gpu_process_host.cc b/chrome/browser/gpu_process_host.cc index 9981133..cae8a35 100644 --- a/chrome/browser/gpu_process_host.cc +++ b/chrome/browser/gpu_process_host.cc @@ -5,41 +5,80 @@ #include "chrome/browser/gpu_process_host.h" #include "base/command_line.h" -#include "base/singleton.h" #include "base/thread.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/child_process_host.h" -#include "chrome/browser/child_process_launcher.h" -#include "chrome/browser/io_thread.h" -#include "chrome/browser/renderer_host/render_process_host.h" -#include "chrome/common/child_process_info.h" +#include "chrome/browser/chrome_thread.h" +#include "chrome/browser/gpu_process_host_ui_shim.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/gpu_messages.h" #include "chrome/common/render_messages.h" #include "ipc/ipc_switches.h" -GpuProcessHost::GpuProcessHost() : last_routing_id_(1) { +namespace { + +// Tasks used by this file +class RouteOnUIThreadTask : public Task { + public: + explicit RouteOnUIThreadTask(const IPC::Message& msg) { + msg_ = new IPC::Message(msg); + } + + private: + void Run() { + GpuProcessHostUIShim::Get()->OnMessageReceived(*msg_); + delete msg_; + msg_ = NULL; + } + IPC::Message* msg_; +}; + +// Global GpuProcessHost instance. +// We can not use Singleton<GpuProcessHost> because that gets +// terminated on the wrong thread (main thread). We need the +// GpuProcessHost to be terminated on the same thread on which it is +// initialized, the IO thread. +static GpuProcessHost* sole_instance_; + +} // anonymous namespace + +GpuProcessHost::GpuProcessHost() + : ChildProcessHost(GPU_PROCESS, NULL), + initialized_(false), + initialized_successfully_(false) { +} + +GpuProcessHost::~GpuProcessHost() { + while (!queued_synchronization_replies_.empty()) { + delete queued_synchronization_replies_.front().reply; + queued_synchronization_replies_.pop(); + } +} + +bool GpuProcessHost::EnsureInitialized() { + if (!initialized_) { + initialized_ = true; + initialized_successfully_ = Init(); + } + return initialized_successfully_; +} + +bool GpuProcessHost::Init() { + if (!CreateChannel()) + return false; + const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); std::wstring gpu_launcher = browser_command_line.GetSwitchValue(switches::kGpuLauncher); FilePath exe_path = ChildProcessHost::GetChildPath(gpu_launcher.empty()); if (exe_path.empty()) - return; - - std::string channel_id = ChildProcessInfo::GenerateRandomChannelID(this); - channel_.reset(new IPC::ChannelProxy( - channel_id, - IPC::Channel::MODE_SERVER, - this, - NULL, // No filter (for now). - g_browser_process->io_thread()->message_loop())); + return false; CommandLine* cmd_line = new CommandLine(exe_path); cmd_line->AppendSwitchWithValue(switches::kProcessType, switches::kGpuProcess); cmd_line->AppendSwitchWithValue(switches::kProcessChannelID, - ASCIIToWide(channel_id)); + ASCIIToWide(channel_id())); const CommandLine& browser_cmd_line = *CommandLine::ForCurrentProcess(); PropagateBrowserCommandLineToGpu(browser_cmd_line, cmd_line); @@ -48,108 +87,65 @@ GpuProcessHost::GpuProcessHost() : last_routing_id_(1) { if (!gpu_launcher.empty()) cmd_line->PrependWrapper(gpu_launcher); - // Spawn the child process asynchronously to avoid blocking the UI thread. - child_process_.reset(new ChildProcessLauncher( + Launch( #if defined(OS_WIN) FilePath(), #elif defined(POSIX) false, // Never use the zygote (GPU plugin can't be sandboxed). base::environment_vector(), - channel_->GetClientFileDescriptor(), #endif - cmd_line, - this)); -} + cmd_line); -GpuProcessHost::~GpuProcessHost() { - while (!queued_synchronization_replies_.empty()) { - delete queued_synchronization_replies_.front(); - queued_synchronization_replies_.pop(); - } + return true; } // static GpuProcessHost* GpuProcessHost::Get() { - GpuProcessHost* host = Singleton<GpuProcessHost>::get(); - if (!host->child_process_.get()) - return NULL; // Failed to init. - return host; -} - -int32 GpuProcessHost::GetNextRoutingId() { - return ++last_routing_id_; + if (sole_instance_ == NULL) + sole_instance_ = new GpuProcessHost(); + return sole_instance_; } -int32 GpuProcessHost::NewRenderWidgetHostView(GpuNativeWindowHandle parent) { - int32 routing_id = GetNextRoutingId(); - Send(new GpuMsg_NewRenderWidgetHostView(parent, routing_id)); - return routing_id; +// static +void GpuProcessHost::Shutdown() { + if (sole_instance_) { + delete sole_instance_; + sole_instance_ = NULL; + } } bool GpuProcessHost::Send(IPC::Message* msg) { - if (!channel_.get()) { - delete msg; + if (!EnsureInitialized()) return false; - } - if (child_process_.get() && child_process_->IsStarting()) { - queued_messages_.push(msg); - return true; - } - - return channel_->Send(msg); + return ChildProcessHost::Send(msg); } void GpuProcessHost::OnMessageReceived(const IPC::Message& message) { if (message.routing_id() == MSG_ROUTING_CONTROL) { OnControlMessageReceived(message); } else { - router_.OnMessageReceived(message); + // Need to transfer this message to the UI thread and the + // GpuProcessHostUIShim for dispatching via its message router. + ChromeThread::PostTask(ChromeThread::UI, + FROM_HERE, + new RouteOnUIThreadTask(message)); } } -void GpuProcessHost::OnChannelConnected(int32 peer_pid) { -} - -void GpuProcessHost::OnChannelError() { -} - -void GpuProcessHost::OnProcessLaunched() { - while (!queued_messages_.empty()) { - Send(queued_messages_.front()); - queued_messages_.pop(); +void GpuProcessHost::EstablishGpuChannel(int renderer_id, + ResourceMessageFilter* filter) { + if (Send(new GpuMsg_EstablishChannel(renderer_id))) { + sent_requests_.push(ChannelRequest(filter)); + } else { + ReplyToRenderer(IPC::ChannelHandle(), filter); } } -void GpuProcessHost::AddRoute(int32 routing_id, - IPC::Channel::Listener* listener) { - router_.AddRoute(routing_id, listener); -} - -void GpuProcessHost::RemoveRoute(int32 routing_id) { - router_.RemoveRoute(routing_id); -} - -void GpuProcessHost::EstablishGpuChannel(int renderer_id) { - if (Send(new GpuMsg_EstablishChannel(renderer_id))) - sent_requests_.push(ChannelRequest(renderer_id)); - else - ReplyToRenderer(renderer_id, IPC::ChannelHandle()); -} - -void GpuProcessHost::Synchronize(int renderer_id, IPC::Message* reply) { - // ************ - // TODO(kbr): the handling of this synchronous message (which is - // needed for proper initialization semantics of APIs like WebGL) is - // currently broken on Windows because the renderer is sending a - // synchronous message to the browser's UI thread. To fix this, the - // GpuProcessHost needs to move to the IO thread, and any backing - // store handling needs to remain on the UI thread in a new - // GpuProcessHostProxy, where work is sent from the IO thread to the - // UI thread via PostTask. - // ************ - queued_synchronization_replies_.push(reply); - CHECK(Send(new GpuMsg_Synchronize(renderer_id))); +void GpuProcessHost::Synchronize(IPC::Message* reply, + ResourceMessageFilter* filter) { + queued_synchronization_replies_.push(SynchronizationRequest(reply, filter)); + Send(new GpuMsg_Synchronize()); } void GpuProcessHost::OnControlMessageReceived(const IPC::Message& message) { @@ -163,37 +159,27 @@ void GpuProcessHost::OnControlMessageReceived(const IPC::Message& message) { void GpuProcessHost::OnChannelEstablished( const IPC::ChannelHandle& channel_handle) { const ChannelRequest& request = sent_requests_.front(); - - ReplyToRenderer(request.renderer_id, channel_handle); + ReplyToRenderer(channel_handle, request.filter); sent_requests_.pop(); } -void GpuProcessHost::OnSynchronizeReply(int renderer_id) { - IPC::Message* reply = queued_synchronization_replies_.front(); +void GpuProcessHost::OnSynchronizeReply() { + const SynchronizationRequest& request = + queued_synchronization_replies_.front(); + request.filter->Send(request.reply); queued_synchronization_replies_.pop(); - RenderProcessHost* process_host = RenderProcessHost::FromID(renderer_id); - if (!process_host) { - delete reply; - return; - } - CHECK(process_host->Send(reply)); } void GpuProcessHost::ReplyToRenderer( - int renderer_id, - const IPC::ChannelHandle& channel) { - // Check whether the renderer process is still around. - RenderProcessHost* process_host = RenderProcessHost::FromID(renderer_id); - if (!process_host) - return; - - ViewMsg_GpuChannelEstablished* msg = + const IPC::ChannelHandle& channel, + ResourceMessageFilter* filter) { + ViewMsg_GpuChannelEstablished* message = new ViewMsg_GpuChannelEstablished(channel); // If the renderer process is performing synchronous initialization, // it needs to handle this message before receiving the reply for // the synchronous ViewHostMsg_SynchronizeGpu message. - msg->set_unblock(true); - CHECK(process_host->Send(msg)); + message->set_unblock(true); + filter->Send(message); } void GpuProcessHost::PropagateBrowserCommandLineToGpu( @@ -215,3 +201,14 @@ void GpuProcessHost::PropagateBrowserCommandLineToGpu( } } } + +URLRequestContext* GpuProcessHost::GetRequestContext( + uint32 request_id, + const ViewHostMsg_Resource_Request& request_data) { + return NULL; +} + +bool GpuProcessHost::CanShutdown() { + return true; +} + diff --git a/chrome/browser/gpu_process_host.h b/chrome/browser/gpu_process_host.h index 27d3fe3..4065124 100644 --- a/chrome/browser/gpu_process_host.h +++ b/chrome/browser/gpu_process_host.h @@ -9,83 +9,74 @@ #include "base/basictypes.h" #include "base/scoped_ptr.h" -#include "base/singleton.h" -#include "chrome/browser/child_process_launcher.h" -#include "chrome/common/gpu_native_window_handle.h" -#include "chrome/common/message_router.h" -#include "gfx/native_widget_types.h" -#include "ipc/ipc_channel_handle.h" -#include "ipc/ipc_channel_proxy.h" +#include "chrome/browser/child_process_host.h" +#include "chrome/browser/renderer_host/resource_message_filter.h" class ChildProcessLauncher; class CommandBufferProxy; -class GpuProcessHost : public IPC::Channel::Sender, - public IPC::Channel::Listener, - public ChildProcessLauncher::Client { +class GpuProcessHost : public ChildProcessHost { public: // Getter for the singleton. This will return NULL on failure. static GpuProcessHost* Get(); - int32 GetNextRoutingId(); + // Shutdown routine, which should only be called upon process + // termination. + static void Shutdown(); - // Creates the new remote view and returns the routing ID for the view, or 0 - // on failure. - int32 NewRenderWidgetHostView(GpuNativeWindowHandle parent); - - // IPC::Channel::Sender implementation. virtual bool Send(IPC::Message* msg); // IPC::Channel::Listener implementation. virtual void OnMessageReceived(const IPC::Message& message); - virtual void OnChannelConnected(int32 peer_pid); - virtual void OnChannelError(); - - // ChildProcessLauncher::Client implementation. - virtual void OnProcessLaunched(); - - // See documentation on MessageRouter for AddRoute and RemoveRoute - void AddRoute(int32 routing_id, IPC::Channel::Listener* listener); - void RemoveRoute(int32 routing_id); // Tells the GPU process to create a new channel for communication with a // renderer. Will asynchronously send message to object with given routing id // on completion. - void EstablishGpuChannel(int renderer_id); + void EstablishGpuChannel(int renderer_id, + ResourceMessageFilter* filter); // Sends a reply message later when the next GpuHostMsg_SynchronizeReply comes // in. - void Synchronize(int renderer_id, IPC::Message* reply); + void Synchronize(IPC::Message* reply, + ResourceMessageFilter* filter); private: - friend struct DefaultSingletonTraits<GpuProcessHost>; - // Used to queue pending channel requests. struct ChannelRequest { - explicit ChannelRequest(int renderer_id) : renderer_id(renderer_id) {} - // Used to identify the renderer. The ID is used instead of a pointer to - // the RenderProcessHost in case it is destroyed while the request is - // pending. - // TODO(apatrick): investigate whether these IDs are used for future - // render processes. - int renderer_id; + explicit ChannelRequest(ResourceMessageFilter* filter) + : filter(filter) {} + // Used to send the reply message back to the renderer. + scoped_refptr<ResourceMessageFilter> filter; + }; + + // Used to queue pending synchronization requests. + struct SynchronizationRequest { + SynchronizationRequest(IPC::Message* reply, + ResourceMessageFilter* filter) + : reply(reply), + filter(filter) {} + // The delayed reply message which needs to be sent to the + // renderer. + IPC::Message* reply; + + // Used to send the reply message back to the renderer. + scoped_refptr<ResourceMessageFilter> filter; }; GpuProcessHost(); virtual ~GpuProcessHost(); + bool EnsureInitialized(); + bool Init(); + void OnControlMessageReceived(const IPC::Message& message); // Message handlers. void OnChannelEstablished(const IPC::ChannelHandle& channel_handle); - void OnSynchronizeReply(int renderer_id); + void OnSynchronizeReply(); - void ReplyToRenderer(int renderer_id, - const IPC::ChannelHandle& channel); - - // These are the channel requests that we have already sent to - // the GPU process, but haven't heard back about yet. - std::queue<ChannelRequest> sent_requests_; + void ReplyToRenderer(const IPC::ChannelHandle& channel, + ResourceMessageFilter* filter); // Copies applicable command line switches from the given |browser_cmd| line // flags to the output |gpu_cmd| line flags. Not all switches will be @@ -93,24 +84,22 @@ class GpuProcessHost : public IPC::Channel::Sender, void PropagateBrowserCommandLineToGpu(const CommandLine& browser_cmd, CommandLine* gpu_cmd) const; - scoped_ptr<ChildProcessLauncher> child_process_; - - // A proxy for our IPC::Channel that lives on the IO thread (see - // browser_process.h). This will be NULL if the class failed to connect. - scoped_ptr<IPC::ChannelProxy> channel_; + // ResourceDispatcherHost::Receiver implementation: + virtual URLRequestContext* GetRequestContext( + uint32 request_id, + const ViewHostMsg_Resource_Request& request_data); - int last_routing_id_; + virtual bool CanShutdown(); - MessageRouter router_; + bool initialized_; + bool initialized_successfully_; - // Messages we queue while waiting for the process handle. We queue them here - // instead of in the channel so that we ensure they're sent after init related - // messages that are sent once the process handle is available. This is - // because the queued messages may have dependencies on the init messages. - std::queue<IPC::Message*> queued_messages_; + // These are the channel requests that we have already sent to + // the GPU process, but haven't heard back about yet. + std::queue<ChannelRequest> sent_requests_; // The pending synchronization requests we need to reply to. - std::queue<IPC::Message*> queued_synchronization_replies_; + std::queue<SynchronizationRequest> queued_synchronization_replies_; DISALLOW_COPY_AND_ASSIGN(GpuProcessHost); }; diff --git a/chrome/browser/gpu_process_host_ui_shim.cc b/chrome/browser/gpu_process_host_ui_shim.cc new file mode 100644 index 0000000..0b25845 --- /dev/null +++ b/chrome/browser/gpu_process_host_ui_shim.cc @@ -0,0 +1,69 @@ +// Copyright (c) 2010 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 "chrome/browser/gpu_process_host_ui_shim.h" + +#include "chrome/browser/chrome_thread.h" +#include "chrome/browser/gpu_process_host.h" +#include "chrome/common/gpu_messages.h" + +// Tasks used by this file +namespace { + +class SendOnIOThreadTask : public Task { + public: + explicit SendOnIOThreadTask(IPC::Message* msg) : msg_(msg) { + } + + private: + void Run() { + GpuProcessHost::Get()->Send(msg_); + } + IPC::Message* msg_; +}; + +} // namespace + +GpuProcessHostUIShim::GpuProcessHostUIShim() : last_routing_id_(1) { +} + +GpuProcessHostUIShim::~GpuProcessHostUIShim() { +} + +// static +GpuProcessHostUIShim* GpuProcessHostUIShim::Get() { + return Singleton<GpuProcessHostUIShim>::get(); +} + +int32 GpuProcessHostUIShim::NewRenderWidgetHostView( + GpuNativeWindowHandle parent) { + int32 routing_id = GetNextRoutingId(); + Send(new GpuMsg_NewRenderWidgetHostView(parent, routing_id)); + return routing_id; +} + +bool GpuProcessHostUIShim::Send(IPC::Message* msg) { + ChromeThread::PostTask(ChromeThread::IO, + FROM_HERE, + new SendOnIOThreadTask(msg)); + return true; +} + +int32 GpuProcessHostUIShim::GetNextRoutingId() { + return ++last_routing_id_; +} + +void GpuProcessHostUIShim::AddRoute(int32 routing_id, + IPC::Channel::Listener* listener) { + router_.AddRoute(routing_id, listener); +} + +void GpuProcessHostUIShim::RemoveRoute(int32 routing_id) { + router_.RemoveRoute(routing_id); +} + +void GpuProcessHostUIShim::OnMessageReceived(const IPC::Message& message) { + router_.RouteMessage(message); +} + diff --git a/chrome/browser/gpu_process_host_ui_shim.h b/chrome/browser/gpu_process_host_ui_shim.h new file mode 100644 index 0000000..70696ca --- /dev/null +++ b/chrome/browser/gpu_process_host_ui_shim.h @@ -0,0 +1,56 @@ +// Copyright (c) 2010 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. + +#ifndef CHROME_BROWSER_GPU_PROCESS_HOST_UI_SHIM_H_ +#define CHROME_BROWSER_GPU_PROCESS_HOST_UI_SHIM_H_ + +// This class lives on the UI thread and supports classes like the +// BackingStoreProxy, which must live on the UI thread. The IO thread +// portion of this class, the GpuProcessHost, is responsible for +// shuttling messages between the browser and GPU processes. + +#include "base/singleton.h" +#include "chrome/common/gpu_native_window_handle.h" +#include "chrome/common/message_router.h" +#include "ipc/ipc_channel.h" +#include "gfx/native_widget_types.h" + +class GpuProcessHostUIShim : public IPC::Channel::Sender, + public IPC::Channel::Listener { + public: + // Getter for the singleton. This will return NULL on failure. + static GpuProcessHostUIShim* Get(); + + int32 GetNextRoutingId(); + + // Creates the new remote view and returns the routing ID for the view, or 0 + // on failure. + int32 NewRenderWidgetHostView(GpuNativeWindowHandle parent); + + // IPC::Channel::Sender implementation. + virtual bool Send(IPC::Message* msg); + + // IPC::Channel::Listener implementation. + // The GpuProcessHost causes this to be called on the UI thread to + // dispatch the incoming messages from the GPU process, which are + // actually received on the IO thread. + virtual void OnMessageReceived(const IPC::Message& message); + + // See documentation on MessageRouter for AddRoute and RemoveRoute + void AddRoute(int32 routing_id, IPC::Channel::Listener* listener); + void RemoveRoute(int32 routing_id); + + private: + friend struct DefaultSingletonTraits<GpuProcessHostUIShim>; + + GpuProcessHostUIShim(); + virtual ~GpuProcessHostUIShim(); + + int last_routing_id_; + + MessageRouter router_; +}; + +#endif // CHROME_BROWSER_GPU_PROCESS_HOST_UI_SHIM_H_ + diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc index 60d0d4e..5f9236b 100644 --- a/chrome/browser/io_thread.cc +++ b/chrome/browser/io_thread.cc @@ -8,6 +8,7 @@ #include "base/logging.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_thread.h" +#include "chrome/browser/gpu_process_host.h" #include "chrome/browser/net/chrome_net_log.h" #include "chrome/browser/net/dns_global.h" #include "chrome/browser/net/passive_log_collector.h" @@ -169,6 +170,8 @@ void IOThread::CleanUp() { globals_->host_resolver.get()->GetAsHostResolverImpl()->Shutdown(); } + GpuProcessHost::Shutdown(); + delete globals_; globals_ = NULL; diff --git a/chrome/browser/renderer_host/backing_store_proxy.cc b/chrome/browser/renderer_host/backing_store_proxy.cc index c41900d..ba3538b 100644 --- a/chrome/browser/renderer_host/backing_store_proxy.cc +++ b/chrome/browser/renderer_host/backing_store_proxy.cc @@ -5,7 +5,7 @@ #include "chrome/browser/renderer_host/backing_store_proxy.h" #include "build/build_config.h" -#include "chrome/browser/gpu_process_host.h" +#include "chrome/browser/gpu_process_host_ui_shim.h" #include "chrome/browser/renderer_host/render_process_host.h" #include "chrome/browser/renderer_host/render_widget_host.h" #include "chrome/common/gpu_messages.h" @@ -18,17 +18,17 @@ BackingStoreProxy::BackingStoreProxy(RenderWidgetHost* widget, const gfx::Size& size, - GpuProcessHost* process, + GpuProcessHostUIShim* process_shim, int32 routing_id) : BackingStore(widget, size), - process_(process), + process_shim_(process_shim), routing_id_(routing_id), waiting_for_paint_ack_(false) { - process_->AddRoute(routing_id_, this); + process_shim_->AddRoute(routing_id_, this); } BackingStoreProxy::~BackingStoreProxy() { - process_->RemoveRoute(routing_id_); + process_shim_->RemoveRoute(routing_id_); } void BackingStoreProxy::PaintToBackingStore( @@ -46,7 +46,7 @@ void BackingStoreProxy::PaintToBackingStore( process_id = process->GetHandle(); #endif - if (process_->Send(new GpuMsg_PaintToBackingStore( + if (process_shim_->Send(new GpuMsg_PaintToBackingStore( routing_id_, process_id, bitmap, bitmap_rect, copy_rects))) { // Message sent successfully, so the caller can not destroy the // TransportDIB. OnDonePaintingToBackingStore will free it later. @@ -67,8 +67,8 @@ bool BackingStoreProxy::CopyFromBackingStore(const gfx::Rect& rect, void BackingStoreProxy::ScrollBackingStore(int dx, int dy, const gfx::Rect& clip_rect, const gfx::Size& view_size) { - process_->Send(new GpuMsg_ScrollBackingStore(routing_id_, dx, dy, - clip_rect, view_size)); + process_shim_->Send(new GpuMsg_ScrollBackingStore(routing_id_, dx, dy, + clip_rect, view_size)); } void BackingStoreProxy::OnMessageReceived(const IPC::Message& msg) { diff --git a/chrome/browser/renderer_host/backing_store_proxy.h b/chrome/browser/renderer_host/backing_store_proxy.h index 0b5059f..4d572b6 100644 --- a/chrome/browser/renderer_host/backing_store_proxy.h +++ b/chrome/browser/renderer_host/backing_store_proxy.h @@ -9,13 +9,13 @@ #include "chrome/browser/renderer_host/backing_store.h" #include "ipc/ipc_channel.h" -class GpuProcessHost; +class GpuProcessHostUIShim; class BackingStoreProxy : public BackingStore, public IPC::Channel::Listener { public: BackingStoreProxy(RenderWidgetHost* widget, const gfx::Size& size, - GpuProcessHost* process, int32 routing_id); + GpuProcessHostUIShim* process_shim, int32 routing_id); virtual ~BackingStoreProxy(); // BackingStore implementation. @@ -39,7 +39,7 @@ class BackingStoreProxy : public BackingStore, // Message handlers. void OnPaintToBackingStoreACK(); - GpuProcessHost* process_; + GpuProcessHostUIShim* process_shim_; int32 routing_id_; // Set to true when we're waiting for the GPU process to do a paint and send diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc index 7f72a79..15517fc 100644 --- a/chrome/browser/renderer_host/browser_render_process_host.cc +++ b/chrome/browser/renderer_host/browser_render_process_host.cc @@ -773,10 +773,6 @@ void BrowserRenderProcessHost::OnMessageReceived(const IPC::Message& msg) { OnExtensionRemoveListener) IPC_MESSAGE_HANDLER(ViewHostMsg_ExtensionCloseChannel, OnExtensionCloseChannel) - IPC_MESSAGE_HANDLER(ViewHostMsg_EstablishGpuChannel, - OnMsgEstablishGpuChannel) - IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_SynchronizeGpu, - OnMsgSynchronizeGpu) IPC_MESSAGE_HANDLER(ViewHostMsg_SpellChecker_RequestDictionary, OnSpellCheckerRequestDictionary) IPC_MESSAGE_UNHANDLED_ERROR() @@ -981,14 +977,6 @@ void BrowserRenderProcessHost::OnExtensionCloseChannel(int port_id) { } } -void BrowserRenderProcessHost::OnMsgEstablishGpuChannel() { - GpuProcessHost::Get()->EstablishGpuChannel(id()); -} - -void BrowserRenderProcessHost::OnMsgSynchronizeGpu(IPC::Message* reply) { - GpuProcessHost::Get()->Synchronize(id(), reply); -} - void BrowserRenderProcessHost::OnSpellCheckerRequestDictionary() { if (profile()->GetSpellCheckHost()) { // The spellchecker initialization already started and finished; just send diff --git a/chrome/browser/renderer_host/browser_render_process_host.h b/chrome/browser/renderer_host/browser_render_process_host.h index 9a9c833..277a53e 100644 --- a/chrome/browser/renderer_host/browser_render_process_host.h +++ b/chrome/browser/renderer_host/browser_render_process_host.h @@ -110,12 +110,6 @@ class BrowserRenderProcessHost : public RenderProcessHost, void OnExtensionAddListener(const std::string& event_name); void OnExtensionRemoveListener(const std::string& event_name); void OnExtensionCloseChannel(int port_id); - // Renderer process is requesting that the browser process establish a GPU - // channel. - void OnMsgEstablishGpuChannel(); - // Renderer process is requesting that outstanding asynchronous GPU-related - // messages are processed. - void OnMsgSynchronizeGpu(IPC::Message* reply); // Initialize support for visited links. Send the renderer process its initial // set of visited links. diff --git a/chrome/browser/renderer_host/gpu_view_host.cc b/chrome/browser/renderer_host/gpu_view_host.cc index a81db6b..fa8c19c 100644 --- a/chrome/browser/renderer_host/gpu_view_host.cc +++ b/chrome/browser/renderer_host/gpu_view_host.cc @@ -4,43 +4,47 @@ #include "chrome/browser/renderer_host/gpu_view_host.h" -#include "chrome/browser/gpu_process_host.h" +#include "chrome/browser/gpu_process_host_ui_shim.h" #include "chrome/browser/renderer_host/backing_store_proxy.h" #include "chrome/browser/renderer_host/video_layer_proxy.h" #include "chrome/common/gpu_messages.h" GpuViewHost::GpuViewHost(RenderWidgetHost* widget, GpuNativeWindowHandle parent) : widget_(widget), - process_(GpuProcessHost::Get()), + process_shim_(GpuProcessHostUIShim::Get()), routing_id_(0) { - if (!process_) { + if (!process_shim_) { // TODO(brettw) handle error. return; } - routing_id_ = process_->NewRenderWidgetHostView(parent); + routing_id_ = process_shim_->NewRenderWidgetHostView(parent); } GpuViewHost::~GpuViewHost() { } BackingStore* GpuViewHost::CreateBackingStore(const gfx::Size& size) { - int32 backing_store_routing_id = process_->GetNextRoutingId(); - process_->Send(new GpuMsg_NewBackingStore(routing_id_, - backing_store_routing_id, - size)); - return new BackingStoreProxy(widget_, size, - process_, backing_store_routing_id); + int32 backing_store_routing_id = process_shim_->GetNextRoutingId(); + BackingStoreProxy* result = + new BackingStoreProxy(widget_, size, + process_shim_, backing_store_routing_id); + process_shim_->Send(new GpuMsg_NewBackingStore(routing_id_, + backing_store_routing_id, + size)); + return result; } VideoLayer* GpuViewHost::CreateVideoLayer(const gfx::Size& size) { - int32 video_layer_routing_id = process_->GetNextRoutingId(); - process_->Send(new GpuMsg_NewVideoLayer(routing_id_, - video_layer_routing_id, - size)); - return new VideoLayerProxy(widget_, size, - process_, video_layer_routing_id); + int32 video_layer_routing_id = process_shim_->GetNextRoutingId(); + VideoLayerProxy* result = + new VideoLayerProxy(widget_, size, + process_shim_, video_layer_routing_id); + process_shim_->Send(new GpuMsg_NewVideoLayer(routing_id_, + video_layer_routing_id, + size)); + return result; } void GpuViewHost::OnWindowPainted() { - process_->Send(new GpuMsg_WindowPainted(routing_id_)); + process_shim_->Send(new GpuMsg_WindowPainted(routing_id_)); } diff --git a/chrome/browser/renderer_host/gpu_view_host.h b/chrome/browser/renderer_host/gpu_view_host.h index 910c978..8d19e07 100644 --- a/chrome/browser/renderer_host/gpu_view_host.h +++ b/chrome/browser/renderer_host/gpu_view_host.h @@ -9,7 +9,7 @@ #include "chrome/common/gpu_native_window_handle.h" class BackingStore; -class GpuProcessHost; +class GpuProcessHostUIShim; class RenderWidgetHost; class VideoLayer; @@ -40,7 +40,7 @@ class GpuViewHost { private: RenderWidgetHost* widget_; - GpuProcessHost* process_; + GpuProcessHostUIShim* process_shim_; int32 routing_id_; DISALLOW_COPY_AND_ASSIGN(GpuViewHost); diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc index de9e836..3dfcf63 100644 --- a/chrome/browser/renderer_host/resource_message_filter.cc +++ b/chrome/browser/renderer_host/resource_message_filter.cc @@ -20,6 +20,7 @@ #include "chrome/browser/extensions/extension_message_service.h" #include "chrome/browser/geolocation/geolocation_permission_context.h" #include "chrome/browser/geolocation/geolocation_dispatcher_host.h" +#include "chrome/browser/gpu_process_host.h" #include "chrome/browser/host_zoom_map.h" #include "chrome/browser/in_process_webkit/dom_storage_dispatcher_host.h" #include "chrome/browser/metrics/histogram_synchronizer.h" @@ -540,6 +541,10 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& msg) { #if defined(USE_TCMALLOC) IPC_MESSAGE_HANDLER(ViewHostMsg_RendererTcmalloc, OnRendererTcmalloc) #endif + IPC_MESSAGE_HANDLER(ViewHostMsg_EstablishGpuChannel, + OnEstablishGpuChannel) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_SynchronizeGpu, + OnSynchronizeGpu) IPC_MESSAGE_UNHANDLED( handled = false) IPC_END_MESSAGE_MAP_EX() @@ -1411,6 +1416,19 @@ void ResourceMessageFilter::OnRendererTcmalloc(base::ProcessId pid, } #endif +void ResourceMessageFilter::OnEstablishGpuChannel() { + GpuProcessHost::Get()->EstablishGpuChannel(id(), this); +} + +void ResourceMessageFilter::OnSynchronizeGpu(IPC::Message* reply) { + // We handle this message (and the other GPU process messages) here + // rather than handing the message to the GpuProcessHost for + // dispatch so that we can use the DELAY_REPLY macro to synthesize + // the reply message, and also send down a "this" pointer so that + // the GPU process host can send the reply later. + GpuProcessHost::Get()->Synchronize(reply, this); +} + void ResourceMessageFilter::OnGetExtensionMessageBundle( const std::string& extension_id, IPC::Message* reply_msg) { ChromeURLRequestContext* context = static_cast<ChromeURLRequestContext*>( diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h index 2abc4c0..a69fd78 100644 --- a/chrome/browser/renderer_host/resource_message_filter.h +++ b/chrome/browser/renderer_host/resource_message_filter.h @@ -328,6 +328,9 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter, void OnTranslateText(ViewHostMsg_TranslateTextParam param); + void OnEstablishGpuChannel(); + void OnSynchronizeGpu(IPC::Message* reply); + #if defined(USE_X11) void SendDelayedReply(IPC::Message* reply_msg); void DoOnGetScreenInfo(gfx::NativeViewId view, IPC::Message* reply_msg); diff --git a/chrome/browser/renderer_host/video_layer_proxy.cc b/chrome/browser/renderer_host/video_layer_proxy.cc index 1fdae24..3df1d25 100644 --- a/chrome/browser/renderer_host/video_layer_proxy.cc +++ b/chrome/browser/renderer_host/video_layer_proxy.cc @@ -4,23 +4,23 @@ #include "chrome/browser/renderer_host/video_layer_proxy.h" -#include "chrome/browser/gpu_process_host.h" +#include "chrome/browser/gpu_process_host_ui_shim.h" #include "chrome/browser/renderer_host/render_process_host.h" #include "chrome/common/gpu_messages.h" #include "gfx/rect.h" VideoLayerProxy::VideoLayerProxy(RenderWidgetHost* widget, const gfx::Size& size, - GpuProcessHost* process, + GpuProcessHostUIShim* process_shim, int32 routing_id) : VideoLayer(widget, size), - process_(process), + process_shim_(process_shim), routing_id_(routing_id) { - process_->AddRoute(routing_id_, this); + process_shim_->AddRoute(routing_id_, this); } VideoLayerProxy::~VideoLayerProxy() { - process_->RemoveRoute(routing_id_); + process_shim_->RemoveRoute(routing_id_); } void VideoLayerProxy::CopyTransportDIB(RenderProcessHost* process, @@ -33,7 +33,7 @@ void VideoLayerProxy::CopyTransportDIB(RenderProcessHost* process, process_id = process->GetHandle(); #endif - if (process_->Send(new GpuMsg_PaintToVideoLayer( + if (process_shim_->Send(new GpuMsg_PaintToVideoLayer( routing_id_, process_id, bitmap, bitmap_rect))) { } else { // TODO(scherkus): what to do ?!?! diff --git a/chrome/browser/renderer_host/video_layer_proxy.h b/chrome/browser/renderer_host/video_layer_proxy.h index 637525e..02b90ed 100644 --- a/chrome/browser/renderer_host/video_layer_proxy.h +++ b/chrome/browser/renderer_host/video_layer_proxy.h @@ -8,13 +8,13 @@ #include "chrome/browser/renderer_host/video_layer.h" #include "ipc/ipc_channel.h" -class GpuProcessHost; +class GpuProcessHostUIShim; // Proxies YUV video layer data to the GPU process for rendering. class VideoLayerProxy : public VideoLayer, public IPC::Channel::Listener { public: VideoLayerProxy(RenderWidgetHost* widget, const gfx::Size& size, - GpuProcessHost* process, int32 routing_id); + GpuProcessHostUIShim* process_shim, int32 routing_id); virtual ~VideoLayerProxy(); // VideoLayer implementation. @@ -32,7 +32,7 @@ class VideoLayerProxy : public VideoLayer, public IPC::Channel::Listener { void OnPaintToVideoLayerACK(); // GPU process receiving our proxied requests. - GpuProcessHost* process_; + GpuProcessHostUIShim* process_shim_; // IPC routing ID to use when communicating with the GPU process. int32 routing_id_; diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index cbd819bc..5335a20b 100755 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -1124,6 +1124,8 @@ 'browser/google_util.h', 'browser/gpu_process_host.cc', 'browser/gpu_process_host.h', + 'browser/gpu_process_host_ui_shim.cc', + 'browser/gpu_process_host_ui_shim.h', 'browser/gtk/about_chrome_dialog.cc', 'browser/gtk/about_chrome_dialog.h', 'browser/gtk/accelerators_gtk.cc', diff --git a/chrome/common/gpu_messages_internal.h b/chrome/common/gpu_messages_internal.h index 628671d..7c8f033 100644 --- a/chrome/common/gpu_messages_internal.h +++ b/chrome/common/gpu_messages_internal.h @@ -31,8 +31,7 @@ IPC_BEGIN_MESSAGES(Gpu) // completed. (This message can't be synchronous because the // GpuProcessHost uses an IPC::ChannelProxy, which sends all messages // asynchronously.) Results in a GpuHostMsg_SynchronizeReply. - IPC_MESSAGE_CONTROL1(GpuMsg_Synchronize, - int /* renderer_id */) + IPC_MESSAGE_CONTROL0(GpuMsg_Synchronize) IPC_MESSAGE_CONTROL2(GpuMsg_NewRenderWidgetHostView, GpuNativeWindowHandle, /* parent window */ @@ -100,8 +99,7 @@ IPC_BEGIN_MESSAGES(GpuHost) IPC::ChannelHandle /* channel_handle */) // Response to a GpuMsg_Synchronize message. - IPC_MESSAGE_CONTROL1(GpuHostMsg_SynchronizeReply, - int /* renderer_id */) + IPC_MESSAGE_CONTROL0(GpuHostMsg_SynchronizeReply) IPC_END_MESSAGES(GpuHost) diff --git a/chrome/common/sandbox_policy.cc b/chrome/common/sandbox_policy.cc index d0766e9..5153c4d 100644 --- a/chrome/common/sandbox_policy.cc +++ b/chrome/common/sandbox_policy.cc @@ -421,7 +421,8 @@ base::ProcessHandle StartProcessWithAccess(CommandLine* cmd_line, (type != ChildProcessInfo::NACL_BROKER_PROCESS) && !browser_command_line.HasSwitch(switches::kNoSandbox) && (type != ChildProcessInfo::PLUGIN_PROCESS || - browser_command_line.HasSwitch(switches::kSafePlugins)); + browser_command_line.HasSwitch(switches::kSafePlugins)) && + (type != ChildProcessInfo::GPU_PROCESS); #if !defined (GOOGLE_CHROME_BUILD) if (browser_command_line.HasSwitch(switches::kInProcessPlugins)) { // In process plugins won't work if the sandbox is enabled. diff --git a/chrome/gpu/gpu_channel.cc b/chrome/gpu/gpu_channel.cc index b2b5bf9..b775acf 100644 --- a/chrome/gpu/gpu_channel.cc +++ b/chrome/gpu/gpu_channel.cc @@ -91,8 +91,10 @@ void GpuChannel::OnChannelError() { #if defined(ENABLE_GPU) // Destroy all the stubs on this channel. - for (size_t i = 0; i < stubs_.size(); ++i) { - router_.RemoveRoute(stubs_[i]->route_id()); + for (StubMap::const_iterator iter = stubs_.begin(); + iter != stubs_.end(); + ++iter) { + router_.RemoveRoute(iter->second->route_id()); } stubs_.clear(); #endif diff --git a/chrome/gpu/gpu_thread.cc b/chrome/gpu/gpu_thread.cc index 5e096a5..c2c190e 100644 --- a/chrome/gpu/gpu_thread.cc +++ b/chrome/gpu/gpu_thread.cc @@ -81,8 +81,8 @@ void GpuThread::OnEstablishChannel(int renderer_id) { Send(new GpuHostMsg_ChannelEstablished(channel_handle)); } -void GpuThread::OnSynchronize(int renderer_id) { - Send(new GpuHostMsg_SynchronizeReply(renderer_id)); +void GpuThread::OnSynchronize() { + Send(new GpuHostMsg_SynchronizeReply()); } void GpuThread::OnNewRenderWidgetHostView(GpuNativeWindowHandle parent_window, diff --git a/chrome/gpu/gpu_thread.h b/chrome/gpu/gpu_thread.h index bc06051..fdef70b 100644 --- a/chrome/gpu/gpu_thread.h +++ b/chrome/gpu/gpu_thread.h @@ -36,7 +36,7 @@ class GpuThread : public ChildThread { // Message handlers. void OnEstablishChannel(int renderer_id); - void OnSynchronize(int renderer_id); + void OnSynchronize(); void OnNewRenderWidgetHostView(GpuNativeWindowHandle parent_window, int32 routing_id); diff --git a/chrome/renderer/gpu_channel_host.cc b/chrome/renderer/gpu_channel_host.cc index 8d2cdd9..3562c0b 100644 --- a/chrome/renderer/gpu_channel_host.cc +++ b/chrome/renderer/gpu_channel_host.cc @@ -44,7 +44,6 @@ void GpuChannelHost::OnChannelError() { // OpenGL as a lost context. for (ProxyMap::iterator iter = proxies_.begin(); iter != proxies_.end(); iter++) { - proxies_.erase(iter->first); router_.RemoveRoute(iter->first); iter->second->OnChannelError(); } diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc index aff8fa6..81636c7 100644 --- a/chrome/renderer/render_thread.cc +++ b/chrome/renderer/render_thread.cc @@ -687,8 +687,10 @@ void RenderThread::UpdateActiveExtensions() { void RenderThread::EstablishGpuChannel() { if (gpu_channel_.get()) { - // Do nothing if we are already establishing GPU channel. - if (gpu_channel_->state() == GpuChannelHost::UNCONNECTED) + // Do nothing if we already have a GPU channel or are already + // establishing one. + if (gpu_channel_->state() == GpuChannelHost::UNCONNECTED || + gpu_channel_->state() == GpuChannelHost::CONNECTED) return; // Recreate the channel if it has been lost. @@ -704,8 +706,16 @@ void RenderThread::EstablishGpuChannel() { } GpuChannelHost* RenderThread::EstablishGpuChannelSync() { - EstablishGpuChannel(); - Send(new ViewHostMsg_SynchronizeGpu()); + // We may need to retry the connection establishment if an existing + // connection has gone bad, which will not be detected in + // EstablishGpuChannel since we do not send duplicate + // ViewHostMsg_EstablishGpuChannel messages -- doing so breaks the + // preexisting connection in bad ways. + bool retry = true; + for (int i = 0; i < 2 && retry; ++i) { + EstablishGpuChannel(); + retry = !Send(new ViewHostMsg_SynchronizeGpu()); + } // TODO(kbr): the GPU channel is still in the unconnected state at this point. // Need to figure out whether it is really safe to return it. return gpu_channel_.get(); |