diff options
author | bauerb@chromium.org <bauerb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-23 14:40:50 +0000 |
---|---|---|
committer | bauerb@chromium.org <bauerb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-23 14:40:50 +0000 |
commit | d8415ad900d21b08c678bc7b06b2e81581311f71 (patch) | |
tree | a22de25afa5b134c071284fe5823fb2b47033c26 /content | |
parent | 574b04420530b62321e47610e7edbcac2165830e (diff) | |
download | chromium_src-d8415ad900d21b08c678bc7b06b2e81581311f71.zip chromium_src-d8415ad900d21b08c678bc7b06b2e81581311f71.tar.gz chromium_src-d8415ad900d21b08c678bc7b06b2e81581311f71.tar.bz2 |
Add hooks to content to request permission to connect to the PPAPI broker.
BUG=142639
TEST=browser_tests:PPAPITest.Broker
Review URL: https://chromiumcodereview.appspot.com/10854040
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@152991 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r-- | content/browser/web_contents/web_contents_impl.cc | 29 | ||||
-rw-r--r-- | content/browser/web_contents/web_contents_impl.h | 7 | ||||
-rw-r--r-- | content/common/view_messages.h | 16 | ||||
-rw-r--r-- | content/public/browser/web_contents_observer.cc | 8 | ||||
-rw-r--r-- | content/public/browser/web_contents_observer.h | 13 | ||||
-rw-r--r-- | content/renderer/pepper/pepper_broker_impl.cc | 119 | ||||
-rw-r--r-- | content/renderer/pepper/pepper_broker_impl.h | 36 | ||||
-rw-r--r-- | content/renderer/pepper/pepper_plugin_delegate_impl.cc | 53 | ||||
-rw-r--r-- | content/renderer/pepper/pepper_plugin_delegate_impl.h | 8 | ||||
-rw-r--r-- | content/renderer/render_view_impl.cc | 8 | ||||
-rw-r--r-- | content/renderer/render_view_impl.h | 1 |
11 files changed, 236 insertions, 62 deletions
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 9ddb933..30d1190 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc @@ -682,6 +682,8 @@ bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host, OnSetSelectedColorInColorChooser) IPC_MESSAGE_HANDLER(ViewHostMsg_PepperPluginHung, OnPepperPluginHung) IPC_MESSAGE_HANDLER(ViewHostMsg_WebUISend, OnWebUISend) + IPC_MESSAGE_HANDLER(ViewHostMsg_RequestPpapiBrokerPermission, + OnRequestPpapiBrokerPermission) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP_EX() message_source_ = NULL; @@ -2240,6 +2242,33 @@ void WebContentsImpl::OnWebUISend(const GURL& source_url, delegate_->WebUISend(this, source_url, name, args); } +void WebContentsImpl::OnRequestPpapiBrokerPermission( + int request_id, + const GURL& url, + const FilePath& plugin_path) { + base::Callback<void(bool)> callback = + base::Bind(&WebContentsImpl::OnPpapiBrokerPermissionResult, + base::Unretained(this), request_id); + ObserverListBase<WebContentsObserver>::Iterator it(observers_); + WebContentsObserver* observer; + while ((observer = it.GetNext()) != NULL) { + if (observer->RequestPpapiBrokerPermission(this, url, plugin_path, + callback)) + return; + } + + // Fall back to allowing the request if no observer handled it. + OnPpapiBrokerPermissionResult(request_id, true); +} + +void WebContentsImpl::OnPpapiBrokerPermissionResult(int request_id, + bool result) { + RenderViewHostImpl* rvh = GetRenderViewHostImpl(); + rvh->Send(new ViewMsg_PpapiBrokerPermissionResult(rvh->GetRoutingID(), + request_id, + result)); +} + // Notifies the RenderWidgetHost instance about the fact that the page is // loading, or done loading and calls the base implementation. void WebContentsImpl::SetIsLoading(bool is_loading, diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index bc95844..a74bc9e 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h @@ -485,6 +485,10 @@ class CONTENT_EXPORT WebContentsImpl bool success, const string16& user_input); + // Callback function when requesting permission to access the PPAPI broker. + // |result| is true if permission was granted. + void OnPpapiBrokerPermissionResult(int request_id, bool result); + // IPC message handlers. void OnRegisterIntentService(const webkit_glue::WebIntentServiceData& data, bool user_gesture); @@ -534,6 +538,9 @@ class CONTENT_EXPORT WebContentsImpl void OnWebUISend(const GURL& source_url, const std::string& name, const base::ListValue& args); + void OnRequestPpapiBrokerPermission(int request_id, + const GURL& url, + const FilePath& plugin_path); // Changes the IsLoading state and notifies delegate as needed // |details| is used to provide details on the load that just finished diff --git a/content/common/view_messages.h b/content/common/view_messages.h index 790b4b3..09b881f 100644 --- a/content/common/view_messages.h +++ b/content/common/view_messages.h @@ -1310,6 +1310,13 @@ IPC_MESSAGE_ROUTED2(ViewMsg_PpapiBrokerChannelCreated, int /* request_id */, IPC::ChannelHandle /* handle */) +// Reply to ViewHostMsg_RequestPpapiBrokerPermission. +// Tells the renderer whether permission to access to PPAPI broker was granted +// or not. +IPC_MESSAGE_ROUTED2(ViewMsg_PpapiBrokerPermissionResult, + int /* request_id */, + bool /* result */) + // Tells the renderer to empty its plugin list cache, optional reloading // pages containing plugins. IPC_MESSAGE_CONTROL1(ViewMsg_PurgePluginListCache, @@ -1849,6 +1856,15 @@ IPC_MESSAGE_CONTROL3(ViewHostMsg_OpenChannelToPpapiBroker, int /* request_id */, FilePath /* path */) +// A renderer sends this to the browser process when it wants to access a PPAPI +// broker. In contrast to ViewHostMsg_OpenChannelToPpapiBroker, this is called +// for every connection. +// The browser will respond with ViewMsg_PpapiBrokerPermissionResult. +IPC_MESSAGE_ROUTED3(ViewHostMsg_RequestPpapiBrokerPermission, + int /* request_id */, + GURL /* document_url */, + FilePath /* plugin_path */) + #if defined(USE_X11) // A renderer sends this when it needs a browser-side widget for // hosting a windowed plugin. id is the XID of the plugin window, for which diff --git a/content/public/browser/web_contents_observer.cc b/content/public/browser/web_contents_observer.cc index 1479029..f40db1d 100644 --- a/content/public/browser/web_contents_observer.cc +++ b/content/public/browser/web_contents_observer.cc @@ -37,6 +37,14 @@ void WebContentsObserver::Observe(WebContents* web_contents) { } } +bool WebContentsObserver::RequestPpapiBrokerPermission( + WebContents* web_contents, + const GURL& url, + const FilePath& plugin_path, + const base::Callback<void(bool)>& callback) { + return false; +} + bool WebContentsObserver::OnMessageReceived(const IPC::Message& message) { return false; } diff --git a/content/public/browser/web_contents_observer.h b/content/public/browser/web_contents_observer.h index 99fc805..ae81b55 100644 --- a/content/public/browser/web_contents_observer.h +++ b/content/public/browser/web_contents_observer.h @@ -5,6 +5,7 @@ #ifndef CONTENT_PUBLIC_BROWSER_WEB_CONTENTS_OBSERVER_H_ #define CONTENT_PUBLIC_BROWSER_WEB_CONTENTS_OBSERVER_H_ +#include "base/callback_forward.h" #include "base/process_util.h" #include "content/common/content_export.h" #include "content/public/browser/navigation_controller.h" @@ -129,6 +130,18 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener, // Called when the user agent override for a WebContents has been changed. virtual void UserAgentOverrideSet(const std::string& user_agent) {} + // Requests permission to access the PPAPI broker. If the object handles the + // request, it should return true and eventually call the passed in |callback| + // with the result. Otherwise it should return false, in which case the next + // observer will be called. + // Implementations should make sure not to call the callback after the + // WebContents has been destroyed. + virtual bool RequestPpapiBrokerPermission( + WebContents* web_contents, + const GURL& url, + const FilePath& plugin_path, + const base::Callback<void(bool)>& callback); + // IPC::Listener implementation. virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; diff --git a/content/renderer/pepper/pepper_broker_impl.cc b/content/renderer/pepper/pepper_broker_impl.cc index 67fdd84..cda23e7 100644 --- a/content/renderer/pepper/pepper_broker_impl.cc +++ b/content/renderer/pepper/pepper_broker_impl.cc @@ -116,24 +116,14 @@ PepperBrokerImpl::PepperBrokerImpl(webkit::ppapi::PluginModule* plugin_module, } PepperBrokerImpl::~PepperBrokerImpl() { - // Report failure to all clients that had pending operations. - for (ClientMap::iterator i = pending_connects_.begin(); - i != pending_connects_.end(); ++i) { - base::WeakPtr<webkit::ppapi::PPB_Broker_Impl>& weak_ptr = i->second; - if (weak_ptr) { - weak_ptr->BrokerConnected( - ppapi::PlatformFileToInt(base::kInvalidPlatformFileValue), - PP_ERROR_ABORTED); - } - } - pending_connects_.clear(); - + ReportFailureToClients(PP_ERROR_ABORTED); plugin_module_->SetBroker(NULL); plugin_module_ = NULL; } // If the channel is not ready, queue the connection. -void PepperBrokerImpl::Connect(webkit::ppapi::PPB_Broker_Impl* client) { +void PepperBrokerImpl::AddPendingConnect( + webkit::ppapi::PPB_Broker_Impl* client) { DCHECK(pending_connects_.find(client) == pending_connects_.end()) << "Connect was already called for this client"; @@ -146,13 +136,7 @@ void PepperBrokerImpl::Connect(webkit::ppapi::PPB_Broker_Impl* client) { // longer using it. AddRef(); - if (!dispatcher_.get()) { - pending_connects_[client] = client->AsWeakPtr(); - return; - } - DCHECK(pending_connects_.empty()); - - ConnectPluginToBroker(client); + pending_connects_[client].client = client->AsWeakPtr(); } void PepperBrokerImpl::Disconnect(webkit::ppapi::PPB_Broker_Impl* client) { @@ -179,7 +163,7 @@ void PepperBrokerImpl::Disconnect(webkit::ppapi::PPB_Broker_Impl* client) { bool stopped = delegate_->StopWaitingForBrokerConnection(this); // Verify the assumption that there are no references other than the one - // client holds, which will be released below. + // |client| holds, which will be released below. DCHECK(!stopped || HasOneRef()); } } @@ -193,26 +177,81 @@ void PepperBrokerImpl::OnBrokerChannelConnected( const IPC::ChannelHandle& channel_handle) { scoped_ptr<PepperBrokerDispatcherWrapper> dispatcher( new PepperBrokerDispatcherWrapper); - if (dispatcher->Init(channel_handle)) { - dispatcher_.reset(dispatcher.release()); - - // Process all pending channel requests from the plugins. - for (ClientMap::iterator i = pending_connects_.begin(); - i != pending_connects_.end(); ++i) { - base::WeakPtr<webkit::ppapi::PPB_Broker_Impl>& weak_ptr = i->second; - if (weak_ptr) - ConnectPluginToBroker(weak_ptr); + if (!dispatcher->Init(channel_handle)) { + ReportFailureToClients(PP_ERROR_FAILED); + return; + } + + dispatcher_.reset(dispatcher.release()); + + // Process all pending channel requests from the plugins. + for (ClientMap::iterator i = pending_connects_.begin(); + i != pending_connects_.end();) { + base::WeakPtr<webkit::ppapi::PPB_Broker_Impl>& weak_ptr = + i->second.client; + if (!i->second.is_authorized) { + ++i; + continue; } - } else { - // Report failure to all clients. - for (ClientMap::iterator i = pending_connects_.begin(); - i != pending_connects_.end(); ++i) { - base::WeakPtr<webkit::ppapi::PPB_Broker_Impl>& weak_ptr = i->second; - if (weak_ptr) { - weak_ptr->BrokerConnected( - ppapi::PlatformFileToInt(base::kInvalidPlatformFileValue), - PP_ERROR_FAILED); - } + + if (weak_ptr) + ConnectPluginToBroker(weak_ptr); + + pending_connects_.erase(i++); + } +} + +void PepperBrokerImpl::OnBrokerPermissionResult( + webkit::ppapi::PPB_Broker_Impl* client, + bool result) { + ClientMap::iterator entry = pending_connects_.find(client); + if (entry == pending_connects_.end()) + return; + + if (!entry->second.client) { + // Client has gone away. + pending_connects_.erase(entry); + return; + } + + if (!result) { + // Report failure. + client->BrokerConnected( + ppapi::PlatformFileToInt(base::kInvalidPlatformFileValue), + PP_ERROR_NOACCESS); + pending_connects_.erase(entry); + return; + } + + if (dispatcher_.get()) { + ConnectPluginToBroker(client); + pending_connects_.erase(entry); + return; + } + + // Mark the request as authorized, continue waiting for the broker + // connection. + DCHECK(!entry->second.is_authorized); + entry->second.is_authorized = true; +} + +PepperBrokerImpl::PendingConnection::PendingConnection() + : is_authorized(false) { +} + +PepperBrokerImpl::PendingConnection::~PendingConnection() { +} + +void PepperBrokerImpl::ReportFailureToClients(int error_code) { + DCHECK_NE(PP_OK, error_code); + for (ClientMap::iterator i = pending_connects_.begin(); + i != pending_connects_.end(); ++i) { + base::WeakPtr<webkit::ppapi::PPB_Broker_Impl>& weak_ptr = + i->second.client; + if (weak_ptr) { + weak_ptr->BrokerConnected( + ppapi::PlatformFileToInt(base::kInvalidPlatformFileValue), + error_code); } } pending_connects_.clear(); diff --git a/content/renderer/pepper/pepper_broker_impl.h b/content/renderer/pepper/pepper_broker_impl.h index 091000e..6ac31bb 100644 --- a/content/renderer/pepper/pepper_broker_impl.h +++ b/content/renderer/pepper/pepper_broker_impl.h @@ -53,32 +53,46 @@ class PepperBrokerImpl : public webkit::ppapi::PluginDelegate::Broker, PepperBrokerImpl(webkit::ppapi::PluginModule* plugin_module, PepperPluginDelegateImpl* delegate_); - // PepperBroker implementation. - virtual void Connect(webkit::ppapi::PPB_Broker_Impl* client) OVERRIDE; + // webkit::ppapi::PluginDelegate::Broker implementation. virtual void Disconnect(webkit::ppapi::PPB_Broker_Impl* client) OVERRIDE; + // Adds a pending connection to the broker. Balances out Disconnect() calls. + void AddPendingConnect(webkit::ppapi::PPB_Broker_Impl* client); + // Called when the channel to the broker has been established. void OnBrokerChannelConnected(const IPC::ChannelHandle& channel_handle); - // Connects the plugin to the broker via a pipe. - void ConnectPluginToBroker(webkit::ppapi::PPB_Broker_Impl* client); + // Called when we know whether permission to access the PPAPI broker was + // granted. + void OnBrokerPermissionResult(webkit::ppapi::PPB_Broker_Impl* client, + bool result); - // Asynchronously sends a pipe to the broker. - int32_t SendHandleToBroker(PP_Instance instance, - base::SyncSocket::Handle handle); - - protected: + private: friend class base::RefCountedThreadSafe<PepperBrokerImpl>; + struct PendingConnection { + PendingConnection(); + ~PendingConnection(); + + bool is_authorized; + base::WeakPtr<webkit::ppapi::PPB_Broker_Impl> client; + }; + virtual ~PepperBrokerImpl(); + // Reports failure to all clients that had pending operations. + void ReportFailureToClients(int error_code); + + // Connects the plugin to the broker via a pipe. + void ConnectPluginToBroker(webkit::ppapi::PPB_Broker_Impl* client); + scoped_ptr<PepperBrokerDispatcherWrapper> dispatcher_; // A map of pointers to objects that have requested a connection to the weak // pointer we can use to reference them. The mapping is needed so we can clean // up entries for objects that may have been deleted. - typedef std::map<webkit::ppapi::PPB_Broker_Impl*, - base::WeakPtr<webkit::ppapi::PPB_Broker_Impl> > ClientMap; + typedef std::map<webkit::ppapi::PPB_Broker_Impl*, PendingConnection> + ClientMap; ClientMap pending_connects_; // Pointer to the associated plugin module. diff --git a/content/renderer/pepper/pepper_plugin_delegate_impl.cc b/content/renderer/pepper/pepper_plugin_delegate_impl.cc index 559d97ce..ef64490 100644 --- a/content/renderer/pepper/pepper_plugin_delegate_impl.cc +++ b/content/renderer/pepper/pepper_plugin_delegate_impl.cc @@ -476,6 +476,7 @@ bool PepperPluginDelegateImpl::StopWaitingForBrokerConnection( return true; } } + return false; } @@ -809,28 +810,58 @@ PepperPluginDelegateImpl::ConnectToBroker( webkit::ppapi::PPB_Broker_Impl* client) { DCHECK(client); - // If a broker needs to be created, this will ensure it does not get deleted - // before Connect() adds a reference. - scoped_refptr<PepperBrokerImpl> broker_impl; - webkit::ppapi::PluginModule* plugin_module = webkit::ppapi::ResourceHelper::GetPluginModule(client); if (!plugin_module) return NULL; - webkit::ppapi::PluginDelegate::Broker* broker = plugin_module->GetBroker(); - if (!broker) { - broker_impl = CreateBroker(plugin_module); - if (!broker_impl.get()) + scoped_refptr<PepperBrokerImpl> broker = + static_cast<PepperBrokerImpl*>(plugin_module->GetBroker()); + if (!broker.get()) { + broker = CreateBroker(plugin_module); + if (!broker.get()) return NULL; - broker = broker_impl; } - // Adds a reference, ensuring not deleted when broker_impl goes out of scope. - broker->Connect(client); + int request_id = pending_permission_requests_.Add( + new base::WeakPtr<webkit::ppapi::PPB_Broker_Impl>(client->AsWeakPtr())); + if (!render_view_->Send( + new ViewHostMsg_RequestPpapiBrokerPermission( + render_view_->routing_id(), + request_id, + client->GetDocumentUrl(), + plugin_module->path()))) { + return NULL; + } + + // Adds a reference, ensuring that the broker is not deleted when + // |broker| goes out of scope. + broker->AddPendingConnect(client); + return broker; } +void PepperPluginDelegateImpl::OnPpapiBrokerPermissionResult( + int request_id, + bool result) { + scoped_ptr<base::WeakPtr<webkit::ppapi::PPB_Broker_Impl> > client_ptr( + pending_permission_requests_.Lookup(request_id)); + DCHECK(client_ptr.get()); + pending_permission_requests_.Remove(request_id); + base::WeakPtr<webkit::ppapi::PPB_Broker_Impl> client = *client_ptr; + if (!client) + return; + + webkit::ppapi::PluginModule* plugin_module = + webkit::ppapi::ResourceHelper::GetPluginModule(client); + if (!plugin_module) + return; + + PepperBrokerImpl* broker = + static_cast<PepperBrokerImpl*>(plugin_module->GetBroker()); + broker->OnBrokerPermissionResult(client, result); +} + bool PepperPluginDelegateImpl::AsyncOpenFile( const FilePath& path, int flags, diff --git a/content/renderer/pepper/pepper_plugin_delegate_impl.h b/content/renderer/pepper/pepper_plugin_delegate_impl.h index 783eeaa..ebfbddd 100644 --- a/content/renderer/pepper/pepper_plugin_delegate_impl.h +++ b/content/renderer/pepper/pepper_plugin_delegate_impl.h @@ -130,6 +130,10 @@ class PepperPluginDelegateImpl // Removes broker from pending_connect_broker_ if present. Returns true if so. bool StopWaitingForBrokerConnection(PepperBrokerImpl* broker); + // Called when we know whether permission to access the PPAPI broker was + // granted. + void OnPpapiBrokerPermissionResult(int request_id, bool result); + // Notification that the render view has been focused or defocused. This // notifies all of the plugins. void OnSetFocus(bool has_focus); @@ -497,6 +501,10 @@ class PepperPluginDelegateImpl typedef IDMap<scoped_refptr<PepperBrokerImpl>, IDMapOwnPointer> BrokerMap; BrokerMap pending_connect_broker_; + typedef IDMap<base::WeakPtr<webkit::ppapi::PPB_Broker_Impl> > + PermissionRequestMap; + PermissionRequestMap pending_permission_requests_; + // Whether or not the focus is on a PPAPI plugin webkit::ppapi::PluginInstance* focused_plugin_; diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index c8669bb..3c9e785 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc @@ -985,6 +985,8 @@ bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(ViewMsg_AsyncOpenFile_ACK, OnAsyncFileOpened) IPC_MESSAGE_HANDLER(ViewMsg_PpapiBrokerChannelCreated, OnPpapiBrokerChannelCreated) + IPC_MESSAGE_HANDLER(ViewMsg_PpapiBrokerPermissionResult, + OnPpapiBrokerPermissionResult) IPC_MESSAGE_HANDLER(ViewMsg_GetAllSavableResourceLinksForCurrentPage, OnGetAllSavableResourceLinksForCurrentPage) IPC_MESSAGE_HANDLER( @@ -5833,6 +5835,12 @@ void RenderViewImpl::OnPpapiBrokerChannelCreated( handle); } +void RenderViewImpl::OnPpapiBrokerPermissionResult( + int request_id, + bool result) { + pepper_delegate_.OnPpapiBrokerPermissionResult(request_id, result); +} + #if defined(OS_MACOSX) void RenderViewImpl::OnSelectPopupMenuItem(int selected_index) { if (external_popup_menu_ == NULL) { diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h index a451a7b..8d64903 100644 --- a/content/renderer/render_view_impl.h +++ b/content/renderer/render_view_impl.h @@ -910,6 +910,7 @@ class RenderViewImpl : public RenderWidget, int message_id); void OnPpapiBrokerChannelCreated(int request_id, const IPC::ChannelHandle& handle); + void OnPpapiBrokerPermissionResult(int request_id, bool result); void OnCancelDownload(int32 download_id); void OnClearFocusedNode(); void OnClosePage(); |