blob: 7b3dd8344e2e8bc2ce5037f70ab90889e084b900 [file] [log] [blame]
// Copyright 2013 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.
// Shim extension to provide permission request API (and possibly other future
// experimental APIs) for <webview> tag.
// See web_view.js for details.
//
// We want to control the permission API feature in <webview> separately from
// the <webview> feature itself. <webview> is available in stable channel, but
// permission API would only be available for channels CHANNEL_DEV and
// CHANNEL_CANARY.
var createEvent = require('webView').CreateEvent;
var messagingNatives = requireNative('messaging_natives');
var WebRequestEvent = require('webRequestInternal').WebRequestEvent;
var webRequestSchema =
requireNative('schema_registry').GetSchema('webRequest');
var WebViewInternal = require('webView').WebViewInternal;
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
*/
WebViewInternal.prototype.maybeAttachWebRequestEventToWebview_ =
function(eventName, webRequestEvent) {
Object.defineProperty(
this.webviewNode_,
eventName,
{
get: webRequestEvent,
enumerable: true
}
);
};
/**
* @private
*/
WebViewInternal.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.warn(output);
};
var self = this;
var browserPluginNode = this.browserPluginNode_;
var webviewNode = this.webviewNode_;
var requestId = event.requestId;
var actionTaken = false;
var validateCall = function() {
var ERROR_MSG_DIALOG_ACTION_ALREADY_TAKEN = '<webview>: ' +
'An action has already been taken for this "dialog" event.';
if (actionTaken) {
throw new Error(ERROR_MSG_DIALOG_ACTION_ALREADY_TAKEN);
}
actionTaken = true;
};
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.
messagingNatives.BindToGC(dialog, function() {
// Avoid showing a warning message if the decision has already been made.
if (actionTaken) {
return;
}
chrome.webview.setPermission(self.instanceId_, requestId, false, '');
showWarningMessage(event.messageType);
});
} else {
actionTaken = true;
// The default action is equivalent to canceling the dialog.
chrome.webview.setPermission(self.instanceId_, requestId, false, '');
showWarningMessage(event.messageType);
}
};
/**
* @private
*/
WebViewInternal.prototype.maybeGetWebviewExperimentalExtEvents_ = function() {
return WEB_VIEW_EXPERIMENTAL_EXT_EVENTS;
};
WebViewInternal.prototype.clearData_ = function(var_args) {
if (!this.instanceId_) {
return;
}
var args = $Array.concat([this.instanceId_], $Array.slice(arguments));
$Function.apply(chrome.webview.clearData, null, args);
};
WebViewInternal.maybeRegisterExperimentalAPIs = function(proto, secret) {
proto.clearData = function(var_args) {
var internal = this.internal_(secret);
$Function.apply(internal.clearData_, internal, arguments);
};
};