Refactor browser plugin permission requests map.
The request/response parts are now done through interface methods.
This is copied from CL originally by 
Michael Thiessen, [email protected], crrev.com/12963006.

BUG=224692
TEST=browser_tests:WebViewTest.*

Review URL: https://chromiumcodereview.appspot.com/14694015

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@198288 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/content/browser/browser_plugin/browser_plugin_guest.cc b/content/browser/browser_plugin/browser_plugin_guest.cc
index 48afb903..cffa56c 100644
--- a/content/browser/browser_plugin/browser_plugin_guest.cc
+++ b/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -58,6 +58,133 @@
 // static
 BrowserPluginHostFactory* BrowserPluginGuest::factory_ = NULL;
 
+// Parent class for the various types of permission requests, each of which
+// should be able to handle the response to their permission request.
+class BrowserPluginGuest::PermissionRequest {
+ public:
+  virtual void Respond(bool should_allow) = 0;
+  virtual ~PermissionRequest() {}
+ protected:
+  PermissionRequest() {}
+};
+
+class BrowserPluginGuest::DownloadRequest : public PermissionRequest {
+ public:
+  explicit DownloadRequest(base::Callback<void(bool)> callback)
+      : callback_(callback) {}
+  virtual void Respond(bool should_allow) OVERRIDE {
+    callback_.Run(should_allow);
+  }
+  virtual ~DownloadRequest() {}
+ private:
+  base::Callback<void(bool)> callback_;
+};
+
+class BrowserPluginGuest::GeolocationRequest : public PermissionRequest {
+ public:
+  GeolocationRequest(GeolocationCallback callback,
+                     int bridge_id,
+                     BrowserPluginGuest* guest,
+                     base::WeakPtrFactory<BrowserPluginGuest>* weak_ptr_factory)
+                     : callback_(callback),
+                       bridge_id_(bridge_id),
+                       guest_(guest),
+                       weak_ptr_factory_(weak_ptr_factory) {}
+
+  virtual void Respond(bool should_allow) OVERRIDE {
+    WebContents* web_contents = guest_->embedder_web_contents();
+    if (should_allow && web_contents) {
+      // If renderer side embedder decides to allow gelocation, we need to check
+      // if the app/embedder itself has geolocation access.
+      BrowserContext* browser_context = web_contents->GetBrowserContext();
+      if (browser_context) {
+        GeolocationPermissionContext* geolocation_context =
+            browser_context->GetGeolocationPermissionContext();
+        if (geolocation_context) {
+          base::Callback<void(bool)> geolocation_callback = base::Bind(
+              &BrowserPluginGuest::SetGeolocationPermission,
+              weak_ptr_factory_->GetWeakPtr(),
+              callback_,
+              bridge_id_);
+          geolocation_context->RequestGeolocationPermission(
+              web_contents->GetRenderProcessHost()->GetID(),
+              web_contents->GetRoutingID(),
+              // The geolocation permission request here is not initiated
+              // through WebGeolocationPermissionRequest. We are only interested
+              // in the fact whether the embedder/app has geolocation
+              // permission. Therefore we use an invalid |bridge_id|.
+              -1 /* bridge_id */,
+              web_contents->GetURL(),
+              geolocation_callback);
+          return;
+        }
+      }
+    }
+    guest_->SetGeolocationPermission(callback_, bridge_id_, false);
+  }
+  virtual ~GeolocationRequest() {}
+ private:
+  base::Callback<void(bool)> callback_;
+  int bridge_id_;
+  BrowserPluginGuest* guest_;
+  base::WeakPtrFactory<BrowserPluginGuest>* weak_ptr_factory_;
+};
+
+class BrowserPluginGuest::MediaRequest : public PermissionRequest {
+ public:
+  MediaRequest(const MediaStreamRequest& request,
+               const MediaResponseCallback& callback,
+               BrowserPluginGuest* guest)
+               : request_(request),
+                 callback_(callback),
+                 guest_(guest) {}
+
+  virtual void Respond(bool should_allow) OVERRIDE {
+    WebContentsImpl* web_contents = guest_->embedder_web_contents();
+    if (should_allow && web_contents) {
+      // Re-route the request to the embedder's WebContents; the guest gets the
+      // permission this way.
+      web_contents->RequestMediaAccessPermission(request_, callback_);
+    } else {
+      // Deny the request.
+      callback_.Run(MediaStreamDevices(), scoped_ptr<MediaStreamUI>());
+    }
+
+  }
+  virtual ~MediaRequest() {}
+ private:
+  MediaStreamRequest request_;
+  MediaResponseCallback callback_;
+  BrowserPluginGuest* guest_;
+};
+
+class BrowserPluginGuest::NewWindowRequest : public PermissionRequest {
+ public:
+  NewWindowRequest(int instance_id, BrowserPluginGuest* guest)
+      : instance_id_(instance_id),
+        guest_(guest) {}
+
+  virtual void Respond(bool should_allow) OVERRIDE {
+    int embedder_render_process_id =
+        guest_->embedder_web_contents()->GetRenderProcessHost()->GetID();
+    BrowserPluginGuest* guest =
+        guest_->GetWebContents()->GetBrowserPluginGuestManager()->
+            GetGuestByInstanceID(instance_id_, embedder_render_process_id);
+    if (!guest) {
+      LOG(INFO) << "Guest not found. Instance ID: " << instance_id_;
+      return;
+    }
+
+    // If we do not destroy the guest then we allow the new window.
+    if (!should_allow)
+      guest->Destroy();
+  }
+  virtual ~NewWindowRequest() {}
+ private:
+  int instance_id_;
+  BrowserPluginGuest* guest_;
+};
+
 namespace {
 const size_t kNumMaxOutstandingPermissionRequests = 1024;
 
@@ -99,7 +226,7 @@
   return std::string();
 }
 
-}
+}  // namespace
 
 class BrowserPluginGuest::EmbedderRenderViewHostObserver
     : public RenderViewHostObserver {
@@ -379,18 +506,15 @@
     int request_id,
     const std::string& request_method,
     const base::Callback<void(bool)>& callback) {
-  if (download_request_callback_map_.size() >=
-          kNumMaxOutstandingPermissionRequests) {
+  if (permission_request_map_.size() >= kNumMaxOutstandingPermissionRequests) {
     // Deny the download request.
     callback.Run(false);
     return;
   }
 
-  // TODO(lazyboy): Remove download specific map
-  // |download_request_callback_map_| once we have generalized request items for
-  // all permission types.
   int permission_request_id = next_permission_request_id_++;
-  download_request_callback_map_[permission_request_id] = callback;
+  permission_request_map_[permission_request_id] =
+      new DownloadRequest(callback);
 
   BrowserThread::PostTaskAndReplyWithResult(
       BrowserThread::IO, FROM_HERE,
@@ -565,7 +689,8 @@
                    base::Value::CreateStringValue(
                        WindowOpenDispositionToString(disposition)));
   int request_id = next_permission_request_id_++;
-  new_window_request_map_[request_id] = guest->instance_id();
+  permission_request_map_[request_id] =
+      new NewWindowRequest(guest->instance_id(), this);
   SendMessageToEmbedder(new BrowserPluginMsg_RequestPermission(
       instance_id(), BrowserPluginPermissionTypeNewWindow,
       request_id, request_info));
@@ -651,13 +776,14 @@
     int bridge_id,
     const GURL& requesting_frame,
     const GeolocationCallback& callback) {
-  if (geolocation_request_map_.size() >= kNumMaxOutstandingPermissionRequests) {
+  if (permission_request_map_.size() >= kNumMaxOutstandingPermissionRequests) {
     // Deny the geolocation request.
     callback.Run(false);
     return;
   }
   int request_id = next_permission_request_id_++;
-  geolocation_request_map_[request_id] = std::make_pair(callback, bridge_id);
+  permission_request_map_[request_id] = new GeolocationRequest(
+      callback, bridge_id, this, &weak_ptr_factory_);
   DCHECK(bridge_id_to_request_id_map_.find(bridge_id) ==
          bridge_id_to_request_id_map_.end());
   bridge_id_to_request_id_map_[bridge_id] = request_id;
@@ -672,28 +798,25 @@
 }
 
 void BrowserPluginGuest::CancelGeolocationRequest(int bridge_id) {
-  std::map<int, int>::iterator iter =
+  std::map<int, int>::iterator bridge_itr =
       bridge_id_to_request_id_map_.find(bridge_id);
-  if (iter == bridge_id_to_request_id_map_.end())
+  if (bridge_itr == bridge_id_to_request_id_map_.end())
     return;
 
-  int request_id = iter->second;
-  GeolocationRequestsMap::iterator callback_iter =
-      geolocation_request_map_.find(request_id);
-  if (callback_iter != geolocation_request_map_.end())
-    geolocation_request_map_.erase(callback_iter);
+  int request_id = bridge_itr->second;
+  bridge_id_to_request_id_map_.erase(bridge_itr);
+  RequestMap::iterator request_itr = permission_request_map_.find(request_id);
+  if (request_itr == permission_request_map_.end())
+    return;
+  delete request_itr->second;
+  permission_request_map_.erase(request_itr);
 }
 
-void BrowserPluginGuest::SetGeolocationPermission(int request_id,
+void BrowserPluginGuest::SetGeolocationPermission(GeolocationCallback callback,
+                                                  int bridge_id,
                                                   bool allowed) {
-  GeolocationRequestsMap::iterator callback_iter =
-      geolocation_request_map_.find(request_id);
-  if (callback_iter != geolocation_request_map_.end()) {
-    GeolocationRequestItem& item = callback_iter->second;
-    item.first.Run(allowed);
-    bridge_id_to_request_id_map_.erase(item.second);
-    geolocation_request_map_.erase(callback_iter);
-  }
+  callback.Run(allowed);
+  CancelGeolocationRequest(bridge_id);
 }
 
 void BrowserPluginGuest::DidCommitProvisionalLoadForFrame(
@@ -1160,22 +1283,18 @@
     BrowserPluginPermissionType permission_type,
     int request_id,
     bool should_allow) {
-  switch (permission_type) {
-    case BrowserPluginPermissionTypeDownload:
-      OnRespondPermissionDownload(request_id, should_allow);
-      break;
-    case BrowserPluginPermissionTypeGeolocation:
-      OnRespondPermissionGeolocation(request_id, should_allow);
-      break;
-    case BrowserPluginPermissionTypeMedia:
-      OnRespondPermissionMedia(request_id, should_allow);
-      break;
-    case BrowserPluginPermissionTypeNewWindow:
-      OnRespondPermissionNewWindow(request_id, should_allow);
-      break;
-    default:
-      NOTREACHED();
-      break;
+  RequestMap::iterator request_itr = permission_request_map_.find(request_id);
+  if (request_itr == permission_request_map_.end()) {
+    LOG(INFO) << "Not a valid request ID.";
+    return;
+  }
+  request_itr->second->Respond(should_allow);
+
+  // Geolocation requests have to hang around for a while, so we don't delete
+  // them here.
+  if (permission_type != BrowserPluginPermissionTypeGeolocation) {
+    delete request_itr->second;
+    permission_request_map_.erase(request_itr);
   }
 }
 
@@ -1277,15 +1396,14 @@
     WebContents* web_contents,
     const MediaStreamRequest& request,
     const MediaResponseCallback& callback) {
-  if (media_requests_map_.size() >= kNumMaxOutstandingPermissionRequests) {
+  if (permission_request_map_.size() >= kNumMaxOutstandingPermissionRequests) {
     // Deny the media request.
     callback.Run(MediaStreamDevices(), scoped_ptr<MediaStreamUI>());
     return;
   }
   int request_id = next_permission_request_id_++;
-  media_requests_map_.insert(
-      std::make_pair(request_id,
-                     std::make_pair(request, callback)));
+  permission_request_map_[request_id] =
+      new MediaRequest(request, callback, this);
 
   base::DictionaryValue request_info;
   request_info.Set(
@@ -1352,106 +1470,13 @@
       new BrowserPluginMsg_UpdateRect(instance_id(), relay_params));
 }
 
-void BrowserPluginGuest::OnRespondPermissionDownload(int request_id,
-                                                     bool should_allow) {
-  DownloadRequestMap::iterator download_request_iter =
-      download_request_callback_map_.find(request_id);
-  if (download_request_iter == download_request_callback_map_.end()) {
-    LOG(INFO) << "Not a valid request ID.";
-    return;
-  }
-
-  const base::Callback<void(bool)>& can_download_callback =
-    download_request_iter->second;
-  can_download_callback.Run(should_allow);
-}
-
-void BrowserPluginGuest::OnRespondPermissionGeolocation(
-    int request_id, bool should_allow) {
-  if (should_allow && embedder_web_contents_) {
-    // If renderer side embedder decides to allow gelocation, we need to check
-    // if the app/embedder itself has geolocation access.
-    BrowserContext* browser_context =
-        embedder_web_contents_->GetBrowserContext();
-    if (browser_context) {
-      GeolocationPermissionContext* geolocation_context =
-          browser_context->GetGeolocationPermissionContext();
-      if (geolocation_context) {
-        base::Callback<void(bool)> geolocation_callback = base::Bind(
-            &BrowserPluginGuest::SetGeolocationPermission,
-            weak_ptr_factory_.GetWeakPtr(),
-            request_id);
-        geolocation_context->RequestGeolocationPermission(
-            embedder_web_contents_->GetRenderProcessHost()->GetID(),
-            embedder_web_contents_->GetRoutingID(),
-            // The geolocation permission request here is not initiated through
-            // WebGeolocationPermissionRequest. We are only interested in the
-            // fact whether the embedder/app has geolocation permission.
-            // Therefore we use an invalid |bridge_id|.
-            -1 /* bridge_id */,
-            embedder_web_contents_->GetURL(),
-            geolocation_callback);
-        return;
-      }
-    }
-  }
-  SetGeolocationPermission(request_id, false);
-}
-
-void BrowserPluginGuest::OnRespondPermissionMedia(
-    int request_id, bool should_allow) {
-  MediaStreamRequestsMap::iterator media_request_iter =
-      media_requests_map_.find(request_id);
-  if (media_request_iter == media_requests_map_.end()) {
-    LOG(INFO) << "Not a valid request ID.";
-    return;
-  }
-  const MediaStreamRequest& request = media_request_iter->second.first;
-  const MediaResponseCallback& callback =
-      media_request_iter->second.second;
-
-  if (should_allow && embedder_web_contents_) {
-    // Re-route the request to the embedder's WebContents; the guest gets the
-    // permission this way.
-    embedder_web_contents_->RequestMediaAccessPermission(request, callback);
-  } else {
-    // Deny the request.
-    callback.Run(MediaStreamDevices(), scoped_ptr<MediaStreamUI>());
-  }
-  media_requests_map_.erase(media_request_iter);
-}
-
-void BrowserPluginGuest::OnRespondPermissionNewWindow(
-    int request_id, bool should_allow) {
-  NewWindowRequestMap::iterator new_window_request_iter =
-      new_window_request_map_.find(request_id);
-  if (new_window_request_iter == new_window_request_map_.end()) {
-    LOG(INFO) << "Not a valid request ID.";
-    return;
-  }
-  int instance_id = new_window_request_iter->second;
-  int embedder_render_process_id =
-      embedder_web_contents_->GetRenderProcessHost()->GetID();
-  BrowserPluginGuest* guest =
-      GetWebContents()->GetBrowserPluginGuestManager()->
-          GetGuestByInstanceID(instance_id, embedder_render_process_id);
-  if (!guest) {
-    LOG(INFO) << "Guest not found. Instance ID: " << instance_id;
-    return;
-  }
-  if (!should_allow)
-    guest->Destroy();
-  // If we do not destroy the guest then we allow the new window.
-  new_window_request_map_.erase(new_window_request_iter);
-}
-
 void BrowserPluginGuest::DidRetrieveDownloadURLFromRequestId(
     const std::string& request_method,
     int permission_request_id,
     const std::string& url) {
   if (url.empty()) {
-    OnRespondPermissionDownload(permission_request_id,
-                                false /* should_allow */);
+    OnRespondPermission(instance_id(), BrowserPluginPermissionTypeDownload,
+                        permission_request_id, false);
     return;
   }