OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Shim extension to provide permission request API (and possibly other future | 5 // Shim extension to provide permission request API (and possibly other future |
6 // experimental APIs) for <webview> tag. | 6 // experimental APIs) for <webview> tag. |
7 // See web_view.js for details. | 7 // See web_view.js for details. |
8 // | 8 // |
9 // We want to control the permission API feature in <webview> separately from | 9 // We want to control the permission API feature in <webview> separately from |
10 // the <webview> feature itself. <webview> is available in stable channel, but | 10 // the <webview> feature itself. <webview> is available in stable channel, but |
11 // permission API would only be available for channels CHANNEL_DEV and | 11 // permission API would only be available for channels CHANNEL_DEV and |
12 // CHANNEL_CANARY. | 12 // CHANNEL_CANARY. |
13 | 13 |
14 var WebRequestEvent = require('webRequestInternal').WebRequestEvent; | 14 var WebRequestEvent = require('webRequestInternal').WebRequestEvent; |
15 var webRequestSchema = | 15 var webRequestSchema = |
16 requireNative('schema_registry').GetSchema('webRequest'); | 16 requireNative('schema_registry').GetSchema('webRequest'); |
17 var WebView = require('webView').WebView; | 17 var WebView = require('webView').WebView; |
18 var createEvent = require('webView').CreateEvent; | |
lazyboy
2013/08/08 19:58:01
nit: can sort these.
Fady Samuel
2013/08/08 20:13:45
Done.
| |
19 | |
20 var WEB_VIEW_EXPERIMENTAL_EXT_EVENTS = { | |
21 'dialog': { | |
22 cancelable: true, | |
23 customHandler: function(webview, event, webviewEvent) { | |
24 webview.maybeSetupExtDialogEvent_(event, webviewEvent); | |
25 }, | |
26 evt: createEvent('webview.onDialog'), | |
27 fields: ['defaultPromptText', 'messageText', 'messageType', 'url'] | |
28 } | |
29 }; | |
18 | 30 |
19 /** | 31 /** |
20 * @private | 32 * @private |
21 */ | 33 */ |
22 WebView.prototype.maybeSetupExperimentalAPI_ = function() { | 34 WebView.prototype.maybeSetupExperimentalAPI_ = function() { |
23 this.setupWebRequestEvents_(); | 35 this.setupWebRequestEvents_(); |
24 this.setupDialogEvent_(); | |
25 }; | 36 }; |
26 | 37 |
27 /** | 38 /** |
28 * @private | 39 * @private |
29 */ | 40 */ |
30 WebView.prototype.setupWebRequestEvents_ = function() { | 41 WebView.prototype.setupWebRequestEvents_ = function() { |
31 var self = this; | 42 var self = this; |
32 var request = {}; | 43 var request = {}; |
33 var createWebRequestEvent = function(webRequestEvent) { | 44 var createWebRequestEvent = function(webRequestEvent) { |
34 return function() { | 45 return function() { |
35 if (!self[webRequestEvent.name + '_']) { | 46 if (!self[webRequestEvent.name + '_']) { |
36 self[webRequestEvent.name + '_'] = | 47 self[webRequestEvent.name + '_'] = |
37 new WebRequestEvent( | 48 new WebRequestEvent( |
38 'webview.' + webRequestEvent.name, | 49 'webview.' + webRequestEvent.name, |
39 webRequestEvent.parameters, | 50 webRequestEvent.parameters, |
40 webRequestEvent.extraParameters, null, | 51 webRequestEvent.extraParameters, null, |
41 self.viewInstanceId_); | 52 self.viewInstanceId_); |
42 } | 53 } |
43 return self[webRequestEvent.name + '_']; | 54 return self[webRequestEvent.name + '_']; |
44 } | 55 }; |
45 }; | 56 }; |
46 | 57 |
47 // Populate the WebRequest events from the API definition. | 58 // Populate the WebRequest events from the API definition. |
48 for (var i = 0; i < webRequestSchema.events.length; ++i) { | 59 for (var i = 0; i < webRequestSchema.events.length; ++i) { |
49 var webRequestEvent = createWebRequestEvent(webRequestSchema.events[i]); | 60 var webRequestEvent = createWebRequestEvent(webRequestSchema.events[i]); |
50 Object.defineProperty( | 61 Object.defineProperty( |
51 request, | 62 request, |
52 webRequestSchema.events[i].name, | 63 webRequestSchema.events[i].name, |
53 { | 64 { |
54 get: webRequestEvent, | 65 get: webRequestEvent, |
(...skipping 19 matching lines...) Expand all Loading... | |
74 configurable: false, | 85 configurable: false, |
75 enumerable: true, | 86 enumerable: true, |
76 writable: false | 87 writable: false |
77 } | 88 } |
78 ); | 89 ); |
79 }; | 90 }; |
80 | 91 |
81 /** | 92 /** |
82 * @private | 93 * @private |
83 */ | 94 */ |
84 WebView.prototype.setupDialogEvent_ = function() { | 95 WebView.prototype.maybeSetupExtDialogEvent_ = function(event, webviewEvent) { |
85 var ERROR_MSG_DIALOG_ACTION_ALREADY_TAKEN = '<webview>: ' + | 96 var ERROR_MSG_DIALOG_ACTION_ALREADY_TAKEN = '<webview>: ' + |
86 'An action has already been taken for this "dialog" event.'; | 97 'An action has already been taken for this "dialog" event.'; |
87 | 98 |
88 var showWarningMessage = function(dialogType) { | 99 var showWarningMessage = function(dialogType) { |
89 var VOWELS = ['a', 'e', 'i', 'o', 'u']; | 100 var VOWELS = ['a', 'e', 'i', 'o', 'u']; |
90 var WARNING_MSG_DIALOG_BLOCKED = '<webview>: %1 %2 dialog was blocked.'; | 101 var WARNING_MSG_DIALOG_BLOCKED = '<webview>: %1 %2 dialog was blocked.'; |
91 var article = (VOWELS.indexOf(dialogType.charAt(0)) >= 0) ? 'An' : 'A'; | 102 var article = (VOWELS.indexOf(dialogType.charAt(0)) >= 0) ? 'An' : 'A'; |
92 var output = WARNING_MSG_DIALOG_BLOCKED.replace('%1', article); | 103 var output = WARNING_MSG_DIALOG_BLOCKED.replace('%1', article); |
93 output = output.replace('%2', dialogType); | 104 output = output.replace('%2', dialogType); |
94 console.log(output); | 105 console.log(output); |
95 }; | 106 }; |
96 | 107 |
97 var DIALOG_EVENT_ATTRIBUTES = [ | 108 var self = this; |
98 'defaultPromptText', | 109 var browserPluginNode = this.browserPluginNode_; |
99 'messageText', | 110 var webviewNode = this.webviewNode_; |
100 'messageType', | |
101 'url' | |
102 ]; | |
103 | 111 |
104 var self = this; | 112 var requestId = event.requestId; |
105 var node = this.webviewNode_; | 113 var actionTaken = false; |
106 var browserPluginNode = this.browserPluginNode_; | |
107 | 114 |
108 var onTrackedObjectGone = function(requestId, dialogType, e) { | 115 var onTrackedObjectGone = function(requestId, dialogType, e) { |
109 var detail = e.detail ? JSON.parse(e.detail) : {}; | 116 var detail = e.detail ? JSON.parse(e.detail) : {}; |
110 if (detail.id != requestId) | 117 if (detail.id != requestId) { |
111 return; | 118 return; |
112 // If the request was pending then show a warning indiciating that a new | |
113 // window was blocked. | |
114 if (browserPluginNode['-internal-setPermission'](requestId, false, '')) { | |
115 showWarningMessage(dialogType); | |
116 } | 119 } |
117 } | |
118 | 120 |
119 browserPluginNode.addEventListener('-internal-dialog', function(e) { | 121 // Avoid showing a warning message if the decision has already been made. |
120 var evt = new Event('dialog', { bubbles: true, cancelable: true }); | |
121 var detail = e.detail ? JSON.parse(e.detail) : {}; | |
122 | |
123 $Array.forEach(DIALOG_EVENT_ATTRIBUTES, function(attribName) { | |
124 evt[attribName] = detail[attribName]; | |
125 }); | |
126 var requestId = detail.requestId; | |
127 var actionTaken = false; | |
128 | |
129 var validateCall = function() { | |
130 if (actionTaken) { | |
131 throw new Error(ERROR_MSG_DIALOG_ACTION_ALREADY_TAKEN); | |
132 } | |
133 actionTaken = true; | |
134 }; | |
135 | |
136 var dialog = { | |
137 ok: function(user_input) { | |
138 validateCall(); | |
139 browserPluginNode['-internal-setPermission']( | |
140 requestId, true, user_input); | |
141 }, | |
142 cancel: function() { | |
143 validateCall(); | |
144 browserPluginNode['-internal-setPermission'](requestId, false, ''); | |
145 } | |
146 }; | |
147 evt.dialog = dialog; | |
148 | |
149 var defaultPrevented = !node.dispatchEvent(evt); | |
150 if (actionTaken) { | 122 if (actionTaken) { |
151 return; | 123 return; |
152 } | 124 } |
153 | 125 |
154 if (defaultPrevented) { | 126 chrome.webview.setPermission(self.instanceId_, requestId, false, ''); |
155 // Tell the JavaScript garbage collector to track lifetime of |dialog| and | 127 showWarningMessage(dialogType); |
156 // call back when the dialog object has been collected. | 128 } |
157 var onTrackedObjectGoneWithRequestId = | 129 |
158 $Function.bind( | 130 var validateCall = function() { |
159 onTrackedObjectGone, self, requestId, detail.messageType); | 131 if (actionTaken) { |
160 browserPluginNode.addEventListener('-internal-trackedobjectgone', | 132 throw new Error(ERROR_MSG_DIALOG_ACTION_ALREADY_TAKEN); |
161 onTrackedObjectGoneWithRequestId); | |
162 browserPluginNode['-internal-trackObjectLifetime'](dialog, requestId); | |
163 } else { | |
164 actionTaken = true; | |
165 // The default action is equivalent to canceling the dialog. | |
166 browserPluginNode['-internal-setPermission'](requestId, false, ''); | |
167 showWarningMessage(detail.messageType); | |
168 } | 133 } |
169 }); | 134 actionTaken = true; |
135 }; | |
136 | |
137 var dialog = { | |
138 ok: function(user_input) { | |
139 validateCall(); | |
140 user_input = user_input || ''; | |
141 chrome.webview.setPermission( | |
142 self.instanceId_, requestId, true, user_input); | |
143 }, | |
144 cancel: function() { | |
145 validateCall(); | |
146 chrome.webview.setPermission(self.instanceId_, requestId, false, ''); | |
147 } | |
148 }; | |
149 webviewEvent.dialog = dialog; | |
150 | |
151 var defaultPrevented = !webviewNode.dispatchEvent(webviewEvent); | |
152 if (actionTaken) { | |
153 return; | |
154 } | |
155 | |
156 if (defaultPrevented) { | |
157 // Tell the JavaScript garbage collector to track lifetime of |dialog| and | |
158 // call back when the dialog object has been collected. | |
159 var onTrackedObjectGoneWithRequestId = | |
160 $Function.bind( | |
161 onTrackedObjectGone, self, requestId, event.messageType); | |
162 browserPluginNode.addEventListener('-internal-trackedobjectgone', | |
163 onTrackedObjectGoneWithRequestId); | |
164 browserPluginNode['-internal-trackObjectLifetime'](dialog, requestId); | |
165 } else { | |
166 actionTaken = true; | |
167 // The default action is equivalent to canceling the dialog. | |
168 chrome.webview.setPermission(self.instanceId_, requestId, false, ''); | |
169 showWarningMessage(event.messageType); | |
170 } | |
170 }; | 171 }; |
172 | |
173 /** | |
174 * @private | |
175 */ | |
176 WebView.prototype.maybeGetWebviewExperimentalExtEvents_ = function() { | |
177 return WEB_VIEW_EXPERIMENTAL_EXT_EVENTS; | |
178 }; | |
OLD | NEW |