diff options
author | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-15 05:08:38 +0000 |
---|---|---|
committer | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-15 05:08:38 +0000 |
commit | b7631cc577c480fa04d0e7f1d4d1b9ffc60b2cdc (patch) | |
tree | 7653d8ec53c9f154be07bc7240ad54d0f0f682e6 | |
parent | a78f03cf0fb7e2053099bcc4b73d558c9d653ed1 (diff) | |
download | chromium_src-b7631cc577c480fa04d0e7f1d4d1b9ffc60b2cdc.zip chromium_src-b7631cc577c480fa04d0e7f1d4d1b9ffc60b2cdc.tar.gz chromium_src-b7631cc577c480fa04d0e7f1d4d1b9ffc60b2cdc.tar.bz2 |
Convert the async device ID getter to a chrome resource host
Review URL: https://codereview.chromium.org/10909138
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@156989 0039d316-1c4b-4281-b951-d872f2087c98
42 files changed, 775 insertions, 227 deletions
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS index 903a8f1..b57c3f5 100644 --- a/chrome/browser/DEPS +++ b/chrome/browser/DEPS @@ -13,6 +13,7 @@ include_rules = [ "+media/base", # For media switches "+policy", # For generated headers and source "+ppapi/c", # For various types. + "+ppapi/host", "+ppapi/proxy", "+ppapi/shared_impl/api_id.h", # Defines some types that are marshalled over IPC. diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 0540dadf..15cc0af 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc @@ -56,6 +56,7 @@ #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/renderer_host/chrome_render_message_filter.h" #include "chrome/browser/renderer_host/chrome_render_view_host_observer.h" +#include "chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h" #include "chrome/browser/renderer_host/plugin_info_message_filter.h" #include "chrome/browser/search_engines/search_provider_install_state_message_filter.h" #include "chrome/browser/speech/chrome_speech_recognition_manager_delegate.h" @@ -83,6 +84,7 @@ #include "chrome/common/url_constants.h" #include "content/public/browser/browser_child_process_host.h" #include "content/public/browser/browser_main_parts.h" +#include "content/public/browser/browser_ppapi_host.h" #include "content/public/browser/browser_url_handler.h" #include "content/public/browser/child_process_security_policy.h" #include "content/public/browser/render_process_host.h" @@ -99,6 +101,7 @@ #include "net/base/ssl_cert_request_info.h" #include "net/cookies/canonical_cookie.h" #include "net/cookies/cookie_options.h" +#include "ppapi/host/ppapi_host.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "webkit/glue/webpreferences.h" @@ -1601,6 +1604,13 @@ std::string ChromeContentBrowserClient::GetDefaultDownloadName() { return l10n_util::GetStringUTF8(IDS_DEFAULT_DOWNLOAD_FILENAME); } +void ChromeContentBrowserClient::DidCreatePpapiPlugin( + content::BrowserPpapiHost* browser_host) { + browser_host->GetPpapiHost()->AddHostFactoryFilter( + scoped_ptr<ppapi::host::HostFactory>( + new ChromeBrowserPepperHostFactory(browser_host))); +} + bool ChromeContentBrowserClient::AllowPepperSocketAPI( content::BrowserContext* browser_context, const GURL& url) { if (!url.is_valid()) diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h index aa20b04..6f0fad4 100644 --- a/chrome/browser/chrome_content_browser_client.h +++ b/chrome/browser/chrome_content_browser_client.h @@ -198,6 +198,8 @@ class ChromeContentBrowserClient : public content::ContentBrowserClient { virtual void ClearCookies(content::RenderViewHost* rvh) OVERRIDE; virtual FilePath GetDefaultDownloadDirectory() OVERRIDE; virtual std::string GetDefaultDownloadName() OVERRIDE; + virtual void DidCreatePpapiPlugin( + content::BrowserPpapiHost* browser_host) OVERRIDE; virtual bool AllowPepperSocketAPI(content::BrowserContext* browser_context, const GURL& url) OVERRIDE; virtual bool AllowPepperPrivateFileAPI() OVERRIDE; diff --git a/chrome/browser/renderer_host/pepper/DEPS b/chrome/browser/renderer_host/pepper/DEPS new file mode 100644 index 0000000..4b73f76 --- /dev/null +++ b/chrome/browser/renderer_host/pepper/DEPS @@ -0,0 +1,5 @@ +include_rules = [ + # ppapi/host and ppapi/proxy are already added at a higher level DEPS file. + "+ppapi/shared_impl", +] + diff --git a/chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.cc b/chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.cc new file mode 100644 index 0000000..5aead89 --- /dev/null +++ b/chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.cc @@ -0,0 +1,49 @@ +// 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 "chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h" + +#include "chrome/browser/renderer_host/pepper/pepper_flash_device_id_host.h" +#include "content/public/browser/browser_ppapi_host.h" +#include "ppapi/host/ppapi_host.h" +#include "ppapi/host/resource_host.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/shared_impl/ppapi_permissions.h" + +using ppapi::host::ResourceHost; + +namespace chrome { + +ChromeBrowserPepperHostFactory::ChromeBrowserPepperHostFactory( + content::BrowserPpapiHost* host) + : host_(host) { +} + +ChromeBrowserPepperHostFactory::~ChromeBrowserPepperHostFactory() { +} + +scoped_ptr<ResourceHost> ChromeBrowserPepperHostFactory::CreateResourceHost( + ppapi::host::PpapiHost* host, + const ppapi::proxy::ResourceMessageCallParams& params, + PP_Instance instance, + const IPC::Message& message) { + DCHECK(host == host_->GetPpapiHost()); + + // Make sure the plugin is giving us a valid instance for this resource. + if (!host_->IsValidInstance(instance)) + return scoped_ptr<ResourceHost>(); + + // Private interfaces. + if (host_->GetPpapiHost()->permissions().HasPermission( + ppapi::PERMISSION_PRIVATE)) { + switch (message.type()) { + case PpapiHostMsg_FlashDeviceID_Create::ID: + return scoped_ptr<ResourceHost>(new PepperFlashDeviceIDHost( + host_, instance, params.pp_resource())); + } + } + return scoped_ptr<ResourceHost>(); +} + +} // namespace chrome diff --git a/chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h b/chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h new file mode 100644 index 0000000..e051c1d --- /dev/null +++ b/chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h @@ -0,0 +1,38 @@ +// 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. + +#ifndef CHROME_BROWSER_RENDERER_HOST_PEPPER_CHROME_BROWSER_PEPPER_HOST_FACTORY_H_ +#define CHROME_BROWSER_RENDERER_HOST_PEPPER_CHROME_BROWSER_PEPPER_HOST_FACTORY_H_ + +#include "base/compiler_specific.h" +#include "ppapi/host/host_factory.h" + +namespace content { +class BrowserPpapiHost; +} // namespace content + +namespace chrome { + +class ChromeBrowserPepperHostFactory : public ppapi::host::HostFactory { + public: + // Non-owning pointer to the filter must outlive this class. + explicit ChromeBrowserPepperHostFactory(content::BrowserPpapiHost* host); + virtual ~ChromeBrowserPepperHostFactory(); + + virtual scoped_ptr<ppapi::host::ResourceHost> CreateResourceHost( + ppapi::host::PpapiHost* host, + const ppapi::proxy::ResourceMessageCallParams& params, + PP_Instance instance, + const IPC::Message& message) OVERRIDE; + + private: + // Non-owning pointer. + content::BrowserPpapiHost* host_; + + DISALLOW_COPY_AND_ASSIGN(ChromeBrowserPepperHostFactory); +}; + +} // namespace chrome + +#endif // CHROME_BROWSER_RENDERER_HOST_PEPPER_CHROME_BROWSER_PEPPER_HOST_FACTORY_H_ diff --git a/chrome/browser/renderer_host/pepper/pepper_flash_device_id_host.cc b/chrome/browser/renderer_host/pepper/pepper_flash_device_id_host.cc new file mode 100644 index 0000000..b355322 --- /dev/null +++ b/chrome/browser/renderer_host/pepper/pepper_flash_device_id_host.cc @@ -0,0 +1,150 @@ +// 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 "chrome/browser/renderer_host/pepper/pepper_flash_device_id_host.h" + +#include "base/bind.h" +#include "base/compiler_specific.h" +#include "base/file_util.h" +#include "base/logging.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/browser_ppapi_host.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/render_view_host.h" +#include "ppapi/c/pp_errors.h" +#include "ppapi/host/dispatch_host_message.h" +#include "ppapi/host/host_message_context.h" +#include "ppapi/host/ppapi_host.h" +#include "ppapi/proxy/ppapi_messages.h" + +using content::BrowserPpapiHost; +using content::BrowserThread; + +namespace chrome { + +namespace { + +// The path to the file containing the DRM ID. +// It is mirrored from +// chrome/browser/chromeos/system/drm_settings.cc +const char kDRMIdentifierFile[] = "Pepper DRM ID.0"; + +} // namespace + +// PepperFlashDeviceIDHost::Fetcher -------------------------------------------- + +PepperFlashDeviceIDHost::Fetcher::Fetcher( + const base::WeakPtr<PepperFlashDeviceIDHost>& host) + : host_(host) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); +} + +PepperFlashDeviceIDHost::Fetcher::~Fetcher() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); +} + +void PepperFlashDeviceIDHost::Fetcher::Start(BrowserPpapiHost* browser_host) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + + int process_id = 0; + int view_id = 0; + browser_host->GetRenderViewIDsForInstance(host_->pp_instance(), + &process_id, + &view_id); + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&PepperFlashDeviceIDHost::Fetcher::GetFilePathOnUIThread, + this, process_id, view_id)); +} + +void PepperFlashDeviceIDHost::Fetcher::GetFilePathOnUIThread( + int render_process_id, + int render_view_id) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + FilePath path; + content::RenderViewHost* render_view_host = + content::RenderViewHost::FromID(render_process_id, render_view_id); + if (render_view_host) { + content::BrowserContext* browser_context = + render_view_host->GetProcess()->GetBrowserContext(); + // Don't use DRM IDs when incognito to prevent tracking. + if (!browser_context->IsOffTheRecord()) + path = browser_context->GetPath().AppendASCII(kDRMIdentifierFile); + } + + // Continue on the file thread (on failure/incognito, this will just send + // the empty path which will forward the error). + BrowserThread::PostTask( + BrowserThread::FILE, FROM_HERE, + base::Bind(&PepperFlashDeviceIDHost::Fetcher::ReadDRMFileOnFileThread, + this, path)); +} + +void PepperFlashDeviceIDHost::Fetcher::ReadDRMFileOnFileThread( + const FilePath& path) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + + std::string contents; + if (!path.empty()) + file_util::ReadFileToString(path, &contents); + + // Give back to the resource host on the IO thread. On failure this will just + // forward the empty string. + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&PepperFlashDeviceIDHost::Fetcher::ReplyOnIOThread, + this, contents)); +} + +void PepperFlashDeviceIDHost::Fetcher::ReplyOnIOThread( + const std::string& contents) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + if (host_.get()) // Plugin or resource could have been deleted. + host_->GotDRMContents(contents); +} + +// PepperFlashDeviceIDHost ----------------------------------------------------- + +PepperFlashDeviceIDHost::PepperFlashDeviceIDHost(BrowserPpapiHost* host, + PP_Instance instance, + PP_Resource resource) + : ppapi::host::ResourceHost(host->GetPpapiHost(), instance, resource), + factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), + browser_ppapi_host_(host) { +} + +PepperFlashDeviceIDHost::~PepperFlashDeviceIDHost() { +} + +int32_t PepperFlashDeviceIDHost::OnResourceMessageReceived( + const IPC::Message& msg, + ppapi::host::HostMessageContext* context) { + IPC_BEGIN_MESSAGE_MAP(PepperFlashDeviceIDHost, msg) + PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FlashDeviceID_GetDeviceID, + OnHostMsgGetDeviceID) + IPC_END_MESSAGE_MAP() + return PP_ERROR_FAILED; +} + +int32_t PepperFlashDeviceIDHost::OnHostMsgGetDeviceID( + const ppapi::host::HostMessageContext* context) { + if (fetcher_) + return PP_ERROR_INPROGRESS; + + fetcher_ = new Fetcher(factory_.GetWeakPtr()); + fetcher_->Start(browser_ppapi_host_); + reply_params_ = context->MakeReplyParams(); + return PP_OK_COMPLETIONPENDING; +} + +void PepperFlashDeviceIDHost::GotDRMContents(const std::string& contents) { + fetcher_ = NULL; + reply_params_.set_result(contents.empty() ? PP_ERROR_FAILED : PP_OK); + host()->SendReply(reply_params_, + PpapiPluginMsg_FlashDeviceID_GetDeviceIDReply(contents)); +} + +} // namespace chrome diff --git a/chrome/browser/renderer_host/pepper/pepper_flash_device_id_host.h b/chrome/browser/renderer_host/pepper/pepper_flash_device_id_host.h new file mode 100644 index 0000000..0be1580 --- /dev/null +++ b/chrome/browser/renderer_host/pepper/pepper_flash_device_id_host.h @@ -0,0 +1,101 @@ +// 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. + +#ifndef CHROME_BROWSER_RENDERER_HOST_PEPPER_PEPPER_FLASH_DEVICE_ID_HOST_H_ +#define CHROME_BROWSER_RENDERER_HOST_PEPPER_PEPPER_FLASH_DEVICE_ID_HOST_H_ + +#include "base/memory/weak_ptr.h" +#include "content/public/browser/browser_thread.h" +#include "ppapi/host/resource_host.h" +#include "ppapi/proxy/resource_message_params.h" + +class FilePath; + +namespace content { +class BrowserPpapiHost; +} + +namespace chrome { + +class PepperFlashDeviceIDHost : public ppapi::host::ResourceHost { + public: + PepperFlashDeviceIDHost(content::BrowserPpapiHost* host, + PP_Instance instance, + PP_Resource resource); + virtual ~PepperFlashDeviceIDHost(); + + // ResourceHost override. + virtual int32_t OnResourceMessageReceived( + const IPC::Message& msg, + ppapi::host::HostMessageContext* context) OVERRIDE; + + private: + // Helper class to manage the unfortunate number of thread transitions + // required for this operation. We must first get the profile info from the + // UI thread, and then actually read the file from the FILE thread before + // returning to the IO thread to forward the result to the plugin. + class Fetcher + : public base::RefCountedThreadSafe< + Fetcher, + content::BrowserThread::DeleteOnIOThread> { + public: + explicit Fetcher(const base::WeakPtr<PepperFlashDeviceIDHost>& host); + + // Schedules the request operation. The host will be called back with + // GotDRMContents. On failure, the contents will be empty. + void Start(content::BrowserPpapiHost* browser_host); + + private: + friend struct content::BrowserThread::DeleteOnThread< + content::BrowserThread::IO>; + friend class base::DeleteHelper<Fetcher>; + + ~Fetcher(); + + // Called on the UI thread to get the file path corresponding to the + // given render view. It will schedule the resulting file to be read on the + // file thread. On error, it will pass the empty path to the file thread. + void GetFilePathOnUIThread(int render_process_id, + int render_view_id); + + // Called on the file thread to read the contents of the file and to + // forward it to the IO thread. The path will be empty on error (in + // which case it will forward the empty string to the IO thread). + void ReadDRMFileOnFileThread(const FilePath& path); + + // Called on the IO thread to call back into the device ID host with the + // file contents, or the empty string on failure. + void ReplyOnIOThread(const std::string& contents); + + // Access only on IO thread (this class is destroyed on the IO thread + // to ensure that this is deleted properly, since weak ptrs aren't + // threadsafe). + base::WeakPtr<PepperFlashDeviceIDHost> host_; + + DISALLOW_COPY_AND_ASSIGN(Fetcher); + }; + friend class Fetcher; + + // IPC message handler. + int32_t OnHostMsgGetDeviceID(const ppapi::host::HostMessageContext* context); + + // Called by the fetcher when the DRM ID was retrieved, or the empty string + // on error. + void GotDRMContents(const std::string& contents); + + base::WeakPtrFactory<PepperFlashDeviceIDHost> factory_; + + content::BrowserPpapiHost* browser_ppapi_host_; + + // When a request is pending, the fetcher will be non-null, and the reply + // params will have the appropriate routing info set for the reply. + scoped_refptr<Fetcher> fetcher_; + ppapi::proxy::ResourceMessageReplyParams reply_params_; + + DISALLOW_COPY_AND_ASSIGN(PepperFlashDeviceIDHost); +}; + +} // namespace chrome + +#endif // CHROME_BROWSER_RENDERER_HOST_PEPPER_PEPPER_FLASH_DEVICE_ID_HOST_H_ diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 0debbe4..69213c6 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -1577,6 +1577,10 @@ 'browser/renderer_host/intercept_navigation_resource_throttle.h', 'browser/renderer_host/offline_resource_throttle.cc', 'browser/renderer_host/offline_resource_throttle.h', + 'browser/renderer_host/pepper/chrome_browser_pepper_host_factory.cc', + 'browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h', + 'browser/renderer_host/pepper/pepper_flash_device_id_host.cc', + 'browser/renderer_host/pepper/pepper_flash_device_id_host.h', 'browser/renderer_host/plugin_info_message_filter.cc', 'browser/renderer_host/plugin_info_message_filter.h', 'browser/renderer_host/safe_browsing_resource_throttle.cc', diff --git a/chrome/renderer/pepper/pepper_helper.cc b/chrome/renderer/pepper/pepper_helper.cc index 37b904c..73ac2b6 100644 --- a/chrome/renderer/pepper/pepper_helper.cc +++ b/chrome/renderer/pepper/pepper_helper.cc @@ -21,7 +21,9 @@ PepperHelper::~PepperHelper() { void PepperHelper::DidCreatePepperPlugin(content::RendererPpapiHost* host) { // TODO(brettw) figure out how to hook up the host factory. It needs some // kind of filter-like system to allow dynamic additions. - // new ChromeRendererPepperHostFactory(host); + host->GetPpapiHost()->AddHostFactoryFilter( + scoped_ptr<ppapi::host::HostFactory>( + new ChromeRendererPepperHostFactory)); host->GetPpapiHost()->AddInstanceMessageFilter( scoped_ptr<ppapi::host::InstanceMessageFilter>( new PepperFlashRendererMessageFilter(host))); diff --git a/content/browser/ppapi_plugin_process_host.cc b/content/browser/ppapi_plugin_process_host.cc index c80ceee..22d8a06 100644 --- a/content/browser/ppapi_plugin_process_host.cc +++ b/content/browser/ppapi_plugin_process_host.cc @@ -72,6 +72,7 @@ PpapiPluginProcessHost::~PpapiPluginProcessHost() { CancelRequests(); } +// static PpapiPluginProcessHost* PpapiPluginProcessHost::CreatePluginHost( const content::PepperPluginInfo& info, const FilePath& profile_data_directory, @@ -85,6 +86,7 @@ PpapiPluginProcessHost* PpapiPluginProcessHost::CreatePluginHost( return NULL; } +// static PpapiPluginProcessHost* PpapiPluginProcessHost::CreateBrokerHost( const content::PepperPluginInfo& info) { PpapiPluginProcessHost* plugin_host = @@ -96,6 +98,48 @@ PpapiPluginProcessHost* PpapiPluginProcessHost::CreateBrokerHost( return NULL; } +// static +void PpapiPluginProcessHost::DidCreateOutOfProcessInstance( + int plugin_process_id, + int32 pp_instance, + int render_process_id, + int render_view_id) { + for (PpapiPluginProcessHostIterator iter; !iter.Done(); ++iter) { + if (iter->process_.get() && + iter->process_->GetData().id == plugin_process_id) { + // Found the plugin. + iter->host_impl_->AddInstanceForView(pp_instance, + render_process_id, render_view_id); + return; + } + } + // We'll see this passed with a 0 process ID for the browser tag stuff that + // is currently in the process of being removed. + // + // TODO(brettw) When old browser tag impl is removed + // (PepperPluginDelegateImpl::CreateBrowserPluginModule passes a 0 plugin + // process ID) this should be converted to a NOTREACHED(). + DCHECK(plugin_process_id == 0) + << "Renderer sent a bad plugin process host ID"; +} + +// static +void PpapiPluginProcessHost::DidDeleteOutOfProcessInstance( + int plugin_process_id, + int32 pp_instance) { + for (PpapiPluginProcessHostIterator iter; !iter.Done(); ++iter) { + if (iter->process_.get() && + iter->process_->GetData().id == plugin_process_id) { + // Found the plugin. + iter->host_impl_->DeleteInstanceForView(pp_instance); + return; + } + } + // Note: It's possible that the plugin process has already been deleted by + // the time this message is received. For example, it could have crashed. + // That's OK, we can just ignore this message. +} + bool PpapiPluginProcessHost::Send(IPC::Message* message) { return process_->Send(message); } @@ -135,6 +179,8 @@ PpapiPluginProcessHost::PpapiPluginProcessHost( process_->GetHost()->AddFilter(filter_.get()); process_->GetHost()->AddFilter(file_filter_.get()); process_->GetHost()->AddFilter(host_impl_.get()); + + content::GetContentClient()->browser()->DidCreatePpapiPlugin(host_impl_); } PpapiPluginProcessHost::PpapiPluginProcessHost() diff --git a/content/browser/ppapi_plugin_process_host.h b/content/browser/ppapi_plugin_process_host.h index de57b52..3c6576c 100644 --- a/content/browser/ppapi_plugin_process_host.h +++ b/content/browser/ppapi_plugin_process_host.h @@ -80,6 +80,19 @@ class PpapiPluginProcessHost : public content::BrowserChildProcessHostDelegate, static PpapiPluginProcessHost* CreateBrokerHost( const content::PepperPluginInfo& info); + // Notification that a PP_Instance has been created for the given + // RenderView/Process pair for the given plugin. This is necessary so that + // when the plugin calls us with a PP_Instance we can find the RenderView + // associated with it without trusting the plugin. + static void DidCreateOutOfProcessInstance(int plugin_process_id, + int32 pp_instance, + int render_process_id, + int render_view_id); + + // The opposite of DIdCreate... above. + static void DidDeleteOutOfProcessInstance(int plugin_process_id, + int32 pp_instance); + // IPC::Sender implementation: virtual bool Send(IPC::Message* message) OVERRIDE; 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 92e5b76..dedd51e 100644 --- a/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc +++ b/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc @@ -4,6 +4,8 @@ #include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_view_host.h" #include "ipc/ipc_message_macros.h" namespace content { @@ -11,9 +13,10 @@ namespace content { BrowserPpapiHostImpl::BrowserPpapiHostImpl( IPC::Sender* sender, const ppapi::PpapiPermissions& permissions) - : host_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), - ppapi_host_(sender, &host_factory_, permissions), + : ppapi_host_(sender, permissions), plugin_process_handle_(base::kNullProcessHandle) { + ppapi_host_.AddHostFactoryFilter(scoped_ptr<ppapi::host::HostFactory>( + new ContentBrowserPepperHostFactory(this))); } BrowserPpapiHostImpl::~BrowserPpapiHostImpl() { @@ -41,4 +44,44 @@ base::ProcessHandle BrowserPpapiHostImpl::GetPluginProcessHandle() const { return plugin_process_handle_; } +bool BrowserPpapiHostImpl::IsValidInstance(PP_Instance instance) const { + return instance_to_view_.find(instance) != instance_to_view_.end(); +} + +bool BrowserPpapiHostImpl::GetRenderViewIDsForInstance( + PP_Instance instance, + int* render_process_id, + int* render_view_id) const { + InstanceToViewMap::const_iterator found = instance_to_view_.find(instance); + if (found == instance_to_view_.end()) { + *render_process_id = 0; + *render_view_id = 0; + return false; + } + + *render_process_id = found->second.process_id; + *render_view_id = found->second.view_id; + return true; +} + +void BrowserPpapiHostImpl::AddInstanceForView(PP_Instance instance, + int render_process_id, + int render_view_id) { + DCHECK(instance_to_view_.find(instance) == instance_to_view_.end()); + + RenderViewIDs ids; + ids.process_id = render_process_id; + ids.view_id = render_view_id; + instance_to_view_[instance] = ids; +} + +void BrowserPpapiHostImpl::DeleteInstanceForView(PP_Instance instance) { + InstanceToViewMap::iterator found = instance_to_view_.find(instance); + if (found == instance_to_view_.end()) { + NOTREACHED(); + return; + } + instance_to_view_.erase(found); +} + } // 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 98edba1..d743d15 100644 --- a/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h +++ b/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h @@ -5,6 +5,8 @@ #ifndef CONTENT_BROWSER_RENDERER_HOST_PEPPER_BROWSER_PPAPI_HOST_IMPL_H_ #define CONTENT_BROWSER_RENDERER_HOST_PEPPER_BROWSER_PPAPI_HOST_IMPL_H_ +#include <map> + #include "base/basictypes.h" #include "base/compiler_specific.h" #include "content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h" @@ -35,20 +37,41 @@ class CONTENT_EXPORT BrowserPpapiHostImpl // BrowserPpapiHost. virtual ppapi::host::PpapiHost* GetPpapiHost() OVERRIDE; virtual base::ProcessHandle GetPluginProcessHandle() const OVERRIDE; + virtual bool IsValidInstance(PP_Instance instance) const OVERRIDE; + virtual bool GetRenderViewIDsForInstance(PP_Instance instance, + int* render_process_id, + int* render_view_id) const OVERRIDE; void set_plugin_process_handle(base::ProcessHandle handle) { plugin_process_handle_ = handle; } + // These two functions are notifications that an instance has been created + // or destroyed. They allow us to maintain a mapping of PP_Instance to view + // IDs in the browser process. + void AddInstanceForView(PP_Instance instance, + int render_process_id, + int render_view_id); + void DeleteInstanceForView(PP_Instance instance); + private: friend class BrowserPpapiHostTest; + struct RenderViewIDs { + int process_id; + int view_id; + }; + typedef std::map<PP_Instance, RenderViewIDs> InstanceToViewMap; + virtual ~BrowserPpapiHostImpl(); - ContentBrowserPepperHostFactory host_factory_; ppapi::host::PpapiHost ppapi_host_; base::ProcessHandle plugin_process_handle_; + // Tracks all PP_Instances in this plugin and maps them to + // RenderProcess/RenderView IDs. + InstanceToViewMap instance_to_view_; + DISALLOW_COPY_AND_ASSIGN(BrowserPpapiHostImpl); }; diff --git a/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc b/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc index d5e7e98..34ba0d3 100644 --- a/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc +++ b/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc @@ -29,11 +29,8 @@ scoped_ptr<ResourceHost> ContentBrowserPepperHostFactory::CreateResourceHost( DCHECK(host == host_->GetPpapiHost()); // Make sure the plugin is giving us a valid instance for this resource. - /* TODO(brettw) make this work. The browser should be aware of all valid - instances. if (!host_->IsValidInstance(instance)) return scoped_ptr<ResourceHost>(); - */ // Public interfaces with no permissions required. switch (message.type()) { diff --git a/content/browser/renderer_host/pepper/pepper_message_filter.cc b/content/browser/renderer_host/pepper/pepper_message_filter.cc index 9aa0912..0355a7c 100644 --- a/content/browser/renderer_host/pepper/pepper_message_filter.cc +++ b/content/browser/renderer_host/pepper/pepper_message_filter.cc @@ -65,6 +65,8 @@ const int kDRMIdentifierSize = (256 / 8) * 2; // The path to the file containing the DRM ID. // It is mirrored from // chrome/browser/chromeos/system/drm_settings.cc +// TODO(brettw) remove this when we remove the sync Device ID getter in +// preference for the async one. const char kDRMIdentifierFile[] = "Pepper DRM ID.0"; void CreateNetAddressListFromAddressList( @@ -122,8 +124,7 @@ void PepperMessageFilter::OverrideThreadForMessage( message.type() == PpapiHostMsg_PPBTCPServerSocket_Listen::ID || message.type() == PpapiHostMsg_PPBHostResolver_Resolve::ID) { *thread = BrowserThread::UI; - } else if (message.type() == PepperMsg_GetDeviceID::ID || - message.type() == PpapiHostMsg_PPBFlashDeviceID_Get::ID) { + } else if (message.type() == PepperMsg_GetDeviceID::ID) { *thread = BrowserThread::FILE; } } @@ -181,7 +182,6 @@ bool PepperMessageFilter::OnMessageReceived(const IPC::Message& msg, // Flash messages. IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_UpdateActivity, OnUpdateActivity) IPC_MESSAGE_HANDLER(PepperMsg_GetDeviceID, OnGetDeviceID) - IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashDeviceID_Get, OnGetDeviceIDAsync) IPC_MESSAGE_HANDLER(PepperMsg_GetLocalDataRestrictions, OnGetLocalDataRestrictions) @@ -701,6 +701,8 @@ void PepperMessageFilter::OnUpdateActivity() { #endif } +// TODO(brettw) remove this when we remove the sync Device ID getter in +// preference for the async one. void PepperMessageFilter::OnGetDeviceID(std::string* id) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); id->clear(); @@ -735,17 +737,6 @@ void PepperMessageFilter::OnGetDeviceID(std::string* id) { id->assign(id_buf, kDRMIdentifierSize); } -void PepperMessageFilter::OnGetDeviceIDAsync(int32_t routing_id, - PP_Resource resource) { - std::string result; - OnGetDeviceID(&result); - Send(new PpapiMsg_PPBFlashDeviceID_GetReply(ppapi::API_ID_PPB_FLASH_DEVICE_ID, - routing_id, resource, - result.empty() ? PP_ERROR_FAILED - : PP_OK, - result)); -} - void PepperMessageFilter::OnGetLocalDataRestrictions( const GURL& document_url, const GURL& plugin_url, diff --git a/content/browser/renderer_host/pepper/pepper_message_filter.h b/content/browser/renderer_host/pepper/pepper_message_filter.h index f6a278b..817ec40 100644 --- a/content/browser/renderer_host/pepper/pepper_message_filter.h +++ b/content/browser/renderer_host/pepper/pepper_message_filter.h @@ -222,7 +222,6 @@ class PepperMessageFilter ppapi::PPB_X509Certificate_Fields* result); void OnUpdateActivity(); void OnGetDeviceID(std::string* id); - void OnGetDeviceIDAsync(int32_t routing_id, PP_Resource resource); void OnGetLocalDataRestrictions(const GURL& document_url, const GURL& plugin_url, PP_FlashLSORestrictions* restrictions); diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc index aa971df..46522c0 100644 --- a/content/browser/renderer_host/render_message_filter.cc +++ b/content/browser/renderer_host/render_message_filter.cc @@ -363,6 +363,10 @@ bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message, OnOpenChannelToPlugin) IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_OpenChannelToPepperPlugin, OnOpenChannelToPepperPlugin) + IPC_MESSAGE_HANDLER(ViewHostMsg_DidCreateOutOfProcessPepperInstance, + OnDidCreateOutOfProcessPepperInstance) + IPC_MESSAGE_HANDLER(ViewHostMsg_DidDeleteOutOfProcessPepperInstance, + OnDidDeleteOutOfProcessPepperInstance) IPC_MESSAGE_HANDLER(ViewHostMsg_OpenChannelToPpapiBroker, OnOpenChannelToPpapiBroker) IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_UpdateRect, @@ -675,6 +679,27 @@ void RenderMessageFilter::OnOpenChannelToPepperPlugin( this, resource_context_, reply_msg)); } +void RenderMessageFilter::OnDidCreateOutOfProcessPepperInstance( + int plugin_child_id, + int32 pp_instance, + int render_view_id) { + // 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); +} + +void RenderMessageFilter::OnDidDeleteOutOfProcessPepperInstance( + int plugin_child_id, + int32 pp_instance) { + PpapiPluginProcessHost::DidDeleteOutOfProcessInstance( + plugin_child_id, pp_instance); +} + void RenderMessageFilter::OnOpenChannelToPpapiBroker(int routing_id, int request_id, const FilePath& path) { diff --git a/content/browser/renderer_host/render_message_filter.h b/content/browser/renderer_host/render_message_filter.h index 0ab0135..51596a2 100644 --- a/content/browser/renderer_host/render_message_filter.h +++ b/content/browser/renderer_host/render_message_filter.h @@ -167,6 +167,11 @@ class RenderMessageFilter : public BrowserMessageFilter { IPC::Message* reply_msg); void OnOpenChannelToPepperPlugin(const FilePath& path, IPC::Message* reply_msg); + void OnDidCreateOutOfProcessPepperInstance(int plugin_child_id, + int32 pp_instance, + int render_view_id); + void OnDidDeleteOutOfProcessPepperInstance(int plugin_child_id, + int32 pp_instance); void OnOpenChannelToPpapiBroker(int routing_id, int request_id, const FilePath& path); diff --git a/content/common/view_messages.h b/content/common/view_messages.h index f745244..422776d 100644 --- a/content/common/view_messages.h +++ b/content/common/view_messages.h @@ -1908,6 +1908,28 @@ IPC_SYNC_MESSAGE_CONTROL1_2(ViewHostMsg_OpenChannelToPepperPlugin, IPC::ChannelHandle /* handle to channel */, int /* plugin_child_id */) +// Notification that a native (non-NaCl) plugin has created a new plugin +// instance. The parameters indicate the plugin process ID that we're creating +// the instance for, and the routing ID of the render view that the plugin +// instance is associated with. This allows us to create a mapping in the +// browser process for what objects a given PP_Instance is associated with. +// +// This message must be sync even though it returns no parameters to avoid +// a race condition with the plugin process. The plugin process sends messages +// to the browser that assume the browser knows about the instance. We need to +// sure that the browser actually knows about the instance before we tell the +// plugin to run. +IPC_SYNC_MESSAGE_CONTROL3_0(ViewHostMsg_DidCreateOutOfProcessPepperInstance, + int /* plugin_child_id */, + int32 /* pp_instance */, + int /* view_routing_id */) + +// Notification that a native (non-NaCl) plugin has destroyed an instance. This +// is the opposite if the "DidCreate" version above. +IPC_MESSAGE_CONTROL2(ViewHostMsg_DidDeleteOutOfProcessPepperInstance, + int /* plugin_child_id */, + int32 /* pp_instance */) + // A renderer sends this to the browser process when it wants to // create a ppapi broker. The browser will create the broker process // if necessary, and will return a handle to the channel on success. diff --git a/content/public/browser/browser_ppapi_host.h b/content/public/browser/browser_ppapi_host.h index aa97990..3e1db99 100644 --- a/content/public/browser/browser_ppapi_host.h +++ b/content/public/browser/browser_ppapi_host.h @@ -5,8 +5,12 @@ #ifndef CONTENT_PUBLIC_BROWSER_BROWSER_PPAPI_HOST_H_ #define CONTENT_PUBLIC_BROWSER_BROWSER_PPAPI_HOST_H_ +#include "base/callback_forward.h" #include "base/process.h" #include "content/common/content_export.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_view_host.h" +#include "ppapi/c/pp_instance.h" namespace ppapi { namespace host { @@ -29,6 +33,22 @@ class CONTENT_EXPORT BrowserPpapiHost { // Returns the handle to the plugin process. virtual base::ProcessHandle GetPluginProcessHandle() const = 0; + // Returns true if the given PP_Instance is valid. + virtual bool IsValidInstance(PP_Instance instance) const = 0; + + // Retrieves the process/view Ids associated with the RenderView containing + // the given instance and returns true on success. If the instance is + // invalid, the ids will be 0 and false will be returned. + // + // When a resource is created, the PP_Instance should already have been + // validated, and the resource hosts will be deleted when the resource is + // destroyed. So it should not generally be necessary to check for errors + // from this function except as a last-minute sanity check if you convert the + // IDs to a RenderView/ProcessHost on the UI thread. + virtual bool GetRenderViewIDsForInstance(PP_Instance instance, + int* render_process_id, + int* render_view_id) const = 0; + protected: virtual ~BrowserPpapiHost() {} }; diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h index 33e216c..7766f55 100644 --- a/content/public/browser/content_browser_client.h +++ b/content/public/browser/content_browser_client.h @@ -54,6 +54,7 @@ class AccessTokenStore; class BrowserChildProcessHost; class BrowserContext; class BrowserMainParts; +class BrowserPpapiHost; class BrowserURLHandler; class MediaObserver; class QuotaPermissionContext; @@ -434,6 +435,11 @@ class CONTENT_EXPORT ContentBrowserClient { // else we should do with the file. virtual std::string GetDefaultDownloadName(); + // Notifification that a pepper plugin has just been spawned. This allows the + // embedder to add filters onto the host to implement interfaces. + // This is called on the IO thread. + virtual void DidCreatePpapiPlugin(BrowserPpapiHost* browser_host) {} + // Returns true if renderer processes can use Pepper TCP/UDP sockets from // the given origin. virtual bool AllowPepperSocketAPI(BrowserContext* browser_context, diff --git a/content/renderer/pepper/mock_renderer_ppapi_host.cc b/content/renderer/pepper/mock_renderer_ppapi_host.cc index 042d3a3..9a31ecd 100644 --- a/content/renderer/pepper/mock_renderer_ppapi_host.cc +++ b/content/renderer/pepper/mock_renderer_ppapi_host.cc @@ -10,7 +10,7 @@ namespace content { MockRendererPpapiHost::MockRendererPpapiHost(RenderView* render_view, PP_Instance instance) : sink_(), - ppapi_host_(&sink_, NULL, ppapi::PpapiPermissions()), + ppapi_host_(&sink_, ppapi::PpapiPermissions()), render_view_(render_view), pp_instance_(instance), has_user_gesture_(false) { diff --git a/content/renderer/pepper/pepper_plugin_delegate_impl.cc b/content/renderer/pepper/pepper_plugin_delegate_impl.cc index 79b7d92..4671f8e 100644 --- a/content/renderer/pepper/pepper_plugin_delegate_impl.cc +++ b/content/renderer/pepper/pepper_plugin_delegate_impl.cc @@ -107,8 +107,11 @@ class HostDispatcherWrapper public: HostDispatcherWrapper(RenderViewImpl* rv, webkit::ppapi::PluginModule* module, + int plugin_child_id, const ppapi::PpapiPermissions& perms) - : module_(module), + : render_view_(rv), + module_(module), + plugin_child_id_(plugin_child_id), permissions_(perms) { } virtual ~HostDispatcherWrapper() {} @@ -150,16 +153,32 @@ class HostDispatcherWrapper } virtual void AddInstance(PP_Instance instance) { ppapi::proxy::HostDispatcher::SetForInstance(instance, dispatcher_.get()); + + render_view_->Send(new ViewHostMsg_DidCreateOutOfProcessPepperInstance( + plugin_child_id_, + instance, + render_view_->routing_id())); } virtual void RemoveInstance(PP_Instance instance) { ppapi::proxy::HostDispatcher::RemoveForInstance(instance); + + render_view_->Send(new ViewHostMsg_DidDeleteOutOfProcessPepperInstance( + plugin_child_id_, + instance)); } ppapi::proxy::HostDispatcher* dispatcher() { return dispatcher_.get(); } private: + RenderViewImpl* render_view_; + webkit::ppapi::PluginModule* module_; + // ID that the browser process uses to idetify the child process for the + // plugin. This isn't directly useful from our process (the renderer) except + // in messages to the browser to disambiguate plugins. + int plugin_child_id_; + ppapi::PpapiPermissions permissions_; scoped_ptr<ppapi::proxy::HostDispatcher> dispatcher_; @@ -361,7 +380,8 @@ PepperPluginDelegateImpl::CreatePepperPluginModule( permissions); PepperPluginRegistry::GetInstance()->AddLiveModule(path, module); scoped_ptr<HostDispatcherWrapper> dispatcher( - new HostDispatcherWrapper(render_view_, module, permissions)); + new HostDispatcherWrapper(render_view_, module, plugin_child_id, + permissions)); if (!dispatcher->Init( channel_handle, webkit::ppapi::PluginModule::GetLocalGetInterfaceFunc(), @@ -406,7 +426,7 @@ scoped_refptr<webkit::ppapi::PluginModule> RenderThreadImpl::current()->browser_plugin_registry()->AddModule( guest_process_id, module); scoped_ptr<HostDispatcherWrapper> dispatcher( - new HostDispatcherWrapper(render_view_, module, permissions)); + new HostDispatcherWrapper(render_view_, module, 0, permissions)); if (!dispatcher->Init( channel_handle, webkit::ppapi::PluginModule::GetLocalGetInterfaceFunc(), diff --git a/content/renderer/pepper/renderer_ppapi_host_impl.cc b/content/renderer/pepper/renderer_ppapi_host_impl.cc index feafc2e..8447093 100644 --- a/content/renderer/pepper/renderer_ppapi_host_impl.cc +++ b/content/renderer/pepper/renderer_ppapi_host_impl.cc @@ -23,11 +23,12 @@ RendererPpapiHostImpl::RendererPpapiHostImpl( webkit::ppapi::PluginModule* module, ppapi::proxy::HostDispatcher* dispatcher, const ppapi::PpapiPermissions& permissions) - : module_(module), - host_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { + : module_(module) { // Hook the PpapiHost up to the dispatcher for out-of-process communication. ppapi_host_.reset( - new ppapi::host::PpapiHost(dispatcher, &host_factory_, permissions)); + new ppapi::host::PpapiHost(dispatcher, permissions)); + ppapi_host_->AddHostFactoryFilter(scoped_ptr<ppapi::host::HostFactory>( + new ContentRendererPepperHostFactory(this))); dispatcher->AddFilter(ppapi_host_.get()); } @@ -35,13 +36,13 @@ RendererPpapiHostImpl::RendererPpapiHostImpl( RendererPpapiHostImpl::RendererPpapiHostImpl( webkit::ppapi::PluginModule* module, const ppapi::PpapiPermissions& permissions) - : module_(module), - host_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { + : module_(module) { // Hook the host up to the in-process router. in_process_router_.reset(new PepperInProcessRouter(this)); ppapi_host_.reset(new ppapi::host::PpapiHost( - in_process_router_->GetRendererToPluginSender(), - &host_factory_, permissions)); + in_process_router_->GetRendererToPluginSender(), permissions)); + ppapi_host_->AddHostFactoryFilter(scoped_ptr<ppapi::host::HostFactory>( + new ContentRendererPepperHostFactory(this))); } RendererPpapiHostImpl::~RendererPpapiHostImpl() { diff --git a/content/renderer/pepper/renderer_ppapi_host_impl.h b/content/renderer/pepper/renderer_ppapi_host_impl.h index a3537fb..24927b1 100644 --- a/content/renderer/pepper/renderer_ppapi_host_impl.h +++ b/content/renderer/pepper/renderer_ppapi_host_impl.h @@ -102,7 +102,6 @@ class RendererPpapiHostImpl webkit::ppapi::PluginModule* module_; // Non-owning pointer. - ContentRendererPepperHostFactory host_factory_; scoped_ptr<ppapi::host::PpapiHost> ppapi_host_; // Null when running out-of-process. diff --git a/ppapi/host/host_message_context.cc b/ppapi/host/host_message_context.cc index 5c1c0d1..ed785bc 100644 --- a/ppapi/host/host_message_context.cc +++ b/ppapi/host/host_message_context.cc @@ -15,7 +15,8 @@ HostMessageContext::HostMessageContext( HostMessageContext::~HostMessageContext() { } -ppapi::proxy::ResourceMessageReplyParams HostMessageContext::MakeReplyParams() { +ppapi::proxy::ResourceMessageReplyParams +HostMessageContext::MakeReplyParams() const { return ppapi::proxy::ResourceMessageReplyParams(params.pp_resource(), params.sequence()); } diff --git a/ppapi/host/host_message_context.h b/ppapi/host/host_message_context.h index 6708261..d0958ab 100644 --- a/ppapi/host/host_message_context.h +++ b/ppapi/host/host_message_context.h @@ -21,7 +21,7 @@ struct PPAPI_HOST_EXPORT HostMessageContext { // Returns a "reply params" struct with the same resource and sequence number // as this request. - ppapi::proxy::ResourceMessageReplyParams MakeReplyParams(); + ppapi::proxy::ResourceMessageReplyParams MakeReplyParams() const; // The original call parameters passed to the resource message call. const ppapi::proxy::ResourceMessageCallParams& params; diff --git a/ppapi/host/ppapi_host.cc b/ppapi/host/ppapi_host.cc index 247c781..0ec37b6 100644 --- a/ppapi/host/ppapi_host.cc +++ b/ppapi/host/ppapi_host.cc @@ -26,10 +26,8 @@ const size_t kMaxResourcesPerPlugin = 1 << 14; } // namespace PpapiHost::PpapiHost(IPC::Sender* sender, - HostFactory* host_factory, const PpapiPermissions& perms) : sender_(sender), - host_factory_(host_factory), permissions_(perms) { } @@ -73,6 +71,9 @@ void PpapiHost::SendReply(const proxy::ResourceMessageReplyParams& params, Send(new PpapiPluginMsg_ResourceReply(params, msg)); } +void PpapiHost::AddHostFactoryFilter(scoped_ptr<HostFactory> filter) { + host_factory_filters_.push_back(filter.release()); +} void PpapiHost::AddInstanceMessageFilter( scoped_ptr<InstanceMessageFilter> filter) { @@ -121,8 +122,15 @@ void PpapiHost::OnHostMsgResourceCreated( if (resources_.size() >= kMaxResourcesPerPlugin) return; - scoped_ptr<ResourceHost> resource_host( - host_factory_->CreateResourceHost(this, params, instance, nested_msg)); + // Run through all filters until one grabs this message. + scoped_ptr<ResourceHost> resource_host; + DCHECK(!host_factory_filters_.empty()); // Caller forgot to add a factory. + for (size_t i = 0; i < host_factory_filters_.size(); i++) { + resource_host = host_factory_filters_[i]->CreateResourceHost( + this, params, instance, nested_msg).Pass(); + if (resource_host.get()) + break; + } if (!resource_host.get()) { NOTREACHED(); return; diff --git a/ppapi/host/ppapi_host.h b/ppapi/host/ppapi_host.h index 3f3605c5..748d47a 100644 --- a/ppapi/host/ppapi_host.h +++ b/ppapi/host/ppapi_host.h @@ -37,12 +37,11 @@ class ResourceHost; // corresponding replies. class PPAPI_HOST_EXPORT PpapiHost : public IPC::Sender, public IPC::Listener { public: - // The sender is the channel to the plugin for outgoing messages. The factory - // will be used to receive resource creation messages from the plugin. Both - // pointers are owned by the caller and must outlive this class. - PpapiHost(IPC::Sender* sender, - HostFactory* host_factory, - const PpapiPermissions& perms); + // The sender is the channel to the plugin for outgoing messages. + // Normally the creator will add filters for resource creation messages + // (AddHostFactoryFilter) and instance messages (AddInstanceMessageFilter) + // after construction. + PpapiHost(IPC::Sender* sender, const PpapiPermissions& perms); virtual ~PpapiHost(); const PpapiPermissions& permissions() const { return permissions_; } @@ -57,6 +56,10 @@ class PPAPI_HOST_EXPORT PpapiHost : public IPC::Sender, public IPC::Listener { void SendReply(const proxy::ResourceMessageReplyParams& params, const IPC::Message& msg); + // Adds the given host factory filter to the host. The PpapiHost will take + // ownership of the pointer. + void AddHostFactoryFilter(scoped_ptr<HostFactory> filter); + // Adds the given message filter to the host. The PpapiHost will take // ownership of the pointer. void AddInstanceMessageFilter(scoped_ptr<InstanceMessageFilter> filter); @@ -78,11 +81,14 @@ class PPAPI_HOST_EXPORT PpapiHost : public IPC::Sender, public IPC::Listener { // Non-owning pointer. IPC::Sender* sender_; - // Non-owning pointer. - HostFactory* host_factory_; - PpapiPermissions permissions_; + // Filters for resource creation messages. Note that since we don't support + // deleting these dynamically we don't need to worry about modifications + // during iteration. If we add that capability, this should be replaced with + // an ObserverList. + ScopedVector<HostFactory> host_factory_filters_; + // Filters for instance messages. Note that since we don't support deleting // these dynamically we don't need to worry about modifications during // iteration. If we add that capability, this should be replaced with an diff --git a/ppapi/ppapi_proxy.gypi b/ppapi/ppapi_proxy.gypi index e737aa5..a802f87 100644 --- a/ppapi/ppapi_proxy.gypi +++ b/ppapi/ppapi_proxy.gypi @@ -27,6 +27,8 @@ 'proxy/enter_proxy.h', 'proxy/file_chooser_resource.cc', 'proxy/file_chooser_resource.h', + 'proxy/flash_device_id_resource.cc', + 'proxy/flash_device_id_resource.h', 'proxy/gamepad_resource.cc', 'proxy/gamepad_resource.h', 'proxy/host_dispatcher.cc', @@ -72,8 +74,6 @@ 'proxy/ppb_file_ref_proxy.h', 'proxy/ppb_file_system_proxy.cc', 'proxy/ppb_file_system_proxy.h', - 'proxy/ppb_flash_device_id_proxy.cc', - 'proxy/ppb_flash_device_id_proxy.h', 'proxy/ppb_flash_proxy.cc', 'proxy/ppb_flash_proxy.h', 'proxy/ppb_flash_menu_proxy.cc', @@ -165,11 +165,11 @@ ['>(nacl_untrusted_build)==1', { 'sources!': [ 'proxy/broker_dispatcher.cc', + 'proxy/flash_device_id_resource.cc', 'proxy/ppb_audio_input_proxy.cc', 'proxy/ppb_broker_proxy.cc', 'proxy/ppb_buffer_proxy.cc', 'proxy/ppb_file_chooser_proxy.cc', - 'proxy/ppb_flash_device_id_proxy.cc', 'proxy/ppb_flash_proxy.cc', 'proxy/ppb_flash_menu_proxy.cc', 'proxy/ppb_flash_message_loop_proxy.cc', diff --git a/ppapi/proxy/flash_device_id_resource.cc b/ppapi/proxy/flash_device_id_resource.cc new file mode 100644 index 0000000..39ff63b --- /dev/null +++ b/ppapi/proxy/flash_device_id_resource.cc @@ -0,0 +1,67 @@ +// 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 "ppapi/proxy/flash_device_id_resource.h" + +#include "ppapi/c/pp_errors.h" +#include "ppapi/proxy/dispatch_reply_message.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/shared_impl/var.h" + +namespace ppapi { +namespace proxy { + +FlashDeviceIDResource::FlashDeviceIDResource(Connection connection, + PP_Instance instance) + : PluginResource(connection, instance), + dest_(NULL) { + SendCreateToBrowser(PpapiHostMsg_FlashDeviceID_Create()); +} + +FlashDeviceIDResource::~FlashDeviceIDResource() { +} + +thunk::PPB_Flash_DeviceID_API* +FlashDeviceIDResource::AsPPB_Flash_DeviceID_API() { + return this; +} + +int32_t FlashDeviceIDResource::GetDeviceID( + PP_Var* id, + scoped_refptr<TrackedCallback> callback) { + if (TrackedCallback::IsPending(callback_)) + return PP_ERROR_INPROGRESS; + if (!id) + return PP_ERROR_BADARGUMENT; + + dest_ = id; + callback_ = callback; + + CallBrowser(PpapiHostMsg_FlashDeviceID_GetDeviceID()); + return PP_OK_COMPLETIONPENDING; +} + +void FlashDeviceIDResource::OnReplyReceived( + const ResourceMessageReplyParams& params, + const IPC::Message& msg) { + IPC_BEGIN_MESSAGE_MAP(FlashDeviceIDResource, msg) + PPAPI_DISPATCH_RESOURCE_REPLY( + PpapiPluginMsg_FlashDeviceID_GetDeviceIDReply, + OnPluginMsgGetDeviceIDReply) + IPC_END_MESSAGE_MAP() +} + +void FlashDeviceIDResource::OnPluginMsgGetDeviceIDReply( + const ResourceMessageReplyParams& params, + const std::string& id) { + if (params.result() == PP_OK) + *dest_ = StringVar::StringToPPVar(id); + else + *dest_ = PP_MakeUndefined(); + dest_ = NULL; + TrackedCallback::ClearAndRun(&callback_, params.result()); +} + +} // namespace proxy +} // namespace ppapi diff --git a/ppapi/proxy/flash_device_id_resource.h b/ppapi/proxy/flash_device_id_resource.h new file mode 100644 index 0000000..b563c80 --- /dev/null +++ b/ppapi/proxy/flash_device_id_resource.h @@ -0,0 +1,51 @@ +// 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. + +#ifndef PPAPI_PROXY_FLASH_DEVICE_ID_RESOURCE_H_ +#define PPAPI_PROXY_FLASH_DEVICE_ID_RESOURCE_H_ + +#include "ppapi/proxy/plugin_resource.h" +#include "ppapi/proxy/ppapi_proxy_export.h" +#include "ppapi/shared_impl/tracked_callback.h" +#include "ppapi/thunk/ppb_flash_device_id_api.h" + +namespace ppapi { +namespace proxy { + +class FlashDeviceIDResource + : public PluginResource, + public thunk::PPB_Flash_DeviceID_API { + public: + FlashDeviceIDResource(Connection connection, + PP_Instance instance); + virtual ~FlashDeviceIDResource(); + + // Resource override. + virtual thunk::PPB_Flash_DeviceID_API* AsPPB_Flash_DeviceID_API() OVERRIDE; + + // PPB_Flash_DeviceID_API implementation. + virtual int32_t GetDeviceID(PP_Var* id, + scoped_refptr<TrackedCallback> callback) OVERRIDE; + + private: + // PluginResource override; + virtual void OnReplyReceived(const ResourceMessageReplyParams& params, + const IPC::Message& msg); + + // IPC message handler. + void OnPluginMsgGetDeviceIDReply(const ResourceMessageReplyParams& params, + const std::string& id); + + // Non-null when a callback is pending. + PP_Var* dest_; + + scoped_refptr<TrackedCallback> callback_; + + DISALLOW_COPY_AND_ASSIGN(FlashDeviceIDResource); +}; + +} // namespace proxy +} // namespace ppapi + +#endif // PPAPI_PROXY_FLASH_DEVICE_ID_RESOURCE_H_ diff --git a/ppapi/proxy/interface_list.cc b/ppapi/proxy/interface_list.cc index 129901c..d77c1cb 100644 --- a/ppapi/proxy/interface_list.cc +++ b/ppapi/proxy/interface_list.cc @@ -84,7 +84,6 @@ #include "ppapi/proxy/ppb_file_io_proxy.h" #include "ppapi/proxy/ppb_file_ref_proxy.h" #include "ppapi/proxy/ppb_file_system_proxy.h" -#include "ppapi/proxy/ppb_flash_device_id_proxy.h" #include "ppapi/proxy/ppb_flash_menu_proxy.h" #include "ppapi/proxy/ppb_flash_message_loop_proxy.h" #include "ppapi/proxy/ppb_flash_proxy.h" diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h index cfdc984..2478b0f 100644 --- a/ppapi/proxy/ppapi_messages.h +++ b/ppapi/proxy/ppapi_messages.h @@ -1549,6 +1549,12 @@ IPC_MESSAGE_CONTROL4(PpapiHostMsg_FileChooser_Show, IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FileChooser_ShowReply, std::vector<ppapi::PPB_FileRef_CreateInfo> /* files */) +// Flash device ID. +IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashDeviceID_Create) +IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashDeviceID_GetDeviceID) +IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashDeviceID_GetDeviceIDReply, + std::string /* id */) + // Gamepad. IPC_MESSAGE_CONTROL0(PpapiHostMsg_Gamepad_Create) diff --git a/ppapi/proxy/ppb_flash_device_id_proxy.cc b/ppapi/proxy/ppb_flash_device_id_proxy.cc deleted file mode 100644 index bb66b33..0000000 --- a/ppapi/proxy/ppb_flash_device_id_proxy.cc +++ /dev/null @@ -1,126 +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 "ppapi/proxy/ppb_flash_device_id_proxy.h" - -#include "base/compiler_specific.h" -#include "ppapi/c/pp_errors.h" -#include "ppapi/proxy/plugin_dispatcher.h" -#include "ppapi/proxy/plugin_globals.h" -#include "ppapi/proxy/plugin_proxy_delegate.h" -#include "ppapi/proxy/ppapi_messages.h" -#include "ppapi/shared_impl/resource.h" -#include "ppapi/shared_impl/tracked_callback.h" -#include "ppapi/shared_impl/var.h" -#include "ppapi/thunk/enter.h" -#include "ppapi/thunk/ppb_flash_device_id_api.h" - -using ppapi::thunk::PPB_Flash_DeviceID_API; - -namespace ppapi { -namespace proxy { - -namespace { - -class DeviceID : public Resource, public PPB_Flash_DeviceID_API { - public: - DeviceID(PP_Instance instance); - virtual ~DeviceID(); - - // Resource overrides. - virtual PPB_Flash_DeviceID_API* AsPPB_Flash_DeviceID_API() OVERRIDE; - - // PPB_Flash_DeviceID_API implementation. - virtual int32_t GetDeviceID(PP_Var* id, - const PP_CompletionCallback& callback) OVERRIDE; - - void OnReply(int32_t result, const std::string& id); - - private: - // Non-null when a callback is pending. - PP_Var* dest_; - - scoped_refptr<TrackedCallback> callback_; - - DISALLOW_COPY_AND_ASSIGN(DeviceID); -}; - -DeviceID::DeviceID(PP_Instance instance) - : Resource(OBJECT_IS_PROXY, instance), - dest_(NULL) { -} - -DeviceID::~DeviceID() { -} - -PPB_Flash_DeviceID_API* DeviceID::AsPPB_Flash_DeviceID_API() { - return this; -} - -int32_t DeviceID::GetDeviceID(PP_Var* id, - const PP_CompletionCallback& callback) { - if (TrackedCallback::IsPending(callback_)) - return PP_ERROR_INPROGRESS; - if (!id) - return PP_ERROR_BADARGUMENT; - - callback_ = new TrackedCallback(this, callback); - dest_ = id; - - PluginDispatcher* dispatcher = - PluginDispatcher::GetForInstance(pp_instance()); - - PluginGlobals::Get()->plugin_proxy_delegate()->SendToBrowser( - new PpapiHostMsg_PPBFlashDeviceID_Get( - API_ID_PPB_FLASH_DEVICE_ID, dispatcher->plugin_dispatcher_id(), - pp_resource())); - return PP_OK_COMPLETIONPENDING; -} - -void DeviceID::OnReply(int32_t result, const std::string& id) { - if (result == PP_OK) - *dest_ = StringVar::StringToPPVar(id); - else - *dest_ = PP_MakeUndefined(); - dest_ = NULL; - TrackedCallback::ClearAndRun(&callback_, result); -} - -} // namespace - -PPB_Flash_DeviceID_Proxy::PPB_Flash_DeviceID_Proxy(Dispatcher* dispatcher) - : InterfaceProxy(dispatcher) { -} - -PPB_Flash_DeviceID_Proxy::~PPB_Flash_DeviceID_Proxy() { -} - -// static -PP_Resource PPB_Flash_DeviceID_Proxy::CreateProxyResource( - PP_Instance instance) { - return (new DeviceID(instance))->GetReference(); -} - -bool PPB_Flash_DeviceID_Proxy::OnMessageReceived(const IPC::Message& msg) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(PPB_Flash_DeviceID_Proxy, msg) - IPC_MESSAGE_HANDLER(PpapiMsg_PPBFlashDeviceID_GetReply, - OnPluginMsgGetReply) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled; -} - -void PPB_Flash_DeviceID_Proxy::OnPluginMsgGetReply(int32 routing_id, - PP_Resource resource, - int32 result, - const std::string& id) { - thunk::EnterResourceNoLock<PPB_Flash_DeviceID_API> enter(resource, false); - if (enter.failed()) - return; // Resource destroyed. - static_cast<DeviceID*>(enter.object())->OnReply(result, id); -} - -} // namespace proxy -} // namespace ppapi diff --git a/ppapi/proxy/ppb_flash_device_id_proxy.h b/ppapi/proxy/ppb_flash_device_id_proxy.h deleted file mode 100644 index f379873..0000000 --- a/ppapi/proxy/ppb_flash_device_id_proxy.h +++ /dev/null @@ -1,41 +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. - -#ifndef PPAPI_PROXY_PPB_FLASH_DEVICE_ID_PROXY_H_ -#define PPAPI_PROXY_PPB_FLASH_DEVICE_ID_PROXY_H_ - -#include <string> - -#include "ppapi/c/pp_instance.h" -#include "ppapi/proxy/interface_proxy.h" - -namespace ppapi { -namespace proxy { - -class PPB_Flash_DeviceID_Proxy : public InterfaceProxy { - public: - PPB_Flash_DeviceID_Proxy(Dispatcher* dispatcher); - virtual ~PPB_Flash_DeviceID_Proxy(); - - static PP_Resource CreateProxyResource(PP_Instance instance); - - // InterfaceProxy implementation. - virtual bool OnMessageReceived(const IPC::Message& msg); - - static const ApiID kApiID = API_ID_PPB_FLASH_DEVICE_ID; - - private: - void OnPluginMsgGetReply(int32 routing_id, - PP_Resource resource, - int32 result, - const std::string& id); - - DISALLOW_COPY_AND_ASSIGN(PPB_Flash_DeviceID_Proxy); -}; - -} // namespace proxy -} // namespace ppapi - -#endif // PPAPI_PROXY_PPB_FLASH_DEVICE_ID_PROXY_H_ - diff --git a/ppapi/proxy/resource_creation_proxy.cc b/ppapi/proxy/resource_creation_proxy.cc index f24f86a..0981b82 100644 --- a/ppapi/proxy/resource_creation_proxy.cc +++ b/ppapi/proxy/resource_creation_proxy.cc @@ -9,6 +9,7 @@ #include "ppapi/c/trusted/ppb_image_data_trusted.h" #include "ppapi/proxy/connection.h" #include "ppapi/proxy/file_chooser_resource.h" +#include "ppapi/proxy/flash_device_id_resource.h" #include "ppapi/proxy/plugin_dispatcher.h" #include "ppapi/proxy/plugin_globals.h" #include "ppapi/proxy/plugin_proxy_delegate.h" @@ -21,7 +22,6 @@ #include "ppapi/proxy/ppb_file_io_proxy.h" #include "ppapi/proxy/ppb_file_ref_proxy.h" #include "ppapi/proxy/ppb_file_system_proxy.h" -#include "ppapi/proxy/ppb_flash_device_id_proxy.h" #include "ppapi/proxy/ppb_flash_menu_proxy.h" #include "ppapi/proxy/ppb_flash_message_loop_proxy.h" #include "ppapi/proxy/ppb_graphics_2d_proxy.h" @@ -303,7 +303,7 @@ PP_Resource ResourceCreationProxy::CreateFileChooser( } PP_Resource ResourceCreationProxy::CreateFlashDeviceID(PP_Instance instance) { - return PPB_Flash_DeviceID_Proxy::CreateProxyResource(instance); + return (new FlashDeviceIDResource(GetConnection(), instance))->GetReference(); } PP_Resource ResourceCreationProxy::CreateFlashMenu( diff --git a/ppapi/shared_impl/ppapi_permissions.h b/ppapi/shared_impl/ppapi_permissions.h index 4b1c6a6..8456fb7 100644 --- a/ppapi/shared_impl/ppapi_permissions.h +++ b/ppapi/shared_impl/ppapi_permissions.h @@ -19,7 +19,7 @@ enum Permission { // Allows ability to bypass user-gesture checks for showing things like // file select dialogs. - PERMISSION_BYPASS_USER_GESTURE = 1 << 3 + PERMISSION_BYPASS_USER_GESTURE = 1 << 3, // NOTE: If you add stuff be sure to update AllPermissions(). }; diff --git a/ppapi/thunk/interfaces_ppb_private_flash.h b/ppapi/thunk/interfaces_ppb_private_flash.h index 7226020..8ec049a 100644 --- a/ppapi/thunk/interfaces_ppb_private_flash.h +++ b/ppapi/thunk/interfaces_ppb_private_flash.h @@ -46,8 +46,7 @@ PROXIED_IFACE(PPB_Flash, PPB_FLASH_FILE_FILEREF_INTERFACE, PPB_Flash_File_FileRef) -PROXIED_API(PPB_Flash_DeviceID) -PROXIED_IFACE(PPB_Flash_DeviceID, +PROXIED_IFACE(NoAPIName, PPB_FLASH_DEVICEID_INTERFACE_1_0, PPB_Flash_DeviceID_1_0) diff --git a/ppapi/thunk/ppb_flash_device_id_api.h b/ppapi/thunk/ppb_flash_device_id_api.h index ae31abd..cbd1bf5 100644 --- a/ppapi/thunk/ppb_flash_device_id_api.h +++ b/ppapi/thunk/ppb_flash_device_id_api.h @@ -2,7 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/memory/ref_counted.h" +#include "ppapi/thunk/ppapi_thunk_export.h" + namespace ppapi { + +class TrackedCallback; + namespace thunk { class PPAPI_THUNK_EXPORT PPB_Flash_DeviceID_API { @@ -10,7 +16,7 @@ class PPAPI_THUNK_EXPORT PPB_Flash_DeviceID_API { virtual ~PPB_Flash_DeviceID_API() {} virtual int32_t GetDeviceID(PP_Var* id, - const PP_CompletionCallback& callback) = 0; + scoped_refptr<TrackedCallback> callback) = 0; }; } // namespace thunk diff --git a/ppapi/thunk/ppb_flash_device_id_thunk.cc b/ppapi/thunk/ppb_flash_device_id_thunk.cc index 9275648..498df75 100644 --- a/ppapi/thunk/ppb_flash_device_id_thunk.cc +++ b/ppapi/thunk/ppb_flash_device_id_thunk.cc @@ -26,7 +26,7 @@ int32_t GetDeviceID(PP_Resource resource, EnterResource<PPB_Flash_DeviceID_API> enter(resource, callback, true); if (enter.failed()) return enter.retval(); - return enter.SetResult(enter.object()->GetDeviceID(id, callback)); + return enter.SetResult(enter.object()->GetDeviceID(id, enter.callback())); } const PPB_Flash_DeviceID g_ppb_flash_deviceid_thunk = { |