Commit 7adb26a7 authored by hanxi@chromium.org's avatar hanxi@chromium.org

WebViewGuest is growing fairly large (~ 1600 lines). This CL aims to move all...

WebViewGuest is growing fairly large (~ 1600 lines). This CL aims to move all permission related code to a new helper class WebViewPermissionHelper:

- Rename PluginPermissionHelper to WebViewPermissionHelper;
- Move permission request code:
--- Include permissions: Download, PointerLock, Media, Geolocation, FileSystem, Plugin;
--- Not include: New Window API, Dialog API.

Review URL: https://codereview.chromium.org/347113002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@282080 0039d316-1c4b-4281-b951-d872f2087c98
parent f695672d
......@@ -9,6 +9,7 @@
#include "chrome/browser/extensions/api/context_menus/context_menus_api.h"
#include "chrome/browser/extensions/api/context_menus/context_menus_api_helpers.h"
#include "chrome/browser/extensions/tab_helper.h"
#include "chrome/browser/guest_view/web_view/web_view_permission_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/api/web_view_internal.h"
#include "content/public/browser/render_process_host.h"
......@@ -505,13 +506,14 @@ bool WebViewInternalSetPermissionFunction::RunAsyncSafe(WebViewGuest* guest) {
webview::SetPermission::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
WebViewGuest::PermissionResponseAction action = WebViewGuest::DEFAULT;
WebViewPermissionHelper::PermissionResponseAction action =
WebViewPermissionHelper::DEFAULT;
switch (params->action) {
case Params::ACTION_ALLOW:
action = WebViewGuest::ALLOW;
action = WebViewPermissionHelper::ALLOW;
break;
case Params::ACTION_DENY:
action = WebViewGuest::DENY;
action = WebViewPermissionHelper::DENY;
break;
case Params::ACTION_DEFAULT:
break;
......@@ -523,13 +525,18 @@ bool WebViewInternalSetPermissionFunction::RunAsyncSafe(WebViewGuest* guest) {
if (params->user_input)
user_input = *params->user_input;
WebViewGuest::SetPermissionResult result =
guest->SetPermission(params->request_id, action, user_input);
WebViewPermissionHelper* web_view_permission_helper =
WebViewPermissionHelper:: FromWebContents(guest->guest_web_contents());
EXTENSION_FUNCTION_VALIDATE(result != WebViewGuest::SET_PERMISSION_INVALID);
WebViewPermissionHelper::SetPermissionResult result =
web_view_permission_helper->SetPermission(
params->request_id, action, user_input);
EXTENSION_FUNCTION_VALIDATE(
result != WebViewPermissionHelper::SET_PERMISSION_INVALID);
SetResult(base::Value::CreateBooleanValue(
result == WebViewGuest::SET_PERMISSION_ALLOWED));
result == WebViewPermissionHelper::SET_PERMISSION_ALLOWED));
SendResponse(true);
return true;
}
......
......@@ -9,7 +9,7 @@
#if defined(ENABLE_EXTENSIONS)
#include "chrome/browser/content_settings/permission_request_id.h"
#include "chrome/browser/extensions/suggest_permission_util.h"
#include "chrome/browser/guest_view/web_view/web_view_guest.h"
#include "chrome/browser/guest_view/web_view/web_view_permission_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/process_map.h"
......@@ -41,12 +41,11 @@ bool GeolocationPermissionContextExtensions::RequestPermission(
#if defined(ENABLE_EXTENSIONS)
GURL requesting_frame_origin = requesting_frame.GetOrigin();
WebViewGuest* guest = WebViewGuest::FromWebContents(web_contents);
if (guest) {
guest->RequestGeolocationPermission(bridge_id,
requesting_frame,
user_gesture,
callback);
WebViewPermissionHelper* web_view_permission_helper =
WebViewPermissionHelper::FromWebContents(web_contents);
if (web_view_permission_helper) {
web_view_permission_helper->RequestGeolocationPermission(
bridge_id, requesting_frame, user_gesture, callback);
*permission_set = false;
*new_permission = false;
return true;
......@@ -91,10 +90,11 @@ bool GeolocationPermissionContextExtensions::CancelPermissionRequest(
content::WebContents* web_contents,
int bridge_id) {
#if defined(ENABLE_EXTENSIONS)
WebViewGuest* guest =
web_contents ? WebViewGuest::FromWebContents(web_contents) : NULL;
if (guest) {
guest->CancelGeolocationPermissionRequest(bridge_id);
WebViewPermissionHelper* web_view_permission_helper =
web_contents ? WebViewPermissionHelper::FromWebContents(web_contents)
: NULL;
if (web_view_permission_helper) {
web_view_permission_helper->CancelGeolocationPermissionRequest(bridge_id);
return true;
}
#endif // defined(ENABLE_EXTENSIONS)
......
......@@ -302,7 +302,7 @@ GuestViewBase::~GuestViewBase() {
pending_events_.clear();
}
void GuestViewBase::DispatchEvent(Event* event) {
void GuestViewBase::DispatchEventToEmbedder(Event* event) {
scoped_ptr<Event> event_ptr(event);
if (!in_extension()) {
NOTREACHED();
......@@ -337,7 +337,7 @@ void GuestViewBase::SendQueuedEvents() {
while (!pending_events_.empty()) {
linked_ptr<Event> event_ptr = pending_events_.front();
pending_events_.pop_front();
DispatchEvent(event_ptr.release());
DispatchEventToEmbedder(event_ptr.release());
}
}
......
......@@ -204,15 +204,15 @@ class GuestViewBase : public content::BrowserPluginGuestDelegate,
content::WebContents* embedder_web_contents,
const base::DictionaryValue& extra_params) OVERRIDE FINAL;
// Dispatches an event |event_name| to the embedder with the |event| fields.
void DispatchEventToEmbedder(Event* event);
protected:
GuestViewBase(content::BrowserContext* browser_context,
int guest_instance_id);
virtual ~GuestViewBase();
// Dispatches an event |event_name| to the embedder with the |event| fields.
void DispatchEvent(Event* event);
private:
class EmbedderWebContentsObserver;
......
......@@ -9,6 +9,7 @@
#include "chrome/browser/guest_view/guest_view_constants.h"
#include "chrome/browser/guest_view/web_view/web_view_constants.h"
#include "chrome/browser/guest_view/web_view/web_view_guest.h"
#include "chrome/browser/guest_view/web_view/web_view_permission_helper.h"
#include "chrome/browser/guest_view/web_view/web_view_permission_types.h"
namespace {
......@@ -31,7 +32,7 @@ std::string JavaScriptMessageTypeToString(
} // namespace
JavaScriptDialogHelper::JavaScriptDialogHelper(WebViewGuest* guest)
: webview_guest_(guest) {
: web_view_guest_(guest) {
}
JavaScriptDialogHelper::~JavaScriptDialogHelper() {
......@@ -56,7 +57,9 @@ void JavaScriptDialogHelper::RunJavaScriptDialog(
new base::StringValue(
JavaScriptMessageTypeToString(javascript_message_type)));
request_info.Set(guestview::kUrl, new base::StringValue(origin_url.spec()));
webview_guest_->RequestPermission(
WebViewPermissionHelper* web_view_permission_helper =
WebViewPermissionHelper::FromWebContents(web_contents);
web_view_permission_helper->RequestPermission(
WEB_VIEW_PERMISSION_TYPE_JAVASCRIPT_DIALOG,
request_info,
base::Bind(&JavaScriptDialogHelper::OnPermissionResponse,
......@@ -94,6 +97,6 @@ void JavaScriptDialogHelper::OnPermissionResponse(
const DialogClosedCallback& callback,
bool allow,
const std::string& user_input) {
callback.Run(allow && webview_guest_->attached(),
callback.Run(allow && web_view_guest_->attached(),
base::UTF8ToUTF16(user_input));
}
......@@ -45,7 +45,7 @@ class JavaScriptDialogHelper : public content::JavaScriptDialogManager {
const std::string& user_input);
// Pointer to the webview that is being helped.
WebViewGuest* const webview_guest_;
WebViewGuest* const web_view_guest_;
DISALLOW_COPY_AND_ASSIGN(JavaScriptDialogHelper);
};
......
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/guest_view/web_view/plugin_permission_helper.h"
#include "chrome/browser/guest_view/web_view/web_view_guest.h"
#include "chrome/browser/guest_view/web_view/web_view_permission_types.h"
#include "chrome/browser/plugins/chrome_plugin_service_filter.h"
#include "chrome/common/render_messages.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/user_metrics.h"
using content::BrowserPluginGuestDelegate;
using content::RenderViewHost;
using content::WebContents;
DEFINE_WEB_CONTENTS_USER_DATA_KEY(PluginPermissionHelper);
PluginPermissionHelper::PluginPermissionHelper(WebContents* contents)
: content::WebContentsObserver(contents),
weak_factory_(this) {
}
PluginPermissionHelper::~PluginPermissionHelper() {
}
bool PluginPermissionHelper::OnMessageReceived(
const IPC::Message& message,
content::RenderFrameHost* render_frame_host) {
IPC_BEGIN_MESSAGE_MAP(PluginPermissionHelper, message)
IPC_MESSAGE_HANDLER(ChromeViewHostMsg_BlockedOutdatedPlugin,
OnBlockedOutdatedPlugin)
IPC_MESSAGE_HANDLER(ChromeViewHostMsg_BlockedUnauthorizedPlugin,
OnBlockedUnauthorizedPlugin)
IPC_MESSAGE_HANDLER(ChromeViewHostMsg_NPAPINotSupported,
OnNPAPINotSupported)
#if defined(ENABLE_PLUGIN_INSTALLATION)
IPC_MESSAGE_HANDLER(ChromeViewHostMsg_FindMissingPlugin,
OnFindMissingPlugin)
#endif
IPC_MESSAGE_UNHANDLED(return false)
IPC_END_MESSAGE_MAP()
return true;
}
bool PluginPermissionHelper::OnMessageReceived(const IPC::Message& message) {
IPC_BEGIN_MESSAGE_MAP(PluginPermissionHelper, message)
IPC_MESSAGE_HANDLER(ChromeViewHostMsg_CouldNotLoadPlugin,
OnCouldNotLoadPlugin)
IPC_MESSAGE_HANDLER(ChromeViewHostMsg_OpenAboutPlugins,
OnOpenAboutPlugins)
#if defined(ENABLE_PLUGIN_INSTALLATION)
IPC_MESSAGE_HANDLER(ChromeViewHostMsg_RemovePluginPlaceholderHost,
OnRemovePluginPlaceholderHost)
#endif
IPC_MESSAGE_UNHANDLED(return false)
IPC_END_MESSAGE_MAP()
return true;
}
void PluginPermissionHelper::OnBlockedUnauthorizedPlugin(
const base::string16& name,
const std::string& identifier) {
const char kPluginName[] = "name";
const char kPluginIdentifier[] = "identifier";
WebViewGuest* webview = WebViewGuest::FromWebContents(web_contents());
if (!webview)
return;
base::DictionaryValue info;
info.SetString(std::string(kPluginName), name);
info.SetString(std::string(kPluginIdentifier), identifier);
webview->RequestPermission(
WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN,
info,
base::Bind(&PluginPermissionHelper::OnPermissionResponse,
weak_factory_.GetWeakPtr(),
identifier),
true /* allowed_by_default */);
content::RecordAction(
base::UserMetricsAction("WebView.Guest.PluginLoadRequest"));
}
void PluginPermissionHelper::OnCouldNotLoadPlugin(
const base::FilePath& plugin_path) {
}
void PluginPermissionHelper::OnBlockedOutdatedPlugin(
int placeholder_id,
const std::string& identifier) {
}
void PluginPermissionHelper::OnNPAPINotSupported(const std::string& id) {
}
void PluginPermissionHelper::OnOpenAboutPlugins() {
}
#if defined(ENABLE_PLUGIN_INSTALLATION)
void PluginPermissionHelper::OnFindMissingPlugin(int placeholder_id,
const std::string& mime_type) {
Send(new ChromeViewMsg_DidNotFindMissingPlugin(placeholder_id));
}
void PluginPermissionHelper::OnRemovePluginPlaceholderHost(int placeholder_id) {
}
#endif // defined(ENABLE_PLUGIN_INSTALLATION)
void PluginPermissionHelper::OnPermissionResponse(const std::string& identifier,
bool allow,
const std::string& input) {
if (allow) {
ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins(
web_contents(), true, identifier);
}
}
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_GUEST_VIEW_WEB_VIEW_PLUGIN_PERMISSION_HELPER_H_
#define CHROME_BROWSER_GUEST_VIEW_WEB_VIEW_PLUGIN_PERMISSION_HELPER_H_
#include "base/memory/weak_ptr.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
class PluginPermissionHelper
: public content::WebContentsUserData<PluginPermissionHelper>,
public content::WebContentsObserver {
public:
virtual ~PluginPermissionHelper();
private:
explicit PluginPermissionHelper(content::WebContents* web_contents);
friend class content::WebContentsUserData<PluginPermissionHelper>;
// content::WebContentsObserver implementation.
virtual bool OnMessageReceived(
const IPC::Message& message,
content::RenderFrameHost* render_frame_host) OVERRIDE;
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
// Message handlers:
void OnBlockedUnauthorizedPlugin(const base::string16& name,
const std::string& identifier);
void OnCouldNotLoadPlugin(const base::FilePath& plugin_path);
void OnBlockedOutdatedPlugin(int placeholder_id,
const std::string& identifier);
void OnNPAPINotSupported(const std::string& identifier);
void OnOpenAboutPlugins();
#if defined(ENABLE_PLUGIN_INSTALLATION)
void OnFindMissingPlugin(int placeholder_id, const std::string& mime_type);
void OnRemovePluginPlaceholderHost(int placeholder_id);
#endif
void OnPermissionResponse(const std::string& identifier,
bool allow,
const std::string& user_input);
base::WeakPtrFactory<PluginPermissionHelper> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(PluginPermissionHelper);
};
#endif // CHROME_BROWSER_GUEST_VIEW_WEB_VIEW_PLUGIN_PERMISSION_HELPER_H_
......@@ -35,7 +35,7 @@ void WebViewFindHelper::DispatchFindUpdateEvent(bool canceled,
args->SetBoolean(webview::kFindCanceled, canceled);
args->SetBoolean(webview::kFindFinalUpdate, final_update);
DCHECK(webview_guest_);
webview_guest_->DispatchEvent(
webview_guest_->DispatchEventToEmbedder(
new GuestViewBase::Event(webview::kEventFindReply, args.Pass()));
}
......
......@@ -8,18 +8,16 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/content_settings/tab_specific_content_settings.h"
#include "chrome/browser/extensions/api/web_request/web_request_api.h"
#include "chrome/browser/extensions/api/web_view/web_view_internal_api.h"
#include "chrome/browser/extensions/chrome_extension_web_contents_observer.h"
#include "chrome/browser/extensions/menu_manager.h"
#include "chrome/browser/extensions/script_executor.h"
#include "chrome/browser/favicon/favicon_tab_helper.h"
#include "chrome/browser/geolocation/geolocation_permission_context.h"
#include "chrome/browser/geolocation/geolocation_permission_context_factory.h"
#include "chrome/browser/guest_view/guest_view_constants.h"
#include "chrome/browser/guest_view/guest_view_manager.h"
#include "chrome/browser/guest_view/web_view/web_view_constants.h"
#include "chrome/browser/guest_view/web_view/web_view_permission_helper.h"
#include "chrome/browser/guest_view/web_view/web_view_permission_types.h"
#include "chrome/browser/guest_view/web_view/web_view_renderer_state.h"
#include "chrome/browser/renderer_context_menu/context_menu_delegate.h"
......@@ -65,10 +63,6 @@
#endif // defined(ENABLE_FULL_PRINTING)
#endif // defined(ENABLE_PRINTING)
#if defined(ENABLE_PLUGINS) && !defined(OS_ANDROID)
#include "chrome/browser/guest_view/web_view/plugin_permission_helper.h"
#endif
#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
#endif
......@@ -121,30 +115,6 @@ static std::string TerminationStatusToString(base::TerminationStatus status) {
return "unknown";
}
static std::string PermissionTypeToString(WebViewPermissionType type) {
switch (type) {
case WEB_VIEW_PERMISSION_TYPE_DOWNLOAD:
return webview::kPermissionTypeDownload;
case WEB_VIEW_PERMISSION_TYPE_FILESYSTEM:
return webview::kPermissionTypeFileSystem;
case WEB_VIEW_PERMISSION_TYPE_GEOLOCATION:
return webview::kPermissionTypeGeolocation;
case WEB_VIEW_PERMISSION_TYPE_JAVASCRIPT_DIALOG:
return webview::kPermissionTypeDialog;
case WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN:
return webview::kPermissionTypeLoadPlugin;
case WEB_VIEW_PERMISSION_TYPE_MEDIA:
return webview::kPermissionTypeMedia;
case WEB_VIEW_PERMISSION_TYPE_NEW_WINDOW:
return webview::kPermissionTypeNewWindow;
case WEB_VIEW_PERMISSION_TYPE_POINTER_LOCK:
return webview::kPermissionTypePointerLock;
default:
NOTREACHED();
return std::string();
}
}
std::string GetStoragePartitionIdFromSiteURL(const GURL& site_url) {
const std::string& partition_id = site_url.query();
bool persist_storage = site_url.path().find("persist") != std::string::npos;
......@@ -164,32 +134,6 @@ void RemoveWebViewEventListenersOnIOThread(
view_instance_id);
}
void AttachWebViewHelpers(WebContents* contents) {
// Create a zoom controller for the guest contents give it access to
// GetZoomLevel() and and SetZoomLevel() in WebViewGuest.
// TODO(wjmaclean) This currently uses the same HostZoomMap as the browser
// context, but we eventually want to isolate the guest contents from zoom
// changes outside the guest (e.g. in the main browser), so we should
// create a separate HostZoomMap for the guest.
ZoomController::CreateForWebContents(contents);
FaviconTabHelper::CreateForWebContents(contents);
extensions::ChromeExtensionWebContentsObserver::CreateForWebContents(
contents);
#if defined(ENABLE_PLUGINS) && !defined(OS_ANDROID)
PluginPermissionHelper::CreateForWebContents(contents);
#endif
#if defined(ENABLE_PRINTING)
#if defined(ENABLE_FULL_PRINTING)
printing::PrintViewManager::CreateForWebContents(contents);
printing::PrintPreviewMessageHandler::CreateForWebContents(contents);
#else
printing::PrintViewManagerBasic::CreateForWebContents(contents);
#endif // defined(ENABLE_FULL_PRINTING)
#endif // defined(ENABLE_PRINTING)
PDFTabHelper::CreateForWebContents(contents);
}
void ParsePartitionParam(const base::DictionaryValue& create_params,
std::string* storage_partition_id,
bool* persist_storage) {
......@@ -225,7 +169,6 @@ WebViewGuest::WebViewGuest(content::BrowserContext* browser_context,
int guest_instance_id)
: GuestView<WebViewGuest>(browser_context, guest_instance_id),
pending_context_menu_request_id_(0),
next_permission_request_id_(0),
is_overriding_user_agent_(false),
chromevox_injected_(false),
current_zoom_factor_(1.0),
......@@ -268,89 +211,6 @@ int WebViewGuest::GetViewInstanceId(WebContents* contents) {
return guest->view_instance_id();
}
// static
void WebViewGuest::RecordUserInitiatedUMA(const PermissionResponseInfo& info,
bool allow) {
if (allow) {
// Note that |allow| == true means the embedder explicitly allowed the
// request. For some requests they might still fail. An example of such
// scenario would be: an embedder allows geolocation request but doesn't
// have geolocation access on its own.
switch (info.permission_type) {
case WEB_VIEW_PERMISSION_TYPE_DOWNLOAD:
content::RecordAction(
UserMetricsAction("WebView.PermissionAllow.Download"));
break;
case WEB_VIEW_PERMISSION_TYPE_FILESYSTEM:
content::RecordAction(
UserMetricsAction("WebView.PermissionAllow.FileSystem"));
break;
case WEB_VIEW_PERMISSION_TYPE_GEOLOCATION:
content::RecordAction(
UserMetricsAction("WebView.PermissionAllow.Geolocation"));
break;
case WEB_VIEW_PERMISSION_TYPE_JAVASCRIPT_DIALOG:
content::RecordAction(
UserMetricsAction("WebView.PermissionAllow.JSDialog"));
break;
case WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN:
content::RecordAction(
UserMetricsAction("WebView.Guest.PermissionAllow.PluginLoad"));
case WEB_VIEW_PERMISSION_TYPE_MEDIA:
content::RecordAction(
UserMetricsAction("WebView.PermissionAllow.Media"));
break;
case WEB_VIEW_PERMISSION_TYPE_NEW_WINDOW:
content::RecordAction(
UserMetricsAction("BrowserPlugin.PermissionAllow.NewWindow"));
break;
case WEB_VIEW_PERMISSION_TYPE_POINTER_LOCK:
content::RecordAction(
UserMetricsAction("WebView.PermissionAllow.PointerLock"));
break;
default:
break;
}
} else {
switch (info.permission_type) {
case WEB_VIEW_PERMISSION_TYPE_DOWNLOAD:
content::RecordAction(
UserMetricsAction("WebView.PermissionDeny.Download"));
break;
case WEB_VIEW_PERMISSION_TYPE_FILESYSTEM:
content::RecordAction(
UserMetricsAction("WebView.PermissionDeny.FileSystem"));
break;
case WEB_VIEW_PERMISSION_TYPE_GEOLOCATION:
content::RecordAction(
UserMetricsAction("WebView.PermissionDeny.Geolocation"));
break;
case WEB_VIEW_PERMISSION_TYPE_JAVASCRIPT_DIALOG:
content::RecordAction(
UserMetricsAction("WebView.PermissionDeny.JSDialog"));
break;
case WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN:
content::RecordAction(
UserMetricsAction("WebView.Guest.PermissionDeny.PluginLoad"));
break;
case WEB_VIEW_PERMISSION_TYPE_MEDIA:
content::RecordAction(
UserMetricsAction("WebView.PermissionDeny.Media"));
break;
case WEB_VIEW_PERMISSION_TYPE_NEW_WINDOW:
content::RecordAction(
UserMetricsAction("BrowserPlugin.PermissionDeny.NewWindow"));
break;
case WEB_VIEW_PERMISSION_TYPE_POINTER_LOCK:
content::RecordAction(
UserMetricsAction("WebView.PermissionDeny.PointerLock"));
break;
default:
break;
}
}
}
// static
scoped_ptr<base::ListValue> WebViewGuest::MenuModelToValue(
const ui::SimpleMenuModel& menu_model) {
......@@ -492,10 +352,34 @@ void WebViewGuest::DidInitialize() {
AttachWebViewHelpers(guest_web_contents());
}
void WebViewGuest::AttachWebViewHelpers(WebContents* contents) {
// Create a zoom controller for the guest contents give it access to
// GetZoomLevel() and and SetZoomLevel() in WebViewGuest.
// TODO(wjmaclean) This currently uses the same HostZoomMap as the browser
// context, but we eventually want to isolate the guest contents from zoom
// changes outside the guest (e.g. in the main browser), so we should
// create a separate HostZoomMap for the guest.
ZoomController::CreateForWebContents(contents);
FaviconTabHelper::CreateForWebContents(contents);
extensions::ChromeExtensionWebContentsObserver::CreateForWebContents(
contents);
#if defined(ENABLE_PRINTING)
#if defined(ENABLE_FULL_PRINTING)
printing::PrintViewManager::CreateForWebContents(contents);
printing::PrintPreviewMessageHandler::CreateForWebContents(contents);
#else
printing::PrintViewManagerBasic::CreateForWebContents(contents);
#endif // defined(ENABLE_FULL_PRINTING)
#endif // defined(ENABLE_PRINTING)
PDFTabHelper::CreateForWebContents(contents);
web_view_permission_helper_.reset(new WebViewPermissionHelper(this));
}
void WebViewGuest::DidStopLoading() {
scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
DispatchEvent(new GuestViewBase::Event(webview::kEventLoadStop, args.Pass()));
DispatchEventToEmbedder(
new GuestViewBase::Event(webview::kEventLoadStop, args.Pass()));
}
void WebViewGuest::EmbedderDestroyed() {
......@@ -547,14 +431,15 @@ bool WebViewGuest::AddMessageToConsole(WebContents* source,
args->SetString(webview::kMessage, message);
args->SetInteger(webview::kLine, line_no);
args->SetString(webview::kSourceId, source_id);
DispatchEvent(
DispatchEventToEmbedder(
new GuestViewBase::Event(webview::kEventConsoleMessage, args.Pass()));
return true;
}
void WebViewGuest::CloseContents(WebContents* source) {
scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
DispatchEvent(new GuestViewBase::Event(webview::kEventClose, args.Pass()));
DispatchEventToEmbedder(
new GuestViewBase::Event(webview::kEventClose, args.Pass()));
}
void WebViewGuest::FindReply(WebContents* source,
......@@ -582,8 +467,8 @@ bool WebViewGuest::HandleContextMenu(
MenuModelToValue(pending_menu_->menu_model());
args->Set(webview::kContextMenuItems, items.release());
args->SetInteger(webview::kRequestId, request_id);
DispatchEvent(new GuestViewBase::Event(webview::kEventContextMenu,
args.Pass()));
DispatchEventToEmbedder(
new GuestViewBase::Event(webview::kEventContextMenu, args.Pass()));
return true;
}
......@@ -611,7 +496,7 @@ void WebViewGuest::LoadProgressChanged(content::WebContents* source,
scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
args->SetString(guestview::kUrl, guest_web_contents()->GetURL().spec());
args->SetDouble(webview::kProgress, progress);
DispatchEvent(
DispatchEventToEmbedder(
new GuestViewBase::Event(webview::kEventLoadProgress, args.Pass()));
}
......@@ -622,7 +507,7 @@ void WebViewGuest::LoadAbort(bool is_top_level,
args->SetBoolean(guestview::kIsTopLevel, is_top_level);
args->SetString(guestview::kUrl, url.possibly_invalid_spec());
args->SetString(guestview::kReason, error_type);
DispatchEvent(
DispatchEventToEmbedder(
new GuestViewBase::Event(webview::kEventLoadAbort, args.Pass()));
}
......@@ -681,7 +566,7 @@ void WebViewGuest::RendererResponsive(content::WebContents* source) {
scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
args->SetInteger(webview::kProcessId,
guest_web_contents()->GetRenderProcessHost()->GetID());
DispatchEvent(
DispatchEventToEmbedder(
new GuestViewBase::Event(webview::kEventResponsive, args.Pass()));
}
......@@ -689,7 +574,7 @@ void WebViewGuest::RendererUnresponsive(content::WebContents* source) {
scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
args->SetInteger(webview::kProcessId,
guest_web_contents()->GetRenderProcessHost()->GetID());
DispatchEvent(
DispatchEventToEmbedder(
new GuestViewBase::Event(webview::kEventUnresponsive, args.Pass()));
}
......@@ -749,154 +634,6 @@ void WebViewGuest::Reload() {
guest_web_contents()->GetController().Reload(false);
}
void WebViewGuest::RequestFileSystemPermission(
const GURL& url,
bool allowed_by_default,
const base::Callback<void(bool)>& callback) {
base::DictionaryValue request_info;
request_info.Set(guestview::kUrl, new base::StringValue(url.spec()));
RequestPermission(
WEB_VIEW_PERMISSION_TYPE_FILESYSTEM,
request_info,
base::Bind(&WebViewGuest::OnWebViewFileSystemPermissionResponse,
base::Unretained(this),
callback),
allowed_by_default);
}
void WebViewGuest::OnWebViewFileSystemPermissionResponse(
const base::Callback<void(bool)>& callback,
bool allow,
const std::string& user_input) {
callback.Run(allow && attached());
}
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,
new base::StringValue(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 = RequestPermission(
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;
}
Profile* profile = Profile::FromBrowserContext(browser_context());
GeolocationPermissionContextFactory::GetForProfile(profile)->
RequestGeolocationPermission(
embedder_web_contents(),
// 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,
embedder_web_contents()->GetLastCommittedURL(),
user_gesture,
callback,
NULL);
}
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);
}
void WebViewGuest::OnWebViewMediaPermissionResponse(
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback,
bool allow,
const std::string& user_input) {
if (!allow || !attached()) {
// Deny the request.
callback.Run(content::MediaStreamDevices(),
content::MEDIA_DEVICE_INVALID_STATE,
scoped_ptr<content::MediaStreamUI>());
return;
}
if (!embedder_web_contents()->GetDelegate())
return;
embedder_web_contents()->GetDelegate()->
RequestMediaAccessPermission(embedder_web_contents(), request, callback);
}
void WebViewGuest::OnWebViewDownloadPermissionResponse(
const base::Callback<void(bool)>& callback,
bool allow,
const std::string& user_input) {
callback.Run(allow && attached());
}
void WebViewGuest::OnWebViewPointerLockPermissionResponse(
const base::Callback<void(bool)>& callback,
bool allow,
const std::string& user_input) {
callback.Run(allow && attached());
}
WebViewGuest::SetPermissionResult WebViewGuest::SetPermission(
int request_id,
PermissionResponseAction action,
const std::string& user_input) {
RequestMap::iterator request_itr =
pending_permission_requests_.find(request_id);
if (request_itr == pending_permission_requests_.end())
return SET_PERMISSION_INVALID;
const PermissionResponseInfo& info = request_itr->second;
bool allow = (action == ALLOW) ||
((action == DEFAULT) && info.allowed_by_default);
info.callback.Run(allow, user_input);
// Only record user initiated (i.e. non-default) actions.
if (action != DEFAULT)
RecordUserInitiatedUMA(info, allow);
pending_permission_requests_.erase(request_itr);
return allow ? SET_PERMISSION_ALLOWED : SET_PERMISSION_DENIED;
}
void WebViewGuest::SetUserAgentOverride(
const std::string& user_agent_override) {
if (!attached())
......@@ -943,78 +680,6 @@ bool WebViewGuest::ClearData(const base::Time remove_since,
return true;
}
// static
void WebViewGuest::FileSystemAccessedAsync(int render_process_id,
int render_frame_id,
int request_id,
const GURL& url,
bool blocked_by_policy) {
WebViewGuest* guest =
WebViewGuest::FromFrameID(render_process_id, render_frame_id);
DCHECK(guest);
guest->RequestFileSystemPermission(
url,
!blocked_by_policy,
base::Bind(&WebViewGuest::FileSystemAccessedAsyncResponse,
render_process_id,
render_frame_id,
request_id,
url));
}
// static
void WebViewGuest::FileSystemAccessedAsyncResponse(int render_process_id,
int render_frame_id,
int request_id,
const GURL& url,
bool allowed) {
TabSpecificContentSettings::FileSystemAccessed(
render_process_id, render_frame_id, url, !allowed);
content::RenderFrameHost* render_frame_host =
content::RenderFrameHost::FromID(render_process_id, render_frame_id);
if (!render_frame_host)
return;
render_frame_host->Send(
new ChromeViewMsg_RequestFileSystemAccessAsyncResponse(
render_frame_id, request_id, allowed));
}
// static
void WebViewGuest::FileSystemAccessedSync(int render_process_id,
int render_frame_id,
const GURL& url,
bool blocked_by_policy,
IPC::Message* reply_msg) {
WebViewGuest* guest =
WebViewGuest::FromFrameID(render_process_id, render_frame_id);
DCHECK(guest);
guest->RequestFileSystemPermission(
url,
!blocked_by_policy,
base::Bind(&WebViewGuest::FileSystemAccessedSyncResponse,
render_process_id,
render_frame_id,
url,
reply_msg));
}
// static
void WebViewGuest::FileSystemAccessedSyncResponse(int render_process_id,
int render_frame_id,
const GURL& url,
IPC::Message* reply_msg,
bool allowed) {
TabSpecificContentSettings::FileSystemAccessed(
render_process_id, render_frame_id, url, !allowed);
ChromeViewHostMsg_RequestFileSystemAccessSync::WriteReplyParams(reply_msg,
allowed);
content::RenderFrameHost* render_frame_host =
content::RenderFrameHost::FromID(render_process_id, render_frame_id);
if (!render_frame_id)
return;
render_frame_host->Send(reply_msg);
}
WebViewGuest::~WebViewGuest() {
}
......@@ -1033,7 +698,7 @@ void WebViewGuest::DidCommitProvisionalLoadForFrame(
guest_web_contents()->GetController().GetEntryCount());
args->SetInteger(webview::kInternalProcessId,
guest_web_contents()->GetRenderProcessHost()->GetID());
DispatchEvent(
DispatchEventToEmbedder(
new GuestViewBase::Event(webview::kEventLoadCommit, args.Pass()));
// Update the current zoom factor for the new page.
......@@ -1066,7 +731,7 @@ void WebViewGuest::DidStartProvisionalLoadForFrame(
scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
args->SetString(guestview::kUrl, validated_url.spec());
args->SetBoolean(guestview::kIsTopLevel, !render_frame_host->GetParent());
DispatchEvent(
DispatchEventToEmbedder(
new GuestViewBase::Event(webview::kEventLoadStart, args.Pass()));
}
......@@ -1094,7 +759,8 @@ void WebViewGuest::RenderProcessGone(base::TerminationStatus status) {
args->SetInteger(webview::kProcessId,
guest_web_contents()->GetRenderProcessHost()->GetID());
args->SetString(webview::kReason, TerminationStatusToString(status));
DispatchEvent(new GuestViewBase::Event(webview::kEventExit, args.Pass()));
DispatchEventToEmbedder(
new GuestViewBase::Event(webview::kEventExit, args.Pass()));
}
void WebViewGuest::UserAgentOverrideSet(const std::string& user_agent) {
......@@ -1119,13 +785,13 @@ void WebViewGuest::ReportFrameNameChange(const std::string& name) {
name_ = name;
scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
args->SetString(webview::kName, name);
DispatchEvent(
DispatchEventToEmbedder(
new GuestViewBase::Event(webview::kEventFrameNameChanged, args.Pass()));
}
void WebViewGuest::LoadHandlerCalled() {
scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
DispatchEvent(
DispatchEventToEmbedder(
new GuestViewBase::Event(webview::kEventContentLoad, args.Pass()));
}
......@@ -1136,7 +802,7 @@ void WebViewGuest::LoadRedirect(const GURL& old_url,
args->SetBoolean(guestview::kIsTopLevel, is_top_level);
args->SetString(webview::kNewURL, new_url.spec());
args->SetString(webview::kOldURL, old_url.spec());
DispatchEvent(
DispatchEventToEmbedder(
new GuestViewBase::Event(webview::kEventLoadRedirect, args.Pass()));
}
......@@ -1198,7 +864,7 @@ void WebViewGuest::SizeChanged(const gfx::Size& old_size,
args->SetInteger(webview::kOldWidth, old_size.width());
args->SetInteger(webview::kNewHeight, new_size.height());
args->SetInteger(webview::kNewWidth, new_size.width());
DispatchEvent(
DispatchEventToEmbedder(
new GuestViewBase::Event(webview::kEventSizeChanged, args.Pass()));
}
......@@ -1206,16 +872,9 @@ void WebViewGuest::RequestMediaAccessPermission(
content::WebContents* source,
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback) {
base::DictionaryValue request_info;
request_info.Set(guestview::kUrl,
new base::StringValue(request.security_origin.spec()));
RequestPermission(WEB_VIEW_PERMISSION_TYPE_MEDIA,
request_info,
base::Bind(&WebViewGuest::OnWebViewMediaPermissionResponse,
base::Unretained(this),
request,
callback),
false /* allowed_by_default */);
web_view_permission_helper_->RequestMediaAccessPermission(source,
request,
callback);
}
void WebViewGuest::CanDownload(
......@@ -1223,37 +882,20 @@ void WebViewGuest::CanDownload(
const GURL& url,
const std::string& request_method,
const base::Callback<void(bool)>& callback) {
base::DictionaryValue request_info;
request_info.Set(guestview::kUrl, new base::StringValue(url.spec()));
RequestPermission(
WEB_VIEW_PERMISSION_TYPE_DOWNLOAD,
request_info,
base::Bind(&WebViewGuest::OnWebViewDownloadPermissionResponse,
base::Unretained(this),
callback),
false /* allowed_by_default */);
web_view_permission_helper_->CanDownload(render_view_host,
url,
request_method,
callback);
}
void WebViewGuest::RequestPointerLockPermission(
bool user_gesture,
bool last_unlocked_by_target,
const base::Callback<void(bool)>& callback) {
base::DictionaryValue request_info;
request_info.Set(guestview::kUserGesture,
base::Value::CreateBooleanValue(user_gesture));
request_info.Set(webview::kLastUnlockedBySelf,
base::Value::CreateBooleanValue(last_unlocked_by_target));
request_info.Set(guestview::kUrl,
new base::StringValue(
guest_web_contents()->GetLastCommittedURL().spec()));
RequestPermission(
WEB_VIEW_PERMISSION_TYPE_POINTER_LOCK,
request_info,
base::Bind(&WebViewGuest::OnWebViewPointerLockPermissionResponse,
base::Unretained(this),
callback),
false /* allowed_by_default */);
web_view_permission_helper_->RequestPointerLockPermission(
user_gesture,
last_unlocked_by_target,
callback);
}
void WebViewGuest::WillAttachToEmbedder() {
......@@ -1347,65 +989,6 @@ 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::RequestPermission(
WebViewPermissionType 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 WEB_VIEW_PERMISSION_TYPE_NEW_WINDOW: {
DispatchEvent(
new GuestViewBase::Event(webview::kEventNewWindow, args.Pass()));
break;
}
case WEB_VIEW_PERMISSION_TYPE_JAVASCRIPT_DIALOG: {
DispatchEvent(
new GuestViewBase::Event(webview::kEventDialog, args.Pass()));
break;
}
default: {
args->SetString(webview::kPermission,
PermissionTypeToString(permission_type));
DispatchEvent(new GuestViewBase::Event(webview::kEventPermissionRequest,
args.Pass()));
break;
}
}
return request_id;
}
bool WebViewGuest::HandleKeyboardShortcuts(
const content::NativeWebKeyboardEvent& event) {
if (event.type != blink::WebInputEvent::RawKeyDown)
......@@ -1446,23 +1029,6 @@ bool WebViewGuest::HandleKeyboardShortcuts(
return false;
}
WebViewGuest::PermissionResponseInfo::PermissionResponseInfo()
: permission_type(WEB_VIEW_PERMISSION_TYPE_UNKNOWN),
allowed_by_default(false) {
}
WebViewGuest::PermissionResponseInfo::PermissionResponseInfo(
const PermissionResponseCallback& callback,
WebViewPermissionType permission_type,
bool allowed_by_default)
: callback(callback),
permission_type(permission_type),
allowed_by_default(allowed_by_default) {
}
WebViewGuest::PermissionResponseInfo::~PermissionResponseInfo() {
}
void WebViewGuest::ShowContextMenu(int request_id,
const MenuItemVector* items) {
if (!pending_menu_.get())
......@@ -1498,7 +1064,7 @@ void WebViewGuest::SetZoom(double zoom_factor) {
scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
args->SetDouble(webview::kOldZoomFactor, current_zoom_factor_);
args->SetDouble(webview::kNewZoomFactor, zoom_factor);
DispatchEvent(
DispatchEventToEmbedder(
new GuestViewBase::Event(webview::kEventZoomChange, args.Pass()));
current_zoom_factor_ = zoom_factor;
......@@ -1613,12 +1179,13 @@ void WebViewGuest::RequestNewWindowPermission(
webview::kWindowOpenDisposition,
new base::StringValue(WindowOpenDispositionToString(disposition)));
RequestPermission(WEB_VIEW_PERMISSION_TYPE_NEW_WINDOW,
request_info,
base::Bind(&WebViewGuest::OnWebViewNewWindowResponse,
base::Unretained(this),
guest->GetGuestInstanceID()),
false /* allowed_by_default */);
web_view_permission_helper_->
RequestPermission(WEB_VIEW_PERMISSION_TYPE_NEW_WINDOW,
request_info,
base::Bind(&WebViewGuest::OnWebViewNewWindowResponse,
base::Unretained(this),
guest->GetGuestInstanceID()),
false /* allowed_by_default */);
}
void WebViewGuest::DestroyUnattachedWindows() {
......
......@@ -12,6 +12,7 @@
#include "chrome/browser/guest_view/guest_view.h"
#include "chrome/browser/guest_view/web_view/javascript_dialog_helper.h"
#include "chrome/browser/guest_view/web_view/web_view_find_helper.h"
#include "chrome/browser/guest_view/web_view/web_view_permission_helper.h"
#include "chrome/browser/guest_view/web_view/web_view_permission_types.h"
#include "chrome/common/extensions/api/web_view_internal.h"
#include "content/public/browser/javascript_dialog_manager.h"
......@@ -203,25 +204,6 @@ class WebViewGuest : public GuestView<WebViewGuest>,
bool allowed_by_default,
const base::Callback<void(bool)>& callback);
enum PermissionResponseAction {
DENY,
ALLOW,
DEFAULT
};
enum SetPermissionResult {
SET_PERMISSION_INVALID,
SET_PERMISSION_ALLOWED,
SET_PERMISSION_DENIED
};
// Responds to the permission request |request_id| with |action| and
// |user_input|. Returns whether there was a pending request for the provided
// |request_id|.
SetPermissionResult SetPermission(int request_id,
PermissionResponseAction action,
const std::string& user_input);
// Overrides the user agent for this guest.
// This affects subsequent guest navigations.
void SetUserAgentOverride(const std::string& user_agent_override);
......@@ -244,105 +226,20 @@ class WebViewGuest : public GuestView<WebViewGuest>,
return script_executor_.get();
}
// Called when file system access is requested by the guest content using the
// asynchronous HTML5 file system API. The request is plumbed through the
// <webview> permission request API. The request will be:
// - Allowed if the embedder explicitly allowed it.
// - Denied if the embedder explicitly denied.
// - Determined by the guest's content settings if the embedder does not
// perform an explicit action.
// If access was blocked due to the page's content settings,
// |blocked_by_policy| should be true, and this function should invoke
// OnContentBlocked.
static void FileSystemAccessedAsync(int render_process_id,
int render_frame_id,
int request_id,
const GURL& url,
bool blocked_by_policy);
// Called when file system access is requested by the guest content using the
// synchronous HTML5 file system API in a worker thread or shared worker. The
// request is plumbed through the <webview> permission request API. The
// request will be:
// - Allowed if the embedder explicitly allowed it.
// - Denied if the embedder explicitly denied.
// - Determined by the guest's content settings if the embedder does not
// perform an explicit action.
// If access was blocked due to the page's content settings,
// |blocked_by_policy| should be true, and this function should invoke
// OnContentBlocked.
static void FileSystemAccessedSync(int render_process_id,
int render_frame_id,
const GURL& url,
bool blocked_by_policy,
IPC::Message* reply_msg);
private:
friend class WebViewPermissionHelper;
virtual ~WebViewGuest();
// A map to store the callback for a request keyed by the request's id.
struct PermissionResponseInfo {
PermissionResponseCallback callback;
WebViewPermissionType permission_type;
bool allowed_by_default;
PermissionResponseInfo();
PermissionResponseInfo(const PermissionResponseCallback& callback,
WebViewPermissionType permission_type,
bool allowed_by_default);
~PermissionResponseInfo();
};
static void RecordUserInitiatedUMA(const PermissionResponseInfo& info,
bool allow);
// Returns the top level items (ignoring submenus) as Value.
static scoped_ptr<base::ListValue> MenuModelToValue(
const ui::SimpleMenuModel& menu_model);
void OnWebViewGeolocationPermissionResponse(
int bridge_id,
bool user_gesture,
const base::Callback<void(bool)>& callback,
bool allow,
const std::string& user_input);
void OnWebViewFileSystemPermissionResponse(
const base::Callback<void(bool)>& callback,
bool allow,
const std::string& user_input);
void OnWebViewMediaPermissionResponse(
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback,
bool allow,
const std::string& user_input);
void OnWebViewDownloadPermissionResponse(
const base::Callback<void(bool)>& callback,
bool allow,
const std::string& user_input);
void OnWebViewPointerLockPermissionResponse(
const base::Callback<void(bool)>& callback,
bool allow,
const std::string& user_input);
void AttachWebViewHelpers(content::WebContents* contents);
void OnWebViewNewWindowResponse(int new_window_instance_id,
bool allow,
const std::string& user_input);
static void FileSystemAccessedAsyncResponse(int render_process_id,
int render_frame_id,
int request_id,
const GURL& url,
bool allowed);
static void FileSystemAccessedSyncResponse(int render_process_id,
int render_frame_id,
const GURL& url,
IPC::Message* reply_msg,
bool allowed);
// WebContentsObserver implementation.
virtual void DidCommitProvisionalLoadForFrame(
content::RenderFrameHost* render_frame_host,
......@@ -390,11 +287,6 @@ class WebViewGuest : public GuestView<WebViewGuest>,
void InjectChromeVoxIfNeeded(content::RenderViewHost* render_view_host);
// Bridge IDs correspond to a geolocation request. This method will remove
// the bookkeeping for a particular geolocation request associated with the
// provided |bridge_id|. It returns the request ID of the geolocation request.
int RemoveBridgeID(int bridge_id);
void LoadURLWithParams(const GURL& url,
const content::Referrer& referrer,
content::PageTransition transition_type,
......@@ -439,13 +331,6 @@ class WebViewGuest : public GuestView<WebViewGuest>,
// We only need the ids to be unique for a given WebViewGuest.
int pending_context_menu_request_id_;
// A counter to generate a unique request id for a permission request.
// We only need the ids to be unique for a given WebViewGuest.
int next_permission_request_id_;
typedef std::map<int, PermissionResponseInfo> RequestMap;
RequestMap pending_permission_requests_;
// True if the user agent is overridden.
bool is_overriding_user_agent_;
......@@ -464,6 +349,9 @@ class WebViewGuest : public GuestView<WebViewGuest>,
// Handles the JavaScript dialog requests.
JavaScriptDialogHelper javascript_dialog_helper_;
// Handels permission requests.
scoped_ptr<WebViewPermissionHelper> web_view_permission_helper_;
friend void WebViewFindHelper::DispatchFindUpdateEvent(bool canceled,
bool final_update);
......@@ -477,8 +365,6 @@ class WebViewGuest : public GuestView<WebViewGuest>,
accessibility_subscription_;
#endif
std::map<int, int> bridge_id_to_request_id_map_;
// Tracks the name, and target URL of the new window. Once the first
// navigation commits, we no longer track this information.
struct NewWindowInfo {
......
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/guest_view/web_view/web_view_permission_helper.h"
#include "chrome/browser/content_settings/tab_specific_content_settings.h"
#include "chrome/browser/geolocation/geolocation_permission_context.h"
#include "chrome/browser/geolocation/geolocation_permission_context_factory.h"
#include "chrome/browser/guest_view/web_view/web_view_constants.h"
#include "chrome/browser/guest_view/web_view/web_view_guest.h"
#include "chrome/browser/guest_view/web_view/web_view_permission_types.h"
#include "chrome/browser/plugins/chrome_plugin_service_filter.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/render_messages.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/user_metrics.h"
using content::BrowserPluginGuestDelegate;
using content::RenderViewHost;
namespace {
static std::string PermissionTypeToString(WebViewPermissionType type) {
switch (type) {
case WEB_VIEW_PERMISSION_TYPE_DOWNLOAD:
return webview::kPermissionTypeDownload;
case WEB_VIEW_PERMISSION_TYPE_FILESYSTEM:
return webview::kPermissionTypeFileSystem;
case WEB_VIEW_PERMISSION_TYPE_GEOLOCATION:
return webview::kPermissionTypeGeolocation;
case WEB_VIEW_PERMISSION_TYPE_JAVASCRIPT_DIALOG:
return webview::kPermissionTypeDialog;
case WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN:
return webview::kPermissionTypeLoadPlugin;
case WEB_VIEW_PERMISSION_TYPE_MEDIA:
return webview::kPermissionTypeMedia;
case WEB_VIEW_PERMISSION_TYPE_NEW_WINDOW:
return webview::kPermissionTypeNewWindow;
case WEB_VIEW_PERMISSION_TYPE_POINTER_LOCK:
return webview::kPermissionTypePointerLock;
default:
NOTREACHED();
return std::string();
}
}
// static
void RecordUserInitiatedUMA(
const WebViewPermissionHelper::PermissionResponseInfo& info,
bool allow) {
if (allow) {
// Note that |allow| == true means the embedder explicitly allowed the
// request. For some requests they might still fail. An example of such
// scenario would be: an embedder allows geolocation request but doesn't
// have geolocation access on its own.
switch (info.permission_type) {
case WEB_VIEW_PERMISSION_TYPE_DOWNLOAD:
content::RecordAction(
UserMetricsAction("WebView.PermissionAllow.Download"));
break;
case WEB_VIEW_PERMISSION_TYPE_FILESYSTEM:
content::RecordAction(
UserMetricsAction("WebView.PermissionAllow.FileSystem"));
break;
case WEB_VIEW_PERMISSION_TYPE_GEOLOCATION:
content::RecordAction(
UserMetricsAction("WebView.PermissionAllow.Geolocation"));
break;
case WEB_VIEW_PERMISSION_TYPE_JAVASCRIPT_DIALOG:
content::RecordAction(
UserMetricsAction("WebView.PermissionAllow.JSDialog"));
break;
case WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN:
content::RecordAction(
UserMetricsAction("WebView.Guest.PermissionAllow.PluginLoad"));
case WEB_VIEW_PERMISSION_TYPE_MEDIA:
content::RecordAction(
UserMetricsAction("WebView.PermissionAllow.Media"));
break;
case WEB_VIEW_PERMISSION_TYPE_NEW_WINDOW:
content::RecordAction(
UserMetricsAction("BrowserPlugin.PermissionAllow.NewWindow"));
break;
case WEB_VIEW_PERMISSION_TYPE_POINTER_LOCK:
content::RecordAction(
UserMetricsAction("WebView.PermissionAllow.PointerLock"));
break;
default:
break;
}
} else {
switch (info.permission_type) {
case WEB_VIEW_PERMISSION_TYPE_DOWNLOAD:
content::RecordAction(
UserMetricsAction("WebView.PermissionDeny.Download"));
break;
case WEB_VIEW_PERMISSION_TYPE_FILESYSTEM:
content::RecordAction(
UserMetricsAction("WebView.PermissionDeny.FileSystem"));
break;
case WEB_VIEW_PERMISSION_TYPE_GEOLOCATION:
content::RecordAction(
UserMetricsAction("WebView.PermissionDeny.Geolocation"));
break;
case WEB_VIEW_PERMISSION_TYPE_JAVASCRIPT_DIALOG:
content::RecordAction(
UserMetricsAction("WebView.PermissionDeny.JSDialog"));
break;
case WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN:
content::RecordAction(
UserMetricsAction("WebView.Guest.PermissionDeny.PluginLoad"));
break;
case WEB_VIEW_PERMISSION_TYPE_MEDIA:
content::RecordAction(
UserMetricsAction("WebView.PermissionDeny.Media"));
break;
case WEB_VIEW_PERMISSION_TYPE_NEW_WINDOW:
content::RecordAction(
UserMetricsAction("BrowserPlugin.PermissionDeny.NewWindow"));
break;
case WEB_VIEW_PERMISSION_TYPE_POINTER_LOCK:
content::RecordAction(
UserMetricsAction("WebView.PermissionDeny.PointerLock"));
break;
default:
break;
}
}
}
} // namespace
WebViewPermissionHelper::WebViewPermissionHelper(WebViewGuest* web_view_guest)
: content::WebContentsObserver(web_view_guest->guest_web_contents()),
next_permission_request_id_(guestview::kInstanceIDNone),
web_view_guest_(web_view_guest),
weak_factory_(this) {
}
WebViewPermissionHelper::~WebViewPermissionHelper() {
}
// static
WebViewPermissionHelper* WebViewPermissionHelper::FromFrameID(
int render_process_id,
int render_frame_id) {
WebViewGuest* web_view_guest = WebViewGuest::FromFrameID(
render_process_id, render_frame_id);
if (!web_view_guest) {
return NULL;
}
return web_view_guest->web_view_permission_helper_.get();
}
// static
WebViewPermissionHelper* WebViewPermissionHelper::FromWebContents(
content::WebContents* web_contents) {
WebViewGuest* web_view_guest = WebViewGuest::FromWebContents(web_contents);
if (!web_view_guest)
return NULL;
return web_view_guest->web_view_permission_helper_.get();
}
#if defined(ENABLE_PLUGINS)
bool WebViewPermissionHelper::OnMessageReceived(
const IPC::Message& message,
content::RenderFrameHost* render_frame_host) {
IPC_BEGIN_MESSAGE_MAP(WebViewPermissionHelper, message)
IPC_MESSAGE_HANDLER(ChromeViewHostMsg_BlockedOutdatedPlugin,
OnBlockedOutdatedPlugin)
IPC_MESSAGE_HANDLER(ChromeViewHostMsg_BlockedUnauthorizedPlugin,
OnBlockedUnauthorizedPlugin)
IPC_MESSAGE_HANDLER(ChromeViewHostMsg_NPAPINotSupported,
OnNPAPINotSupported)
#if defined(ENABLE_PLUGIN_INSTALLATION)
IPC_MESSAGE_HANDLER(ChromeViewHostMsg_FindMissingPlugin,
OnFindMissingPlugin)
#endif
IPC_MESSAGE_UNHANDLED(return false)
IPC_END_MESSAGE_MAP()
return true;
}
bool WebViewPermissionHelper::OnMessageReceived(const IPC::Message& message) {
IPC_BEGIN_MESSAGE_MAP(WebViewPermissionHelper, message)
IPC_MESSAGE_HANDLER(ChromeViewHostMsg_CouldNotLoadPlugin,
OnCouldNotLoadPlugin)
IPC_MESSAGE_HANDLER(ChromeViewHostMsg_OpenAboutPlugins,
OnOpenAboutPlugins)
#if defined(ENABLE_PLUGIN_INSTALLATION)
IPC_MESSAGE_HANDLER(ChromeViewHostMsg_RemovePluginPlaceholderHost,
OnRemovePluginPlaceholderHost)
#endif
IPC_MESSAGE_UNHANDLED(return false)
IPC_END_MESSAGE_MAP()
return true;
}
void WebViewPermissionHelper::OnBlockedUnauthorizedPlugin(
const base::string16& name,
const std::string& identifier) {
const char kPluginName[] = "name";
const char kPluginIdentifier[] = "identifier";
base::DictionaryValue info;
info.SetString(std::string(kPluginName), name);
info.SetString(std::string(kPluginIdentifier), identifier);
RequestPermission(
WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN,
info,
base::Bind(&WebViewPermissionHelper::OnPermissionResponse,
weak_factory_.GetWeakPtr(),
identifier),
true /* allowed_by_default */);
content::RecordAction(
base::UserMetricsAction("WebView.Guest.PluginLoadRequest"));
}
void WebViewPermissionHelper::OnCouldNotLoadPlugin(
const base::FilePath& plugin_path) {
}
void WebViewPermissionHelper::OnBlockedOutdatedPlugin(
int placeholder_id,
const std::string& identifier) {
}
void WebViewPermissionHelper::OnNPAPINotSupported(const std::string& id) {
}
void WebViewPermissionHelper::OnOpenAboutPlugins() {
}
#if defined(ENABLE_PLUGIN_INSTALLATION)
void WebViewPermissionHelper::OnFindMissingPlugin(
int placeholder_id,
const std::string& mime_type) {
Send(new ChromeViewMsg_DidNotFindMissingPlugin(placeholder_id));
}
void WebViewPermissionHelper::OnRemovePluginPlaceholderHost(
int placeholder_id) {
}
#endif // defined(ENABLE_PLUGIN_INSTALLATION)
void WebViewPermissionHelper::OnPermissionResponse(
const std::string& identifier,
bool allow,
const std::string& input) {
if (allow) {
ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins(
web_contents(), true, identifier);
}
}
#endif // defined(ENABLE_PLUGINS)
void WebViewPermissionHelper::RequestMediaAccessPermission(
content::WebContents* source,
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback) {
base::DictionaryValue request_info;
request_info.Set(guestview::kUrl,
new base::StringValue(request.security_origin.spec()));
RequestPermission(WEB_VIEW_PERMISSION_TYPE_MEDIA,
request_info,
base::Bind(&WebViewPermissionHelper::
OnMediaPermissionResponse,
base::Unretained(this),
request,
callback),
false /* allowed_by_default */);
}
void WebViewPermissionHelper::OnMediaPermissionResponse(
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback,
bool allow,
const std::string& user_input) {
if (!allow || !web_view_guest_->attached()) {
// Deny the request.
callback.Run(content::MediaStreamDevices(),
content::MEDIA_DEVICE_INVALID_STATE,
scoped_ptr<content::MediaStreamUI>());
return;
}
if (!web_view_guest_->embedder_web_contents()->GetDelegate())
return;
web_view_guest_->embedder_web_contents()->GetDelegate()->
RequestMediaAccessPermission(web_view_guest_->embedder_web_contents(),
request,
callback);
}
void WebViewPermissionHelper::CanDownload(
content::RenderViewHost* render_view_host,
const GURL& url,
const std::string& request_method,
const base::Callback<void(bool)>& callback) {
base::DictionaryValue request_info;
request_info.Set(guestview::kUrl, new base::StringValue(url.spec()));
RequestPermission(
WEB_VIEW_PERMISSION_TYPE_DOWNLOAD,
request_info,
base::Bind(&WebViewPermissionHelper::OnDownloadPermissionResponse,
base::Unretained(this),
callback),
false /* allowed_by_default */);
}
void WebViewPermissionHelper::OnDownloadPermissionResponse(
const base::Callback<void(bool)>& callback,
bool allow,
const std::string& user_input) {
callback.Run(allow && web_view_guest_->attached());
}
void WebViewPermissionHelper::RequestPointerLockPermission(
bool user_gesture,
bool last_unlocked_by_target,
const base::Callback<void(bool)>& callback) {
base::DictionaryValue request_info;
request_info.Set(guestview::kUserGesture,
base::Value::CreateBooleanValue(user_gesture));
request_info.Set(webview::kLastUnlockedBySelf,
base::Value::CreateBooleanValue(last_unlocked_by_target));
request_info.Set(guestview::kUrl,
new base::StringValue(
web_contents()->GetLastCommittedURL().spec()));
RequestPermission(
WEB_VIEW_PERMISSION_TYPE_POINTER_LOCK,
request_info,
base::Bind(
&WebViewPermissionHelper::OnPointerLockPermissionResponse,
base::Unretained(this),
callback),
false /* allowed_by_default */);
}
void WebViewPermissionHelper::OnPointerLockPermissionResponse(
const base::Callback<void(bool)>& callback,
bool allow,
const std::string& user_input) {
callback.Run(allow && web_view_guest_->attached());
}
void WebViewPermissionHelper::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,
new base::StringValue(requesting_frame.spec()));
request_info.Set(guestview::kUserGesture,
base::Value::CreateBooleanValue(user_gesture));
// It is safe to hold an unretained pointer to WebViewPermissionHelper because
// this callback is called from WebViewPermissionHelper::SetPermission.
const PermissionResponseCallback permission_callback =
base::Bind(
&WebViewPermissionHelper::OnGeolocationPermissionResponse,
base::Unretained(this),
bridge_id,
user_gesture,
callback);
int request_id = RequestPermission(
WEB_VIEW_PERMISSION_TYPE_GEOLOCATION,
request_info,
permission_callback,
false /* allowed_by_default */);
bridge_id_to_request_id_map_[bridge_id] = request_id;
}
void WebViewPermissionHelper::OnGeolocationPermissionResponse(
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 || !web_view_guest_->attached()) {
callback.Run(false);
return;
}
Profile* profile = Profile::FromBrowserContext(
web_view_guest_->browser_context());
GeolocationPermissionContextFactory::GetForProfile(profile)->
RequestGeolocationPermission(
web_view_guest_->embedder_web_contents(),
// 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,
web_view_guest_->embedder_web_contents()->GetLastCommittedURL(),
user_gesture,
callback,
NULL);
}
void WebViewPermissionHelper::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);
}
int WebViewPermissionHelper::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;
}
void WebViewPermissionHelper::RequestFileSystemPermission(
const GURL& url,
bool allowed_by_default,
const base::Callback<void(bool)>& callback) {
base::DictionaryValue request_info;
request_info.Set(guestview::kUrl, new base::StringValue(url.spec()));
RequestPermission(
WEB_VIEW_PERMISSION_TYPE_FILESYSTEM,
request_info,
base::Bind(
&WebViewPermissionHelper::OnFileSystemPermissionResponse,
base::Unretained(this),
callback),
allowed_by_default);
}
void WebViewPermissionHelper::OnFileSystemPermissionResponse(
const base::Callback<void(bool)>& callback,
bool allow,
const std::string& user_input) {
callback.Run(allow && web_view_guest_->attached());
}
void WebViewPermissionHelper::FileSystemAccessedAsync(int render_process_id,
int render_frame_id,
int request_id,
const GURL& url,
bool blocked_by_policy) {
RequestFileSystemPermission(
url,
!blocked_by_policy,
base::Bind(&WebViewPermissionHelper::FileSystemAccessedAsyncResponse,
base::Unretained(this),
render_process_id,
render_frame_id,
request_id,
url));
}
void WebViewPermissionHelper::FileSystemAccessedAsyncResponse(
int render_process_id,
int render_frame_id,
int request_id,
const GURL& url,
bool allowed) {
TabSpecificContentSettings::FileSystemAccessed(
render_process_id, render_frame_id, url, !allowed);
Send(new ChromeViewMsg_RequestFileSystemAccessAsyncResponse(
render_frame_id, request_id, allowed));
}
void WebViewPermissionHelper::FileSystemAccessedSync(int render_process_id,
int render_frame_id,
const GURL& url,
bool blocked_by_policy,
IPC::Message* reply_msg) {
RequestFileSystemPermission(
url,
!blocked_by_policy,
base::Bind(&WebViewPermissionHelper::FileSystemAccessedSyncResponse,
base::Unretained(this),
render_process_id,
render_frame_id,
url,
reply_msg));
}
void WebViewPermissionHelper::FileSystemAccessedSyncResponse(
int render_process_id,
int render_frame_id,
const GURL& url,
IPC::Message* reply_msg,
bool allowed) {
TabSpecificContentSettings::FileSystemAccessed(
render_process_id, render_frame_id, url, !allowed);
ChromeViewHostMsg_RequestFileSystemAccessSync::WriteReplyParams(reply_msg,
allowed);
Send(reply_msg);
}
int WebViewPermissionHelper::RequestPermission(
WebViewPermissionType 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 WEB_VIEW_PERMISSION_TYPE_NEW_WINDOW: {
web_view_guest_->DispatchEventToEmbedder(
new GuestViewBase::Event(webview::kEventNewWindow, args.Pass()));
break;
}
case WEB_VIEW_PERMISSION_TYPE_JAVASCRIPT_DIALOG: {
web_view_guest_->DispatchEventToEmbedder(
new GuestViewBase::Event(webview::kEventDialog, args.Pass()));
break;
}
default: {
args->SetString(webview::kPermission,
PermissionTypeToString(permission_type));
web_view_guest_->DispatchEventToEmbedder(new GuestViewBase::Event(
webview::kEventPermissionRequest,
args.Pass()));
break;
}
}
return request_id;
}
WebViewPermissionHelper::SetPermissionResult
WebViewPermissionHelper::SetPermission(
int request_id,
PermissionResponseAction action,
const std::string& user_input) {
RequestMap::iterator request_itr =
pending_permission_requests_.find(request_id);
if (request_itr == pending_permission_requests_.end())
return SET_PERMISSION_INVALID;
const PermissionResponseInfo& info = request_itr->second;
bool allow = (action == ALLOW) ||
((action == DEFAULT) && info.allowed_by_default);
info.callback.Run(allow, user_input);
// Only record user initiated (i.e. non-default) actions.
if (action != DEFAULT)
RecordUserInitiatedUMA(info, allow);
pending_permission_requests_.erase(request_itr);
return allow ? SET_PERMISSION_ALLOWED : SET_PERMISSION_DENIED;
}
WebViewPermissionHelper::PermissionResponseInfo::PermissionResponseInfo()
: permission_type(WEB_VIEW_PERMISSION_TYPE_UNKNOWN),
allowed_by_default(false) {
}
WebViewPermissionHelper::PermissionResponseInfo::PermissionResponseInfo(
const PermissionResponseCallback& callback,
WebViewPermissionType permission_type,
bool allowed_by_default)
: callback(callback),
permission_type(permission_type),
allowed_by_default(allowed_by_default) {
}
WebViewPermissionHelper::PermissionResponseInfo::~PermissionResponseInfo() {
}
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_GUEST_VIEW_WEB_VIEW_WEB_VIEW_PERMISSION_HELPER_H_
#define CHROME_BROWSER_GUEST_VIEW_WEB_VIEW_WEB_VIEW_PERMISSION_HELPER_H_
#include "base/memory/weak_ptr.h"
#include "base/metrics/user_metrics_action.h"
#include "chrome/browser/guest_view/guest_view_constants.h"
#include "chrome/browser/guest_view/web_view/web_view_permission_types.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/media_stream_request.h"
using base::UserMetricsAction;
class WebViewGuest;
// WebViewPermissionHelper manages <webview> permission requests. This helper
// class is owned by WebViewGuest. Its purpose is to request permission for
// various operations from the <webview> embedder, and reply back via callbacks
// to the callers on a response from the embedder.
class WebViewPermissionHelper
: public content::WebContentsObserver {
public:
explicit WebViewPermissionHelper(WebViewGuest* guest);
virtual ~WebViewPermissionHelper();
typedef base::Callback<
void(bool /* allow */, const std::string& /* user_input */)>
PermissionResponseCallback;
// A map to store the callback for a request keyed by the request's id.
struct PermissionResponseInfo {
PermissionResponseCallback callback;
WebViewPermissionType permission_type;
bool allowed_by_default;
PermissionResponseInfo();
PermissionResponseInfo(const PermissionResponseCallback& callback,
WebViewPermissionType permission_type,
bool allowed_by_default);
~PermissionResponseInfo();
};
typedef std::map<int, PermissionResponseInfo> RequestMap;
int RequestPermission(WebViewPermissionType permission_type,
const base::DictionaryValue& request_info,
const PermissionResponseCallback& callback,
bool allowed_by_default);
static WebViewPermissionHelper* FromWebContents(
content::WebContents* web_contents);
static WebViewPermissionHelper* FromFrameID(int render_process_id,
int render_frame_id);
void RequestMediaAccessPermission(
content::WebContents* source,
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback);
void CanDownload(content::RenderViewHost* render_view_host,
const GURL& url,
const std::string& request_method,
const base::Callback<void(bool)>& callback);
void RequestPointerLockPermission(bool user_gesture,
bool last_unlocked_by_target,
const base::Callback<void(bool)>& callback);
// Requests Geolocation Permission from the embedder.
void RequestGeolocationPermission(int bridge_id,
const GURL& requesting_frame,
bool user_gesture,
const base::Callback<void(bool)>& callback);
void CancelGeolocationPermissionRequest(int bridge_id);
void RequestFileSystemPermission(const GURL& url,
bool allowed_by_default,
const base::Callback<void(bool)>& callback);
// Called when file system access is requested by the guest content using the
// asynchronous HTML5 file system API. The request is plumbed through the
// <webview> permission request API. The request will be:
// - Allowed if the embedder explicitly allowed it.
// - Denied if the embedder explicitly denied.
// - Determined by the guest's content settings if the embedder does not
// perform an explicit action.
// If access was blocked due to the page's content settings,
// |blocked_by_policy| should be true, and this function should invoke
// OnContentBlocked.
void FileSystemAccessedAsync(int render_process_id,
int render_frame_id,
int request_id,
const GURL& url,
bool blocked_by_policy);
// Called when file system access is requested by the guest content using the
// synchronous HTML5 file system API in a worker thread or shared worker. The
// request is plumbed through the <webview> permission request API. The
// request will be:
// - Allowed if the embedder explicitly allowed it.
// - Denied if the embedder explicitly denied.
// - Determined by the guest's content settings if the embedder does not
// perform an explicit action.
// If access was blocked due to the page's content settings,
// |blocked_by_policy| should be true, and this function should invoke
// OnContentBlocked.
void FileSystemAccessedSync(int render_process_id,
int render_frame_id,
const GURL& url,
bool blocked_by_policy,
IPC::Message* reply_msg);
enum PermissionResponseAction { DENY, ALLOW, DEFAULT };
enum SetPermissionResult {
SET_PERMISSION_INVALID,
SET_PERMISSION_ALLOWED,
SET_PERMISSION_DENIED
};
// Responds to the permission request |request_id| with |action| and
// |user_input|. Returns whether there was a pending request for the provided
// |request_id|.
SetPermissionResult SetPermission(int request_id,
PermissionResponseAction action,
const std::string& user_input);
private:
#if defined(ENABLE_PLUGINS)
// content::WebContentsObserver implementation.
virtual bool OnMessageReceived(
const IPC::Message& message,
content::RenderFrameHost* render_frame_host) OVERRIDE;
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
// Message handlers:
void OnBlockedUnauthorizedPlugin(const base::string16& name,
const std::string& identifier);
void OnCouldNotLoadPlugin(const base::FilePath& plugin_path);
void OnBlockedOutdatedPlugin(int placeholder_id,
const std::string& identifier);
void OnNPAPINotSupported(const std::string& identifier);
void OnOpenAboutPlugins();
#if defined(ENABLE_PLUGIN_INSTALLATION)
void OnFindMissingPlugin(int placeholder_id, const std::string& mime_type);
void OnRemovePluginPlaceholderHost(int placeholder_id);
#endif // defined(ENABLE_PLUGIN_INSTALLATION)
void OnPermissionResponse(const std::string& identifier,
bool allow,
const std::string& user_input);
#endif // defiend(ENABLE_PLUGINS)
void OnGeolocationPermissionResponse(
int bridge_id,
bool user_gesture,
const base::Callback<void(bool)>& callback,
bool allow,
const std::string& user_input);
void OnFileSystemPermissionResponse(
const base::Callback<void(bool)>& callback,
bool allow,
const std::string& user_input);
void OnMediaPermissionResponse(
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback,
bool allow,
const std::string& user_input);
void OnDownloadPermissionResponse(
const base::Callback<void(bool)>& callback,
bool allow,
const std::string& user_input);
void OnPointerLockPermissionResponse(
const base::Callback<void(bool)>& callback,
bool allow,
const std::string& user_input);
// Bridge IDs correspond to a geolocation request. This method will remove
// the bookkeeping for a particular geolocation request associated with the
// provided |bridge_id|. It returns the request ID of the geolocation request.
int RemoveBridgeID(int bridge_id);
void FileSystemAccessedAsyncResponse(int render_process_id,
int render_frame_id,
int request_id,
const GURL& url,
bool allowed);
void FileSystemAccessedSyncResponse(int render_process_id,
int render_frame_id,
const GURL& url,
IPC::Message* reply_msg,
bool allowed);
// A counter to generate a unique request id for a permission request.
// We only need the ids to be unique for a given WebViewGuest.
int next_permission_request_id_;
WebViewPermissionHelper::RequestMap pending_permission_requests_;
std::map<int, int> bridge_id_to_request_id_map_;
WebViewGuest* web_view_guest_;
base::WeakPtrFactory<WebViewPermissionHelper> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(WebViewPermissionHelper);
};
#endif // CHROME_BROWSER_GUEST_VIEW_WEB_VIEW_WEB_VIEW_PERMISSION_HELPER_H_
......@@ -14,7 +14,7 @@
#include "chrome/browser/content_settings/tab_specific_content_settings.h"
#if defined(ENABLE_EXTENSIONS)
#include "chrome/browser/guest_view/web_view/web_view_guest.h"
#include "chrome/browser/guest_view/web_view/web_view_permission_helper.h"
#include "chrome/browser/guest_view/web_view/web_view_renderer_state.h"
#endif
......@@ -208,14 +208,16 @@ void ChromeRenderMessageFilter::OnRequestFileSystemAccessSync(
WebViewRendererState::GetInstance()->IsGuest(render_process_id_);
if (is_web_view_guest) {
// Record access to file system for potential display in UI.
BrowserThread::PostTask(BrowserThread::UI,
FROM_HERE,
base::Bind(&WebViewGuest::FileSystemAccessedSync,
render_process_id_,
render_frame_id,
origin_url,
!allowed,
reply_msg));
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
base::Bind(&ChromeRenderMessageFilter::
FileSystemAccessedSyncOnUIThread,
render_process_id_,
render_frame_id,
origin_url,
!allowed,
reply_msg));
return;
}
#endif
......@@ -233,6 +235,24 @@ void ChromeRenderMessageFilter::OnRequestFileSystemAccessSync(
!allowed));
}
#if defined(ENABLE_EXTENSIONS)
void ChromeRenderMessageFilter::FileSystemAccessedSyncOnUIThread(
int render_process_id,
int render_frame_id,
const GURL& url,
bool blocked_by_policy,
IPC::Message* reply_msg) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
WebViewPermissionHelper* web_view_permission_helper =
WebViewPermissionHelper::FromFrameID(render_process_id, render_frame_id);
web_view_permission_helper->FileSystemAccessedSync(render_process_id,
render_frame_id,
url,
blocked_by_policy,
reply_msg);
}
#endif
void ChromeRenderMessageFilter::OnRequestFileSystemAccessAsync(
int render_frame_id,
int request_id,
......@@ -248,14 +268,16 @@ void ChromeRenderMessageFilter::OnRequestFileSystemAccessAsync(
WebViewRendererState::GetInstance()->IsGuest(render_process_id_);
if (is_web_view_guest) {
// Record access to file system for potential display in UI.
BrowserThread::PostTask(BrowserThread::UI,
FROM_HERE,
base::Bind(&WebViewGuest::FileSystemAccessedAsync,
render_process_id_,
render_frame_id,
request_id,
origin_url,
!allowed));
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
base::Bind(&ChromeRenderMessageFilter::
FileSystemAccessedAsyncOnUIThread,
render_process_id_,
render_frame_id,
request_id,
origin_url,
!allowed));
return;
}
#endif
......@@ -273,6 +295,24 @@ void ChromeRenderMessageFilter::OnRequestFileSystemAccessAsync(
!allowed));
}
#if defined(ENABLE_EXTENSIONS)
void ChromeRenderMessageFilter::FileSystemAccessedAsyncOnUIThread(
int render_process_id,
int render_frame_id,
int request_id,
const GURL& url,
bool blocked_by_policy) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
WebViewPermissionHelper* web_view_permission_helper =
WebViewPermissionHelper::FromFrameID(render_process_id, render_frame_id);
web_view_permission_helper->FileSystemAccessedAsync(render_process_id,
render_frame_id,
request_id,
url,
blocked_by_policy);
}
#endif
void ChromeRenderMessageFilter::OnAllowIndexedDB(int render_frame_id,
const GURL& origin_url,
const GURL& top_origin_url,
......
......@@ -76,10 +76,27 @@ class ChromeRenderMessageFilter : public content::BrowserMessageFilter {
const GURL& origin_url,
const GURL& top_origin_url,
IPC::Message* message);
#if defined(ENABLE_EXTENSIONS)
static void FileSystemAccessedSyncOnUIThread(
int render_process_id,
int render_frame_id,
const GURL& url,
bool blocked_by_policy,
IPC::Message* reply_msg);
#endif
void OnRequestFileSystemAccessAsync(int render_frame_id,
int request_id,
const GURL& origin_url,
const GURL& top_origin_url);
#if defined(ENABLE_EXTENSIONS)
static void FileSystemAccessedAsyncOnUIThread(
int render_process_id,
int render_frame_id,
int request_id,
const GURL& url,
bool blocked_by_policy);
#endif
void OnAllowIndexedDB(int render_frame_id,
const GURL& origin_url,
const GURL& top_origin_url,
......
......@@ -1526,6 +1526,8 @@
'browser/guest_view/web_view/web_view_guest.cc',
'browser/guest_view/web_view/web_view_guest.h',
'browser/guest_view/web_view/web_view_permission_types.h',
'browser/guest_view/web_view/web_view_permission_helper.cc',
'browser/guest_view/web_view/web_view_permission_helper.h',
'browser/guest_view/web_view/web_view_renderer_state.cc',
'browser/guest_view/web_view/web_view_renderer_state.h',
'browser/infobars/infobar_extension_api.cc',
......@@ -1761,8 +1763,6 @@
],
# See also the plugin_installation_sources list below.
'chrome_browser_plugins_sources': [
'browser/guest_view/web_view/plugin_permission_helper.cc',
'browser/guest_view/web_view/plugin_permission_helper.h',
'browser/metrics/plugin_metrics_provider.cc',
'browser/metrics/plugin_metrics_provider.h',
'browser/pepper_broker_infobar_delegate.cc',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment