NaCl: Update revision in DEPS, r12770 -> r12773
[chromium-blink-merge.git] / chrome / renderer / resources / extensions / web_view_experimental.js
blob82e52e82350f6312d961368218ef619009a108cc
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // This module implements experimental API for <webview>.
6 // See web_view.js for details.
7 //
8 // <webview> Experimental API is only available on canary and dev channels of
9 // Chrome.
11 var CreateEvent = require('webView').CreateEvent;
12 var MessagingNatives = requireNative('messaging_natives');
13 var WebViewInternal = require('webView').WebViewInternal;
14 var WebView = require('webView').WebView;
16 // WEB_VIEW_EXPERIMENTAL_EVENTS is a map of experimental <webview> DOM event
17 // names to their associated extension event descriptor objects.
18 // An event listener will be attached to the extension event |evt| specified in
19 // the descriptor.
20 // |fields| specifies the public-facing fields in the DOM event that are
21 // accessible to <webview> developers.
22 // |customHandler| allows a handler function to be called each time an extension
23 // event is caught by its event listener. The DOM event should be dispatched
24 // within this handler function. With no handler function, the DOM event
25 // will be dispatched by default each time the extension event is caught.
26 // |cancelable| (default: false) specifies whether the event's default
27 // behavior can be canceled. If the default action associated with the event
28 // is prevented, then its dispatch function will return false in its event
29 // handler. The event must have a custom handler for this to be meaningful.
30 var WEB_VIEW_EXPERIMENTAL_EVENTS = {
31 'dialog': {
32 cancelable: true,
33 customHandler: function(webViewInternal, event, webViewEvent) {
34 webViewInternal.handleDialogEvent(event, webViewEvent);
36 evt: CreateEvent('webview.onDialog'),
37 fields: ['defaultPromptText', 'messageText', 'messageType', 'url']
39 'zoomchange': {
40 evt: CreateEvent('webview.onZoomChange'),
41 fields: ['oldZoomFactor', 'newZoomFactor']
45 /**
46 * @private
48 WebViewInternal.prototype.maybeAttachWebRequestEventToObject =
49 function(obj, eventName, webRequestEvent) {
50 Object.defineProperty(
51 obj,
52 eventName,
54 get: webRequestEvent,
55 enumerable: true
60 /**
61 * @private
63 WebViewInternal.prototype.setZoom = function(zoomFactor) {
64 if (!this.instanceId) {
65 return;
67 WebView.setZoom(this.instanceId, zoomFactor);
70 /**
71 * @private
73 WebViewInternal.prototype.handleDialogEvent =
74 function(event, webViewEvent) {
75 var showWarningMessage = function(dialogType) {
76 var VOWELS = ['a', 'e', 'i', 'o', 'u'];
77 var WARNING_MSG_DIALOG_BLOCKED = '<webview>: %1 %2 dialog was blocked.';
78 var article = (VOWELS.indexOf(dialogType.charAt(0)) >= 0) ? 'An' : 'A';
79 var output = WARNING_MSG_DIALOG_BLOCKED.replace('%1', article);
80 output = output.replace('%2', dialogType);
81 window.console.warn(output);
84 var self = this;
85 var browserPluginNode = this.browserPluginNode;
86 var webviewNode = this.webviewNode;
88 var requestId = event.requestId;
89 var actionTaken = false;
91 var validateCall = function() {
92 var ERROR_MSG_DIALOG_ACTION_ALREADY_TAKEN = '<webview>: ' +
93 'An action has already been taken for this "dialog" event.';
95 if (actionTaken) {
96 throw new Error(ERROR_MSG_DIALOG_ACTION_ALREADY_TAKEN);
98 actionTaken = true;
101 var dialog = {
102 ok: function(user_input) {
103 validateCall();
104 user_input = user_input || '';
105 WebView.setPermission(self.instanceId, requestId, 'allow', user_input);
107 cancel: function() {
108 validateCall();
109 WebView.setPermission(self.instanceId, requestId, 'deny');
112 webViewEvent.dialog = dialog;
114 var defaultPrevented = !webviewNode.dispatchEvent(webViewEvent);
115 if (actionTaken) {
116 return;
119 if (defaultPrevented) {
120 // Tell the JavaScript garbage collector to track lifetime of |dialog| and
121 // call back when the dialog object has been collected.
122 MessagingNatives.BindToGC(dialog, function() {
123 // Avoid showing a warning message if the decision has already been made.
124 if (actionTaken) {
125 return;
127 WebView.setPermission(
128 self.instanceId, requestId, 'default', '', function(allowed) {
129 if (allowed) {
130 return;
132 showWarningMessage(event.messageType);
135 } else {
136 actionTaken = true;
137 // The default action is equivalent to canceling the dialog.
138 WebView.setPermission(
139 self.instanceId, requestId, 'default', '', function(allowed) {
140 if (allowed) {
141 return;
143 showWarningMessage(event.messageType);
148 WebViewInternal.prototype.maybeGetExperimentalEvents = function() {
149 return WEB_VIEW_EXPERIMENTAL_EVENTS;
152 /** @private */
153 WebViewInternal.prototype.maybeGetExperimentalPermissions = function() {
154 return [];
157 /** @private */
158 WebViewInternal.prototype.maybeSetCurrentZoomFactor =
159 function(zoomFactor) {
160 this.currentZoomFactor = zoomFactor;
163 /** @private */
164 WebViewInternal.prototype.clearData = function(var_args) {
165 if (!this.instanceId) {
166 return;
168 var args = $Array.concat([this.instanceId], $Array.slice(arguments));
169 $Function.apply(WebView.clearData, null, args);
172 /** @private */
173 WebViewInternal.prototype.setZoom = function(zoomFactor, callback) {
174 if (!this.instanceId) {
175 return;
177 WebView.setZoom(this.instanceId, zoomFactor, callback);
180 WebViewInternal.prototype.getZoom = function(callback) {
181 if (!this.instanceId) {
182 return;
184 WebView.getZoom(this.instanceId, callback);
187 /** @private */
188 WebViewInternal.prototype.captureVisibleRegion = function(spec, callback) {
189 WebView.captureVisibleRegion(this.instanceId, spec, callback);
192 WebViewInternal.maybeRegisterExperimentalAPIs = function(proto) {
193 proto.clearData = function(var_args) {
194 var internal = privates(this).internal;
195 $Function.apply(internal.clearData, internal, arguments);
198 proto.setZoom = function(zoomFactor, callback) {
199 privates(this).internal.setZoom(zoomFactor, callback);
202 proto.getZoom = function(callback) {
203 return privates(this).internal.getZoom(callback);
206 proto.captureVisibleRegion = function(spec, callback) {
207 privates(this).internal.captureVisibleRegion(spec, callback);