diff options
-rw-r--r-- | content/browser/gpu/gpu_process_host.cc | 67 | ||||
-rw-r--r-- | content/browser/gpu/gpu_process_host.h | 18 | ||||
-rw-r--r-- | content/common/gpu/gpu_command_buffer_stub.cc | 19 | ||||
-rw-r--r-- | content/common/gpu/gpu_messages.h | 11 | ||||
-rw-r--r-- | content/common/webkitplatformsupport_impl.cc | 6 |
5 files changed, 117 insertions, 4 deletions
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc index 8de0164..633f6d3 100644 --- a/content/browser/gpu/gpu_process_host.cc +++ b/content/browser/gpu/gpu_process_host.cc @@ -429,6 +429,11 @@ GpuProcessHost::~GpuProcessHost() { if (g_gpu_process_hosts[kind_] == this) g_gpu_process_hosts[kind_] = NULL; + // If there are any remaining offscreen contexts at the point the + // GPU process exits, assume something went wrong, and block their + // URLs from accessing client 3D APIs without prompting. + BlockLiveOffscreenContexts(); + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(&GpuProcessHostUIShim::Destroy, host_id_)); @@ -507,6 +512,11 @@ bool GpuProcessHost::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(GpuHostMsg_CommandBufferCreated, OnCommandBufferCreated) IPC_MESSAGE_HANDLER(GpuHostMsg_DestroyCommandBuffer, OnDestroyCommandBuffer) IPC_MESSAGE_HANDLER(GpuHostMsg_ImageCreated, OnImageCreated) + IPC_MESSAGE_HANDLER(GpuHostMsg_DidCreateOffscreenContext, + OnDidCreateOffscreenContext) + IPC_MESSAGE_HANDLER(GpuHostMsg_DidLoseContext, OnDidLoseContext) + IPC_MESSAGE_HANDLER(GpuHostMsg_DidDestroyOffscreenContext, + OnDidDestroyOffscreenContext) #if defined(OS_MACOSX) IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceBuffersSwapped, OnAcceleratedSurfaceBuffersSwapped) @@ -686,6 +696,54 @@ void GpuProcessHost::OnImageCreated(const gfx::Size size) { } } +void GpuProcessHost::OnDidCreateOffscreenContext( + const GURL& url) { + urls_with_live_offscreen_contexts_.insert(url); +} + +void GpuProcessHost::OnDidLoseContext(bool offscreen, + gpu::error::ContextLostReason reason, + const GURL& url) { + // TODO(kbr): would be nice to see the "offscreen" flag too. + TRACE_EVENT2("gpu", "GpuProcessHost::OnDidLoseContext", + "reason", reason, + "url", + url.possibly_invalid_spec()); + + if (!offscreen || url.is_empty()) { + // Assume that the loss of the compositor's or accelerated canvas' + // context is a serious event and blame the loss on all live + // offscreen contexts. This more robustly handles situations where + // the GPU process may not actually detect the context loss in the + // offscreen context. + BlockLiveOffscreenContexts(); + return; + } + + // Initialization only needed because compiler is stupid. + GpuDataManagerImpl::DomainGuilt guilt = + GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN; + + switch (reason) { + case gpu::error::kGuilty: + guilt = GpuDataManagerImpl::DOMAIN_GUILT_KNOWN; + break; + case gpu::error::kUnknown: + guilt = GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN; + break; + case gpu::error::kInnocent: + return; + } + + GpuDataManagerImpl::GetInstance()->BlockDomainFrom3DAPIs( + url, guilt); +} + +void GpuProcessHost::OnDidDestroyOffscreenContext( + const GURL& url) { + urls_with_live_offscreen_contexts_.erase(url); +} + #if defined(OS_MACOSX) void GpuProcessHost::OnAcceleratedSurfaceBuffersSwapped( const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params) { @@ -988,4 +1046,13 @@ void GpuProcessHost::CreateImageError( callback.Run(size); } +void GpuProcessHost::BlockLiveOffscreenContexts() { + for (std::multiset<GURL>::iterator iter = + urls_with_live_offscreen_contexts_.begin(); + iter != urls_with_live_offscreen_contexts_.end(); ++iter) { + GpuDataManagerImpl::GetInstance()->BlockDomainFrom3DAPIs( + *iter, GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN); + } +} + } // namespace content diff --git a/content/browser/gpu/gpu_process_host.h b/content/browser/gpu/gpu_process_host.h index ab74fed..7424963 100644 --- a/content/browser/gpu/gpu_process_host.h +++ b/content/browser/gpu/gpu_process_host.h @@ -7,6 +7,7 @@ #include <map> #include <queue> +#include <set> #include <string> #include "base/callback.h" @@ -18,6 +19,8 @@ #include "content/public/browser/browser_child_process_host_delegate.h" #include "content/public/browser/gpu_data_manager.h" #include "content/public/common/gpu_info.h" +#include "googleurl/src/gurl.h" +#include "gpu/command_buffer/common/constants.h" #include "ipc/ipc_channel_proxy.h" #include "ipc/ipc_sender.h" #include "ui/gfx/native_widget_types.h" @@ -141,7 +144,11 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate, void OnCommandBufferCreated(const int32 route_id); void OnDestroyCommandBuffer(int32 surface_id); void OnImageCreated(const gfx::Size size); - + void OnDidCreateOffscreenContext(const GURL& url); + void OnDidLoseContext(bool offscreen, + gpu::error::ContextLostReason reason, + const GURL& url); + void OnDidDestroyOffscreenContext(const GURL& url); #if defined(OS_MACOSX) void OnAcceleratedSurfaceBuffersSwapped( const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params); @@ -170,6 +177,8 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate, void CreateImageError(const CreateImageCallback& callback, const gfx::Size size); + void BlockLiveOffscreenContexts(); + // The serial number of the GpuProcessHost / GpuProcessHostUIShim pair. int host_id_; @@ -226,6 +235,13 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate, scoped_ptr<BrowserChildProcessHostImpl> process_; + // Track the URLs of the pages which have live offscreen contexts, + // assumed to be associated with untrusted content such as WebGL. + // For best robustness, when any context lost notification is + // received, assume all of these URLs are guilty, and block + // automatic execution of 3D content from those domains. + std::multiset<GURL> urls_with_live_offscreen_contexts_; + DISALLOW_COPY_AND_ASSIGN(GpuProcessHost); }; diff --git a/content/common/gpu/gpu_command_buffer_stub.cc b/content/common/gpu/gpu_command_buffer_stub.cc index 61b1822..e2f1e15 100644 --- a/content/common/gpu/gpu_command_buffer_stub.cc +++ b/content/common/gpu/gpu_command_buffer_stub.cc @@ -301,6 +301,12 @@ bool GpuCommandBufferStub::MakeCurrent() { } void GpuCommandBufferStub::Destroy() { + if (handle_.is_null() && !active_url_.is_empty()) { + GpuChannelManager* gpu_channel_manager = channel_->gpu_channel_manager(); + gpu_channel_manager->Send(new GpuHostMsg_DidDestroyOffscreenContext( + active_url_)); + } + GetMemoryManager()->RemoveClient(this); while (!sync_points_.empty()) @@ -507,6 +513,12 @@ void GpuCommandBufferStub::OnInitialize( GpuCommandBufferMsg_Initialize::WriteReplyParams(reply_message, true); Send(reply_message); + + if (handle_.is_null() && !active_url_.is_empty()) { + GpuChannelManager* gpu_channel_manager = channel_->gpu_channel_manager(); + gpu_channel_manager->Send(new GpuHostMsg_DidCreateOffscreenContext( + active_url_)); + } } void GpuCommandBufferStub::OnSetGetBuffer( @@ -583,6 +595,13 @@ void GpuCommandBufferStub::OnParseError() { route_id_, state.context_lost_reason); msg->set_unblock(true); Send(msg); + + // Tell the browser about this context loss as well, so it can + // determine whether client APIs like WebGL need to be immediately + // blocked from automatically running. + GpuChannelManager* gpu_channel_manager = channel_->gpu_channel_manager(); + gpu_channel_manager->Send(new GpuHostMsg_DidLoseContext( + handle_.is_null(), state.context_lost_reason, active_url_)); } void GpuCommandBufferStub::OnGetStateFast(IPC::Message* reply_message) { diff --git a/content/common/gpu/gpu_messages.h b/content/common/gpu/gpu_messages.h index 11278f3..3f3cf67 100644 --- a/content/common/gpu/gpu_messages.h +++ b/content/common/gpu/gpu_messages.h @@ -400,6 +400,17 @@ IPC_MESSAGE_CONTROL3(GpuHostMsg_UpdateVSyncParameters, base::TimeTicks /* timebase */, base::TimeDelta /* interval */) +IPC_MESSAGE_CONTROL1(GpuHostMsg_DidCreateOffscreenContext, + GURL /* url */) + +IPC_MESSAGE_CONTROL3(GpuHostMsg_DidLoseContext, + bool /* offscreen */, + gpu::error::ContextLostReason /* reason */, + GURL /* url */) + +IPC_MESSAGE_CONTROL1(GpuHostMsg_DidDestroyOffscreenContext, + GURL /* url */) + //------------------------------------------------------------------------------ // GPU Channel Messages // These are messages from a renderer process to the GPU process. diff --git a/content/common/webkitplatformsupport_impl.cc b/content/common/webkitplatformsupport_impl.cc index 991dc1e..e25c267 100644 --- a/content/common/webkitplatformsupport_impl.cc +++ b/content/common/webkitplatformsupport_impl.cc @@ -9,6 +9,7 @@ #include "content/common/webkitplatformsupport_impl.h" #include "content/public/common/content_client.h" #include "content/public/common/content_switches.h" +#include "googleurl/src/gurl.h" #include "webkit/gpu/webgraphicscontext3d_in_process_impl.h" namespace content { @@ -68,10 +69,9 @@ WebKitPlatformSupportImpl::createOffscreenGraphicsContext3D( return webkit::gpu::WebGraphicsContext3DInProcessImpl::CreateForWebView( attributes, false); } else { - // Intentionally blank URL provided for offscreen contexts -- blank URLs are - // ignored in the GPU process for crash reporting. return WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext( - GetGpuChannelHostFactory(), attributes, GURL()); + GetGpuChannelHostFactory(), attributes, + GURL(attributes.topDocumentURL)); } } |