blob: afa20b11014e407fbb8f5e8a75d1acbf9c8ad618 [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 WebView = require('webView').WebView;
var WEB_VIEW_EXPERIMENTAL_EVENTS = {
'dialog': {
cancelable: true,
customHandler: function(webViewInternal, event, webViewEvent) {
webViewInternal.handleDialogEvent_(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.handleDialogEvent_ =
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 || '';
WebView.setPermission(self.instanceId_, requestId, true, user_input);
},
cancel: function() {
validateCall();
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;
}
WebView.setPermission(self.instanceId_, requestId, false, '');
showWarningMessage(event.messageType);
});
} else {
actionTaken = true;
// The default action is equivalent to canceling the dialog.
WebView.setPermission(self.instanceId_, requestId, false, '');
showWarningMessage(event.messageType);
}
};
/**
* @private
*/
WebViewInternal.prototype.maybeGetExperimentalEvents_ = function() {
return WEB_VIEW_EXPERIMENTAL_EVENTS;
};
WebViewInternal.prototype.clearData_ = function(var_args) {
if (!this.instanceId_) {
return;
}
var args = $Array.concat([this.instanceId_], $Array.slice(arguments));
$Function.apply(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);
};
};