diff options
author | bbudge@chromium.org <bbudge@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-07 19:05:03 +0000 |
---|---|---|
committer | bbudge@chromium.org <bbudge@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-07 19:05:03 +0000 |
commit | 0c719374f8228f5615005cdd9fa4fc7cbc7554f2 (patch) | |
tree | de64ef9fe5e711ba6553935e933d3015adc3fafd /content/browser | |
parent | c24c9e0439b57dc1f6b785255bbac78aaa31fd2d (diff) | |
download | chromium_src-0c719374f8228f5615005cdd9fa4fc7cbc7554f2.zip chromium_src-0c719374f8228f5615005cdd9fa4fc7cbc7554f2.tar.gz chromium_src-0c719374f8228f5615005cdd9fa4fc7cbc7554f2.tar.bz2 |
Add support for external out-of-process PPAPI plugins in the browser.
- Modifies content::BrowserPpapiHostImpl so it's not ref-counted.
- Adds a public content API method, BrowserPpapiHost::CreateExternalPluginProcess
which allows the embedder to associate a browser ppapi host with a plugin process.
- Adds a public content API method, ContentBrowserClient::GetExternalBrowserPpapiHost,
so content can track instance creation and deletion for external plugins (e.g. NaCl)
- Removes the content API method EnablePepperSupportForChannel. This is now done
when creating the BrowserPpapiHost.
BUG=116317
TEST=none
Review URL: https://chromiumcodereview.appspot.com/11368019
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@166480 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser')
9 files changed, 114 insertions, 66 deletions
diff --git a/content/browser/pepper_helper.cc b/content/browser/pepper_helper.cc deleted file mode 100644 index 5838b21..0000000 --- a/content/browser/pepper_helper.cc +++ /dev/null @@ -1,24 +0,0 @@ -// 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/public/browser/pepper_helper.h" - -#include "content/browser/renderer_host/pepper/pepper_message_filter.h" -#include "ipc/ipc_channel_proxy.h" -#include "net/base/host_resolver.h" - -namespace content { - -void EnablePepperSupportForChannel(IPC::ChannelProxy* channel, - net::HostResolver* host_resolver, - int process_id, - int render_view_id) { - channel->AddFilter(new PepperMessageFilter(PepperMessageFilter::NACL, - host_resolver, - process_id, - render_view_id)); -} - -} // namespace content - diff --git a/content/browser/ppapi_plugin_process_host.cc b/content/browser/ppapi_plugin_process_host.cc index 07a42b6..5214527 100644 --- a/content/browser/ppapi_plugin_process_host.cc +++ b/content/browser/ppapi_plugin_process_host.cc @@ -171,16 +171,16 @@ PpapiPluginProcessHost::PpapiPluginProcessHost( filter_ = new PepperMessageFilter(PepperMessageFilter::PLUGIN, host_resolver); - host_impl_ = new BrowserPpapiHostImpl(this, permissions_); + host_impl_.reset(new BrowserPpapiHostImpl(this, permissions_)); file_filter_ = new PepperTrustedFileMessageFilter( process_->GetData().id, info.name, profile_data_directory); process_->GetHost()->AddFilter(filter_.get()); process_->GetHost()->AddFilter(file_filter_.get()); - process_->GetHost()->AddFilter(host_impl_.get()); + process_->GetHost()->AddFilter(host_impl_->message_filter()); - GetContentClient()->browser()->DidCreatePpapiPlugin(host_impl_); + GetContentClient()->browser()->DidCreatePpapiPlugin(host_impl_.get()); } PpapiPluginProcessHost::PpapiPluginProcessHost() @@ -189,7 +189,7 @@ PpapiPluginProcessHost::PpapiPluginProcessHost() PROCESS_TYPE_PPAPI_BROKER, this)); ppapi::PpapiPermissions permissions; // No permissions. - host_impl_ = new BrowserPpapiHostImpl(this, permissions); + host_impl_.reset(new BrowserPpapiHostImpl(this, permissions)); } bool PpapiPluginProcessHost::Init(const PepperPluginInfo& info) { diff --git a/content/browser/ppapi_plugin_process_host.h b/content/browser/ppapi_plugin_process_host.h index e472c11..cbab68c 100644 --- a/content/browser/ppapi_plugin_process_host.h +++ b/content/browser/ppapi_plugin_process_host.h @@ -138,7 +138,7 @@ class PpapiPluginProcessHost : public BrowserChildProcessHostDelegate, scoped_refptr<PepperMessageFilter> filter_; ppapi::PpapiPermissions permissions_; - scoped_refptr<BrowserPpapiHostImpl> host_impl_; + scoped_ptr<BrowserPpapiHostImpl> host_impl_; // Handles filesystem requests from flash plugins. May be NULL. scoped_refptr<PepperFileMessageFilter> file_filter_; diff --git a/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc b/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc index dedd51e..2cb3522 100644 --- a/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc +++ b/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h" +#include "content/browser/renderer_host/pepper/pepper_message_filter.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_view_host.h" @@ -10,28 +11,41 @@ namespace content { +// static +BrowserPpapiHost* BrowserPpapiHost::CreateExternalPluginProcess( + IPC::Sender* sender, + ppapi::PpapiPermissions permissions, + base::ProcessHandle plugin_child_process, + IPC::ChannelProxy* channel, + net::HostResolver* host_resolver, + int render_process_id, + int render_view_id) { + BrowserPpapiHostImpl* browser_ppapi_host = + new BrowserPpapiHostImpl(sender, permissions); + browser_ppapi_host->set_plugin_process_handle(plugin_child_process); + + channel->AddFilter( + new PepperMessageFilter(PepperMessageFilter::NACL, + host_resolver, + render_process_id, + render_view_id)); + + return browser_ppapi_host; +} + BrowserPpapiHostImpl::BrowserPpapiHostImpl( IPC::Sender* sender, const ppapi::PpapiPermissions& permissions) : ppapi_host_(sender, permissions), plugin_process_handle_(base::kNullProcessHandle) { + message_filter_ = new HostMessageFilter(&ppapi_host_); ppapi_host_.AddHostFactoryFilter(scoped_ptr<ppapi::host::HostFactory>( new ContentBrowserPepperHostFactory(this))); } BrowserPpapiHostImpl::~BrowserPpapiHostImpl() { -} - -bool BrowserPpapiHostImpl::OnMessageReceived(const IPC::Message& msg) { - /* TODO(brettw) when we add messages, here, the code should look like this: - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(BrowserPpapiHostImpl, msg) - // Add necessary message handlers here. - IPC_MESSAGE_UNHANDLED(handled = ppapi_host_.OnMessageReceived(msg)) - IPC_END_MESSAGE_MAP(); - return handled; - */ - return ppapi_host_.OnMessageReceived(msg); + // Notify the filter so it won't foward messages to us. + message_filter_->OnHostDestroyed(); } ppapi::host::PpapiHost* BrowserPpapiHostImpl::GetPpapiHost() { @@ -84,4 +98,26 @@ void BrowserPpapiHostImpl::DeleteInstanceForView(PP_Instance instance) { instance_to_view_.erase(found); } +bool BrowserPpapiHostImpl::HostMessageFilter::OnMessageReceived( + const IPC::Message& msg) { + // Don't forward messages if our owner object has been destroyed. + if (!ppapi_host_) + return false; + + /* TODO(brettw) when we add messages, here, the code should look like this: + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(BrowserPpapiHostImpl, msg) + // Add necessary message handlers here. + IPC_MESSAGE_UNHANDLED(handled = ppapi_host_->OnMessageReceived(msg)) + IPC_END_MESSAGE_MAP(); + return handled; + */ + return ppapi_host_->OnMessageReceived(msg); +} + +void BrowserPpapiHostImpl::HostMessageFilter::OnHostDestroyed() { + DCHECK(ppapi_host_); + ppapi_host_ = NULL; +} + } // namespace content diff --git a/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h b/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h index d743d15..bee35a6 100644 --- a/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h +++ b/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h @@ -15,24 +15,16 @@ #include "ipc/ipc_channel_proxy.h" #include "ppapi/host/ppapi_host.h" -namespace IPC { -class Sender; -} - namespace content { -class CONTENT_EXPORT BrowserPpapiHostImpl - : public BrowserPpapiHost, - public IPC::ChannelProxy::MessageFilter { +class CONTENT_EXPORT BrowserPpapiHostImpl : public BrowserPpapiHost { public: // The creator is responsible for calling set_plugin_process_handle as soon // as it is known (we start the process asynchronously so it won't be known // when this object is created). BrowserPpapiHostImpl(IPC::Sender* sender, const ppapi::PpapiPermissions& permissions); - - // IPC::ChannelProxy::MessageFilter. - virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE; + virtual ~BrowserPpapiHostImpl(); // BrowserPpapiHost. virtual ppapi::host::PpapiHost* GetPpapiHost() OVERRIDE; @@ -54,6 +46,10 @@ class CONTENT_EXPORT BrowserPpapiHostImpl int render_view_id); void DeleteInstanceForView(PP_Instance instance); + scoped_refptr<IPC::ChannelProxy::MessageFilter> message_filter() { + return message_filter_; + } + private: friend class BrowserPpapiHostTest; @@ -63,7 +59,23 @@ class CONTENT_EXPORT BrowserPpapiHostImpl }; typedef std::map<PP_Instance, RenderViewIDs> InstanceToViewMap; - virtual ~BrowserPpapiHostImpl(); + // Implementing MessageFilter on BrowserPpapiHostImpl makes it ref-counted, + // preventing us from returning these to embedders without holding a + // reference. To avoid that, define a message filter object. + class HostMessageFilter : public IPC::ChannelProxy::MessageFilter { + public: + explicit HostMessageFilter(ppapi::host::PpapiHost* ppapi_host) + : ppapi_host_(ppapi_host) {} + // IPC::ChannelProxy::MessageFilter. + virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE; + + void OnHostDestroyed(); + + private: + virtual ~HostMessageFilter() {} + + ppapi::host::PpapiHost* ppapi_host_; + }; ppapi::host::PpapiHost ppapi_host_; base::ProcessHandle plugin_process_handle_; @@ -72,6 +84,8 @@ class CONTENT_EXPORT BrowserPpapiHostImpl // RenderProcess/RenderView IDs. InstanceToViewMap instance_to_view_; + scoped_refptr<HostMessageFilter> message_filter_; + DISALLOW_COPY_AND_ASSIGN(BrowserPpapiHostImpl); }; diff --git a/content/browser/renderer_host/pepper/browser_ppapi_host_test.cc b/content/browser/renderer_host/pepper/browser_ppapi_host_test.cc index 42fc6c0..941782c 100644 --- a/content/browser/renderer_host/pepper/browser_ppapi_host_test.cc +++ b/content/browser/renderer_host/pepper/browser_ppapi_host_test.cc @@ -10,10 +10,10 @@ namespace content { BrowserPpapiHostTest::BrowserPpapiHostTest() - : sink_(), - ppapi_host_(new BrowserPpapiHostImpl( - &sink_, - ppapi::PpapiPermissions::AllPermissions())) { + : sink_() { + ppapi_host_.reset(new BrowserPpapiHostImpl( + &sink_, + ppapi::PpapiPermissions::AllPermissions())); ppapi_host_->set_plugin_process_handle(base::GetCurrentProcessHandle()); } @@ -21,7 +21,7 @@ BrowserPpapiHostTest::~BrowserPpapiHostTest() { } BrowserPpapiHost* BrowserPpapiHostTest::GetBrowserPpapiHost() { - return ppapi_host_; + return ppapi_host_.get(); } } // namespace content diff --git a/content/browser/renderer_host/pepper/browser_ppapi_host_test.h b/content/browser/renderer_host/pepper/browser_ppapi_host_test.h index d9e73a1..3f375ee 100644 --- a/content/browser/renderer_host/pepper/browser_ppapi_host_test.h +++ b/content/browser/renderer_host/pepper/browser_ppapi_host_test.h @@ -27,7 +27,7 @@ class BrowserPpapiHostTest { private: ppapi::proxy::ResourceMessageTestSink sink_; - scoped_refptr<BrowserPpapiHostImpl> ppapi_host_; + scoped_ptr<BrowserPpapiHostImpl> ppapi_host_; DISALLOW_COPY_AND_ASSIGN(BrowserPpapiHostTest); }; diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc index be51239..7a677d1 100644 --- a/content/browser/renderer_host/render_message_filter.cc +++ b/content/browser/renderer_host/render_message_filter.cc @@ -681,22 +681,42 @@ void RenderMessageFilter::OnOpenChannelToPepperPlugin( void RenderMessageFilter::OnDidCreateOutOfProcessPepperInstance( int plugin_child_id, int32 pp_instance, - int render_view_id) { + int render_view_id, + bool is_external) { // It's important that we supply the render process ID ourselves based on the // channel the message arrived on. We use the // PP_Instance -> (process id, view id) // mapping to decide how to handle messages received from the (untrusted) // plugin, so an exploited renderer must not be able to insert fake mappings // that may allow it access to other render processes. - PpapiPluginProcessHost::DidCreateOutOfProcessInstance( - plugin_child_id, pp_instance, render_process_id_, render_view_id); + if (is_external) { + // We provide the BrowserPpapiHost to the embedder, so it's safe to cast. + BrowserPpapiHostImpl* host = static_cast<BrowserPpapiHostImpl*>( + GetContentClient()->browser()->GetExternalBrowserPpapiHost( + plugin_child_id)); + if (host) + host->AddInstanceForView(pp_instance, render_process_id_, render_view_id); + } else { + PpapiPluginProcessHost::DidCreateOutOfProcessInstance( + plugin_child_id, pp_instance, render_process_id_, render_view_id); + } } void RenderMessageFilter::OnDidDeleteOutOfProcessPepperInstance( int plugin_child_id, - int32 pp_instance) { - PpapiPluginProcessHost::DidDeleteOutOfProcessInstance( - plugin_child_id, pp_instance); + int32 pp_instance, + bool is_external) { + if (is_external) { + // We provide the BrowserPpapiHost to the embedder, so it's safe to cast. + BrowserPpapiHostImpl* host = static_cast<BrowserPpapiHostImpl*>( + GetContentClient()->browser()->GetExternalBrowserPpapiHost( + plugin_child_id)); + if (host) + host->DeleteInstanceForView(pp_instance); + } else { + PpapiPluginProcessHost::DidDeleteOutOfProcessInstance( + plugin_child_id, pp_instance); + } } void RenderMessageFilter::OnOpenChannelToPpapiBroker(int routing_id, diff --git a/content/browser/renderer_host/render_message_filter.h b/content/browser/renderer_host/render_message_filter.h index c7c9071e..a4f9174 100644 --- a/content/browser/renderer_host/render_message_filter.h +++ b/content/browser/renderer_host/render_message_filter.h @@ -162,9 +162,11 @@ class RenderMessageFilter : public BrowserMessageFilter { IPC::Message* reply_msg); void OnDidCreateOutOfProcessPepperInstance(int plugin_child_id, int32 pp_instance, - int render_view_id); + int render_view_id, + bool is_external); void OnDidDeleteOutOfProcessPepperInstance(int plugin_child_id, - int32 pp_instance); + int32 pp_instance, + bool is_external); void OnOpenChannelToPpapiBroker(int routing_id, int request_id, const FilePath& path); |