Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / extensions / renderer / resources / guest_view / web_view / web_view_action_requests.js
blobf5be50aecd571bd4fa838a9dc9c3a14656e5989b
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;
41   }
43   this.actionTaken = true;
44   WebViewInternal.setPermission(this.guestInstanceId, this.requestId,
45                                 'default', '', function(allowed) {
46     if (allowed) {
47       return;
48     }
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;
65   }
67   if (defaultPrevented) {
68     // Track the lifetime of |request| with the garbage collector.
69     var portId = -1;  // (hack) there is no Extension Port to release
70     MessagingNatives.BindToGC(request, this.defaultAction.bind(this), portId);
71   } else {
72     this.defaultAction();
73   }
76 // Displays a warning message when an action request is blocked by default.
77 WebViewActionRequest.prototype.showWarningMessage = function() {
78   window.console.warn(this.WARNING_MSG_REQUEST_BLOCKED);
81 // This function ensures that each action is taken at most once.
82 WebViewActionRequest.prototype.validateCall = function() {
83   if (this.actionTaken) {
84     throw new Error(this.ERROR_MSG_ACTION_ALREADY_TAKEN);
85   }
86   this.actionTaken = true;
89 // The following are implemented by the specific action request.
91 // Returns the interface object for this action request.
92 WebViewActionRequest.prototype.getInterfaceObject = undefined;
94 // Error/warning messages.
95 WebViewActionRequest.prototype.ERROR_MSG_ACTION_ALREADY_TAKEN = undefined;
96 WebViewActionRequest.prototype.WARNING_MSG_REQUEST_BLOCKED = undefined;
98 // -----------------------------------------------------------------------------
99 // Dialog object.
101 // Represents a dialog box request (e.g. alert()).
102 function Dialog(webViewImpl, event, webViewEvent) {
103   WebViewActionRequest.call(this, webViewImpl, event, webViewEvent, 'dialog');
105   this.handleActionRequestEvent();
108 Dialog.prototype.__proto__ = WebViewActionRequest.prototype;
110 Dialog.prototype.getInterfaceObject = function() {
111   return {
112     ok: function(user_input) {
113       this.validateCall();
114       user_input = user_input || '';
115       WebViewInternal.setPermission(
116           this.guestInstanceId, this.requestId, 'allow', user_input);
117     }.bind(this),
118     cancel: function() {
119       this.validateCall();
120       WebViewInternal.setPermission(
121           this.guestInstanceId, this.requestId, 'deny');
122     }.bind(this)
123   };
126 Dialog.prototype.showWarningMessage = function() {
127   var VOWELS = ['a', 'e', 'i', 'o', 'u'];
128   var dialogType = this.event.messageType;
129   var article = (VOWELS.indexOf(dialogType.charAt(0)) >= 0) ? 'An' : 'A';
130   this.WARNING_MSG_REQUEST_BLOCKED = this.WARNING_MSG_REQUEST_BLOCKED.
131       replace('%1', article).replace('%2', dialogType);
132   window.console.warn(this.WARNING_MSG_REQUEST_BLOCKED);
135 Dialog.prototype.ERROR_MSG_ACTION_ALREADY_TAKEN =
136     WebViewConstants.ERROR_MSG_DIALOG_ACTION_ALREADY_TAKEN;
137 Dialog.prototype.WARNING_MSG_REQUEST_BLOCKED =
138     WebViewConstants.WARNING_MSG_DIALOG_REQUEST_BLOCKED;
140 // -----------------------------------------------------------------------------
141 // NewWindow object.
143 // Represents a new window request.
144 function NewWindow(webViewImpl, event, webViewEvent) {
145   WebViewActionRequest.call(this, webViewImpl, event, webViewEvent, 'window');
147   this.handleActionRequestEvent();
150 NewWindow.prototype.__proto__ = WebViewActionRequest.prototype;
152 NewWindow.prototype.getInterfaceObject = function() {
153   return {
154     attach: function(webview) {
155       this.validateCall();
156       if (!webview || !webview.tagName || webview.tagName != 'WEBVIEW') {
157         throw new Error(ERROR_MSG_WEBVIEW_EXPECTED);
158       }
160       var webViewImpl = privates(webview).internal;
161       // Update the partition.
162       if (this.event.partition) {
163         webViewImpl.onAttach(this.event.partition);
164       }
166       var attached = webViewImpl.attachWindow(this.event.windowId);
167       if (!attached) {
168         window.console.error(ERROR_MSG_NEWWINDOW_UNABLE_TO_ATTACH);
169       }
171       if (this.guestInstanceId != this.webViewImpl.guest.getId()) {
172         // If the opener is already gone, then its guestInstanceId will be
173         // stale.
174         return;
175       }
177       // If the object being passed into attach is not a valid <webview>
178       // then we will fail and it will be treated as if the new window
179       // was rejected. The permission API plumbing is used here to clean
180       // up the state created for the new window if attaching fails.
181       WebViewInternal.setPermission(this.guestInstanceId, this.requestId,
182                                     attached ? 'allow' : 'deny');
183     }.bind(this),
184     discard: function() {
185       this.validateCall();
186       if (!this.guestInstanceId) {
187         // If the opener is already gone, then we won't have its
188         // guestInstanceId.
189         return;
190       }
191       WebViewInternal.setPermission(
192           this.guestInstanceId, this.requestId, 'deny');
193     }.bind(this)
194   };
197 NewWindow.prototype.ERROR_MSG_ACTION_ALREADY_TAKEN =
198     WebViewConstants.ERROR_MSG_NEWWINDOW_ACTION_ALREADY_TAKEN;
199 NewWindow.prototype.WARNING_MSG_REQUEST_BLOCKED =
200     WebViewConstants.WARNING_MSG_NEWWINDOW_REQUEST_BLOCKED;
202 // -----------------------------------------------------------------------------
203 // PermissionRequest object.
205 // Represents a permission request (e.g. to access the filesystem).
206 function PermissionRequest(webViewImpl, event, webViewEvent) {
207   WebViewActionRequest.call(this, webViewImpl, event, webViewEvent, 'request');
209   if (!this.validPermissionCheck()) {
210     return;
211   }
213   this.handleActionRequestEvent();
216 PermissionRequest.prototype.__proto__ = WebViewActionRequest.prototype;
218 PermissionRequest.prototype.getInterfaceObject = function() {
219   return {
220     allow: function() {
221       this.validateCall();
222       WebViewInternal.setPermission(
223           this.guestInstanceId, this.requestId, 'allow');
224     }.bind(this),
225     deny: function() {
226       this.validateCall();
227       WebViewInternal.setPermission(
228           this.guestInstanceId, this.requestId, 'deny');
229     }.bind(this)
230   };
233 PermissionRequest.prototype.showWarningMessage = function() {
234   window.console.warn(
235       this.WARNING_MSG_REQUEST_BLOCKED.replace('%1', this.event.permission));
238 // Checks that the requested permission is valid. Returns true if valid.
239 PermissionRequest.prototype.validPermissionCheck = function() {
240   if (PERMISSION_TYPES.indexOf(this.event.permission) < 0) {
241     // The permission type is not allowed. Trigger the default response.
242     this.defaultAction();
243     return false;
244   }
245   return true;
248 PermissionRequest.prototype.ERROR_MSG_ACTION_ALREADY_TAKEN =
249     WebViewConstants.ERROR_MSG_PERMISSION_ACTION_ALREADY_TAKEN;
250 PermissionRequest.prototype.WARNING_MSG_REQUEST_BLOCKED =
251     WebViewConstants.WARNING_MSG_PERMISSION_REQUEST_BLOCKED;
253 // -----------------------------------------------------------------------------
255 // FullscreenPermissionRequest object.
257 // Represents a fullscreen permission request.
258 function FullscreenPermissionRequest(webViewImpl, event, webViewEvent) {
259   PermissionRequest.call(this, webViewImpl, event, webViewEvent);
262 FullscreenPermissionRequest.prototype.__proto__ = PermissionRequest.prototype;
264 FullscreenPermissionRequest.prototype.getInterfaceObject = function() {
265   return {
266     allow: function() {
267       this.validateCall();
268       WebViewInternal.setPermission(
269           this.guestInstanceId, this.requestId, 'allow');
270       // Now make the <webview> element go fullscreen.
271       this.webViewImpl.makeElementFullscreen();
272     }.bind(this),
273     deny: function() {
274       this.validateCall();
275       WebViewInternal.setPermission(
276           this.guestInstanceId, this.requestId, 'deny');
277     }.bind(this)
278   };
281 var WebViewActionRequests = {
282   WebViewActionRequest: WebViewActionRequest,
283   Dialog: Dialog,
284   NewWindow: NewWindow,
285   PermissionRequest: PermissionRequest,
286   FullscreenPermissionRequest: FullscreenPermissionRequest
289 // Exports.
290 exports.WebViewActionRequests = WebViewActionRequests;