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

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

Issue 299753011: Move allocate instance id to chrome/. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: address comments Created 6 years, 6 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 EventBindings = require('event_bindings'); 10 var EventBindings = require('event_bindings');
11 var GuestView = require('binding').Binding.create('guestview').generate();
11 var IdGenerator = requireNative('id_generator'); 12 var IdGenerator = requireNative('id_generator');
12 var MessagingNatives = requireNative('messaging_natives'); 13 var MessagingNatives = requireNative('messaging_natives');
13 var WebRequestEvent = require('webRequestInternal').WebRequestEvent; 14 var WebRequestEvent = require('webRequestInternal').WebRequestEvent;
14 var WebRequestSchema = 15 var WebRequestSchema =
15 requireNative('schema_registry').GetSchema('webRequest'); 16 requireNative('schema_registry').GetSchema('webRequest');
16 var DeclarativeWebRequestSchema = 17 var DeclarativeWebRequestSchema =
17 requireNative('schema_registry').GetSchema('declarativeWebRequest'); 18 requireNative('schema_registry').GetSchema('declarativeWebRequest');
18 var WebView = require('webview').WebView; 19 var WebView = require('webview').WebView;
19 20
20 var WEB_VIEW_ATTRIBUTE_MAXHEIGHT = 'maxheight'; 21 var WEB_VIEW_ATTRIBUTE_MAXHEIGHT = 'maxheight';
21 var WEB_VIEW_ATTRIBUTE_MAXWIDTH = 'maxwidth'; 22 var WEB_VIEW_ATTRIBUTE_MAXWIDTH = 'maxwidth';
22 var WEB_VIEW_ATTRIBUTE_MINHEIGHT = 'minheight'; 23 var WEB_VIEW_ATTRIBUTE_MINHEIGHT = 'minheight';
23 var WEB_VIEW_ATTRIBUTE_MINWIDTH = 'minwidth'; 24 var WEB_VIEW_ATTRIBUTE_MINWIDTH = 'minwidth';
25 var WEB_VIEW_ATTRIBUTE_PARTITION = 'partition';
26
27 var ERROR_MSG_ALREADY_NAVIGATED =
28 'The object has already navigated, so its partition cannot be changed.';
29 var ERROR_MSG_INVALID_PARTITION_ATTRIBUTE =
30 'Invalid partition attribute.';
31
32 var LOG = function(msg) {
33 window.console.log(msg);
34 };
24 35
25 /** @type {Array.<string>} */ 36 /** @type {Array.<string>} */
26 var WEB_VIEW_ATTRIBUTES = [ 37 var WEB_VIEW_ATTRIBUTES = [
27 'allowtransparency', 38 'allowtransparency',
28 'autosize', 39 'autosize',
29 'partition',
30 WEB_VIEW_ATTRIBUTE_MINHEIGHT, 40 WEB_VIEW_ATTRIBUTE_MINHEIGHT,
31 WEB_VIEW_ATTRIBUTE_MINWIDTH, 41 WEB_VIEW_ATTRIBUTE_MINWIDTH,
32 WEB_VIEW_ATTRIBUTE_MAXHEIGHT, 42 WEB_VIEW_ATTRIBUTE_MAXHEIGHT,
33 WEB_VIEW_ATTRIBUTE_MAXWIDTH 43 WEB_VIEW_ATTRIBUTE_MAXWIDTH
34 ]; 44 ];
35 45
46 /** @class representing state of storage partition. */
47 function Partition() {
48 this.validPartitionId_ = true;
49 this.persist_storage_ = false;
50 this.storage_partition_id_ = '';
51 };
52
53 Partition.prototype.toAttribute = function() {
54 LOG('Partition.toAttribute');
55 if (!this.validPartitionId_) {
56 LOG('Warning we have invalid partition id');
57 return '';
58 }
59 return (this.persist_storage_ ? 'persist:' : '') + this.storage_partition_id_;
60 };
61
62 Partition.prototype.fromAttribute = function(value, hasNavigated) {
63 LOG('Partition.fromAttribute');
64 LOG('value: ' + value + ', hasNavigated: ' + hasNavigated);
65 var result = {};
66 if (hasNavigated) {
67 result.error = ERROR_MSG_ALREADY_NAVIGATED;
68 return result;
69 }
70 if (!value) {
71 LOG('Partition.fromAttribute got empty value');
72 value = '';
73 }
74
75 var LEN = 'persist:'.length;
76 if (value.substr(0, LEN) == 'persist:') {
77 value = value.substr(LEN);
78 if (!value) {
79 this.validPartitionId_ = false;
80 result.error = ERROR_MSG_INVALID_PARTITION_ATTRIBUTE;
81 return result;
82 }
83 this.persist_storage_ = true;
84 } else {
85 this.persist_storage_ = false;
86 }
87
88 this.storage_partition_id_ = value;
89 return result;
90 };
91
36 var CreateEvent = function(name) { 92 var CreateEvent = function(name) {
37 var eventOpts = {supportsListeners: true, supportsFilters: true}; 93 var eventOpts = {supportsListeners: true, supportsFilters: true};
38 return new EventBindings.Event(name, undefined, eventOpts); 94 return new EventBindings.Event(name, undefined, eventOpts);
39 }; 95 };
40 96
41 // WEB_VIEW_EVENTS is a map of stable <webview> DOM event names to their 97 // WEB_VIEW_EVENTS is a map of stable <webview> DOM event names to their
42 // associated extension event descriptor objects. 98 // associated extension event descriptor objects.
43 // An event listener will be attached to the extension event |evt| specified in 99 // An event listener will be attached to the extension event |evt| specified in
44 // the descriptor. 100 // the descriptor.
45 // |fields| specifies the public-facing fields in the DOM event that are 101 // |fields| specifies the public-facing fields in the DOM event that are
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 } 222 }
167 }; 223 };
168 224
169 // Implemented when the experimental API is available. 225 // Implemented when the experimental API is available.
170 WebViewInternal.maybeRegisterExperimentalAPIs = function(proto) {} 226 WebViewInternal.maybeRegisterExperimentalAPIs = function(proto) {}
171 227
172 /** 228 /**
173 * @constructor 229 * @constructor
174 */ 230 */
175 function WebViewInternal(webviewNode) { 231 function WebViewInternal(webviewNode) {
232 LOG('WebViewInternal.constructor');
176 privates(webviewNode).internal = this; 233 privates(webviewNode).internal = this;
177 this.webviewNode = webviewNode; 234 this.webviewNode = webviewNode;
178 this.attached = false; 235 this.attached = false;
236
237 this.beforeFirstNavigation_ = true;
Fady Samuel 2014/05/29 20:35:23 We haven't been using _ for privates now. Let's dr
lazyboy 2014/05/30 05:48:21 Ya, underscores are supposed to be for privates ac
238 this.validPartitionId_ = true;
239
179 this.browserPluginNode = this.createBrowserPluginNode(); 240 this.browserPluginNode = this.createBrowserPluginNode();
180 var shadowRoot = this.webviewNode.createShadowRoot(); 241 var shadowRoot = this.webviewNode.createShadowRoot();
181 shadowRoot.appendChild(this.browserPluginNode); 242 shadowRoot.appendChild(this.browserPluginNode);
182 243
183 this.setupWebviewNodeAttributes(); 244 this.setupWebviewNodeAttributes();
184 this.setupFocusPropagation(); 245 this.setupFocusPropagation();
185 this.setupWebviewNodeProperties(); 246 this.setupWebviewNodeProperties();
247
248 this.viewInstanceId = IdGenerator.GetNextId();
249
250 //this.allocateInstanceId();
251 this.partition_ = new Partition();
252 this.parseAttributes();
253
186 this.setupWebviewNodeEvents(); 254 this.setupWebviewNodeEvents();
187 } 255 }
188 256
189 /** 257 /**
190 * @private 258 * @private
191 */ 259 */
192 WebViewInternal.prototype.createBrowserPluginNode = function() { 260 WebViewInternal.prototype.createBrowserPluginNode = function() {
193 // We create BrowserPlugin as a custom element in order to observe changes 261 // We create BrowserPlugin as a custom element in order to observe changes
194 // to attributes synchronously. 262 // to attributes synchronously.
195 var browserPluginNode = new WebViewInternal.BrowserPlugin(); 263 var browserPluginNode = new WebViewInternal.BrowserPlugin();
196 privates(browserPluginNode).internal = this; 264 privates(browserPluginNode).internal = this;
197 265
198 var ALL_ATTRIBUTES = WEB_VIEW_ATTRIBUTES.concat(['src']); 266 $Array.forEach(WEB_VIEW_ATTRIBUTES, function(attributeName) {
199 $Array.forEach(ALL_ATTRIBUTES, function(attributeName) {
200 // Only copy attributes that have been assigned values, rather than copying 267 // Only copy attributes that have been assigned values, rather than copying
201 // a series of undefined attributes to BrowserPlugin. 268 // a series of undefined attributes to BrowserPlugin.
202 if (this.webviewNode.hasAttribute(attributeName)) { 269 if (this.webviewNode.hasAttribute(attributeName)) {
203 browserPluginNode.setAttribute( 270 browserPluginNode.setAttribute(
204 attributeName, this.webviewNode.getAttribute(attributeName)); 271 attributeName, this.webviewNode.getAttribute(attributeName));
205 } else if (this.webviewNode[attributeName]){ 272 } else if (this.webviewNode[attributeName]){
206 // Reading property using has/getAttribute does not work on 273 // Reading property using has/getAttribute does not work on
207 // document.DOMContentLoaded event (but works on 274 // document.DOMContentLoaded event (but works on
208 // window.DOMContentLoaded event). 275 // window.DOMContentLoaded event).
209 // So copy from property if copying from attribute fails. 276 // So copy from property if copying from attribute fails.
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 Object.defineProperty(this.webviewNode, 'name', { 459 Object.defineProperty(this.webviewNode, 'name', {
393 get: function() { 460 get: function() {
394 return self.name; 461 return self.name;
395 }, 462 },
396 set: function(value) { 463 set: function(value) {
397 self.webviewNode.setAttribute('name', value); 464 self.webviewNode.setAttribute('name', value);
398 }, 465 },
399 enumerable: true 466 enumerable: true
400 }); 467 });
401 468
469 Object.defineProperty(this.webviewNode, 'partition', {
470 get: function() {
471 window.console.log('getter.partition');
472 var ret = self.partition_.toAttribute();
473 window.console.log('returning: ' + ret);
474 return ret;
475 },
476 set: function(value) {
477 window.console.log('setter.partition, value: ' + value);
478 var result = self.partition_.fromAttribute(value, self.hasNavigated());
479 if (result.error) {
480 throw result.error;
481 }
482 self.webviewNode.setAttribute('partition', value);
483
484 // TODO(lazyboy): CanRemovePartitionAttribute() when removeAttribute().
485 },
486 enumerable: true
487 });
488
402 // We cannot use {writable: true} property descriptor because we want a 489 // We cannot use {writable: true} property descriptor because we want a
403 // dynamic getter value. 490 // dynamic getter value.
404 Object.defineProperty(this.webviewNode, 'contentWindow', { 491 Object.defineProperty(this.webviewNode, 'contentWindow', {
405 get: function() { 492 get: function() {
406 if (browserPluginNode.contentWindow) 493 if (browserPluginNode.contentWindow)
407 return browserPluginNode.contentWindow; 494 return browserPluginNode.contentWindow;
408 window.console.error(ERROR_MSG_CONTENTWINDOW_NOT_AVAILABLE); 495 window.console.error(ERROR_MSG_CONTENTWINDOW_NOT_AVAILABLE);
409 }, 496 },
410 // No setter. 497 // No setter.
411 enumerable: true 498 enumerable: true
(...skipping 10 matching lines...) Expand all
422 /** 509 /**
423 * @private 510 * @private
424 */ 511 */
425 WebViewInternal.prototype.setupWebViewSrcAttributeMutationObserver = 512 WebViewInternal.prototype.setupWebViewSrcAttributeMutationObserver =
426 function() { 513 function() {
427 // The purpose of this mutation observer is to catch assignment to the src 514 // The purpose of this mutation observer is to catch assignment to the src
428 // attribute without any changes to its value. This is useful in the case 515 // attribute without any changes to its value. This is useful in the case
429 // where the webview guest has crashed and navigating to the same address 516 // where the webview guest has crashed and navigating to the same address
430 // spawns off a new process. 517 // spawns off a new process.
431 var self = this; 518 var self = this;
432 this.srcObserver = new MutationObserver(function(mutations) { 519 this.srcAndPartitionObserver = new MutationObserver(function(mutations) {
433 $Array.forEach(mutations, function(mutation) { 520 $Array.forEach(mutations, function(mutation) {
434 var oldValue = mutation.oldValue; 521 var oldValue = mutation.oldValue;
435 var newValue = self.webviewNode.getAttribute(mutation.attributeName); 522 var newValue = self.webviewNode.getAttribute(mutation.attributeName);
436 if (oldValue != newValue) { 523 if (oldValue != newValue) {
437 return; 524 return;
438 } 525 }
439 self.handleWebviewAttributeMutation( 526 self.handleWebviewAttributeMutation(
440 mutation.attributeName, oldValue, newValue); 527 mutation.attributeName, oldValue, newValue);
441 }); 528 });
442 }); 529 });
443 var params = { 530 var params = {
444 attributes: true, 531 attributes: true,
445 attributeOldValue: true, 532 attributeOldValue: true,
446 attributeFilter: ['src'] 533 attributeFilter: ['src', 'partition']
447 }; 534 };
448 this.srcObserver.observe(this.webviewNode, params); 535 this.srcAndPartitionObserver.observe(this.webviewNode, params);
449 }; 536 };
450 537
451 /** 538 /**
452 * @private 539 * @private
453 */ 540 */
454 WebViewInternal.prototype.handleWebviewAttributeMutation = 541 WebViewInternal.prototype.handleWebviewAttributeMutation =
455 function(name, oldValue, newValue) { 542 function(name, oldValue, newValue) {
543 window.console.log('handleWebviewAttributeMutation, name = ' + name);
456 // This observer monitors mutations to attributes of the <webview> and 544 // This observer monitors mutations to attributes of the <webview> and
457 // updates the BrowserPlugin properties accordingly. In turn, updating 545 // updates the BrowserPlugin properties accordingly. In turn, updating
458 // a BrowserPlugin property will update the corresponding BrowserPlugin 546 // a BrowserPlugin property will update the corresponding BrowserPlugin
459 // attribute, if necessary. See BrowserPlugin::UpdateDOMAttribute for more 547 // attribute, if necessary. See BrowserPlugin::UpdateDOMAttribute for more
460 // details. 548 // details.
461 if (name == 'name') { 549 if (name == 'name') {
462 // We treat null attribute (attribute removed) and the empty string as 550 // We treat null attribute (attribute removed) and the empty string as
463 // one case. 551 // one case.
464 oldValue = oldValue || ''; 552 oldValue = oldValue || '';
465 newValue = newValue || ''; 553 newValue = newValue || '';
466 554
467 if (oldValue === newValue) { 555 if (oldValue === newValue) {
468 return; 556 return;
469 } 557 }
470 this.name = newValue; 558 this.name = newValue;
471 if (!this.instanceId) { 559 if (!this.instanceId) {
472 return; 560 return;
473 } 561 }
474 WebView.setName(this.instanceId, newValue); 562 WebView.setName(this.instanceId, newValue);
475 return; 563 return;
476 } else if (name == 'src') { 564 } else if (name == 'src') {
477 // We treat null attribute (attribute removed) and the empty string as 565 // We treat null attribute (attribute removed) and the empty string as
478 // one case. 566 // one case.
479 oldValue = oldValue || ''; 567 oldValue = oldValue || '';
480 newValue = newValue || ''; 568 newValue = newValue || '';
569 LOG('WebViewInternal.handleWebviewAttributeMutation, old = ' + oldValue + ', new = ' + newValue);
481 // Once we have navigated, we don't allow clearing the src attribute. 570 // Once we have navigated, we don't allow clearing the src attribute.
482 // Once <webview> enters a navigated state, it cannot be return back to a 571 // Once <webview> enters a navigated state, it cannot be return back to a
483 // placeholder state. 572 // placeholder state.
484 if (newValue == '' && oldValue != '') { 573 if (newValue == '' && oldValue != '') {
485 // src attribute changes normally initiate a navigation. We suppress 574 // src attribute changes normally initiate a navigation. We suppress
486 // the next src attribute handler call to avoid reloading the page 575 // the next src attribute handler call to avoid reloading the page
487 // on every guest-initiated navigation. 576 // on every guest-initiated navigation.
488 this.ignoreNextSrcAttributeChange = true; 577 this.ignoreNextSrcAttributeChange = true;
489 this.webviewNode.setAttribute('src', oldValue); 578 this.webviewNode.setAttribute('src', oldValue);
490 return; 579 return;
491 } 580 }
492 this.src = newValue; 581 this.src = newValue;
493 if (this.ignoreNextSrcAttributeChange) { 582 if (this.ignoreNextSrcAttributeChange) {
494 // Don't allow the src mutation observer to see this change. 583 // Don't allow the src mutation observer to see this change.
495 this.srcObserver.takeRecords(); 584 this.srcAndPartitionObserver.takeRecords();
496 this.ignoreNextSrcAttributeChange = false; 585 this.ignoreNextSrcAttributeChange = false;
497 return; 586 return;
498 } 587 }
588 LOG('srcAttributeChanged');
589 var result = {};
590 this.parseSrcAttribute(result);
591
592 if (result.error) {
593 throw result.error;
594 }
595 } else if (name == 'partition') {
596 LOG('handleWebviewAttributeMutation.partition');
597 LOG('newValue: ' + newValue + ', oldValue: ' + oldValue);
598 // TODO(lazyboy): Do we do extra work here if we get here from
599 // Object.set.partition?
600 this.partition_.fromAttribute(newValue, this.hasNavigated());
499 } 601 }
500 if (this.browserPluginNode.hasOwnProperty(name)) { 602
501 this.browserPluginNode[name] = newValue; 603 // No <webview> -> <object> mutation propagation for these attributes.
502 } else { 604 if (name != 'src' && name != 'partition') {
503 this.browserPluginNode.setAttribute(name, newValue); 605 if (this.browserPluginNode.hasOwnProperty(name)) {
606 this.browserPluginNode[name] = newValue;
607 } else {
608 this.browserPluginNode.setAttribute(name, newValue);
609 }
504 } 610 }
505 }; 611 };
506 612
507 /** 613 /**
508 * @private 614 * @private
509 */ 615 */
510 WebViewInternal.prototype.handleBrowserPluginAttributeMutation = 616 WebViewInternal.prototype.handleBrowserPluginAttributeMutation =
511 function(name, newValue) { 617 function(name, newValue) {
618 if (name == 'src') {
619 // name == 'src' here implies autoNavigate = true;
620 this.autoNavigate_ = true;
621 this.partition_.fromAttribute('persist:custom_plugin', this.hasNavigated());
622 }
623
512 // This observer monitors mutations to attributes of the BrowserPlugin and 624 // This observer monitors mutations to attributes of the BrowserPlugin and
513 // updates the <webview> attributes accordingly. 625 // updates the <webview> attributes accordingly.
514 // |newValue| is null if the attribute |name| has been removed. 626 // |newValue| is null if the attribute |name| has been removed.
515 if (newValue != null) { 627 if (newValue != null) {
516 // Update the <webview> attribute to match the BrowserPlugin attribute. 628 // Update the <webview> attribute to match the BrowserPlugin attribute.
517 // Note: Calling setAttribute on <webview> will trigger its mutation 629 // Note: Calling setAttribute on <webview> will trigger its mutation
518 // observer which will then propagate that attribute to BrowserPlugin. In 630 // observer which will then propagate that attribute to BrowserPlugin. In
519 // cases where we permit assigning a BrowserPlugin attribute the same value 631 // cases where we permit assigning a BrowserPlugin attribute the same value
520 // again (such as navigation when crashed), this could end up in an infinite 632 // again (such as navigation when crashed), this could end up in an infinite
521 // loop. Thus, we avoid this loop by only updating the <webview> attribute 633 // loop. Thus, we avoid this loop by only updating the <webview> attribute
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 if (webViewEvent.newWidth >= minWidth && 702 if (webViewEvent.newWidth >= minWidth &&
591 webViewEvent.newWidth <= maxWidth && 703 webViewEvent.newWidth <= maxWidth &&
592 webViewEvent.newHeight >= minHeight && 704 webViewEvent.newHeight >= minHeight &&
593 webViewEvent.newHeight <= maxHeight) { 705 webViewEvent.newHeight <= maxHeight) {
594 node.style.width = webViewEvent.newWidth + 'px'; 706 node.style.width = webViewEvent.newWidth + 'px';
595 node.style.height = webViewEvent.newHeight + 'px'; 707 node.style.height = webViewEvent.newHeight + 'px';
596 } 708 }
597 node.dispatchEvent(webViewEvent); 709 node.dispatchEvent(webViewEvent);
598 }; 710 };
599 711
712 WebViewInternal.prototype.hasNavigated = function() {
713 return !this.beforeFirstNavigation_;
714 };
715
716 /** @return {boolean} */
717 WebViewInternal.prototype.parseSrcAttribute = function(result) {
718 LOG('parseSrcAttribute');
719 if (!this.partition_.validPartitionId_) {
720 LOG('ERROR_MSG_INVALID_PARTITION_ATTRIBUTE');
721 result.error = ERROR_MSG_INVALID_PARTITION_ATTRIBUTE;
722 return false;
723 }
724
725 this.src = this.webviewNode.getAttribute('src');
726 LOG('parseSrcAttribute, srcAttribute: ' + this.src);
727
728 if (!this.src) {
729 LOG('src empty');
730 return true;
731 }
732
733 LOG('hasGuestInstanceID: ' + this.hasGuestInstanceID());
734 LOG('beforeFirstNavigation_: ' + this.beforeFirstNavigation_);
735 if (!this.hasGuestInstanceID()) {
736 if (this.beforeFirstNavigation_) {
737 this.beforeFirstNavigation_ = false;
738 this.allocateInstanceId();
739 }
740 return true;
741 }
742
743 LOG('Webview.navigate, i: ' + this.instanceId + ', src = ' + this.src);
744
745 // Navigate to this.src.
746 WebView.navigate(this.instanceId, this.src);
747 return true;
748 };
749
750 /** @return {boolean} */
751 WebViewInternal.prototype.parseAttributes = function() {
752 LOG('parseAttributes');
753 var hasNavigated = this.hasNavigated();
754
755 var attributeValue = this.webviewNode.getAttribute('partition');
756 LOG('parseAttributes, partition.ttributeValue: ' + attributeValue);
757 var result = this.partition_.fromAttribute(attributeValue, hasNavigated);
758 return this.parseSrcAttribute(result);
759 };
760
761 WebViewInternal.prototype.hasGuestInstanceID = function() {
762 return this.instanceId != undefined;
763 };
764
765 WebViewInternal.prototype.allocateInstanceId = function() {
766 LOG('allocateInstanceId');
767 //this.viewInstanceId = IdGenerator.GetNextId();
768 LOG('cur partition: ' + this.webviewNode.getAttribute('partition'));
769 LOG('cur partition prop: ' + this.webviewNode['partition']);
770
771 // Parse .src and .partition.
772
773 var self = this;
774 GuestView.allocateInstanceId(
775 'webview',
776 this.viewInstanceId,
777 function(info) {
778 LOG('allocateInstanceId.callback.info: ' + info);
779 self.instanceId = info;
780 // TODO(lazyboy): Make sure this.autoNavigate_ stuff correctly updated
781 // |self.src| at this point.
782 self.attachWindowAndSetUpEvents(self.instanceId, self.src);
783 });
784 };
785
600 /** 786 /**
601 * @private 787 * @private
602 */ 788 */
603 WebViewInternal.prototype.setupWebviewNodeEvents = function() { 789 WebViewInternal.prototype.setupWebviewNodeEvents = function() {
604 var self = this;
605 this.viewInstanceId = IdGenerator.GetNextId();
606 var onInstanceIdAllocated = function(e) {
607 var detail = e.detail ? JSON.parse(e.detail) : {};
608 self.attachWindowAndSetUpEvents(detail.windowId);
609 };
610 this.browserPluginNode.addEventListener('-internal-instanceid-allocated',
611 onInstanceIdAllocated);
612 this.setupWebRequestEvents(); 790 this.setupWebRequestEvents();
613 this.setupExperimentalContextMenus_(); 791 this.setupExperimentalContextMenus_();
614 792
615 this.on = {}; 793 this.on = {};
616 var events = self.getEvents(); 794 var events = this.getEvents();
617 for (var eventName in events) { 795 for (var eventName in events) {
618 this.setupEventProperty(eventName); 796 this.setupEventProperty(eventName);
619 } 797 }
620 }; 798 };
621 799
622 /** 800 /**
623 * @private 801 * @private
624 */ 802 */
625 WebViewInternal.prototype.setupNameAttribute = function() { 803 WebViewInternal.prototype.setupNameAttribute = function() {
626 var self = this; 804 var self = this;
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
838 validateCall(); 1016 validateCall();
839 if (!webview || !webview.tagName || webview.tagName != 'WEBVIEW') 1017 if (!webview || !webview.tagName || webview.tagName != 'WEBVIEW')
840 throw new Error(ERROR_MSG_WEBVIEW_EXPECTED); 1018 throw new Error(ERROR_MSG_WEBVIEW_EXPECTED);
841 // Attach happens asynchronously to give the tagWatcher an opportunity 1019 // Attach happens asynchronously to give the tagWatcher an opportunity
842 // to pick up the new webview before attach operates on it, if it hasn't 1020 // to pick up the new webview before attach operates on it, if it hasn't
843 // been attached to the DOM already. 1021 // been attached to the DOM already.
844 // Note: Any subsequent errors cannot be exceptions because they happen 1022 // Note: Any subsequent errors cannot be exceptions because they happen
845 // asynchronously. 1023 // asynchronously.
846 setTimeout(function() { 1024 setTimeout(function() {
847 var webViewInternal = privates(webview).internal; 1025 var webViewInternal = privates(webview).internal;
1026 LOG('=== Attach w/o a src');
1027
1028 if (event.storagePartitionId) {
1029 LOG('read partition string: ' + event.storagePartitionId);
1030 webViewInternal.webviewNode.setAttribute(
1031 'partition', event.storagePartitionId);
1032 var partition = new Partition();
1033 partition.fromAttribute(event.storagePartitionId,
1034 webViewInternal.hasNavigated());
1035 webViewInternal.partition_ = partition;
1036 }
1037
848 var attached = 1038 var attached =
849 webViewInternal.attachWindowAndSetUpEvents(event.windowId); 1039 webViewInternal.attachWindowAndSetUpEvents(
1040 event.windowId, undefined, event.storagePartitionId);
850 1041
851 if (!attached) { 1042 if (!attached) {
852 window.console.error(ERROR_MSG_NEWWINDOW_UNABLE_TO_ATTACH); 1043 window.console.error(ERROR_MSG_NEWWINDOW_UNABLE_TO_ATTACH);
853 } 1044 }
854 // If the object being passed into attach is not a valid <webview> 1045 // If the object being passed into attach is not a valid <webview>
855 // then we will fail and it will be treated as if the new window 1046 // then we will fail and it will be treated as if the new window
856 // was rejected. The permission API plumbing is used here to clean 1047 // was rejected. The permission API plumbing is used here to clean
857 // up the state created for the new window if attaching fails. 1048 // up the state created for the new window if attaching fails.
858 WebView.setPermission( 1049 WebView.setPermission(
859 self.instanceId, requestId, attached ? 'allow' : 'deny'); 1050 self.instanceId, requestId, attached ? 'allow' : 'deny');
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
1050 this.userAgentOverride = userAgentOverride; 1241 this.userAgentOverride = userAgentOverride;
1051 if (!this.instanceId) { 1242 if (!this.instanceId) {
1052 // If we are not attached yet, then we will pick up the user agent on 1243 // If we are not attached yet, then we will pick up the user agent on
1053 // attachment. 1244 // attachment.
1054 return; 1245 return;
1055 } 1246 }
1056 WebView.overrideUserAgent(this.instanceId, userAgentOverride); 1247 WebView.overrideUserAgent(this.instanceId, userAgentOverride);
1057 }; 1248 };
1058 1249
1059 /** @private */ 1250 /** @private */
1060 WebViewInternal.prototype.attachWindowAndSetUpEvents = function(instanceId) { 1251 WebViewInternal.prototype.attachWindowAndSetUpEvents = function(
1252 instanceId, opt_src, opt_partitionId) {
1061 this.instanceId = instanceId; 1253 this.instanceId = instanceId;
1254 // If we have a partition from the opener, use that instead.
1255 var storagePartitionId =
1256 opt_partitionId ||
1257 this.webviewNode.getAttribute(WEB_VIEW_ATTRIBUTE_PARTITION) ||
1258 this.webviewNode[WEB_VIEW_ATTRIBUTE_PARTITION];
1062 var params = { 1259 var params = {
1063 'api': 'webview', 1260 'api': 'webview',
1064 'instanceId': this.viewInstanceId, 1261 'instanceId': this.viewInstanceId,
1065 'name': this.name 1262 'name': this.name,
1263 'src': opt_src,
1264 'storagePartitionId': storagePartitionId,
1265 'userAgentOverride': this.userAgentOverride
1066 }; 1266 };
1067 if (this.userAgentOverride) {
1068 params['userAgentOverride'] = this.userAgentOverride;
1069 }
1070 this.setupNameAttribute(); 1267 this.setupNameAttribute();
1071 var events = this.getEvents(); 1268 var events = this.getEvents();
1072 for (var eventName in events) { 1269 for (var eventName in events) {
1073 this.setupEvent(eventName, events[eventName]); 1270 this.setupEvent(eventName, events[eventName]);
1074 } 1271 }
1075 1272
1076 return this.browserPluginNode['-internal-attach'](this.instanceId, params); 1273 return this.browserPluginNode['-internal-attach'](this.instanceId, params);
1077 }; 1274 };
1078 1275
1079 // Registers browser plugin <object> custom element. 1276 // Registers browser plugin <object> custom element.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1111 } 1308 }
1112 1309
1113 // Registers <webview> custom element. 1310 // Registers <webview> custom element.
1114 function registerWebViewElement() { 1311 function registerWebViewElement() {
1115 var proto = Object.create(HTMLElement.prototype); 1312 var proto = Object.create(HTMLElement.prototype);
1116 1313
1117 proto.createdCallback = function() { 1314 proto.createdCallback = function() {
1118 new WebViewInternal(this); 1315 new WebViewInternal(this);
1119 }; 1316 };
1120 1317
1318 proto.customElementDetached = false;
1319
1121 proto.attributeChangedCallback = function(name, oldValue, newValue) { 1320 proto.attributeChangedCallback = function(name, oldValue, newValue) {
1122 var internal = privates(this).internal; 1321 var internal = privates(this).internal;
1123 if (!internal) { 1322 if (!internal) {
1124 return; 1323 return;
1125 } 1324 }
1126 internal.handleWebviewAttributeMutation(name, oldValue, newValue); 1325 internal.handleWebviewAttributeMutation(name, oldValue, newValue);
1127 }; 1326 };
1128 1327
1328 proto.detachedCallback = function() {
1329 LOG('<webview> got detached');
1330 LOG('this.customElementDetached was: ' + this.customElementDetached);
1331 this.customElementDetached = true;
1332 };
1333 proto.attachedCallback = function() {
1334 LOG('attached, for the first time or subsequent, must init later');
1335 LOG('this.customElementDetached was: ' + this.customElementDetached);
1336 if (this.customElementDetached) {
1337 var otherThis = privates(this).internal;
1338 LOG('allocateInstanceId again');
1339 otherThis.instanceId = undefined;
1340 otherThis.beforeFirstNavigation_ = true;
1341 otherThis.validPartitionId_ = true;
1342 otherThis.partition_.validPartitionId_ = true;
1343
1344 otherThis.allocateInstanceId();
1345 }
1346 this.customElementDetached = false;
1347 };
1348
1129 proto.back = function() { 1349 proto.back = function() {
1130 this.go(-1); 1350 this.go(-1);
1131 }; 1351 };
1132 1352
1133 proto.forward = function() { 1353 proto.forward = function() {
1134 this.go(1); 1354 this.go(1);
1135 }; 1355 };
1136 1356
1137 proto.canGoBack = function() { 1357 proto.canGoBack = function() {
1138 return privates(this).internal.canGoBack(); 1358 return privates(this).internal.canGoBack();
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
1248 1468
1249 /** 1469 /**
1250 * Implemented when the experimental API is available. 1470 * Implemented when the experimental API is available.
1251 * @private 1471 * @private
1252 */ 1472 */
1253 WebViewInternal.prototype.setupExperimentalContextMenus_ = function() {}; 1473 WebViewInternal.prototype.setupExperimentalContextMenus_ = function() {};
1254 1474
1255 exports.WebView = WebView; 1475 exports.WebView = WebView;
1256 exports.WebViewInternal = WebViewInternal; 1476 exports.WebViewInternal = WebViewInternal;
1257 exports.CreateEvent = CreateEvent; 1477 exports.CreateEvent = CreateEvent;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698