| 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..fc82fbbe3e9996565e6133f8617233d06cab346d 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:
|
| @@ -91,6 +91,8 @@ static std::string PermissionTypeToString(BrowserPluginPermissionType type) {
|
| default: {
|
| WebViewPermissionType webview = static_cast<WebViewPermissionType>(type);
|
| switch (webview) {
|
| + case WEB_VIEW_PERMISSION_TYPE_GEOLOCATION:
|
| + return webview::kPermissionTypeGeolocation;
|
| case WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN:
|
| return webview::kPermissionTypeLoadPlugin;
|
| }
|
| @@ -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"));
|
| @@ -219,6 +217,10 @@ void WebViewGuest::RecordUserInitiatedUMA(const PermissionResponseInfo& info,
|
| WebViewPermissionType webview_permission_type =
|
| static_cast<WebViewPermissionType>(info.permission_type);
|
| switch (webview_permission_type) {
|
| + case WEB_VIEW_PERMISSION_TYPE_GEOLOCATION:
|
| + content::RecordAction(
|
| + UserMetricsAction("WebView.PermissionAllow.Geolocation"));
|
| + break;
|
| case WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN:
|
| content::RecordAction(
|
| UserMetricsAction("WebView.Guest.PermissionAllow.PluginLoad"));
|
| @@ -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"));
|
| @@ -260,6 +258,10 @@ void WebViewGuest::RecordUserInitiatedUMA(const PermissionResponseInfo& info,
|
| WebViewPermissionType webview_permission_type =
|
| static_cast<WebViewPermissionType>(info.permission_type);
|
| switch (webview_permission_type) {
|
| + case WEB_VIEW_PERMISSION_TYPE_GEOLOCATION:
|
| + content::RecordAction(
|
| + UserMetricsAction("WebView.PermissionDeny.Geolocation"));
|
| + break;
|
| case WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN:
|
| content::RecordAction(
|
| UserMetricsAction("WebView.Guest.PermissionDeny.PluginLoad"));
|
| @@ -437,43 +439,15 @@ void WebViewGuest::RendererUnresponsive() {
|
| DispatchEvent(new GuestView::Event(webview::kEventUnresponsive, args.Pass()));
|
| }
|
|
|
| -bool WebViewGuest::RequestPermission(
|
| +void WebViewGuest::RequestPermission(
|
| BrowserPluginPermissionType permission_type,
|
| const base::DictionaryValue& request_info,
|
| const PermissionResponseCallback& callback,
|
| bool allowed_by_default) {
|
| - // 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;
|
| - }
|
| -
|
| - int request_id = next_permission_request_id_++;
|
| - pending_permission_requests_[request_id] =
|
| - PermissionResponseInfo(callback, permission_type, allowed_by_default);
|
| - scoped_ptr<base::DictionaryValue> args(request_info.DeepCopy());
|
| - args->SetInteger(webview::kRequestId, request_id);
|
| - switch (permission_type) {
|
| - case BROWSER_PLUGIN_PERMISSION_TYPE_NEW_WINDOW: {
|
| - DispatchEvent(new GuestView::Event(webview::kEventNewWindow,
|
| - args.Pass()));
|
| - break;
|
| - }
|
| - case BROWSER_PLUGIN_PERMISSION_TYPE_JAVASCRIPT_DIALOG: {
|
| - DispatchEvent(new GuestView::Event(webview::kEventDialog,
|
| - args.Pass()));
|
| - break;
|
| - }
|
| - default: {
|
| - args->SetString(webview::kPermission,
|
| - PermissionTypeToString(permission_type));
|
| - DispatchEvent(new GuestView::Event(webview::kEventPermissionRequest,
|
| - args.Pass()));
|
| - break;
|
| - }
|
| - }
|
| - return true;
|
| + RequestPermissionInternal(permission_type,
|
| + request_info,
|
| + callback,
|
| + allowed_by_default);
|
| }
|
|
|
| void WebViewGuest::Observe(int type,
|
| @@ -544,6 +518,78 @@ 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));
|
| +
|
| + // It is safe to hold an unretained pointer to WebViewGuest because this
|
| + // callback is called from WebViewGuest::SetPermission.
|
| + const PermissionResponseCallback permission_callback =
|
| + base::Bind(&WebViewGuest::OnWebViewGeolocationPermissionResponse,
|
| + base::Unretained(this),
|
| + bridge_id,
|
| + user_gesture,
|
| + callback);
|
| + int request_id = RequestPermissionInternal(
|
| + static_cast<BrowserPluginPermissionType>(
|
| + WEB_VIEW_PERMISSION_TYPE_GEOLOCATION),
|
| + request_info,
|
| + permission_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 +864,65 @@ 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;
|
| +}
|
| +
|
| +int WebViewGuest::RequestPermissionInternal(
|
| + BrowserPluginPermissionType permission_type,
|
| + const base::DictionaryValue& request_info,
|
| + const PermissionResponseCallback& callback,
|
| + bool allowed_by_default) {
|
| + // If there are too many pending permission requests then reject this request.
|
| + if (pending_permission_requests_.size() >=
|
| + webview::kMaxOutstandingPermissionRequests) {
|
| + // 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_++;
|
| + pending_permission_requests_[request_id] =
|
| + PermissionResponseInfo(callback, permission_type, allowed_by_default);
|
| + scoped_ptr<base::DictionaryValue> args(request_info.DeepCopy());
|
| + args->SetInteger(webview::kRequestId, request_id);
|
| + switch (permission_type) {
|
| + case BROWSER_PLUGIN_PERMISSION_TYPE_NEW_WINDOW: {
|
| + DispatchEvent(new GuestView::Event(webview::kEventNewWindow,
|
| + args.Pass()));
|
| + break;
|
| + }
|
| + case BROWSER_PLUGIN_PERMISSION_TYPE_JAVASCRIPT_DIALOG: {
|
| + DispatchEvent(new GuestView::Event(webview::kEventDialog,
|
| + args.Pass()));
|
| + break;
|
| + }
|
| + default: {
|
| + args->SetString(webview::kPermission,
|
| + PermissionTypeToString(permission_type));
|
| + DispatchEvent(new GuestView::Event(webview::kEventPermissionRequest,
|
| + args.Pass()));
|
| + break;
|
| + }
|
| + }
|
| + return request_id;
|
| +}
|
| +
|
| WebViewGuest::PermissionResponseInfo::PermissionResponseInfo()
|
| : permission_type(BROWSER_PLUGIN_PERMISSION_TYPE_UNKNOWN),
|
| allowed_by_default(false) {
|
|
|