Commit af1718c9 authored by fsamuel@chromium.org's avatar fsamuel@chromium.org

<webview>: Refactor Permission API to chrome

BUG=166165
Test=WebViewTest.*, WebViewInteractiveTest.*
TBR=cdn@chromium.org for removing IPCs in browser_plugin_messages.h
NOTRY=true, previous patch worked, just merging.

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@217057 0039d316-1c4b-4281-b951-d872f2087c98
parent b4d47f80
......@@ -108,13 +108,13 @@ bool WebviewGoFunction::RunImpl() {
return true;
}
WebviewStopFunction::WebviewStopFunction() {
WebviewReloadFunction::WebviewReloadFunction() {
}
WebviewStopFunction::~WebviewStopFunction() {
WebviewReloadFunction::~WebviewReloadFunction() {
}
bool WebviewStopFunction::RunImpl() {
bool WebviewReloadFunction::RunImpl() {
int instance_id = 0;
EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &instance_id));
......@@ -123,26 +123,55 @@ bool WebviewStopFunction::RunImpl() {
if (!guest)
return false;
guest->Stop();
guest->Reload();
return true;
}
WebviewReloadFunction::WebviewReloadFunction() {
WebviewSetPermissionFunction::WebviewSetPermissionFunction() {
}
WebviewReloadFunction::~WebviewReloadFunction() {
WebviewSetPermissionFunction::~WebviewSetPermissionFunction() {
}
bool WebviewReloadFunction::RunImpl() {
bool WebviewSetPermissionFunction::RunImpl() {
int instance_id = 0;
EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &instance_id));
int request_id = 0;
EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(1, &request_id));
bool should_allow = false;
EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(2, &should_allow));
std::string user_input;
EXTENSION_FUNCTION_VALIDATE(args_->GetString(3, &user_input));
WebViewGuest* guest = WebViewGuest::From(
render_view_host()->GetProcess()->GetID(), instance_id);
if (!guest)
return false;
guest->Reload();
EXTENSION_FUNCTION_VALIDATE(
guest->SetPermission(request_id, should_allow, user_input));
return true;
}
WebviewStopFunction::WebviewStopFunction() {
}
WebviewStopFunction::~WebviewStopFunction() {
}
bool WebviewStopFunction::RunImpl() {
int instance_id = 0;
EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &instance_id));
WebViewGuest* guest = WebViewGuest::From(
render_view_host()->GetProcess()->GetID(), instance_id);
if (!guest)
return false;
guest->Stop();
return true;
}
......
......@@ -96,6 +96,22 @@ class WebviewReloadFunction : public AsyncExtensionFunction {
DISALLOW_COPY_AND_ASSIGN(WebviewReloadFunction);
};
class WebviewSetPermissionFunction : public AsyncExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("webview.setPermission", WEBVIEW_SETPERMISSION);
WebviewSetPermissionFunction();
protected:
virtual ~WebviewSetPermissionFunction();
// ExtensionFunction implementation.
virtual bool RunImpl() OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(WebviewSetPermissionFunction);
};
class WebviewStopFunction : public AsyncExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("webview.stop", WEBVIEW_STOP);
......
......@@ -590,6 +590,7 @@ enum HistogramValue {
LOGPRIVATE_GETHISTORICAL,
EXPERIMENTAL_INPUT_VIRTUALKEYBOARD_MOVECURSOR,
METRICSPRIVATE_GETVARIATIONPARAMS,
WEBVIEW_SETPERMISSION,
ENUM_BOUNDARY // Last entry: Add new entries above.
};
......
......@@ -10,12 +10,15 @@ namespace webview {
const char kEventClose[] = "webview.onClose";
const char kEventConsoleMessage[] = "webview.onConsoleMessage";
const char kEventContentLoad[] = "webview.onContentLoad";
const char kEventDialog[] = "webview.onDialog";
const char kEventExit[] = "webview.onExit";
const char kEventLoadAbort[] = "webview.onLoadAbort";
const char kEventLoadCommit[] = "webview.onLoadCommit";
const char kEventLoadRedirect[] = "webview.onLoadRedirect";
const char kEventLoadStart[] = "webview.onLoadStart";
const char kEventLoadStop[] = "webview.onLoadStop";
const char kEventNewWindow[] = "webview.onNewWindow";
const char kEventPermissionRequest[] = "webview.onPermissionRequest";
const char kEventResponsive[] = "webview.onResponsive";
const char kEventUnresponsive[] = "webview.onUnresponsive";
......@@ -25,8 +28,16 @@ const char kLine[] = "line";
const char kMessage[] = "message";
const char kNewURL[] = "newUrl";
const char kOldURL[] = "oldUrl";
const char kPermission[] = "permission";
const char kPermissionTypeDialog[] = "dialog";
const char kPermissionTypeDownload[] = "download";
const char kPermissionTypeGeolocation[] = "geolocation";
const char kPermissionTypeMedia[] = "media";
const char kPermissionTypeNewWindow[] = "newwindow";
const char kPermissionTypePointerLock[] = "pointerLock";
const char kProcessId[] = "processId";
const char kReason[] = "reason";
const char kRequestId[] = "requestId";
const char kSourceId[] = "sourceId";
// Internal parameters/properties on events.
......
......@@ -13,12 +13,15 @@ namespace webview {
extern const char kEventClose[];
extern const char kEventConsoleMessage[];
extern const char kEventContentLoad[];
extern const char kEventDialog[];
extern const char kEventExit[];
extern const char kEventLoadAbort[];
extern const char kEventLoadCommit[];
extern const char kEventLoadRedirect[];
extern const char kEventLoadStart[];
extern const char kEventLoadStop[];
extern const char kEventNewWindow[];
extern const char kEventPermissionRequest[];
extern const char kEventResponsive[];
extern const char kEventUnresponsive[];
......@@ -28,8 +31,16 @@ extern const char kLine[];
extern const char kMessage[];
extern const char kNewURL[];
extern const char kOldURL[];
extern const char kPermission[];
extern const char kPermissionTypeDialog[];
extern const char kPermissionTypeDownload[];
extern const char kPermissionTypeGeolocation[];
extern const char kPermissionTypeMedia[];
extern const char kPermissionTypeNewWindow[];
extern const char kPermissionTypePointerLock[];
extern const char kProcessId[];
extern const char kReason[];
extern const char kRequestId[];
extern const char kSourceId[];
// Internal parameters/properties on events.
......
......@@ -43,6 +43,28 @@ static std::string TerminationStatusToString(base::TerminationStatus status) {
return "unknown";
}
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:
return webview::kPermissionTypeNewWindow;
case BROWSER_PLUGIN_PERMISSION_TYPE_POINTER_LOCK:
return webview::kPermissionTypePointerLock;
case BROWSER_PLUGIN_PERMISSION_TYPE_JAVASCRIPT_DIALOG:
return webview::kPermissionTypeDialog;
case BROWSER_PLUGIN_PERMISSION_TYPE_UNKNOWN:
default:
NOTREACHED();
break;
}
return std::string();
}
void RemoveWebViewEventListenersOnIOThread(
void* profile,
const std::string& extension_id,
......@@ -59,7 +81,8 @@ WebViewGuest::WebViewGuest(WebContents* guest_web_contents)
: GuestView(guest_web_contents),
WebContentsObserver(guest_web_contents),
script_executor_(new extensions::ScriptExecutor(guest_web_contents,
&script_observers_)) {
&script_observers_)),
next_permission_request_id_(0) {
notification_registrar_.Add(
this, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
content::Source<WebContents>(guest_web_contents));
......@@ -175,6 +198,36 @@ void WebViewGuest::RendererUnresponsive() {
DispatchEvent(new GuestView::Event(webview::kEventUnresponsive, args.Pass()));
}
bool WebViewGuest::RequestPermission(
BrowserPluginPermissionType permission_type,
const base::DictionaryValue& request_info,
const PermissionResponseCallback& callback) {
int request_id = next_permission_request_id_++;
pending_permission_requests_[request_id] = callback;
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;
}
void WebViewGuest::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
......@@ -215,6 +268,20 @@ void WebViewGuest::Reload() {
guest_web_contents()->GetController().Reload(false);
}
bool WebViewGuest::SetPermission(int request_id,
bool should_allow,
const std::string& user_input) {
RequestMap::iterator request_itr =
pending_permission_requests_.find(request_id);
if (request_itr == pending_permission_requests_.end())
return false;
request_itr->second.Run(should_allow, user_input);
pending_permission_requests_.erase(request_itr);
return true;
}
void WebViewGuest::Stop() {
guest_web_contents()->Stop();
}
......
......@@ -49,6 +49,10 @@ class WebViewGuest : public GuestView,
const content::NativeWebKeyboardEvent& event) OVERRIDE;
virtual void RendererResponsive() OVERRIDE;
virtual void RendererUnresponsive() OVERRIDE;
virtual bool RequestPermission(
BrowserPluginPermissionType permission_type,
const base::DictionaryValue& request_info,
const PermissionResponseCallback& callback) OVERRIDE;
// NotificationObserver implementation.
virtual void Observe(int type,
......@@ -62,6 +66,13 @@ class WebViewGuest : public GuestView,
// Reload the guest.
void Reload();
// Responds to the permission request |request_id| with |should_allow| and
// |user_input|. Returns whether there was a pending request for the provided
// |request_id|.
bool SetPermission(int request_id,
bool should_allow,
const std::string& user_input);
// Stop loading the guest.
void Stop();
......@@ -120,6 +131,14 @@ class WebViewGuest : public GuestView,
content::NotificationRegistrar notification_registrar_;
// 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_;
// A map to store the callback for a request keyed by the request's id.
typedef std::map<int, PermissionResponseCallback> RequestMap;
RequestMap pending_permission_requests_;
DISALLOW_COPY_AND_ASSIGN(WebViewGuest);
};
......
......@@ -95,6 +95,28 @@
}
]
},
{
"name": "setPermission",
"type": "function",
"parameters": [
{
"type": "integer",
"name": "instanceId"
},
{
"type": "integer",
"name": "requestId"
},
{
"type": "boolean",
"name": "shouldAllow"
},
{
"type": "string",
"name": "userInput"
}
]
},
{
"name": "stop",
"type": "function",
......
......@@ -11,17 +11,28 @@
// permission API would only be available for channels CHANNEL_DEV and
// CHANNEL_CANARY.
var createEvent = require('webView').CreateEvent;
var WebRequestEvent = require('webRequestInternal').WebRequestEvent;
var webRequestSchema =
requireNative('schema_registry').GetSchema('webRequest');
var WebView = require('webView').WebView;
var WEB_VIEW_EXPERIMENTAL_EXT_EVENTS = {
'dialog': {
cancelable: true,
customHandler: function(webview, event, webviewEvent) {
webview.maybeSetupExtDialogEvent_(event, webviewEvent);
},
evt: createEvent('webview.onDialog'),
fields: ['defaultPromptText', 'messageText', 'messageType', 'url']
}
};
/**
* @private
*/
WebView.prototype.maybeSetupExperimentalAPI_ = function() {
this.setupWebRequestEvents_();
this.setupDialogEvent_();
};
/**
......@@ -78,90 +89,87 @@ WebView.prototype.setupWebRequestEvents_ = function() {
/**
* @private
*/
WebView.prototype.setupDialogEvent_ = function() {
var ERROR_MSG_DIALOG_ACTION_ALREADY_TAKEN = '<webview>: ' +
'An action has already been taken for this "dialog" event.';
WebView.prototype.maybeSetupExtDialogEvent_ = function(event, webviewEvent) {
var showWarningMessage = function(dialogType) {
var VOWELS = ['a', 'e', 'i', 'o', 'u'];
var WARNING_MSG_DIALOG_BLOCKED = '<webview>: %1 %2 dialog was blocked.';
var article = (VOWELS.indexOf(dialogType.charAt(0)) >= 0) ? 'An' : 'A';
var output = WARNING_MSG_DIALOG_BLOCKED.replace('%1', article);
output = output.replace('%2', dialogType);
console.log(output);
console.warn(output);
};
var DIALOG_EVENT_ATTRIBUTES = [
'defaultPromptText',
'messageText',
'messageType',
'url'
];
var self = this;
var node = this.webviewNode_;
var browserPluginNode = this.browserPluginNode_;
var webviewNode = this.webviewNode_;
var requestId = event.requestId;
var actionTaken = false;
var onTrackedObjectGone = function(requestId, dialogType, e) {
var detail = e.detail ? JSON.parse(e.detail) : {};
if (detail.id != requestId)
if (detail.id != requestId) {
return;
// If the request was pending then show a warning indiciating that a new
// window was blocked.
if (browserPluginNode['-internal-setPermission'](requestId, false, '')) {
showWarningMessage(dialogType);
}
};
browserPluginNode.addEventListener('-internal-dialog', function(e) {
var evt = new Event('dialog', { bubbles: true, cancelable: true });
var detail = e.detail ? JSON.parse(e.detail) : {};
// Avoid showing a warning message if the decision has already been made.
if (actionTaken) {
return;
}
$Array.forEach(DIALOG_EVENT_ATTRIBUTES, function(attribName) {
evt[attribName] = detail[attribName];
});
var requestId = detail.requestId;
var actionTaken = false;
chrome.webview.setPermission(self.instanceId_, requestId, false, '');
showWarningMessage(dialogType);
}
var validateCall = function() {
if (actionTaken) {
throw new Error(ERROR_MSG_DIALOG_ACTION_ALREADY_TAKEN);
}
actionTaken = true;
};
var validateCall = function() {
var ERROR_MSG_DIALOG_ACTION_ALREADY_TAKEN = '<webview>: ' +
'An action has already been taken for this "dialog" event.';
var dialog = {
ok: function(user_input) {
validateCall();
browserPluginNode['-internal-setPermission'](
requestId, true, user_input);
},
cancel: function() {
validateCall();
browserPluginNode['-internal-setPermission'](requestId, false, '');
}
};
evt.dialog = dialog;
var defaultPrevented = !node.dispatchEvent(evt);
if (actionTaken) {
return;
throw new Error(ERROR_MSG_DIALOG_ACTION_ALREADY_TAKEN);
}
actionTaken = true;
};
if (defaultPrevented) {
// Tell the JavaScript garbage collector to track lifetime of |dialog| and
// call back when the dialog object has been collected.
var onTrackedObjectGoneWithRequestId =
$Function.bind(
onTrackedObjectGone, self, requestId, detail.messageType);
browserPluginNode.addEventListener('-internal-trackedobjectgone',
onTrackedObjectGoneWithRequestId);
browserPluginNode['-internal-trackObjectLifetime'](dialog, requestId);
} else {
actionTaken = true;
// The default action is equivalent to canceling the dialog.
browserPluginNode['-internal-setPermission'](requestId, false, '');
showWarningMessage(detail.messageType);
var dialog = {
ok: function(user_input) {
validateCall();
user_input = user_input || '';
chrome.webview.setPermission(
self.instanceId_, requestId, true, user_input);
},
cancel: function() {
validateCall();
chrome.webview.setPermission(self.instanceId_, requestId, false, '');
}
});
};
webviewEvent.dialog = dialog;
var defaultPrevented = !webviewNode.dispatchEvent(webviewEvent);
if (actionTaken) {
return;
}
if (defaultPrevented) {
// Tell the JavaScript garbage collector to track lifetime of |dialog| and
// call back when the dialog object has been collected.
var onTrackedObjectGoneWithRequestId =
$Function.bind(
onTrackedObjectGone, self, requestId, event.messageType);
browserPluginNode.addEventListener('-internal-trackedobjectgone',
onTrackedObjectGoneWithRequestId);
browserPluginNode['-internal-trackObjectLifetime'](dialog, requestId);
} else {
actionTaken = true;
// The default action is equivalent to canceling the dialog.
chrome.webview.setPermission(self.instanceId_, requestId, false, '');
showWarningMessage(event.messageType);
}
};
/**
* @private
*/
WebView.prototype.maybeGetWebviewExperimentalExtEvents_ = function() {
return WEB_VIEW_EXPERIMENTAL_EXT_EVENTS;
};
......@@ -346,7 +346,7 @@ BrowserPluginGuest::BrowserPluginGuest(
mouse_locked_(false),
pending_lock_request_(false),
embedder_visible_(true),
next_permission_request_id_(0),
next_permission_request_id_(browser_plugin::kInvalidPermissionRequestID),
has_render_view_(has_render_view) {
DCHECK(web_contents);
web_contents->SetDelegate(this);
......@@ -383,15 +383,39 @@ void BrowserPluginGuest::DestroyUnattachedWindows() {
DCHECK_EQ(0ul, pending_new_windows_.size());
}
void BrowserPluginGuest::RespondToPermissionRequest(
int request_id,
bool should_allow,
const std::string& user_input) {
RequestMap::iterator request_itr = permission_request_map_.find(request_id);
if (request_itr == permission_request_map_.end()) {
LOG(INFO) << "Not a valid request ID.";
return;
}
request_itr->second->Respond(should_allow, user_input);
permission_request_map_.erase(request_itr);
}
int BrowserPluginGuest::RequestPermission(
BrowserPluginPermissionType permission_type,
scoped_refptr<BrowserPluginGuest::PermissionRequest> request,
const base::DictionaryValue& request_info) {
int request_id = next_permission_request_id_++;
if (!delegate_) {
request->Respond(false, "");
return browser_plugin::kInvalidPermissionRequestID;
}
int request_id = ++next_permission_request_id_;
permission_request_map_[request_id] = request;
SendMessageToEmbedder(new BrowserPluginMsg_RequestPermission(
instance_id(), permission_type, request_id, request_info));
BrowserPluginGuestDelegate::PermissionResponseCallback callback =
base::Bind(&BrowserPluginGuest::RespondToPermissionRequest,
AsWeakPtr(),
request_id);
// If BrowserPluginGuestDelegate hasn't handled the permission then we simply
// reject it immediately.
if (!delegate_->RequestPermission(permission_type, request_info, callback))
callback.Run(false, "");
return request_id;
}
......@@ -422,8 +446,6 @@ bool BrowserPluginGuest::OnMessageReceivedFromEmbedder(
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_NavigateGuest, OnNavigateGuest)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_PluginDestroyed, OnPluginDestroyed)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ResizeGuest, OnResizeGuest)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_RespondPermission,
OnRespondPermission)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetAutoSize, OnSetSize)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent,
OnSetEditCommandsForNextKeyEvent)
......@@ -809,7 +831,7 @@ void BrowserPluginGuest::RequestNewWindowPermission(
base::Value::CreateStringValue(
WindowOpenDispositionToString(disposition)));
RequestPermission(BrowserPluginPermissionTypeNewWindow,
RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_NEW_WINDOW,
new NewWindowRequest(guest->instance_id(), this),
request_info);
}
......@@ -880,7 +902,7 @@ void BrowserPluginGuest::AskEmbedderForGeolocationPermission(
base::Value::CreateStringValue(requesting_frame.spec()));
int request_id =
RequestPermission(BrowserPluginPermissionTypeGeolocation,
RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_GEOLOCATION,
new GeolocationRequest(
callback, bridge_id, &weak_ptr_factory_),
request_info);
......@@ -894,7 +916,7 @@ int BrowserPluginGuest::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 -1;
return browser_plugin::kInvalidPermissionRequestID;
int request_id = bridge_itr->second;
bridge_id_to_request_id_map_.erase(bridge_itr);
......@@ -1016,7 +1038,6 @@ bool BrowserPluginGuest::ShouldForwardToBrowserPluginGuest(
case BrowserPluginHostMsg_NavigateGuest::ID:
case BrowserPluginHostMsg_PluginDestroyed::ID:
case BrowserPluginHostMsg_ResizeGuest::ID:
case BrowserPluginHostMsg_RespondPermission::ID:
case BrowserPluginHostMsg_SetAutoSize::ID:
case BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent::ID:
case BrowserPluginHostMsg_SetFocus::ID:
......@@ -1240,7 +1261,7 @@ void BrowserPluginGuest::OnLockMouse(bool user_gesture,
base::Value::CreateStringValue(
web_contents()->GetURL().spec()));
RequestPermission(BrowserPluginPermissionTypePointerLock,
RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_POINTER_LOCK,
new PointerLockRequest(this),
request_info);
}
......@@ -1371,20 +1392,6 @@ void BrowserPluginGuest::OnSetVisibility(int instance_id, bool visible) {
GetWebContents()->WasHidden();
}
void BrowserPluginGuest::OnRespondPermission(
int instance_id,
int request_id,
bool should_allow,
const std::string& user_input) {
RequestMap::iterator request_itr = permission_request_map_.find(request_id);
if (request_itr == permission_request_map_.end()) {
LOG(INFO) << "Not a valid request ID.";
return;
}
request_itr->second->Respond(should_allow, user_input);
permission_request_map_.erase(request_itr);
}
void BrowserPluginGuest::OnSwapBuffersACK(int instance_id,
int route_id,
int gpu_host_id,
......@@ -1499,7 +1506,7 @@ void BrowserPluginGuest::RequestMediaAccessPermission(
browser_plugin::kURL,
base::Value::CreateStringValue(request.security_origin.spec()));
RequestPermission(BrowserPluginPermissionTypeMedia,
RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_MEDIA,
new MediaRequest(request, callback, this),
request_info);
}
......@@ -1533,7 +1540,7 @@ void BrowserPluginGuest::RunJavaScriptDialog(
browser_plugin::kURL,
base::Value::CreateStringValue(origin_url.spec()));
RequestPermission(BrowserPluginPermissionTypeJavaScriptDialog,
RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_JAVASCRIPT_DIALOG,
new JavaScriptDialogRequest(callback),
request_info);
}
......@@ -1630,7 +1637,7 @@ void BrowserPluginGuest::DidRetrieveDownloadURLFromRequestId(
base::Value::CreateStringValue(request_method));
request_info.Set(browser_plugin::kURL, base::Value::CreateStringValue(url));
RequestPermission(BrowserPluginPermissionTypeDownload,
RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_DOWNLOAD,
new DownloadRequest(callback),
request_info);
}
......
......@@ -29,7 +29,6 @@
#include "base/memory/shared_memory.h"
#include "base/memory/weak_ptr.h"
#include "base/values.h"
#include "content/common/browser_plugin/browser_plugin_message_enums.h"
#include "content/common/edit_command.h"
#include "content/port/common/input_event_ack_state.h"
#include "content/public/browser/browser_plugin_guest_delegate.h"
......@@ -39,6 +38,7 @@
#include "content/public/browser/render_view_host_observer.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/browser_plugin_permission_type.h"
#include "third_party/WebKit/public/web/WebDragOperation.h"
#include "third_party/WebKit/public/web/WebDragStatus.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
......@@ -282,6 +282,10 @@ class CONTENT_EXPORT BrowserPluginGuest
// |this| takes ownership of |delegate|.
void SetDelegate(BrowserPluginGuestDelegate* delegate);
void RespondToPermissionRequest(int request_id,
bool should_allow,
const std::string& user_input);
private:
class EmbedderRenderViewHostObserver;
friend class TestBrowserPluginGuest;
......@@ -339,12 +343,6 @@ class CONTENT_EXPORT BrowserPluginGuest
int renderer_host_id,
const cc::CompositorFrameAck& ack);
// Allows or denies a permission request access, after the embedder has had a
// chance to decide.
void OnRespondPermission(int instance_id,
int request_id,
bool should_allow,
const std::string& user_input);
// Handles drag events from the embedder.
// When dragging, the drag events go to the embedder first, and if the drag
// happens on the browser plugin, then the plugin sends a corresponding
......
......@@ -25,7 +25,6 @@ const char kMethodInternalAttach[] = "-internal-attach";
const char kMethodInternalAttachWindowTo[] = "-internal-attachWindowTo";
const char kMethodInternalTrackObjectLifetime[] =
"-internal-trackObjectLifetime";
const char kMethodInternalSetPermission[] = "-internal-setPermission";
// Internal events.
const char kEventInternalInstanceIDAllocated[] = "instanceid-allocated";
......@@ -44,9 +43,6 @@ const char kAttributePartition[] = "partition";
const char kAttributeSrc[] = "src";
// Events.
const char kEventDialog[] = "dialog";
const char kEventNewWindow[] = "newwindow";
const char kEventRequestPermission[] = "permissionrequest";
const char kEventSizeChanged[] = "sizechanged";
// Parameters/properties on events.
......@@ -90,6 +86,7 @@ const char kErrorCannotRemovePartition[] =
// Other.
const char kBrowserPluginGuestManagerKeyName[] = "browser_plugin_guest_manager";
const int kInstanceIDNone = 0;
const int kInvalidPermissionRequestID = 0;
} // namespace browser_plugin
......
......@@ -25,7 +25,6 @@ extern const char kMethodTerminate[];
extern const char kMethodInternalAttach[];
extern const char kMethodInternalAttachWindowTo[];
extern const char kMethodInternalTrackObjectLifetime[];
extern const char kMethodInternalSetPermission[];
// Internal events
extern const char kEventInternalInstanceIDAllocated[];
......@@ -44,12 +43,7 @@ extern const char kAttributePartition[];
extern const char kAttributeSrc[];
// Events.
extern const char kEventDialog[];
extern const char kEventNewWindow[];
extern const char kEventRequestPermission[];
extern const char kEventResponsive[];
extern const char kEventSizeChanged[];
extern const char kEventUnresponsive[];
// Parameters/properties on events.
extern const char kDefaultPromptText[];
......@@ -89,6 +83,7 @@ extern const char kErrorCannotRemovePartition[];
// Other.
extern const char kBrowserPluginGuestManagerKeyName[];
extern const int kInstanceIDNone;
extern const int kInvalidPermissionRequestID;
} // namespace browser_plugin
......
......@@ -12,10 +12,10 @@
#include "base/values.h"
#include "cc/output/compositor_frame.h"
#include "cc/output/compositor_frame_ack.h"
#include "content/common/browser_plugin/browser_plugin_message_enums.h"
#include "content/common/content_export.h"
#include "content/common/content_param_traits.h"
#include "content/common/edit_command.h"
#include "content/public/common/browser_plugin_permission_type.h"
#include "content/public/common/common_param_traits.h"
#include "content/public/common/drop_data.h"
#include "ipc/ipc_channel_handle.h"
......@@ -34,7 +34,6 @@
#define IPC_MESSAGE_START BrowserPluginMsgStart
IPC_ENUM_TRAITS(BrowserPluginPermissionType)
IPC_ENUM_TRAITS(WebKit::WebDragStatus)
IPC_STRUCT_BEGIN(BrowserPluginHostMsg_AutoSize_Params)
......@@ -248,19 +247,6 @@ IPC_MESSAGE_ROUTED2(BrowserPluginHostMsg_SetName,
int /* instance_id */,
std::string /* name */)
// Tells the guest that its request for an API permission has been allowed or
// denied.
// Note that |allow| = true does not readily mean that the guest will be granted
// permission, since a security check in the embedder might follow. For example
// for media access permission, the guest will be granted permission only if its
// embedder also has access. For certain APIs, such as the Dialog API,
// additional information may be passed by the developer through |user_input|.
IPC_MESSAGE_ROUTED4(BrowserPluginHostMsg_RespondPermission,
int /* instance_id */,
int /* request_id */,
bool /* allow */,
std::string /* user_input */)
// Sends a PointerLock Lock ACK to the BrowserPluginGuest.
IPC_MESSAGE_ROUTED2(BrowserPluginHostMsg_LockMouse_ACK,
int /* instance_id */,
......@@ -363,14 +349,6 @@ IPC_MESSAGE_CONTROL5(BrowserPluginMsg_CompositorFrameSwapped,
uint32 /* output_surface_id */,
int /* renderer_host_id */)
// When the guest requests permission, the browser process forwards this
// request to the embeddder through this message.
IPC_MESSAGE_CONTROL4(BrowserPluginMsg_RequestPermission,
int /* instance_id */,
BrowserPluginPermissionType /* permission_type */,
int /* request_id */,
base::DictionaryValue /* request_info */)
// Forwards a PointerLock Unlock request to the BrowserPlugin.
IPC_MESSAGE_CONTROL2(BrowserPluginMsg_SetMouseLock,
int /* instance_id */,
......
......@@ -126,7 +126,6 @@
'common/appcache_messages.h',
'common/browser_plugin/browser_plugin_constants.cc',
'common/browser_plugin/browser_plugin_constants.h',
'common/browser_plugin/browser_plugin_message_enums.h',
'common/browser_plugin/browser_plugin_messages.h',
'common/browser_rendering_stats.cc',
'common/browser_rendering_stats.h',
......@@ -350,6 +349,7 @@
'common/worker_messages.h',
'common/zygote_commands_linux.h',
'port/common/input_event_ack_state.h',
'public/common/browser_plugin_permission_type.h',
'public/common/common_param_traits.cc',
'public/common/common_param_traits.h',
'public/common/common_param_traits_macros.h',
......
......@@ -11,4 +11,11 @@ bool BrowserPluginGuestDelegate::HandleKeyboardEvent(
return false;
}
bool BrowserPluginGuestDelegate::RequestPermission(
BrowserPluginPermissionType permission_type,
const base::DictionaryValue& request_info,
const PermissionResponseCallback& callback) {
return false;
}
} // namespace content
......@@ -5,9 +5,12 @@
#ifndef CONTENT_PUBLIC_BROWSER_BROWSER_PLUGIN_GUEST_DELEGATE_H_
#define CONTENT_PUBLIC_BROWSER_BROWSER_PLUGIN_GUEST_DELEGATE_H_
#include "base/callback_forward.h"
#include "base/process/kill.h"
#include "base/strings/string16.h"
#include "base/values.h"
#include "content/common/content_export.h"
#include "content/public/common/browser_plugin_permission_type.h"
namespace content {
......@@ -41,6 +44,19 @@ class CONTENT_EXPORT BrowserPluginGuestDelegate {
// Notification that the guest is hung.
virtual void RendererUnresponsive() {}
typedef base::Callback<void(bool /* allow */,
const std::string& /* user_input */)>
PermissionResponseCallback;
// Request permission from the delegate to perform an action of the provided
// |permission_type|. Details of the permission request are found in
// |request_info|. A |callback| is provided to make the decision.
// Returns whether the delegate has, or will handle the permission request.
virtual bool RequestPermission(
BrowserPluginPermissionType permission_type,
const base::DictionaryValue& request_info,
const PermissionResponseCallback& callback);
};
} // namespace content
......
......@@ -2,37 +2,33 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_COMMON_BROWSER_PLUGIN_BROWSER_PLUGIN_MESSAGE_ENUMS_H_
#define CONTENT_COMMON_BROWSER_PLUGIN_BROWSER_PLUGIN_MESSAGE_ENUMS_H_
#ifndef CONTENT_COMMON_BROWSER_PLUGIN_PERMISSION_TYPE_H_
#define CONTENT_COMMON_BROWSER_PLUGIN_PERMISSION_TYPE_H_
enum BrowserPluginPermissionType {
// Unknown type of permission request.
BrowserPluginPermissionTypeUnknown,
BROWSER_PLUGIN_PERMISSION_TYPE_UNKNOWN,
// Download.
BrowserPluginPermissionTypeDownload,
BROWSER_PLUGIN_PERMISSION_TYPE_DOWNLOAD,
// Geolocation.
BrowserPluginPermissionTypeGeolocation,
BROWSER_PLUGIN_PERMISSION_TYPE_GEOLOCATION,
// Media access (audio/video) permission request type.
BrowserPluginPermissionTypeMedia,
// PointerLock
BrowserPluginPermissionTypePointerLock,
BROWSER_PLUGIN_PERMISSION_TYPE_MEDIA,
BROWSER_PLUGIN_PERMISSION_TYPE_POINTER_LOCK,
// New window requests.
// Note: Even though new windows don't use the permission API, the new window
// API is sufficiently similar that it's convenient to consider it a
// permission type for code reuse.
BrowserPluginPermissionTypeNewWindow,
BROWSER_PLUGIN_PERMISSION_TYPE_NEW_WINDOW,
// JavaScript Dialogs: prompt, alert, confirm
// Note: Even through dialogs do not use the permission API, the dialog API
// is sufficiently similiar that it's convenient to consider it a permission
// type for code reuse.
BrowserPluginPermissionTypeJavaScriptDialog
BROWSER_PLUGIN_PERMISSION_TYPE_JAVASCRIPT_DIALOG
};
#endif // CONTENT_COMMON_BROWSER_PLUGIN_BROWSER_PLUGIN_MESSAGE_ENUMS_H_
#endif // CONTENT_COMMON_BROWSER_PLUGIN_PERMISSION_TYPE_H_
......@@ -59,28 +59,6 @@ static std::string GetInternalEventName(const char* event_name) {
return base::StringPrintf("-internal-%s", event_name);
}
static std::string PermissionTypeToString(BrowserPluginPermissionType type) {
switch (type) {
case BrowserPluginPermissionTypeDownload:
return browser_plugin::kPermissionTypeDownload;
case BrowserPluginPermissionTypeGeolocation:
return browser_plugin::kPermissionTypeGeolocation;
case BrowserPluginPermissionTypeMedia:
return browser_plugin::kPermissionTypeMedia;
case BrowserPluginPermissionTypeNewWindow:
return browser_plugin::kPermissionTypeNewWindow;
case BrowserPluginPermissionTypePointerLock:
return browser_plugin::kPermissionTypePointerLock;
case BrowserPluginPermissionTypeJavaScriptDialog:
return browser_plugin::kPermissionTypeDialog;
case BrowserPluginPermissionTypeUnknown:
default:
NOTREACHED();
break;
}
return std::string();
}
typedef std::map<WebKit::WebPluginContainer*,
BrowserPlugin*> PluginContainerMap;
static base::LazyInstance<PluginContainerMap> g_plugin_container_map =
......@@ -146,7 +124,6 @@ bool BrowserPlugin::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(BrowserPluginMsg_GuestContentWindowReady,
OnGuestContentWindowReady)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_GuestGone, OnGuestGone)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_RequestPermission, OnRequestPermission)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetCursor, OnSetCursor)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetMouseLock, OnSetMouseLock)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_ShouldAcceptTouchEvents,
......@@ -480,38 +457,6 @@ void BrowserPlugin::OnGuestGone(int guest_instance_id) {
weak_ptr_factory_.GetWeakPtr()));
}
void BrowserPlugin::OnRequestPermission(
int guest_instance_id,
BrowserPluginPermissionType permission_type,
int request_id,
const base::DictionaryValue& request_info) {
// The New Window API is very similiar to the permission API in structure,
// but exposes a slightly different interface to the developer and so we put
// it in a separate event.
const char* event_name = NULL;
if (permission_type == BrowserPluginPermissionTypeNewWindow) {
event_name = browser_plugin::kEventNewWindow;
} else if (permission_type == BrowserPluginPermissionTypeJavaScriptDialog) {
event_name = browser_plugin::kEventDialog;
} else {
event_name = browser_plugin::kEventRequestPermission;
}
AddPermissionRequestToSet(request_id);
std::map<std::string, base::Value*> props;
props[browser_plugin::kPermission] =
base::Value::CreateStringValue(PermissionTypeToString(permission_type));
props[browser_plugin::kRequestId] =
base::Value::CreateIntegerValue(request_id);
// Fill in the info provided by the browser.
for (DictionaryValue::Iterator iter(request_info); !iter.IsAtEnd();
iter.Advance()) {
props[iter.key()] = iter.value().DeepCopy();
}
TriggerEvent(event_name, &props);
}
void BrowserPlugin::OnSetCursor(int guest_instance_id,
const WebCursor& cursor) {
cursor_ = cursor;
......@@ -546,11 +491,6 @@ void BrowserPlugin::OnUpdatedName(int guest_instance_id,
UpdateDOMAttribute(browser_plugin::kAttributeName, name);
}
void BrowserPlugin::AddPermissionRequestToSet(int request_id) {
DCHECK(!pending_permission_requests_.count(request_id));
pending_permission_requests_.insert(request_id);
}
void BrowserPlugin::OnUpdateRect(
int guest_instance_id,
const BrowserPluginMsg_UpdateRect_Params& params) {
......@@ -965,26 +905,6 @@ WebKit::WebPluginContainer* BrowserPlugin::container() const {
return container_;
}
void BrowserPlugin::RespondPermission(
int request_id, bool allow, const std::string& user_input) {
browser_plugin_manager()->Send(
new BrowserPluginHostMsg_RespondPermission(
render_view_routing_id_, guest_instance_id_,
request_id, allow, user_input));
}
bool BrowserPlugin::RespondPermissionIfRequestIsPending(
int request_id, bool allow, const std::string& user_input) {
PendingPermissionRequests::iterator iter =
pending_permission_requests_.find(request_id);
if (iter == pending_permission_requests_.end())
return false;
pending_permission_requests_.erase(iter);
RespondPermission(request_id, allow, user_input);
return true;
}
bool BrowserPlugin::initialize(WebPluginContainer* container) {
if (!container)
return false;
......@@ -1149,7 +1069,6 @@ bool BrowserPlugin::ShouldForwardToBrowserPlugin(
case BrowserPluginMsg_CompositorFrameSwapped::ID:
case BrowserPluginMsg_GuestContentWindowReady::ID:
case BrowserPluginMsg_GuestGone::ID:
case BrowserPluginMsg_RequestPermission::ID:
case BrowserPluginMsg_SetCursor::ID:
case BrowserPluginMsg_SetMouseLock::ID:
case BrowserPluginMsg_ShouldAcceptTouchEvents::ID:
......
......@@ -14,7 +14,7 @@
#include "base/memory/shared_memory.h"
#endif
#include "base/values.h"
#include "content/common/browser_plugin/browser_plugin_message_enums.h"
#include "content/public/common/browser_plugin_permission_type.h"
#include "content/renderer/browser_plugin/browser_plugin_backing_store.h"
#include "content/renderer/browser_plugin/browser_plugin_bindings.h"
#include "content/renderer/mouse_lock_dispatcher.h"
......@@ -120,13 +120,6 @@ class CONTENT_EXPORT BrowserPlugin :
// window objects.
void TrackObjectLifetime(const NPVariant* request, int id);
// If the request with id |request_id| is pending then informs the
// BrowserPlugin that the guest's permission request has been allowed or
// denied by the embedder. Returns whether the request was pending.
bool RespondPermissionIfRequestIsPending(int request_id,
bool allow,
const std::string& user_input);
// Returns true if |point| lies within the bounds of the plugin rectangle.
// Not OK to use this function for making security-sensitive decision since it
// can return false positives when the plugin has rotation transformation
......@@ -290,14 +283,6 @@ class CONTENT_EXPORT BrowserPlugin :
bool UsesPendingDamageBuffer(
const BrowserPluginMsg_UpdateRect_Params& params);
void AddPermissionRequestToSet(int request_id);
// Informs the BrowserPlugin that the guest's permission request has been
// allowed or denied by the embedder.
void RespondPermission(int request_id,
bool allow,
const std::string& user_input);
// Called when the tracked object of |id| ID becomes unreachable in
// JavaScript.
void OnTrackedObjectGarbageCollected(int id);
......@@ -317,13 +302,6 @@ class CONTENT_EXPORT BrowserPlugin :
void OnGuestContentWindowReady(int instance_id,
int content_window_routing_id);
void OnGuestGone(int instance_id);
void OnGuestResponsive(int instance_id, int process_id);
void OnGuestUnresponsive(int instance_id, int process_id);
// Requests permission from the embedder.
void OnRequestPermission(int instance_id,
BrowserPluginPermissionType permission_type,
int request_id,
const base::DictionaryValue& request_info);
void OnSetCursor(int instance_id, const WebCursor& cursor);
void OnSetMouseLock(int instance_id, bool enable);
void OnShouldAcceptTouchEvents(int instance_id, bool accept);
......@@ -369,10 +347,6 @@ class CONTENT_EXPORT BrowserPlugin :
bool before_first_navigation_;
bool mouse_locked_;
// The set of permission request IDs that have not yet been processed.
typedef std::set<int> PendingPermissionRequests;
PendingPermissionRequests pending_permission_requests_;
typedef std::pair<int, base::WeakPtr<BrowserPlugin> > TrackedV8ObjectID;
std::map<int, TrackedV8ObjectID*> tracked_v8_objects_;
......
......@@ -327,32 +327,6 @@ class BrowserPluginBindingTrackObjectLifetime
DISALLOW_COPY_AND_ASSIGN(BrowserPluginBindingTrackObjectLifetime);
};
// Note: This is a method that is used internally by the <webview> shim only.
// This should not be exposed to developers.
class BrowserPluginBindingSetPermission : public BrowserPluginMethodBinding {
public:
BrowserPluginBindingSetPermission()
: BrowserPluginMethodBinding(
browser_plugin::kMethodInternalSetPermission, 3) {
}
virtual bool Invoke(BrowserPluginBindings* bindings,
const NPVariant* args,
NPVariant* result) OVERRIDE {
int request_id = IntFromNPVariant(args[0]);
bool allow = NPVARIANT_TO_BOOLEAN(args[1]);
std::string user_input = StringFromNPVariant(args[2]);
bool request_was_pending =
bindings->instance()->RespondPermissionIfRequestIsPending(
request_id, allow, user_input);
BOOLEAN_TO_NPVARIANT(request_was_pending, *result);
return true;
}
private:
DISALLOW_COPY_AND_ASSIGN(BrowserPluginBindingSetPermission);
};
// BrowserPluginPropertyBinding ------------------------------------------------
class BrowserPluginPropertyBinding {
......@@ -712,7 +686,6 @@ BrowserPluginBindings::BrowserPluginBindings(BrowserPlugin* instance)
method_bindings_.push_back(new BrowserPluginBindingAttach);
method_bindings_.push_back(new BrowserPluginBindingAttachWindowTo);
method_bindings_.push_back(new BrowserPluginBindingGetGuestInstanceID);
method_bindings_.push_back(new BrowserPluginBindingSetPermission);
method_bindings_.push_back(new BrowserPluginBindingTrackObjectLifetime);
property_bindings_.push_back(new BrowserPluginPropertyBindingAutoSize);
......
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