OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 // This module implements WebView (<webview>) as a custom element that wraps a | 5 // This module implements WebView (<webview>) as a custom element that wraps a |
6 // BrowserPlugin object element. The object element is hidden within | 6 // BrowserPlugin object element. The object element is hidden within |
7 // the shadow DOM of the WebView element. | 7 // the shadow DOM of the WebView element. |
8 | 8 |
9 var DocumentNatives = requireNative('document_natives'); | 9 var DocumentNatives = requireNative('document_natives'); |
10 var GuestViewInternal = | 10 var GuestViewInternal = |
11 require('binding').Binding.create('guestViewInternal').generate(); | 11 require('binding').Binding.create('guestViewInternal').generate(); |
12 var guestViewInternalNatives = requireNative('guest_view_internal'); | 12 var guestViewInternalNatives = requireNative('guest_view_internal'); |
13 var IdGenerator = requireNative('id_generator'); | 13 var IdGenerator = requireNative('id_generator'); |
14 var WebViewConstants = require('webViewConstants').WebViewConstants; | 14 var WebViewConstants = require('webViewConstants').WebViewConstants; |
15 var WebViewEvents = require('webViewEvents').WebViewEvents; | 15 var WebViewEvents = require('webViewEvents').WebViewEvents; |
16 var WebViewInternal = require('webViewInternal').WebViewInternal; | 16 var WebViewInternal = require('webViewInternal').WebViewInternal; |
17 | 17 |
18 // Attributes. | |
19 var BROWSER_PLUGIN_ATTRIBUTE_INTERNALINSTANCEID = 'internalinstanceid' | |
Fady Samuel
2014/10/22 21:48:26
Move to WebViewConstants?
paulmeyer
2014/10/23 21:39:56
Done.
| |
18 var AUTO_SIZE_ATTRIBUTES = [ | 20 var AUTO_SIZE_ATTRIBUTES = [ |
19 WebViewConstants.ATTRIBUTE_AUTOSIZE, | 21 WebViewConstants.ATTRIBUTE_AUTOSIZE, |
20 WebViewConstants.ATTRIBUTE_MAXHEIGHT, | 22 WebViewConstants.ATTRIBUTE_MAXHEIGHT, |
21 WebViewConstants.ATTRIBUTE_MAXWIDTH, | 23 WebViewConstants.ATTRIBUTE_MAXWIDTH, |
22 WebViewConstants.ATTRIBUTE_MINHEIGHT, | 24 WebViewConstants.ATTRIBUTE_MINHEIGHT, |
23 WebViewConstants.ATTRIBUTE_MINWIDTH | 25 WebViewConstants.ATTRIBUTE_MINWIDTH |
24 ]; | 26 ]; |
25 | 27 |
26 // Represents the state of the storage partition. | |
27 function Partition() { | |
28 this.validPartitionId = true; | |
29 this.persistStorage = false; | |
30 this.storagePartitionId = ''; | |
31 } | |
32 | |
33 Partition.prototype.toAttribute = function() { | |
34 if (!this.validPartitionId) { | |
35 return ''; | |
36 } | |
37 return (this.persistStorage ? 'persist:' : '') + this.storagePartitionId; | |
38 }; | |
39 | |
40 Partition.prototype.fromAttribute = function(value, hasNavigated) { | |
41 var result = {}; | |
42 if (hasNavigated) { | |
43 result.error = WebViewConstants.ERROR_MSG_ALREADY_NAVIGATED; | |
44 return result; | |
45 } | |
46 if (!value) { | |
47 value = ''; | |
48 } | |
49 | |
50 var LEN = 'persist:'.length; | |
51 if (value.substr(0, LEN) == 'persist:') { | |
52 value = value.substr(LEN); | |
53 if (!value) { | |
54 this.validPartitionId = false; | |
55 result.error = WebViewConstants.ERROR_MSG_INVALID_PARTITION_ATTRIBUTE; | |
56 return result; | |
57 } | |
58 this.persistStorage = true; | |
59 } else { | |
60 this.persistStorage = false; | |
61 } | |
62 | |
63 this.storagePartitionId = value; | |
64 return result; | |
65 }; | |
66 | |
67 // Represents the internal state of the WebView node. | 28 // Represents the internal state of the WebView node. |
68 function WebView(webviewNode) { | 29 function WebView(webviewNode) { |
69 privates(webviewNode).internal = this; | 30 privates(webviewNode).internal = this; |
70 this.webviewNode = webviewNode; | 31 this.webviewNode = webviewNode; |
71 this.attached = false; | 32 this.attached = false; |
72 this.pendingGuestCreation = false; | 33 this.pendingGuestCreation = false; |
73 this.elementAttached = false; | 34 this.elementAttached = false; |
74 | 35 |
75 this.beforeFirstNavigation = true; | 36 this.beforeFirstNavigation = true; |
76 this.contentWindow = null; | 37 this.contentWindow = null; |
77 this.validPartitionId = true; | 38 this.validPartitionId = true; |
78 // Used to save some state upon deferred attachment. | 39 // Used to save some state upon deferred attachment. |
79 // If <object> bindings is not available, we defer attachment. | 40 // If <object> bindings is not available, we defer attachment. |
80 // This state contains whether or not the attachment request was for | 41 // This state contains whether or not the attachment request was for |
81 // newwindow. | 42 // newwindow. |
82 this.deferredAttachState = null; | 43 this.deferredAttachState = null; |
83 | 44 |
84 // on* Event handlers. | 45 // on* Event handlers. |
85 this.on = {}; | 46 this.on = {}; |
86 | 47 |
87 this.browserPluginNode = this.createBrowserPluginNode(); | 48 this.browserPluginNode = this.createBrowserPluginNode(); |
88 var shadowRoot = this.webviewNode.createShadowRoot(); | 49 var shadowRoot = this.webviewNode.createShadowRoot(); |
89 this.partition = new Partition(); | 50 this.setupWebViewAttributes(); |
90 | |
91 this.setupWebViewSrcAttributeMutationObserver(); | 51 this.setupWebViewSrcAttributeMutationObserver(); |
92 this.setupFocusPropagation(); | 52 this.setupFocusPropagation(); |
93 this.setupWebviewNodeProperties(); | 53 this.setupWebviewNodeProperties(); |
94 | 54 |
95 this.viewInstanceId = IdGenerator.GetNextId(); | 55 this.viewInstanceId = IdGenerator.GetNextId(); |
96 | 56 |
97 new WebViewEvents(this, this.viewInstanceId); | 57 new WebViewEvents(this, this.viewInstanceId); |
98 | 58 |
99 shadowRoot.appendChild(this.browserPluginNode); | 59 shadowRoot.appendChild(this.browserPluginNode); |
100 } | 60 } |
(...skipping 16 matching lines...) Expand all Loading... | |
117 // already picked up a partition ID. Thus, we need to reset the initialization | 77 // already picked up a partition ID. Thus, we need to reset the initialization |
118 // state. However, it may be the case that beforeFirstNavigation is false BUT | 78 // state. However, it may be the case that beforeFirstNavigation is false BUT |
119 // guestInstanceId has yet to be initialized. This means that we have not | 79 // guestInstanceId has yet to be initialized. This means that we have not |
120 // heard back from createGuest yet. We will not reset the flag in this case so | 80 // heard back from createGuest yet. We will not reset the flag in this case so |
121 // that we don't end up allocating a second guest. | 81 // that we don't end up allocating a second guest. |
122 if (this.guestInstanceId) { | 82 if (this.guestInstanceId) { |
123 GuestViewInternal.destroyGuest(this.guestInstanceId); | 83 GuestViewInternal.destroyGuest(this.guestInstanceId); |
124 this.guestInstanceId = undefined; | 84 this.guestInstanceId = undefined; |
125 this.beforeFirstNavigation = true; | 85 this.beforeFirstNavigation = true; |
126 this.validPartitionId = true; | 86 this.validPartitionId = true; |
127 this.partition.validPartitionId = true; | 87 this.attributes[WebViewConstants.ATTRIBUTE_PARTITION].validPartitionId = |
88 true; | |
128 this.contentWindow = null; | 89 this.contentWindow = null; |
129 } | 90 } |
130 this.internalInstanceId = 0; | 91 this.internalInstanceId = 0; |
131 }; | 92 }; |
132 | 93 |
133 // Sets the <webview>.request property. | 94 // Sets the <webview>.request property. |
134 WebView.prototype.setRequestPropertyOnWebViewNode = function(request) { | 95 WebView.prototype.setRequestPropertyOnWebViewNode = function(request) { |
135 Object.defineProperty( | 96 Object.defineProperty( |
136 this.webviewNode, | 97 this.webviewNode, |
137 'request', | 98 'request', |
(...skipping 24 matching lines...) Expand all Loading... | |
162 | 123 |
163 // Validation helper function for executeScript() and insertCSS(). | 124 // Validation helper function for executeScript() and insertCSS(). |
164 WebView.prototype.validateExecuteCodeCall = function() { | 125 WebView.prototype.validateExecuteCodeCall = function() { |
165 if (!this.guestInstanceId) { | 126 if (!this.guestInstanceId) { |
166 throw new Error(WebViewConstants.ERROR_MSG_CANNOT_INJECT_SCRIPT); | 127 throw new Error(WebViewConstants.ERROR_MSG_CANNOT_INJECT_SCRIPT); |
167 } | 128 } |
168 }; | 129 }; |
169 | 130 |
170 WebView.prototype.setupAutoSizeProperties = function() { | 131 WebView.prototype.setupAutoSizeProperties = function() { |
171 $Array.forEach(AUTO_SIZE_ATTRIBUTES, function(attributeName) { | 132 $Array.forEach(AUTO_SIZE_ATTRIBUTES, function(attributeName) { |
172 this[attributeName] = this.webviewNode.getAttribute(attributeName); | 133 this.attributes[attributeName].setValue( |
134 this.webviewNode.getAttribute(attributeName)); | |
173 Object.defineProperty(this.webviewNode, attributeName, { | 135 Object.defineProperty(this.webviewNode, attributeName, { |
174 get: function() { | 136 get: function() { |
175 return this[attributeName]; | 137 return this.attributes[attributeName]; |
176 }.bind(this), | 138 }.bind(this), |
177 set: function(value) { | 139 set: function(value) { |
178 this.webviewNode.setAttribute(attributeName, value); | 140 this.webviewNode.setAttribute(attributeName, value); |
179 }.bind(this), | 141 }.bind(this), |
180 enumerable: true | 142 enumerable: true |
181 }); | 143 }); |
182 }.bind(this), this); | 144 }.bind(this), this); |
183 }; | 145 }; |
184 | 146 |
185 WebView.prototype.setupWebviewNodeProperties = function() { | 147 WebView.prototype.setupWebviewNodeProperties = function() { |
(...skipping 19 matching lines...) Expand all Loading... | |
205 if (this.contentWindow) { | 167 if (this.contentWindow) { |
206 return this.contentWindow; | 168 return this.contentWindow; |
207 } | 169 } |
208 window.console.error( | 170 window.console.error( |
209 WebViewConstants.ERROR_MSG_CONTENTWINDOW_NOT_AVAILABLE); | 171 WebViewConstants.ERROR_MSG_CONTENTWINDOW_NOT_AVAILABLE); |
210 }.bind(this), | 172 }.bind(this), |
211 // No setter. | 173 // No setter. |
212 enumerable: true | 174 enumerable: true |
213 }); | 175 }); |
214 | 176 |
215 Object.defineProperty(this.webviewNode, 'name', { | 177 Object.defineProperty(this.webviewNode, WebViewConstants.ATTRIBUTE_NAME, { |
216 get: function() { | 178 get: function() { |
217 return this.name; | 179 return this.attributes[WebViewConstants.ATTRIBUTE_NAME].getValue(); |
218 }.bind(this), | 180 }.bind(this), |
219 set: function(value) { | 181 set: function(value) { |
220 this.webviewNode.setAttribute('name', value); | 182 this.webviewNode.setAttribute(WebViewConstants.ATTRIBUTE_NAME, value); |
221 }.bind(this), | 183 }.bind(this), |
222 enumerable: true | 184 enumerable: true |
223 }); | 185 }); |
224 | 186 |
225 Object.defineProperty(this.webviewNode, 'partition', { | 187 Object.defineProperty(this.webviewNode, |
188 WebViewConstants.ATTRIBUTE_PARTITION, { | |
226 get: function() { | 189 get: function() { |
227 return this.partition.toAttribute(); | 190 return this.attributes[WebViewConstants.ATTRIBUTE_PARTITION].getValue(); |
228 }.bind(this), | 191 }.bind(this), |
229 set: function(value) { | 192 set: function(value) { |
230 var result = this.partition.fromAttribute(value, this.hasNavigated()); | 193 var result = this.attributes[WebViewConstants.ATTRIBUTE_PARTITION]. |
194 setValue(value); | |
231 if (result.error) { | 195 if (result.error) { |
232 throw result.error; | 196 throw result.error; |
233 } | 197 } |
234 this.webviewNode.setAttribute('partition', value); | 198 this.webviewNode.setAttribute(WebViewConstants.ATTRIBUTE_PARTITION, |
199 value); | |
235 }.bind(this), | 200 }.bind(this), |
236 enumerable: true | 201 enumerable: true |
237 }); | 202 }); |
238 | 203 |
239 this.src = this.webviewNode.getAttribute('src'); | 204 this.attributes[WebViewConstants.ATTRIBUTE_SRC].setValue( |
240 Object.defineProperty(this.webviewNode, 'src', { | 205 this.webviewNode.getAttribute(WebViewConstants.ATTRIBUTE_SRC)); |
206 Object.defineProperty(this.webviewNode, WebViewConstants.ATTRIBUTE_SRC, { | |
241 get: function() { | 207 get: function() { |
242 return this.src; | 208 return this.attributes[WebViewConstants.ATTRIBUTE_SRC].getValue(); |
243 }.bind(this), | 209 }.bind(this), |
244 set: function(value) { | 210 set: function(value) { |
245 this.webviewNode.setAttribute('src', value); | 211 this.webviewNode.setAttribute(WebViewConstants.ATTRIBUTE_SRC, value); |
246 }.bind(this), | 212 }.bind(this), |
247 // No setter. | |
248 enumerable: true | 213 enumerable: true |
249 }); | 214 }); |
250 }; | 215 }; |
251 | 216 |
252 // The purpose of this mutation observer is to catch assignment to the src | 217 // The purpose of this mutation observer is to catch assignment to the src |
253 // attribute without any changes to its value. This is useful in the case | 218 // attribute without any changes to its value. This is useful in the case |
254 // where the webview guest has crashed and navigating to the same address | 219 // where the webview guest has crashed and navigating to the same address |
255 // spawns off a new process. | 220 // spawns off a new process. |
256 WebView.prototype.setupWebViewSrcAttributeMutationObserver = | 221 WebView.prototype.setupWebViewSrcAttributeMutationObserver = |
257 function() { | 222 function() { |
258 this.srcAndPartitionObserver = new MutationObserver(function(mutations) { | 223 this.srcAndPartitionObserver = new MutationObserver(function(mutations) { |
259 $Array.forEach(mutations, function(mutation) { | 224 $Array.forEach(mutations, function(mutation) { |
260 var oldValue = mutation.oldValue; | 225 var oldValue = mutation.oldValue; |
261 var newValue = this.webviewNode.getAttribute(mutation.attributeName); | 226 var newValue = this.webviewNode.getAttribute(mutation.attributeName); |
262 if (oldValue != newValue) { | 227 if (oldValue != newValue) { |
263 return; | 228 return; |
264 } | 229 } |
265 this.handleWebviewAttributeMutation( | 230 this.handleWebviewAttributeMutation( |
266 mutation.attributeName, oldValue, newValue); | 231 mutation.attributeName, oldValue, newValue); |
267 }.bind(this)); | 232 }.bind(this)); |
268 }.bind(this)); | 233 }.bind(this)); |
269 var params = { | 234 var params = { |
270 attributes: true, | 235 attributes: true, |
271 attributeOldValue: true, | 236 attributeOldValue: true, |
272 attributeFilter: ['src', 'partition'] | 237 attributeFilter: [WebViewConstants.ATTRIBUTE_SRC, |
238 WebViewConstants.ATTRIBUTE_PARTITION] | |
273 }; | 239 }; |
274 this.srcAndPartitionObserver.observe(this.webviewNode, params); | 240 this.srcAndPartitionObserver.observe(this.webviewNode, params); |
275 }; | 241 }; |
276 | 242 |
277 // This observer monitors mutations to attributes of the <webview> and | 243 // This observer monitors mutations to attributes of the <webview> and |
278 // updates the BrowserPlugin properties accordingly. In turn, updating | 244 // updates the BrowserPlugin properties accordingly. In turn, updating |
279 // a BrowserPlugin property will update the corresponding BrowserPlugin | 245 // a BrowserPlugin property will update the corresponding BrowserPlugin |
280 // attribute, if necessary. See BrowserPlugin::UpdateDOMAttribute for more | 246 // attribute, if necessary. See BrowserPlugin::UpdateDOMAttribute for more |
281 // details. | 247 // details. |
282 WebView.prototype.handleWebviewAttributeMutation = | 248 WebView.prototype.handleWebviewAttributeMutation = |
283 function(name, oldValue, newValue) { | 249 function(name, oldValue, newValue) { |
284 if (AUTO_SIZE_ATTRIBUTES.indexOf(name) > -1) { | 250 if (AUTO_SIZE_ATTRIBUTES.indexOf(name) > -1) { |
285 this[name] = newValue; | 251 this.attributes[name] = newValue; |
286 if (!this.guestInstanceId) { | 252 if (!this.guestInstanceId) { |
287 return; | 253 return; |
288 } | 254 } |
289 // Convert autosize attribute to boolean. | 255 // Convert autosize attribute to boolean. |
256 // TODO(paulmeyer) is this right? | |
Fady Samuel
2014/10/22 21:48:26
Yes, we're not looking specifically for any value
paulmeyer
2014/10/23 21:39:56
Acknowledged.
| |
290 var autosize = this.webviewNode.hasAttribute( | 257 var autosize = this.webviewNode.hasAttribute( |
291 WebViewConstants.ATTRIBUTE_AUTOSIZE); | 258 WebViewConstants.ATTRIBUTE_AUTOSIZE); |
292 GuestViewInternal.setAutoSize(this.guestInstanceId, { | 259 GuestViewInternal.setAutoSize(this.guestInstanceId, { |
293 'enableAutoSize': autosize, | 260 'enableAutoSize': autosize, |
294 'min': { | 261 'min': { |
295 'width': parseInt(this.minwidth || 0), | 262 'width': parseInt(this. |
296 'height': parseInt(this.minheight || 0) | 263 attributes[WebViewConstants.ATTRIBUTE_MINWIDTH].getValue() || 0), |
264 'height': parseInt(this. | |
265 attributes[WebViewConstants.ATTRIBUTE_MINHEIGHT].getValue() || 0) | |
297 }, | 266 }, |
298 'max': { | 267 'max': { |
299 'width': parseInt(this.maxwidth || 0), | 268 'width': parseInt(this. |
300 'height': parseInt(this.maxheight || 0) | 269 attributes[WebViewConstants.ATTRIBUTE_MAXWIDTH].getValue() || 0), |
270 'height': parseInt(this. | |
271 attributes[WebViewConstants.ATTRIBUTE_MAXHEIGHT].getValue() || 0) | |
301 } | 272 } |
302 }); | 273 }); |
303 return; | 274 return; |
304 } else if (name == WebViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY) { | 275 } else if (name == WebViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY) { |
305 // We treat null attribute (attribute removed) and the empty string as | 276 // We treat null attribute (attribute removed) and the empty string as |
306 // one case. | 277 // one case. |
307 oldValue = oldValue || ''; | 278 oldValue = oldValue || ''; |
308 newValue = newValue || ''; | 279 newValue = newValue || ''; |
309 | 280 |
310 if (oldValue === newValue) { | 281 if (oldValue === newValue) { |
311 return; | 282 return; |
312 } | 283 } |
313 this.allowtransparency = newValue != ''; | 284 this.allowtransparency = newValue != ''; |
314 | 285 |
315 if (!this.guestInstanceId) { | 286 if (!this.guestInstanceId) { |
316 return; | 287 return; |
317 } | 288 } |
318 | 289 |
319 WebViewInternal.setAllowTransparency(this.guestInstanceId, | 290 WebViewInternal.setAllowTransparency(this.guestInstanceId, |
320 this.allowtransparency); | 291 this.allowtransparency); |
321 return; | 292 return; |
322 } else if (name == 'name') { | 293 } else if (name == WebViewConstants.ATTRIBUTE_NAME) { |
323 // We treat null attribute (attribute removed) and the empty string as | 294 // We treat null attribute (attribute removed) and the empty string as |
324 // one case. | 295 // one case. |
325 oldValue = oldValue || ''; | 296 oldValue = oldValue || ''; |
326 newValue = newValue || ''; | 297 newValue = newValue || ''; |
327 | 298 |
328 if (oldValue === newValue) { | 299 if (oldValue === newValue) { |
329 return; | 300 return; |
330 } | 301 } |
331 this.name = newValue; | 302 this.attributes[WebViewConstants.ATTRIBUTE_NAME].setValue(newValue); |
332 if (!this.guestInstanceId) { | 303 if (!this.guestInstanceId) { |
333 return; | 304 return; |
334 } | 305 } |
335 WebViewInternal.setName(this.guestInstanceId, newValue); | 306 WebViewInternal.setName(this.guestInstanceId, newValue); |
336 return; | 307 return; |
337 } else if (name == 'src') { | 308 } else if (name == WebViewConstants.ATTRIBUTE_SRC) { |
338 // We treat null attribute (attribute removed) and the empty string as | 309 // We treat null attribute (attribute removed) and the empty string as |
339 // one case. | 310 // one case. |
340 oldValue = oldValue || ''; | 311 oldValue = oldValue || ''; |
341 newValue = newValue || ''; | 312 newValue = newValue || ''; |
342 // Once we have navigated, we don't allow clearing the src attribute. | 313 // Once we have navigated, we don't allow clearing the src attribute. |
343 // Once <webview> enters a navigated state, it cannot be return back to a | 314 // Once <webview> enters a navigated state, it cannot be return back to a |
344 // placeholder state. | 315 // placeholder state. |
345 if (newValue == '' && oldValue != '') { | 316 if (newValue == '' && oldValue != '') { |
346 // src attribute changes normally initiate a navigation. We suppress | 317 // src attribute changes normally initiate a navigation. We suppress |
347 // the next src attribute handler call to avoid reloading the page | 318 // the next src attribute handler call to avoid reloading the page |
348 // on every guest-initiated navigation. | 319 // on every guest-initiated navigation. |
349 this.ignoreNextSrcAttributeChange = true; | 320 this.ignoreNextSrcAttributeChange = true; |
350 this.webviewNode.setAttribute('src', oldValue); | 321 this.webviewNode.setAttribute(WebViewConstants.ATTRIBUTE_SRC, oldValue); |
351 return; | 322 return; |
352 } | 323 } |
353 this.src = newValue; | 324 this.attributes[WebViewConstants.ATTRIBUTE_SRC].setValue(newValue); |
354 if (this.ignoreNextSrcAttributeChange) { | 325 if (this.ignoreNextSrcAttributeChange) { |
355 // Don't allow the src mutation observer to see this change. | 326 // Don't allow the src mutation observer to see this change. |
356 this.srcAndPartitionObserver.takeRecords(); | 327 this.srcAndPartitionObserver.takeRecords(); |
357 this.ignoreNextSrcAttributeChange = false; | 328 this.ignoreNextSrcAttributeChange = false; |
358 return; | 329 return; |
359 } | 330 } |
360 var result = {}; | 331 var result = {}; |
361 this.parseSrcAttribute(result); | 332 this.parseSrcAttribute(result); |
362 | 333 |
363 if (result.error) { | 334 if (result.error) { |
364 throw result.error; | 335 throw result.error; |
365 } | 336 } |
366 } else if (name == 'partition') { | 337 } else if (name == WebViewConstants.ATTRIBUTE_PARTITION) { |
367 // Note that throwing error here won't synchronously propagate. | 338 // Note that throwing error here won't synchronously propagate. |
368 this.partition.fromAttribute(newValue, this.hasNavigated()); | 339 this.attributes[WebViewConstants.ATTRIBUTE_PARTITION].setValue(newValue); |
369 } | 340 } |
370 }; | 341 }; |
371 | 342 |
372 WebView.prototype.handleBrowserPluginAttributeMutation = | 343 WebView.prototype.handleBrowserPluginAttributeMutation = |
373 function(name, oldValue, newValue) { | 344 function(name, oldValue, newValue) { |
374 if (name == 'internalinstanceid' && !oldValue && !!newValue) { | 345 if (name == BROWSER_PLUGIN_ATTRIBUTE_INTERNALINSTANCEID && |
375 this.browserPluginNode.removeAttribute('internalinstanceid'); | 346 !oldValue && !!newValue) { |
347 this.browserPluginNode.removeAttribute( | |
348 BROWSER_PLUGIN_ATTRIBUTE_INTERNALINSTANCEID); | |
376 this.internalInstanceId = parseInt(newValue); | 349 this.internalInstanceId = parseInt(newValue); |
377 | 350 |
378 if (!!this.guestInstanceId && this.guestInstanceId != 0) { | 351 if (!!this.guestInstanceId && this.guestInstanceId != 0) { |
379 var isNewWindow = this.deferredAttachState ? | 352 var isNewWindow = this.deferredAttachState ? |
380 this.deferredAttachState.isNewWindow : false; | 353 this.deferredAttachState.isNewWindow : false; |
381 var params = this.buildAttachParams(isNewWindow); | 354 var params = this.buildAttachParams(isNewWindow); |
382 guestViewInternalNatives.AttachGuest( | 355 guestViewInternalNatives.AttachGuest( |
383 this.internalInstanceId, | 356 this.internalInstanceId, |
384 this.guestInstanceId, | 357 this.guestInstanceId, |
385 params, | 358 params, |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
458 // Returns if <object> is in the render tree. | 431 // Returns if <object> is in the render tree. |
459 WebView.prototype.isPluginInRenderTree = function() { | 432 WebView.prototype.isPluginInRenderTree = function() { |
460 return !!this.internalInstanceId && this.internalInstanceId != 0; | 433 return !!this.internalInstanceId && this.internalInstanceId != 0; |
461 }; | 434 }; |
462 | 435 |
463 WebView.prototype.hasNavigated = function() { | 436 WebView.prototype.hasNavigated = function() { |
464 return !this.beforeFirstNavigation; | 437 return !this.beforeFirstNavigation; |
465 }; | 438 }; |
466 | 439 |
467 WebView.prototype.parseSrcAttribute = function(result) { | 440 WebView.prototype.parseSrcAttribute = function(result) { |
468 if (!this.partition.validPartitionId) { | 441 if (!this.attributes[WebViewConstants.ATTRIBUTE_PARTITION].validPartitionId) { |
469 result.error = WebViewConstants.ERROR_MSG_INVALID_PARTITION_ATTRIBUTE; | 442 result.error = WebViewConstants.ERROR_MSG_INVALID_PARTITION_ATTRIBUTE; |
470 return; | 443 return; |
471 } | 444 } |
472 this.src = this.webviewNode.getAttribute('src'); | 445 this.attributes[WebViewConstants.ATTRIBUTE_SRC].setValue( |
446 this.webviewNode.getAttribute(WebViewConstants.ATTRIBUTE_SRC)); | |
473 | 447 |
474 if (!this.src) { | 448 if (!this.attributes[WebViewConstants.ATTRIBUTE_SRC].getValue()) { |
475 return; | 449 return; |
476 } | 450 } |
477 | 451 |
478 if (this.guestInstanceId == undefined) { | 452 if (this.guestInstanceId == undefined) { |
479 if (this.beforeFirstNavigation) { | 453 if (this.beforeFirstNavigation) { |
480 this.beforeFirstNavigation = false; | 454 this.beforeFirstNavigation = false; |
481 this.createGuest(); | 455 this.createGuest(); |
482 } | 456 } |
483 return; | 457 return; |
484 } | 458 } |
485 | 459 |
486 // Navigate to |this.src|. | 460 // Navigate to |this.src|. |
487 WebViewInternal.navigate(this.guestInstanceId, this.src); | 461 WebViewInternal.navigate( |
462 this.guestInstanceId, | |
463 this.attributes[WebViewConstants.ATTRIBUTE_SRC].getValue()); | |
488 }; | 464 }; |
489 | 465 |
490 WebView.prototype.parseAttributes = function() { | 466 WebView.prototype.parseAttributes = function() { |
491 if (!this.elementAttached) { | 467 if (!this.elementAttached) { |
492 return; | 468 return; |
493 } | 469 } |
494 var hasNavigated = this.hasNavigated(); | 470 var attributeValue = this.webviewNode.getAttribute( |
495 var attributeValue = this.webviewNode.getAttribute('partition'); | 471 WebViewConstants.ATTRIBUTE_PARTITION); |
496 var result = this.partition.fromAttribute(attributeValue, hasNavigated); | 472 var result = this.attributes[WebViewConstants.ATTRIBUTE_PARTITION].setValue( |
473 attributeValue); | |
497 this.parseSrcAttribute(result); | 474 this.parseSrcAttribute(result); |
498 }; | 475 }; |
499 | 476 |
500 WebView.prototype.createGuest = function() { | 477 WebView.prototype.createGuest = function() { |
501 if (this.pendingGuestCreation) { | 478 if (this.pendingGuestCreation) { |
502 return; | 479 return; |
503 } | 480 } |
481 // TODO(paulmeyer) this looks wacky. | |
Fady Samuel
2014/10/22 21:48:26
Please ask Istiaque about this. I'm not sure why t
paulmeyer
2014/10/23 21:39:55
This will get cleaned up when I unify the storage/
| |
504 var storagePartitionId = | 482 var storagePartitionId = |
505 this.webviewNode.getAttribute(WebViewConstants.ATTRIBUTE_PARTITION) || | 483 this.webviewNode.getAttribute(WebViewConstants.ATTRIBUTE_PARTITION) || |
506 this.webviewNode[WebViewConstants.ATTRIBUTE_PARTITION]; | 484 this.webviewNode[WebViewConstants.ATTRIBUTE_PARTITION]; |
507 var params = { | 485 var params = { |
508 'storagePartitionId': storagePartitionId | 486 'storagePartitionId': storagePartitionId |
509 }; | 487 }; |
510 GuestViewInternal.createGuest( | 488 GuestViewInternal.createGuest( |
511 'webview', | 489 'webview', |
512 params, | 490 params, |
513 function(guestInstanceId) { | 491 function(guestInstanceId) { |
514 this.pendingGuestCreation = false; | 492 this.pendingGuestCreation = false; |
515 if (!this.elementAttached) { | 493 if (!this.elementAttached) { |
516 GuestViewInternal.destroyGuest(guestInstanceId); | 494 GuestViewInternal.destroyGuest(guestInstanceId); |
517 return; | 495 return; |
518 } | 496 } |
519 this.attachWindow(guestInstanceId, false); | 497 this.attachWindow(guestInstanceId, false); |
520 }.bind(this) | 498 }.bind(this) |
521 ); | 499 ); |
522 this.pendingGuestCreation = true; | 500 this.pendingGuestCreation = true; |
523 }; | 501 }; |
524 | 502 |
525 WebView.prototype.onFrameNameChanged = function(name) { | 503 WebView.prototype.onFrameNameChanged = function(name) { |
526 this.name = name || ''; | 504 this.attributes[WebViewConstants.ATTRIBUTE_NAME].setValue(name || ''); |
527 if (this.name === '') { | 505 if (this.attributes[WebViewConstants.ATTRIBUTE_NAME].getValue() === '') { |
528 this.webviewNode.removeAttribute('name'); | 506 this.webviewNode.removeAttribute(WebViewConstants.ATTRIBUTE_NAME); |
529 } else { | 507 } else { |
530 this.webviewNode.setAttribute('name', this.name); | 508 this.webviewNode.setAttribute( |
509 WebViewConstants.ATTRIBUTE_NAME, | |
510 this.attributes[WebViewConstants.ATTRIBUTE_NAME].getValue()); | |
531 } | 511 } |
532 }; | 512 }; |
533 | 513 |
534 WebView.prototype.dispatchEvent = function(webViewEvent) { | 514 WebView.prototype.dispatchEvent = function(webViewEvent) { |
535 return this.webviewNode.dispatchEvent(webViewEvent); | 515 return this.webviewNode.dispatchEvent(webViewEvent); |
536 }; | 516 }; |
537 | 517 |
538 // Adds an 'on<event>' property on the webview, which can be used to set/unset | 518 // Adds an 'on<event>' property on the webview, which can be used to set/unset |
539 // an event handler. | 519 // an event handler. |
540 WebView.prototype.setupEventProperty = function(eventName) { | 520 WebView.prototype.setupEventProperty = function(eventName) { |
(...skipping 14 matching lines...) Expand all Loading... | |
555 }; | 535 }; |
556 | 536 |
557 // Updates state upon loadcommit. | 537 // Updates state upon loadcommit. |
558 WebView.prototype.onLoadCommit = function( | 538 WebView.prototype.onLoadCommit = function( |
559 baseUrlForDataUrl, currentEntryIndex, entryCount, | 539 baseUrlForDataUrl, currentEntryIndex, entryCount, |
560 processId, url, isTopLevel) { | 540 processId, url, isTopLevel) { |
561 this.baseUrlForDataUrl = baseUrlForDataUrl; | 541 this.baseUrlForDataUrl = baseUrlForDataUrl; |
562 this.currentEntryIndex = currentEntryIndex; | 542 this.currentEntryIndex = currentEntryIndex; |
563 this.entryCount = entryCount; | 543 this.entryCount = entryCount; |
564 this.processId = processId; | 544 this.processId = processId; |
565 var oldValue = this.webviewNode.getAttribute('src'); | 545 var oldValue = this.webviewNode.getAttribute(WebViewConstants.ATTRIBUTE_SRC); |
566 var newValue = url; | 546 var newValue = url; |
567 if (isTopLevel && (oldValue != newValue)) { | 547 if (isTopLevel && (oldValue != newValue)) { |
568 // Touching the src attribute triggers a navigation. To avoid | 548 // Touching the src attribute triggers a navigation. To avoid |
569 // triggering a page reload on every guest-initiated navigation, | 549 // triggering a page reload on every guest-initiated navigation, |
570 // we use the flag ignoreNextSrcAttributeChange here. | 550 // we use the flag ignoreNextSrcAttributeChange here. |
571 this.ignoreNextSrcAttributeChange = true; | 551 this.ignoreNextSrcAttributeChange = true; |
572 this.webviewNode.setAttribute('src', newValue); | 552 this.webviewNode.setAttribute(WebViewConstants.ATTRIBUTE_SRC, newValue); |
573 } | 553 } |
574 }; | 554 }; |
575 | 555 |
576 WebView.prototype.onAttach = function(storagePartitionId) { | 556 WebView.prototype.onAttach = function(storagePartitionId) { |
577 this.webviewNode.setAttribute('partition', storagePartitionId); | 557 this.webviewNode.setAttribute(WebViewConstants.ATTRIBUTE_PARTITION, |
578 this.partition.fromAttribute(storagePartitionId, this.hasNavigated()); | 558 storagePartitionId); |
559 this.attributes[WebViewConstants.ATTRIBUTE_PARTITION].setValue( | |
560 storagePartitionId); | |
579 }; | 561 }; |
580 | 562 |
581 WebView.prototype.buildAttachParams = function(isNewWindow) { | 563 WebView.prototype.buildAttachParams = function(isNewWindow) { |
582 var params = { | 564 var params = { |
583 'allowtransparency': this.allowtransparency || false, | 565 'allowtransparency': this.allowtransparency || false, |
584 'autosize': this.webviewNode.hasAttribute( | 566 'autosize': this.webviewNode.hasAttribute( |
585 WebViewConstants.ATTRIBUTE_AUTOSIZE), | 567 WebViewConstants.ATTRIBUTE_AUTOSIZE), |
586 'instanceId': this.viewInstanceId, | 568 'instanceId': this.viewInstanceId, |
587 'maxheight': parseInt(this.maxheight || 0), | 569 'maxheight': parseInt(this.attributes[WebViewConstants.ATTRIBUTE_MAXHEIGHT]. |
Fady Samuel
2014/10/22 21:48:26
I feel like the key names should probably also mat
paulmeyer
2014/10/23 21:39:56
I agree, and hopefully there will be a nice concis
| |
588 'maxwidth': parseInt(this.maxwidth || 0), | 570 getValue() || 0), |
589 'minheight': parseInt(this.minheight || 0), | 571 'maxwidth': parseInt(this.attributes[WebViewConstants.ATTRIBUTE_MAXWIDTH]. |
590 'minwidth': parseInt(this.minwidth || 0), | 572 getValue() || 0), |
591 'name': this.name, | 573 'minheight': parseInt(this.attributes[WebViewConstants.ATTRIBUTE_MINHEIGHT]. |
574 getValue() || 0), | |
575 'minwidth': parseInt(this.attributes[WebViewConstants.ATTRIBUTE_MINWIDTH]. | |
576 getValue() || 0), | |
577 'name': this.attributes[WebViewConstants.ATTRIBUTE_NAME].getValue(), | |
592 // We don't need to navigate new window from here. | 578 // We don't need to navigate new window from here. |
593 'src': isNewWindow ? undefined : this.src, | 579 'src': isNewWindow ? undefined : |
580 this.attributes[WebViewConstants.ATTRIBUTE_SRC].getValue(), | |
594 // If we have a partition from the opener, that will also be already | 581 // If we have a partition from the opener, that will also be already |
595 // set via this.onAttach(). | 582 // set via this.onAttach(). |
596 'storagePartitionId': this.partition.toAttribute(), | 583 'storagePartitionId': this.attributes[WebViewConstants.ATTRIBUTE_PARTITION]. |
584 getValue(), | |
597 'userAgentOverride': this.userAgentOverride | 585 'userAgentOverride': this.userAgentOverride |
598 }; | 586 }; |
599 return params; | 587 return params; |
600 }; | 588 }; |
601 | 589 |
602 WebView.prototype.attachWindow = function(guestInstanceId, | 590 WebView.prototype.attachWindow = function(guestInstanceId, |
603 isNewWindow) { | 591 isNewWindow) { |
604 this.guestInstanceId = guestInstanceId; | 592 this.guestInstanceId = guestInstanceId; |
605 var params = this.buildAttachParams(isNewWindow); | 593 var params = this.buildAttachParams(isNewWindow); |
606 | 594 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
644 if (!this.guestInstanceId) { | 632 if (!this.guestInstanceId) { |
645 return; | 633 return; |
646 } | 634 } |
647 var args = $Array.concat([this.guestInstanceId], $Array.slice(arguments)); | 635 var args = $Array.concat([this.guestInstanceId], $Array.slice(arguments)); |
648 $Function.apply(WebViewInternal.clearData, null, args); | 636 $Function.apply(WebViewInternal.clearData, null, args); |
649 }; | 637 }; |
650 | 638 |
651 // Injects JavaScript code into the guest page. | 639 // Injects JavaScript code into the guest page. |
652 WebView.prototype.executeScript = function(var_args) { | 640 WebView.prototype.executeScript = function(var_args) { |
653 this.validateExecuteCodeCall(); | 641 this.validateExecuteCodeCall(); |
654 var webviewSrc = this.src; | 642 var webviewSrc = this.attributes[WebViewConstants.ATTRIBUTE_SRC].getValue(); |
655 if (this.baseUrlForDataUrl != '') { | 643 if (this.baseUrlForDataUrl != '') { |
656 webviewSrc = this.baseUrlForDataUrl; | 644 webviewSrc = this.baseUrlForDataUrl; |
657 } | 645 } |
658 var args = $Array.concat([this.guestInstanceId, webviewSrc], | 646 var args = $Array.concat([this.guestInstanceId, webviewSrc], |
659 $Array.slice(arguments)); | 647 $Array.slice(arguments)); |
660 $Function.apply(WebViewInternal.executeScript, null, args); | 648 $Function.apply(WebViewInternal.executeScript, null, args); |
661 }; | 649 }; |
662 | 650 |
663 // Initiates a find-in-page request. | 651 // Initiates a find-in-page request. |
664 WebView.prototype.find = function(search_text, options, callback) { | 652 WebView.prototype.find = function(search_text, options, callback) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
697 WebView.prototype.go = function(relativeIndex, callback) { | 685 WebView.prototype.go = function(relativeIndex, callback) { |
698 if (!this.guestInstanceId) { | 686 if (!this.guestInstanceId) { |
699 return; | 687 return; |
700 } | 688 } |
701 WebViewInternal.go(this.guestInstanceId, relativeIndex, callback); | 689 WebViewInternal.go(this.guestInstanceId, relativeIndex, callback); |
702 }; | 690 }; |
703 | 691 |
704 // Injects CSS into the guest page. | 692 // Injects CSS into the guest page. |
705 WebView.prototype.insertCSS = function(var_args) { | 693 WebView.prototype.insertCSS = function(var_args) { |
706 this.validateExecuteCodeCall(); | 694 this.validateExecuteCodeCall(); |
707 var webviewSrc = this.src; | 695 var webviewSrc = this.attributes[WebViewConstants.ATTRIBUTE_SRC].getValue(); |
708 if (this.baseUrlForDataUrl != '') { | 696 if (this.baseUrlForDataUrl != '') { |
709 webviewSrc = this.baseUrlForDataUrl; | 697 webviewSrc = this.baseUrlForDataUrl; |
710 } | 698 } |
711 var args = $Array.concat([this.guestInstanceId, webviewSrc], | 699 var args = $Array.concat([this.guestInstanceId, webviewSrc], |
712 $Array.slice(arguments)); | 700 $Array.slice(arguments)); |
713 $Function.apply(WebViewInternal.insertCSS, null, args); | 701 $Function.apply(WebViewInternal.insertCSS, null, args); |
714 }; | 702 }; |
715 | 703 |
716 // Indicates whether or not the webview's user agent string has been overridden. | 704 // Indicates whether or not the webview's user agent string has been overridden. |
717 WebView.prototype.isUserAgentOverridden = function() { | 705 WebView.prototype.isUserAgentOverridden = function() { |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
913 WebView.prototype.maybeGetChromeWebViewEvents = function() {}; | 901 WebView.prototype.maybeGetChromeWebViewEvents = function() {}; |
914 | 902 |
915 // Implemented when the experimental WebView API is available. | 903 // Implemented when the experimental WebView API is available. |
916 WebView.maybeGetExperimentalAPIs = function() {}; | 904 WebView.maybeGetExperimentalAPIs = function() {}; |
917 WebView.prototype.maybeGetExperimentalEvents = function() {}; | 905 WebView.prototype.maybeGetExperimentalEvents = function() {}; |
918 WebView.prototype.setupExperimentalContextMenus = function() {}; | 906 WebView.prototype.setupExperimentalContextMenus = function() {}; |
919 | 907 |
920 // Exports. | 908 // Exports. |
921 exports.WebView = WebView; | 909 exports.WebView = WebView; |
922 exports.WebViewInternal = WebViewInternal; | 910 exports.WebViewInternal = WebViewInternal; |
OLD | NEW |