Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(98)

Side by Side Diff: extensions/renderer/resources/guest_view/web_view.js

Issue 663483004: Webview attributes overhaul. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed comments. Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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.
18 var AUTO_SIZE_ATTRIBUTES = [ 19 var AUTO_SIZE_ATTRIBUTES = [
19 WebViewConstants.ATTRIBUTE_AUTOSIZE, 20 WebViewConstants.ATTRIBUTE_AUTOSIZE,
20 WebViewConstants.ATTRIBUTE_MAXHEIGHT, 21 WebViewConstants.ATTRIBUTE_MAXHEIGHT,
21 WebViewConstants.ATTRIBUTE_MAXWIDTH, 22 WebViewConstants.ATTRIBUTE_MAXWIDTH,
22 WebViewConstants.ATTRIBUTE_MINHEIGHT, 23 WebViewConstants.ATTRIBUTE_MINHEIGHT,
23 WebViewConstants.ATTRIBUTE_MINWIDTH 24 WebViewConstants.ATTRIBUTE_MINWIDTH
24 ]; 25 ];
25 26
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. 27 // Represents the internal state of the WebView node.
68 function WebView(webviewNode) { 28 function WebView(webviewNode) {
69 privates(webviewNode).internal = this; 29 privates(webviewNode).internal = this;
70 this.webviewNode = webviewNode; 30 this.webviewNode = webviewNode;
71 this.attached = false; 31 this.attached = false;
72 this.pendingGuestCreation = false; 32 this.pendingGuestCreation = false;
73 this.elementAttached = false; 33 this.elementAttached = false;
74 34
75 this.beforeFirstNavigation = true; 35 this.beforeFirstNavigation = true;
76 this.contentWindow = null; 36 this.contentWindow = null;
77 this.validPartitionId = true; 37 this.validPartitionId = true;
78 // Used to save some state upon deferred attachment. 38 // Used to save some state upon deferred attachment.
79 // If <object> bindings is not available, we defer attachment. 39 // If <object> bindings is not available, we defer attachment.
80 // This state contains whether or not the attachment request was for 40 // This state contains whether or not the attachment request was for
81 // newwindow. 41 // newwindow.
82 this.deferredAttachState = null; 42 this.deferredAttachState = null;
83 43
84 // on* Event handlers. 44 // on* Event handlers.
85 this.on = {}; 45 this.on = {};
86 46
87 this.browserPluginNode = this.createBrowserPluginNode(); 47 this.browserPluginNode = this.createBrowserPluginNode();
88 var shadowRoot = this.webviewNode.createShadowRoot(); 48 var shadowRoot = this.webviewNode.createShadowRoot();
89 this.partition = new Partition(); 49 this.setupWebViewAttributes();
90
91 this.setupWebViewSrcAttributeMutationObserver(); 50 this.setupWebViewSrcAttributeMutationObserver();
92 this.setupFocusPropagation(); 51 this.setupFocusPropagation();
93 this.setupWebviewNodeProperties(); 52 this.setupWebviewNodeProperties();
94 53
95 this.viewInstanceId = IdGenerator.GetNextId(); 54 this.viewInstanceId = IdGenerator.GetNextId();
96 55
97 new WebViewEvents(this, this.viewInstanceId); 56 new WebViewEvents(this, this.viewInstanceId);
98 57
99 shadowRoot.appendChild(this.browserPluginNode); 58 shadowRoot.appendChild(this.browserPluginNode);
100 } 59 }
(...skipping 16 matching lines...) Expand all
117 // already picked up a partition ID. Thus, we need to reset the initialization 76 // 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 77 // 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 78 // 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 79 // 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. 80 // that we don't end up allocating a second guest.
122 if (this.guestInstanceId) { 81 if (this.guestInstanceId) {
123 GuestViewInternal.destroyGuest(this.guestInstanceId); 82 GuestViewInternal.destroyGuest(this.guestInstanceId);
124 this.guestInstanceId = undefined; 83 this.guestInstanceId = undefined;
125 this.beforeFirstNavigation = true; 84 this.beforeFirstNavigation = true;
126 this.validPartitionId = true; 85 this.validPartitionId = true;
127 this.partition.validPartitionId = true; 86 this.attributes[WebViewConstants.ATTRIBUTE_PARTITION].validPartitionId =
87 true;
128 this.contentWindow = null; 88 this.contentWindow = null;
129 } 89 }
130 this.internalInstanceId = 0; 90 this.internalInstanceId = 0;
131 }; 91 };
132 92
133 // Sets the <webview>.request property. 93 // Sets the <webview>.request property.
134 WebView.prototype.setRequestPropertyOnWebViewNode = function(request) { 94 WebView.prototype.setRequestPropertyOnWebViewNode = function(request) {
135 Object.defineProperty( 95 Object.defineProperty(
136 this.webviewNode, 96 this.webviewNode,
137 'request', 97 'request',
(...skipping 24 matching lines...) Expand all
162 122
163 // Validation helper function for executeScript() and insertCSS(). 123 // Validation helper function for executeScript() and insertCSS().
164 WebView.prototype.validateExecuteCodeCall = function() { 124 WebView.prototype.validateExecuteCodeCall = function() {
165 if (!this.guestInstanceId) { 125 if (!this.guestInstanceId) {
166 throw new Error(WebViewConstants.ERROR_MSG_CANNOT_INJECT_SCRIPT); 126 throw new Error(WebViewConstants.ERROR_MSG_CANNOT_INJECT_SCRIPT);
167 } 127 }
168 }; 128 };
169 129
170 WebView.prototype.setupAutoSizeProperties = function() { 130 WebView.prototype.setupAutoSizeProperties = function() {
171 $Array.forEach(AUTO_SIZE_ATTRIBUTES, function(attributeName) { 131 $Array.forEach(AUTO_SIZE_ATTRIBUTES, function(attributeName) {
172 this[attributeName] = this.webviewNode.getAttribute(attributeName); 132 this.attributes[attributeName].setValue(
133 this.webviewNode.getAttribute(attributeName));
173 Object.defineProperty(this.webviewNode, attributeName, { 134 Object.defineProperty(this.webviewNode, attributeName, {
174 get: function() { 135 get: function() {
175 return this[attributeName]; 136 return this.attributes[attributeName].getValue();
176 }.bind(this), 137 }.bind(this),
177 set: function(value) { 138 set: function(value) {
178 this.webviewNode.setAttribute(attributeName, value); 139 this.webviewNode.setAttribute(attributeName, value);
179 }.bind(this), 140 }.bind(this),
180 enumerable: true 141 enumerable: true
181 }); 142 });
182 }.bind(this), this); 143 }.bind(this), this);
183 }; 144 };
184 145
185 WebView.prototype.setupWebviewNodeProperties = function() { 146 WebView.prototype.setupWebviewNodeProperties = function() {
186 this.setupAutoSizeProperties(); 147 this.setupAutoSizeProperties();
187 148
188 Object.defineProperty(this.webviewNode, 149 Object.defineProperty(this.webviewNode,
189 WebViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY, { 150 WebViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY, {
190 get: function() { 151 get: function() {
191 return this.allowtransparency; 152 return this.attributes[WebViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY].
153 getValue();
192 }.bind(this), 154 }.bind(this),
193 set: function(value) { 155 set: function(value) {
194 this.webviewNode.setAttribute( 156 this.webviewNode.setAttribute(
195 WebViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY, 157 WebViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY,
196 value); 158 value);
197 }.bind(this), 159 }.bind(this),
198 enumerable: true 160 enumerable: true
199 }); 161 });
200 162
201 // We cannot use {writable: true} property descriptor because we want a 163 // We cannot use {writable: true} property descriptor because we want a
202 // dynamic getter value. 164 // dynamic getter value.
203 Object.defineProperty(this.webviewNode, 'contentWindow', { 165 Object.defineProperty(this.webviewNode, 'contentWindow', {
204 get: function() { 166 get: function() {
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].setValue(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.
290 var autosize = this.webviewNode.hasAttribute( 256 var autosize = this.webviewNode.hasAttribute(
291 WebViewConstants.ATTRIBUTE_AUTOSIZE); 257 WebViewConstants.ATTRIBUTE_AUTOSIZE);
292 GuestViewInternal.setAutoSize(this.guestInstanceId, { 258 GuestViewInternal.setAutoSize(this.guestInstanceId, {
293 'enableAutoSize': autosize, 259 'enableAutoSize': autosize,
294 'min': { 260 'min': {
295 'width': parseInt(this.minwidth || 0), 261 'width': parseInt(this.
296 'height': parseInt(this.minheight || 0) 262 attributes[WebViewConstants.ATTRIBUTE_MINWIDTH].getValue() || 0),
263 'height': parseInt(this.
264 attributes[WebViewConstants.ATTRIBUTE_MINHEIGHT].getValue() || 0)
297 }, 265 },
298 'max': { 266 'max': {
299 'width': parseInt(this.maxwidth || 0), 267 'width': parseInt(this.
300 'height': parseInt(this.maxheight || 0) 268 attributes[WebViewConstants.ATTRIBUTE_MAXWIDTH].getValue() || 0),
269 'height': parseInt(this.
270 attributes[WebViewConstants.ATTRIBUTE_MAXHEIGHT].getValue() || 0)
301 } 271 }
302 }); 272 });
303 return; 273 return;
304 } else if (name == WebViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY) { 274 } else if (name == WebViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY) {
305 // We treat null attribute (attribute removed) and the empty string as 275 // We treat null attribute (attribute removed) and the empty string as
306 // one case. 276 // one case.
307 oldValue = oldValue || ''; 277 oldValue = oldValue || '';
308 newValue = newValue || ''; 278 newValue = newValue || '';
309 279
310 if (oldValue === newValue) { 280 if (oldValue === newValue) {
311 return; 281 return;
312 } 282 }
313 this.allowtransparency = newValue != ''; 283 this.attributes[WebViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY].
284 setValue(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(
320 this.allowtransparency); 291 this.guestInstanceId,
292 this.attributes[WebViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY].
293 getValue());
321 return; 294 return;
322 } else if (name == 'name') { 295 } else if (name == WebViewConstants.ATTRIBUTE_NAME) {
323 // We treat null attribute (attribute removed) and the empty string as 296 // We treat null attribute (attribute removed) and the empty string as
324 // one case. 297 // one case.
325 oldValue = oldValue || ''; 298 oldValue = oldValue || '';
326 newValue = newValue || ''; 299 newValue = newValue || '';
327 300
328 if (oldValue === newValue) { 301 if (oldValue === newValue) {
329 return; 302 return;
330 } 303 }
331 this.name = newValue; 304 this.attributes[WebViewConstants.ATTRIBUTE_NAME].setValue(newValue);
332 if (!this.guestInstanceId) { 305 if (!this.guestInstanceId) {
333 return; 306 return;
334 } 307 }
335 WebViewInternal.setName(this.guestInstanceId, newValue); 308 WebViewInternal.setName(this.guestInstanceId, newValue);
336 return; 309 return;
337 } else if (name == 'src') { 310 } else if (name == WebViewConstants.ATTRIBUTE_SRC) {
338 // We treat null attribute (attribute removed) and the empty string as 311 // We treat null attribute (attribute removed) and the empty string as
339 // one case. 312 // one case.
340 oldValue = oldValue || ''; 313 oldValue = oldValue || '';
341 newValue = newValue || ''; 314 newValue = newValue || '';
342 // Once we have navigated, we don't allow clearing the src attribute. 315 // 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 316 // Once <webview> enters a navigated state, it cannot be return back to a
344 // placeholder state. 317 // placeholder state.
345 if (newValue == '' && oldValue != '') { 318 if (newValue == '' && oldValue != '') {
346 // src attribute changes normally initiate a navigation. We suppress 319 // src attribute changes normally initiate a navigation. We suppress
347 // the next src attribute handler call to avoid reloading the page 320 // the next src attribute handler call to avoid reloading the page
348 // on every guest-initiated navigation. 321 // on every guest-initiated navigation.
349 this.ignoreNextSrcAttributeChange = true; 322 this.ignoreNextSrcAttributeChange = true;
350 this.webviewNode.setAttribute('src', oldValue); 323 this.webviewNode.setAttribute(WebViewConstants.ATTRIBUTE_SRC, oldValue);
351 return; 324 return;
352 } 325 }
353 this.src = newValue; 326 this.attributes[WebViewConstants.ATTRIBUTE_SRC].setValue(newValue);
354 if (this.ignoreNextSrcAttributeChange) { 327 if (this.ignoreNextSrcAttributeChange) {
355 // Don't allow the src mutation observer to see this change. 328 // Don't allow the src mutation observer to see this change.
356 this.srcAndPartitionObserver.takeRecords(); 329 this.srcAndPartitionObserver.takeRecords();
357 this.ignoreNextSrcAttributeChange = false; 330 this.ignoreNextSrcAttributeChange = false;
358 return; 331 return;
359 } 332 }
360 var result = {}; 333 var result = {};
361 this.parseSrcAttribute(result); 334 this.parseSrcAttribute(result);
362 335
363 if (result.error) { 336 if (result.error) {
364 throw result.error; 337 throw result.error;
365 } 338 }
366 } else if (name == 'partition') { 339 } else if (name == WebViewConstants.ATTRIBUTE_PARTITION) {
367 // Note that throwing error here won't synchronously propagate. 340 // Note that throwing error here won't synchronously propagate.
368 this.partition.fromAttribute(newValue, this.hasNavigated()); 341 this.attributes[WebViewConstants.ATTRIBUTE_PARTITION].setValue(newValue);
369 } 342 }
370 }; 343 };
371 344
372 WebView.prototype.handleBrowserPluginAttributeMutation = 345 WebView.prototype.handleBrowserPluginAttributeMutation =
373 function(name, oldValue, newValue) { 346 function(name, oldValue, newValue) {
374 if (name == 'internalinstanceid' && !oldValue && !!newValue) { 347 if (name == WebViewConstants.ATTRIBUTE_INTERNALINSTANCEID &&
375 this.browserPluginNode.removeAttribute('internalinstanceid'); 348 !oldValue && !!newValue) {
349 this.browserPluginNode.removeAttribute(
350 WebViewConstants.ATTRIBUTE_INTERNALINSTANCEID);
376 this.internalInstanceId = parseInt(newValue); 351 this.internalInstanceId = parseInt(newValue);
377 352
378 if (!!this.guestInstanceId && this.guestInstanceId != 0) { 353 if (!!this.guestInstanceId && this.guestInstanceId != 0) {
379 var isNewWindow = this.deferredAttachState ? 354 var isNewWindow = this.deferredAttachState ?
380 this.deferredAttachState.isNewWindow : false; 355 this.deferredAttachState.isNewWindow : false;
381 var params = this.buildAttachParams(isNewWindow); 356 var params = this.buildAttachParams(isNewWindow);
382 guestViewInternalNatives.AttachGuest( 357 guestViewInternalNatives.AttachGuest(
383 this.internalInstanceId, 358 this.internalInstanceId,
384 this.guestInstanceId, 359 this.guestInstanceId,
385 params, 360 params,
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
458 // Returns if <object> is in the render tree. 433 // Returns if <object> is in the render tree.
459 WebView.prototype.isPluginInRenderTree = function() { 434 WebView.prototype.isPluginInRenderTree = function() {
460 return !!this.internalInstanceId && this.internalInstanceId != 0; 435 return !!this.internalInstanceId && this.internalInstanceId != 0;
461 }; 436 };
462 437
463 WebView.prototype.hasNavigated = function() { 438 WebView.prototype.hasNavigated = function() {
464 return !this.beforeFirstNavigation; 439 return !this.beforeFirstNavigation;
465 }; 440 };
466 441
467 WebView.prototype.parseSrcAttribute = function(result) { 442 WebView.prototype.parseSrcAttribute = function(result) {
468 if (!this.partition.validPartitionId) { 443 if (!this.attributes[WebViewConstants.ATTRIBUTE_PARTITION].validPartitionId) {
469 result.error = WebViewConstants.ERROR_MSG_INVALID_PARTITION_ATTRIBUTE; 444 result.error = WebViewConstants.ERROR_MSG_INVALID_PARTITION_ATTRIBUTE;
470 return; 445 return;
471 } 446 }
472 this.src = this.webviewNode.getAttribute('src'); 447 this.attributes[WebViewConstants.ATTRIBUTE_SRC].setValue(
448 this.webviewNode.getAttribute(WebViewConstants.ATTRIBUTE_SRC));
473 449
474 if (!this.src) { 450 if (!this.attributes[WebViewConstants.ATTRIBUTE_SRC].getValue()) {
475 return; 451 return;
476 } 452 }
477 453
478 if (this.guestInstanceId == undefined) { 454 if (this.guestInstanceId == undefined) {
479 if (this.beforeFirstNavigation) { 455 if (this.beforeFirstNavigation) {
480 this.beforeFirstNavigation = false; 456 this.beforeFirstNavigation = false;
481 this.createGuest(); 457 this.createGuest();
482 } 458 }
483 return; 459 return;
484 } 460 }
485 461
486 // Navigate to |this.src|. 462 // Navigate to |this.src|.
487 WebViewInternal.navigate(this.guestInstanceId, this.src); 463 WebViewInternal.navigate(
464 this.guestInstanceId,
465 this.attributes[WebViewConstants.ATTRIBUTE_SRC].getValue());
488 }; 466 };
489 467
490 WebView.prototype.parseAttributes = function() { 468 WebView.prototype.parseAttributes = function() {
491 if (!this.elementAttached) { 469 if (!this.elementAttached) {
492 return; 470 return;
493 } 471 }
494 var hasNavigated = this.hasNavigated(); 472 var attributeValue = this.webviewNode.getAttribute(
495 var attributeValue = this.webviewNode.getAttribute('partition'); 473 WebViewConstants.ATTRIBUTE_PARTITION);
496 var result = this.partition.fromAttribute(attributeValue, hasNavigated); 474 var result = this.attributes[WebViewConstants.ATTRIBUTE_PARTITION].setValue(
475 attributeValue);
497 this.parseSrcAttribute(result); 476 this.parseSrcAttribute(result);
498 }; 477 };
499 478
500 WebView.prototype.createGuest = function() { 479 WebView.prototype.createGuest = function() {
501 if (this.pendingGuestCreation) { 480 if (this.pendingGuestCreation) {
502 return; 481 return;
503 } 482 }
504 var storagePartitionId = 483 var storagePartitionId =
505 this.webviewNode.getAttribute(WebViewConstants.ATTRIBUTE_PARTITION) || 484 this.webviewNode.getAttribute(WebViewConstants.ATTRIBUTE_PARTITION) ||
506 this.webviewNode[WebViewConstants.ATTRIBUTE_PARTITION]; 485 this.webviewNode[WebViewConstants.ATTRIBUTE_PARTITION];
507 var params = { 486 var params = {
508 'storagePartitionId': storagePartitionId 487 'storagePartitionId': storagePartitionId
509 }; 488 };
510 GuestViewInternal.createGuest( 489 GuestViewInternal.createGuest(
511 'webview', 490 'webview',
512 params, 491 params,
513 function(guestInstanceId) { 492 function(guestInstanceId) {
514 this.pendingGuestCreation = false; 493 this.pendingGuestCreation = false;
515 if (!this.elementAttached) { 494 if (!this.elementAttached) {
516 GuestViewInternal.destroyGuest(guestInstanceId); 495 GuestViewInternal.destroyGuest(guestInstanceId);
517 return; 496 return;
518 } 497 }
519 this.attachWindow(guestInstanceId, false); 498 this.attachWindow(guestInstanceId, false);
520 }.bind(this) 499 }.bind(this)
521 ); 500 );
522 this.pendingGuestCreation = true; 501 this.pendingGuestCreation = true;
523 }; 502 };
524 503
525 WebView.prototype.onFrameNameChanged = function(name) { 504 WebView.prototype.onFrameNameChanged = function(name) {
526 this.name = name || ''; 505 this.attributes[WebViewConstants.ATTRIBUTE_NAME].setValue(name || '');
527 if (this.name === '') { 506 if (this.attributes[WebViewConstants.ATTRIBUTE_NAME].getValue() === '') {
528 this.webviewNode.removeAttribute('name'); 507 this.webviewNode.removeAttribute(WebViewConstants.ATTRIBUTE_NAME);
529 } else { 508 } else {
530 this.webviewNode.setAttribute('name', this.name); 509 this.webviewNode.setAttribute(
510 WebViewConstants.ATTRIBUTE_NAME,
511 this.attributes[WebViewConstants.ATTRIBUTE_NAME].getValue());
531 } 512 }
532 }; 513 };
533 514
534 WebView.prototype.dispatchEvent = function(webViewEvent) { 515 WebView.prototype.dispatchEvent = function(webViewEvent) {
535 return this.webviewNode.dispatchEvent(webViewEvent); 516 return this.webviewNode.dispatchEvent(webViewEvent);
536 }; 517 };
537 518
538 // Adds an 'on<event>' property on the webview, which can be used to set/unset 519 // Adds an 'on<event>' property on the webview, which can be used to set/unset
539 // an event handler. 520 // an event handler.
540 WebView.prototype.setupEventProperty = function(eventName) { 521 WebView.prototype.setupEventProperty = function(eventName) {
(...skipping 14 matching lines...) Expand all
555 }; 536 };
556 537
557 // Updates state upon loadcommit. 538 // Updates state upon loadcommit.
558 WebView.prototype.onLoadCommit = function( 539 WebView.prototype.onLoadCommit = function(
559 baseUrlForDataUrl, currentEntryIndex, entryCount, 540 baseUrlForDataUrl, currentEntryIndex, entryCount,
560 processId, url, isTopLevel) { 541 processId, url, isTopLevel) {
561 this.baseUrlForDataUrl = baseUrlForDataUrl; 542 this.baseUrlForDataUrl = baseUrlForDataUrl;
562 this.currentEntryIndex = currentEntryIndex; 543 this.currentEntryIndex = currentEntryIndex;
563 this.entryCount = entryCount; 544 this.entryCount = entryCount;
564 this.processId = processId; 545 this.processId = processId;
565 var oldValue = this.webviewNode.getAttribute('src'); 546 var oldValue = this.webviewNode.getAttribute(WebViewConstants.ATTRIBUTE_SRC);
566 var newValue = url; 547 var newValue = url;
567 if (isTopLevel && (oldValue != newValue)) { 548 if (isTopLevel && (oldValue != newValue)) {
568 // Touching the src attribute triggers a navigation. To avoid 549 // Touching the src attribute triggers a navigation. To avoid
569 // triggering a page reload on every guest-initiated navigation, 550 // triggering a page reload on every guest-initiated navigation,
570 // we use the flag ignoreNextSrcAttributeChange here. 551 // we use the flag ignoreNextSrcAttributeChange here.
571 this.ignoreNextSrcAttributeChange = true; 552 this.ignoreNextSrcAttributeChange = true;
572 this.webviewNode.setAttribute('src', newValue); 553 this.webviewNode.setAttribute(WebViewConstants.ATTRIBUTE_SRC, newValue);
573 } 554 }
574 }; 555 };
575 556
576 WebView.prototype.onAttach = function(storagePartitionId) { 557 WebView.prototype.onAttach = function(storagePartitionId) {
577 this.webviewNode.setAttribute('partition', storagePartitionId); 558 this.webviewNode.setAttribute(WebViewConstants.ATTRIBUTE_PARTITION,
578 this.partition.fromAttribute(storagePartitionId, this.hasNavigated()); 559 storagePartitionId);
560 this.attributes[WebViewConstants.ATTRIBUTE_PARTITION].setValue(
561 storagePartitionId);
579 }; 562 };
580 563
581 WebView.prototype.buildAttachParams = function(isNewWindow) { 564 WebView.prototype.buildAttachParams = function(isNewWindow) {
582 var params = { 565 var params = {
583 'allowtransparency': this.allowtransparency || false, 566 'allowtransparency': this.attributes[
567 WebViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY].getValue() || false,
584 'autosize': this.webviewNode.hasAttribute( 568 'autosize': this.webviewNode.hasAttribute(
585 WebViewConstants.ATTRIBUTE_AUTOSIZE), 569 WebViewConstants.ATTRIBUTE_AUTOSIZE),
586 'instanceId': this.viewInstanceId, 570 'instanceId': this.viewInstanceId,
587 'maxheight': parseInt(this.maxheight || 0), 571 'maxheight': parseInt(this.attributes[WebViewConstants.ATTRIBUTE_MAXHEIGHT].
588 'maxwidth': parseInt(this.maxwidth || 0), 572 getValue() || 0),
589 'minheight': parseInt(this.minheight || 0), 573 'maxwidth': parseInt(this.attributes[WebViewConstants.ATTRIBUTE_MAXWIDTH].
590 'minwidth': parseInt(this.minwidth || 0), 574 getValue() || 0),
591 'name': this.name, 575 'minheight': parseInt(this.attributes[WebViewConstants.ATTRIBUTE_MINHEIGHT].
576 getValue() || 0),
577 'minwidth': parseInt(this.attributes[WebViewConstants.ATTRIBUTE_MINWIDTH].
578 getValue() || 0),
579 'name': this.attributes[WebViewConstants.ATTRIBUTE_NAME].getValue(),
592 // We don't need to navigate new window from here. 580 // We don't need to navigate new window from here.
593 'src': isNewWindow ? undefined : this.src, 581 'src': isNewWindow ? undefined :
582 this.attributes[WebViewConstants.ATTRIBUTE_SRC].getValue(),
594 // If we have a partition from the opener, that will also be already 583 // If we have a partition from the opener, that will also be already
595 // set via this.onAttach(). 584 // set via this.onAttach().
596 'storagePartitionId': this.partition.toAttribute(), 585 'storagePartitionId': this.attributes[WebViewConstants.ATTRIBUTE_PARTITION].
586 getValue(),
597 'userAgentOverride': this.userAgentOverride 587 'userAgentOverride': this.userAgentOverride
598 }; 588 };
599 return params; 589 return params;
600 }; 590 };
601 591
602 WebView.prototype.attachWindow = function(guestInstanceId, 592 WebView.prototype.attachWindow = function(guestInstanceId,
603 isNewWindow) { 593 isNewWindow) {
604 this.guestInstanceId = guestInstanceId; 594 this.guestInstanceId = guestInstanceId;
605 var params = this.buildAttachParams(isNewWindow); 595 var params = this.buildAttachParams(isNewWindow);
606 596
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
644 if (!this.guestInstanceId) { 634 if (!this.guestInstanceId) {
645 return; 635 return;
646 } 636 }
647 var args = $Array.concat([this.guestInstanceId], $Array.slice(arguments)); 637 var args = $Array.concat([this.guestInstanceId], $Array.slice(arguments));
648 $Function.apply(WebViewInternal.clearData, null, args); 638 $Function.apply(WebViewInternal.clearData, null, args);
649 }; 639 };
650 640
651 // Injects JavaScript code into the guest page. 641 // Injects JavaScript code into the guest page.
652 WebView.prototype.executeScript = function(var_args) { 642 WebView.prototype.executeScript = function(var_args) {
653 this.validateExecuteCodeCall(); 643 this.validateExecuteCodeCall();
654 var webviewSrc = this.src; 644 var webviewSrc = this.attributes[WebViewConstants.ATTRIBUTE_SRC].getValue();
655 if (this.baseUrlForDataUrl != '') { 645 if (this.baseUrlForDataUrl != '') {
656 webviewSrc = this.baseUrlForDataUrl; 646 webviewSrc = this.baseUrlForDataUrl;
657 } 647 }
658 var args = $Array.concat([this.guestInstanceId, webviewSrc], 648 var args = $Array.concat([this.guestInstanceId, webviewSrc],
659 $Array.slice(arguments)); 649 $Array.slice(arguments));
660 $Function.apply(WebViewInternal.executeScript, null, args); 650 $Function.apply(WebViewInternal.executeScript, null, args);
661 }; 651 };
662 652
663 // Initiates a find-in-page request. 653 // Initiates a find-in-page request.
664 WebView.prototype.find = function(search_text, options, callback) { 654 WebView.prototype.find = function(search_text, options, callback) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
697 WebView.prototype.go = function(relativeIndex, callback) { 687 WebView.prototype.go = function(relativeIndex, callback) {
698 if (!this.guestInstanceId) { 688 if (!this.guestInstanceId) {
699 return; 689 return;
700 } 690 }
701 WebViewInternal.go(this.guestInstanceId, relativeIndex, callback); 691 WebViewInternal.go(this.guestInstanceId, relativeIndex, callback);
702 }; 692 };
703 693
704 // Injects CSS into the guest page. 694 // Injects CSS into the guest page.
705 WebView.prototype.insertCSS = function(var_args) { 695 WebView.prototype.insertCSS = function(var_args) {
706 this.validateExecuteCodeCall(); 696 this.validateExecuteCodeCall();
707 var webviewSrc = this.src; 697 var webviewSrc = this.attributes[WebViewConstants.ATTRIBUTE_SRC].getValue();
708 if (this.baseUrlForDataUrl != '') { 698 if (this.baseUrlForDataUrl != '') {
709 webviewSrc = this.baseUrlForDataUrl; 699 webviewSrc = this.baseUrlForDataUrl;
710 } 700 }
711 var args = $Array.concat([this.guestInstanceId, webviewSrc], 701 var args = $Array.concat([this.guestInstanceId, webviewSrc],
712 $Array.slice(arguments)); 702 $Array.slice(arguments));
713 $Function.apply(WebViewInternal.insertCSS, null, args); 703 $Function.apply(WebViewInternal.insertCSS, null, args);
714 }; 704 };
715 705
716 // Indicates whether or not the webview's user agent string has been overridden. 706 // Indicates whether or not the webview's user agent string has been overridden.
717 WebView.prototype.isUserAgentOverridden = function() { 707 WebView.prototype.isUserAgentOverridden = function() {
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
913 WebView.prototype.maybeGetChromeWebViewEvents = function() {}; 903 WebView.prototype.maybeGetChromeWebViewEvents = function() {};
914 904
915 // Implemented when the experimental WebView API is available. 905 // Implemented when the experimental WebView API is available.
916 WebView.maybeGetExperimentalAPIs = function() {}; 906 WebView.maybeGetExperimentalAPIs = function() {};
917 WebView.prototype.maybeGetExperimentalEvents = function() {}; 907 WebView.prototype.maybeGetExperimentalEvents = function() {};
918 WebView.prototype.setupExperimentalContextMenus = function() {}; 908 WebView.prototype.setupExperimentalContextMenus = function() {};
919 909
920 // Exports. 910 // Exports.
921 exports.WebView = WebView; 911 exports.WebView = WebView;
922 exports.WebViewInternal = WebViewInternal; 912 exports.WebViewInternal = WebViewInternal;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698