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
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 9ddb9336..30d1190 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -682,6 +682,8 @@
                         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 @@
     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 bc95844d..a74bc9e 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -485,6 +485,10 @@
                       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 @@
   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 @@
                     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 @@
                      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 14790293..f40db1d 100644
--- a/content/public/browser/web_contents_observer.cc
+++ b/content/public/browser/web_contents_observer.cc
@@ -37,6 +37,14 @@
   }
 }
 
+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..ae81b550 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 @@
   // 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() {
-  // 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 @@
   // 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 @@
       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 @@
     const IPC::ChannelHandle& channel_handle) {
   scoped_ptr<PepperBrokerDispatcherWrapper> dispatcher(
       new PepperBrokerDispatcherWrapper);
-  if (dispatcher->Init(channel_handle)) {
-    dispatcher_.reset(dispatcher.release());
+  if (!dispatcher->Init(channel_handle)) {
+    ReportFailureToClients(PP_ERROR_FAILED);
+    return;
+  }
 
-    // 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);
+  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..6ac31bb1 100644
--- a/content/renderer/pepper/pepper_broker_impl.h
+++ b/content/renderer/pepper/pepper_broker_impl.h
@@ -53,32 +53,46 @@
   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 @@
       return true;
     }
   }
+
   return false;
 }
 
@@ -809,28 +810,58 @@
     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 @@
   // 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 @@
   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..3c9e7856 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -985,6 +985,8 @@
     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 @@
                                                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 @@
                          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();
diff --git a/webkit/plugins/ppapi/plugin_delegate.h b/webkit/plugins/ppapi/plugin_delegate.h
index 7418070..3e75cc5 100644
--- a/webkit/plugins/ppapi/plugin_delegate.h
+++ b/webkit/plugins/ppapi/plugin_delegate.h
@@ -299,12 +299,10 @@
   // Provides access to the ppapi broker.
   class Broker {
    public:
-    virtual void Connect(webkit::ppapi::PPB_Broker_Impl* client) = 0;
-
     // Decrements the references to the broker.
     // When there are no more references, this renderer's dispatcher is
     // destroyed, allowing the broker to shutdown if appropriate.
-    // Callers should not reference this object after calling Disconnect.
+    // Callers should not reference this object after calling Disconnect().
     virtual void Disconnect(webkit::ppapi::PPB_Broker_Impl* client) = 0;
 
    protected:
@@ -404,7 +402,7 @@
 
   // A pointer is returned immediately, but it is not ready to be used until
   // BrokerConnected has been called.
-  // The caller is responsible for calling Release() on the returned pointer
+  // The caller is responsible for calling Disconnect() on the returned pointer
   // to clean up the corresponding resources allocated during this call.
   virtual Broker* ConnectToBroker(webkit::ppapi::PPB_Broker_Impl* client) = 0;
 
diff --git a/webkit/plugins/ppapi/ppb_broker_impl.cc b/webkit/plugins/ppapi/ppb_broker_impl.cc
index 2386e0d..49342fc 100644
--- a/webkit/plugins/ppapi/ppb_broker_impl.cc
+++ b/webkit/plugins/ppapi/ppb_broker_impl.cc
@@ -6,6 +6,9 @@
 
 #include "base/logging.h"
 #include "ppapi/shared_impl/platform_file.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h"
 #include "webkit/plugins/ppapi/common.h"
 #include "webkit/plugins/ppapi/plugin_module.h"
 #include "webkit/plugins/ppapi/resource_helper.h"
@@ -75,6 +78,11 @@
   return PP_OK;
 }
 
+GURL PPB_Broker_Impl::GetDocumentUrl() {
+  PluginInstance* plugin_instance = ResourceHelper::GetPluginInstance(this);
+  return plugin_instance->container()->element().document().url();
+}
+
 // Transfers ownership of the handle to the plugin.
 void PPB_Broker_Impl::BrokerConnected(int32_t handle, int32_t result) {
   DCHECK(pipe_handle_ ==
diff --git a/webkit/plugins/ppapi/ppb_broker_impl.h b/webkit/plugins/ppapi/ppb_broker_impl.h
index 6799c4f8..ab02ae8 100644
--- a/webkit/plugins/ppapi/ppb_broker_impl.h
+++ b/webkit/plugins/ppapi/ppb_broker_impl.h
@@ -36,6 +36,10 @@
       scoped_refptr< ::ppapi::TrackedCallback> connect_callback) OVERRIDE;
   virtual int32_t GetHandle(int32_t* handle) OVERRIDE;
 
+  // Returns the URL of the document this plug-in runs in. This is necessary to
+  // decide whether to grant access to the PPAPI broker.
+  GURL GetDocumentUrl();
+
   void BrokerConnected(int32_t handle, int32_t result);
 
  private: