Index: chrome/browser/guestview/webview/webview_guest.cc |
diff --git a/chrome/browser/guestview/webview/webview_guest.cc b/chrome/browser/guestview/webview/webview_guest.cc |
index a57a445e5dc99288c4e68244b08519da1159852d..c05fa7cd06369e284d7644bc8a733d3264672996 100644 |
--- a/chrome/browser/guestview/webview/webview_guest.cc |
+++ b/chrome/browser/guestview/webview/webview_guest.cc |
@@ -4,6 +4,7 @@ |
#include "chrome/browser/guestview/webview/webview_guest.h" |
+#include "base/message_loop/message_loop.h" |
#include "base/strings/stringprintf.h" |
#include "chrome/browser/chrome_notification_types.h" |
#include "chrome/browser/extensions/api/web_request/web_request_api.h" |
@@ -18,6 +19,7 @@ |
#include "chrome/browser/guestview/webview/webview_permission_types.h" |
#include "chrome/common/chrome_version_info.h" |
#include "content/public/browser/browser_thread.h" |
+#include "content/public/browser/geolocation_permission_context.h" |
#include "content/public/browser/native_web_keyboard_event.h" |
#include "content/public/browser/navigation_entry.h" |
#include "content/public/browser/notification_details.h" |
@@ -75,8 +77,6 @@ static std::string PermissionTypeToString(BrowserPluginPermissionType type) { |
switch (type) { |
case BROWSER_PLUGIN_PERMISSION_TYPE_DOWNLOAD: |
return webview::kPermissionTypeDownload; |
- case BROWSER_PLUGIN_PERMISSION_TYPE_GEOLOCATION: |
- return webview::kPermissionTypeGeolocation; |
case BROWSER_PLUGIN_PERMISSION_TYPE_MEDIA: |
return webview::kPermissionTypeMedia; |
case BROWSER_PLUGIN_PERMISSION_TYPE_NEW_WINDOW: |
@@ -93,6 +93,8 @@ static std::string PermissionTypeToString(BrowserPluginPermissionType type) { |
switch (webview) { |
case WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN: |
return webview::kPermissionTypeLoadPlugin; |
+ case WEB_VIEW_PERMISSION_TYPE_GEOLOCATION: |
+ return webview::kPermissionTypeGeolocation; |
} |
NOTREACHED(); |
} |
@@ -193,10 +195,6 @@ void WebViewGuest::RecordUserInitiatedUMA(const PermissionResponseInfo& info, |
content::RecordAction( |
UserMetricsAction("BrowserPlugin.PermissionAllow.Download")); |
break; |
- case BROWSER_PLUGIN_PERMISSION_TYPE_GEOLOCATION: |
- content::RecordAction( |
- UserMetricsAction("BrowserPlugin.PermissionAllow.Geolocation")); |
- break; |
case BROWSER_PLUGIN_PERMISSION_TYPE_MEDIA: |
content::RecordAction( |
UserMetricsAction("BrowserPlugin.PermissionAllow.Media")); |
@@ -223,6 +221,10 @@ void WebViewGuest::RecordUserInitiatedUMA(const PermissionResponseInfo& info, |
content::RecordAction( |
UserMetricsAction("WebView.Guest.PermissionAllow.PluginLoad")); |
break; |
+ case WEB_VIEW_PERMISSION_TYPE_GEOLOCATION: |
+ content::RecordAction( |
+ UserMetricsAction("WebView.PermissionAllow.Geolocation")); |
+ break; |
default: |
break; |
} |
@@ -234,10 +236,6 @@ void WebViewGuest::RecordUserInitiatedUMA(const PermissionResponseInfo& info, |
content::RecordAction( |
UserMetricsAction("BrowserPlugin.PermissionDeny.Download")); |
break; |
- case BROWSER_PLUGIN_PERMISSION_TYPE_GEOLOCATION: |
- content::RecordAction( |
- UserMetricsAction("BrowserPlugin.PermissionDeny.Geolocation")); |
- break; |
case BROWSER_PLUGIN_PERMISSION_TYPE_MEDIA: |
content::RecordAction( |
UserMetricsAction("BrowserPlugin.PermissionDeny.Media")); |
@@ -264,6 +262,10 @@ void WebViewGuest::RecordUserInitiatedUMA(const PermissionResponseInfo& info, |
content::RecordAction( |
UserMetricsAction("WebView.Guest.PermissionDeny.PluginLoad")); |
break; |
+ case WEB_VIEW_PERMISSION_TYPE_GEOLOCATION: |
+ content::RecordAction( |
+ UserMetricsAction("WebView.PermissionDeny.Geolocation")); |
+ break; |
default: |
break; |
} |
@@ -437,7 +439,7 @@ void WebViewGuest::RendererUnresponsive() { |
DispatchEvent(new GuestView::Event(webview::kEventUnresponsive, args.Pass())); |
} |
-bool WebViewGuest::RequestPermission( |
+int WebViewGuest::RequestPermission( |
BrowserPluginPermissionType permission_type, |
const base::DictionaryValue& request_info, |
const PermissionResponseCallback& callback, |
@@ -445,8 +447,17 @@ bool WebViewGuest::RequestPermission( |
// If there are too many pending permission requests then reject this request. |
if (pending_permission_requests_.size() >= |
webview::kMaxOutstandingPermissionRequests) { |
- callback.Run(false, std::string()); |
- return true; |
+ // Let the stack unwind before we deny the permission request so that |
+ // objects held by the permission request are not destroyed immediately |
+ // after creation. This is to allow those same objects to be accessed again |
+ // in the same scope without fear of use after freeing. |
+ base::MessageLoop::current()->PostTask( |
+ FROM_HERE, |
+ base::Bind(&PermissionResponseCallback::Run, |
+ base::Owned(new PermissionResponseCallback(callback)), |
+ allowed_by_default, |
+ std::string())); |
+ return webview::kInvalidPermissionRequestID; |
} |
int request_id = next_permission_request_id_++; |
@@ -473,7 +484,7 @@ bool WebViewGuest::RequestPermission( |
break; |
} |
} |
- return true; |
+ return request_id; |
} |
void WebViewGuest::Observe(int type, |
@@ -544,6 +555,73 @@ void WebViewGuest::Reload() { |
guest_web_contents()->GetController().Reload(false); |
} |
+ |
+void WebViewGuest::RequestGeolocationPermission( |
+ int bridge_id, |
+ const GURL& requesting_frame, |
+ bool user_gesture, |
+ const base::Callback<void(bool)>& callback) { |
+ base::DictionaryValue request_info; |
+ request_info.Set(guestview::kUrl, |
+ base::Value::CreateStringValue(requesting_frame.spec())); |
+ request_info.Set(guestview::kUserGesture, |
+ base::Value::CreateBooleanValue(user_gesture)); |
+ int request_id = RequestPermission( |
+ static_cast<BrowserPluginPermissionType>( |
+ WEB_VIEW_PERMISSION_TYPE_GEOLOCATION), |
+ request_info, |
+ base::Bind(&WebViewGuest::OnWebViewGeolocationPermissionResponse, |
+ base::Unretained(this), |
+ bridge_id, |
+ user_gesture, |
+ callback), |
+ false /* allowed_by_default */); |
+ bridge_id_to_request_id_map_[bridge_id] = request_id; |
+} |
+ |
+void WebViewGuest::OnWebViewGeolocationPermissionResponse( |
+ int bridge_id, |
+ bool user_gesture, |
+ const base::Callback<void(bool)>& callback, |
+ bool allow, |
+ const std::string& user_input) { |
+ // The <webview> embedder has allowed the permission. We now need to make sure |
+ // that the embedder has geolocation permission. |
+ RemoveBridgeID(bridge_id); |
+ |
+ if (!allow || !attached()) { |
+ callback.Run(false); |
+ return; |
+ } |
+ |
+ content::GeolocationPermissionContext* geolocation_context = |
+ browser_context()->GetGeolocationPermissionContext(); |
+ |
+ DCHECK(geolocation_context); |
+ 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()->GetLastCommittedURL(), |
+ user_gesture, |
+ callback); |
+} |
+ |
+void WebViewGuest::CancelGeolocationPermissionRequest(int bridge_id) { |
+ int request_id = RemoveBridgeID(bridge_id); |
+ RequestMap::iterator request_itr = |
+ pending_permission_requests_.find(request_id); |
+ |
+ if (request_itr == pending_permission_requests_.end()) |
+ return; |
+ |
+ pending_permission_requests_.erase(request_itr); |
+} |
+ |
WebViewGuest::SetPermissionResult WebViewGuest::SetPermission( |
int request_id, |
PermissionResponseAction action, |
@@ -818,6 +896,18 @@ void WebViewGuest::InjectChromeVoxIfNeeded( |
#endif |
} |
+int WebViewGuest::RemoveBridgeID(int bridge_id) { |
+ std::map<int, int>::iterator bridge_itr = |
+ bridge_id_to_request_id_map_.find(bridge_id); |
+ if (bridge_itr == bridge_id_to_request_id_map_.end()) |
+ return webview::kInvalidPermissionRequestID; |
+ |
+ int request_id = bridge_itr->second; |
+ bridge_id_to_request_id_map_.erase(bridge_itr); |
+ return request_id; |
+} |
+ |
+ |
WebViewGuest::PermissionResponseInfo::PermissionResponseInfo() |
: permission_type(BROWSER_PLUGIN_PERMISSION_TYPE_UNKNOWN), |
allowed_by_default(false) { |