Supervised user whitelists: Cleanup
[chromium-blink-merge.git] / extensions / renderer / resources / guest_view / web_view / web_view_action_requests.js
blobe58e620d2ae19dc0e7e0d7483676ab1ab36811c8
1 // Copyright 2014 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 helper objects for the dialog, newwindow, and
6 // permissionrequest <webview> events.
8 var MessagingNatives = requireNative('messaging_natives');
9 var WebViewConstants = require('webViewConstants').WebViewConstants;
10 var WebViewInternal = require('webViewInternal').WebViewInternal;
12 var PERMISSION_TYPES = ['media',
13 'geolocation',
14 'pointerLock',
15 'download',
16 'loadplugin',
17 'filesystem',
18 'fullscreen'];
20 // -----------------------------------------------------------------------------
21 // WebViewActionRequest object.
23 // Default partial implementation of a webview action request.
24 function WebViewActionRequest(webViewImpl, event, webViewEvent, interfaceName) {
25 this.webViewImpl = webViewImpl;
26 this.event = event;
27 this.webViewEvent = webViewEvent;
28 this.interfaceName = interfaceName;
29 this.guestInstanceId = this.webViewImpl.guest.getId();
30 this.requestId = event.requestId;
31 this.actionTaken = false;
34 // Performs the default action for the request.
35 WebViewActionRequest.prototype.defaultAction = function() {
36 // Do nothing if the action has already been taken or the requester is
37 // already gone (in which case its guestInstanceId will be stale).
38 if (this.actionTaken ||
39 this.guestInstanceId != this.webViewImpl.guest.getId()) {
40 return;
43 this.actionTaken = true;
44 WebViewInternal.setPermission(this.guestInstanceId, this.requestId,
45 'default', '', function(allowed) {
46 if (allowed) {
47 return;
49 this.showWarningMessage();
50 }.bind(this));
53 // Called to handle the action request's event.
54 WebViewActionRequest.prototype.handleActionRequestEvent = function() {
55 // Construct the interface object and attach it to |webViewEvent|.
56 var request = this.getInterfaceObject();
57 this.webViewEvent[this.interfaceName] = request;
59 var defaultPrevented = !this.webViewImpl.dispatchEvent(this.webViewEvent);
60 // Set |webViewEvent| to null to break the circular reference to |request| so
61 // that the garbage collector can eventually collect it.
62 this.webViewEvent = null;
63 if (this.actionTaken) {
64 return;
67 if (defaultPrevented) {
68 // Track the lifetime of |request| with the garbage collector.
69 MessagingNatives.BindToGC(request, this.defaultAction.bind(this));
70 } else {
71 this.defaultAction();
75 // Displays a warning message when an action request is blocked by default.
76 WebViewActionRequest.prototype.showWarningMessage = function() {
77 window.console.warn(this.WARNING_MSG_REQUEST_BLOCKED);
80 // This function ensures that each action is taken at most once.
81 WebViewActionRequest.prototype.validateCall = function() {
82 if (this.actionTaken) {
83 throw new Error(this.ERROR_MSG_ACTION_ALREADY_TAKEN);
85 this.actionTaken = true;
88 // The following are implemented by the specific action request.
90 // Returns the interface object for this action request.
91 WebViewActionRequest.prototype.getInterfaceObject = undefined;
93 // Error/warning messages.
94 WebViewActionRequest.prototype.ERROR_MSG_ACTION_ALREADY_TAKEN = undefined;
95 WebViewActionRequest.prototype.WARNING_MSG_REQUEST_BLOCKED = undefined;
97 // -----------------------------------------------------------------------------
98 // Dialog object.
100 // Represents a dialog box request (e.g. alert()).
101 function Dialog(webViewImpl, event, webViewEvent) {
102 WebViewActionRequest.call(this, webViewImpl, event, webViewEvent, 'dialog');
104 this.handleActionRequestEvent();
107 Dialog.prototype.__proto__ = WebViewActionRequest.prototype;
109 Dialog.prototype.getInterfaceObject = function() {
110 return {
111 ok: function(user_input) {
112 this.validateCall();
113 user_input = user_input || '';
114 WebViewInternal.setPermission(
115 this.guestInstanceId, this.requestId, 'allow', user_input);
116 }.bind(this),
117 cancel: function() {
118 this.validateCall();
119 WebViewInternal.setPermission(
120 this.guestInstanceId, this.requestId, 'deny');
121 }.bind(this)
125 Dialog.prototype.showWarningMessage = function() {
126 var VOWELS = ['a', 'e', 'i', 'o', 'u'];
127 var dialogType = this.event.messageType;
128 var article = (VOWELS.indexOf(dialogType.charAt(0)) >= 0) ? 'An' : 'A';
129 this.WARNING_MSG_REQUEST_BLOCKED = this.WARNING_MSG_REQUEST_BLOCKED.
130 replace('%1', article).replace('%2', dialogType);
131 window.console.warn(this.WARNING_MSG_REQUEST_BLOCKED);
134 Dialog.prototype.ERROR_MSG_ACTION_ALREADY_TAKEN =
135 WebViewConstants.ERROR_MSG_DIALOG_ACTION_ALREADY_TAKEN;
136 Dialog.prototype.WARNING_MSG_REQUEST_BLOCKED =
137 WebViewConstants.WARNING_MSG_DIALOG_REQUEST_BLOCKED;
139 // -----------------------------------------------------------------------------
140 // NewWindow object.
142 // Represents a new window request.
143 function NewWindow(webViewImpl, event, webViewEvent) {
144 WebViewActionRequest.call(this, webViewImpl, event, webViewEvent, 'window');
146 this.handleActionRequestEvent();
149 NewWindow.prototype.__proto__ = WebViewActionRequest.prototype;
151 NewWindow.prototype.getInterfaceObject = function() {
152 return {
153 attach: function(webview) {
154 this.validateCall();
155 if (!webview || !webview.tagName || webview.tagName != 'WEBVIEW') {
156 throw new Error(ERROR_MSG_WEBVIEW_EXPECTED);
159 var webViewImpl = privates(webview).internal;
160 // Update the partition.
161 if (this.event.partition) {
162 webViewImpl.onAttach(this.event.partition);
165 var attached = webViewImpl.attachWindow(this.event.windowId);
166 if (!attached) {
167 window.console.error(ERROR_MSG_NEWWINDOW_UNABLE_TO_ATTACH);
170 if (this.guestInstanceId != this.webViewImpl.guest.getId()) {
171 // If the opener is already gone, then its guestInstanceId will be
172 // stale.
173 return;
176 // If the object being passed into attach is not a valid <webview>
177 // then we will fail and it will be treated as if the new window
178 // was rejected. The permission API plumbing is used here to clean
179 // up the state created for the new window if attaching fails.
180 WebViewInternal.setPermission(this.guestInstanceId, this.requestId,
181 attached ? 'allow' : 'deny');
182 }.bind(this),
183 discard: function() {
184 this.validateCall();
185 if (!this.guestInstanceId) {
186 // If the opener is already gone, then we won't have its
187 // guestInstanceId.
188 return;
190 WebViewInternal.setPermission(
191 this.guestInstanceId, this.requestId, 'deny');
192 }.bind(this)
196 NewWindow.prototype.ERROR_MSG_ACTION_ALREADY_TAKEN =
197 WebViewConstants.ERROR_MSG_NEWWINDOW_ACTION_ALREADY_TAKEN;
198 NewWindow.prototype.WARNING_MSG_REQUEST_BLOCKED =
199 WebViewConstants.WARNING_MSG_NEWWINDOW_REQUEST_BLOCKED;
201 // -----------------------------------------------------------------------------
202 // PermissionRequest object.
204 // Represents a permission request (e.g. to access the filesystem).
205 function PermissionRequest(webViewImpl, event, webViewEvent) {
206 WebViewActionRequest.call(this, webViewImpl, event, webViewEvent, 'request');
208 if (!this.validPermissionCheck()) {
209 return;
212 this.handleActionRequestEvent();
215 PermissionRequest.prototype.__proto__ = WebViewActionRequest.prototype;
217 PermissionRequest.prototype.getInterfaceObject = function() {
218 return {
219 allow: function() {
220 this.validateCall();
221 WebViewInternal.setPermission(
222 this.guestInstanceId, this.requestId, 'allow');
223 }.bind(this),
224 deny: function() {
225 this.validateCall();
226 WebViewInternal.setPermission(
227 this.guestInstanceId, this.requestId, 'deny');
228 }.bind(this)
232 PermissionRequest.prototype.showWarningMessage = function() {
233 window.console.warn(
234 this.WARNING_MSG_REQUEST_BLOCKED.replace('%1', this.event.permission));
237 // Checks that the requested permission is valid. Returns true if valid.
238 PermissionRequest.prototype.validPermissionCheck = function() {
239 if (PERMISSION_TYPES.indexOf(this.event.permission) < 0) {
240 // The permission type is not allowed. Trigger the default response.
241 this.defaultAction();
242 return false;
244 return true;
247 PermissionRequest.prototype.ERROR_MSG_ACTION_ALREADY_TAKEN =
248 WebViewConstants.ERROR_MSG_PERMISSION_ACTION_ALREADY_TAKEN;
249 PermissionRequest.prototype.WARNING_MSG_REQUEST_BLOCKED =
250 WebViewConstants.WARNING_MSG_PERMISSION_REQUEST_BLOCKED;
252 // -----------------------------------------------------------------------------
254 // FullscreenPermissionRequest object.
256 // Represents a fullscreen permission request.
257 function FullscreenPermissionRequest(webViewImpl, event, webViewEvent) {
258 PermissionRequest.call(this, webViewImpl, event, webViewEvent);
261 FullscreenPermissionRequest.prototype.__proto__ = PermissionRequest.prototype;
263 FullscreenPermissionRequest.prototype.getInterfaceObject = function() {
264 return {
265 allow: function() {
266 this.validateCall();
267 WebViewInternal.setPermission(
268 this.guestInstanceId, this.requestId, 'allow');
269 // Now make the <webview> element go fullscreen.
270 this.webViewImpl.makeElementFullscreen();
271 }.bind(this),
272 deny: function() {
273 this.validateCall();
274 WebViewInternal.setPermission(
275 this.guestInstanceId, this.requestId, 'deny');
276 }.bind(this)
280 var WebViewActionRequests = {
281 WebViewActionRequest: WebViewActionRequest,
282 Dialog: Dialog,
283 NewWindow: NewWindow,
284 PermissionRequest: PermissionRequest,
285 FullscreenPermissionRequest: FullscreenPermissionRequest
288 // Exports.
289 exports.WebViewActionRequests = WebViewActionRequests;