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 = |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 // Implemented when the experimental API is available. | 80 // Implemented when the experimental API is available. |
81 WebViewInternal.maybeRegisterExperimentalAPIs = function(proto) {} | 81 WebViewInternal.maybeRegisterExperimentalAPIs = function(proto) {} |
82 | 82 |
83 /** | 83 /** |
84 * @constructor | 84 * @constructor |
85 */ | 85 */ |
86 function WebViewInternal(webviewNode) { | 86 function WebViewInternal(webviewNode) { |
87 privates(webviewNode).internal = this; | 87 privates(webviewNode).internal = this; |
88 this.webviewNode = webviewNode; | 88 this.webviewNode = webviewNode; |
89 this.attached = false; | 89 this.attached = false; |
| 90 this.pendingGuestCreation = false; |
90 this.elementAttached = false; | 91 this.elementAttached = false; |
91 | 92 |
92 this.beforeFirstNavigation = true; | 93 this.beforeFirstNavigation = true; |
93 this.contentWindow = null; | 94 this.contentWindow = null; |
94 this.validPartitionId = true; | 95 this.validPartitionId = true; |
95 // Used to save some state upon deferred attachment. | 96 // Used to save some state upon deferred attachment. |
96 // If <object> bindings is not available, we defer attachment. | 97 // If <object> bindings is not available, we defer attachment. |
97 // This state contains whether or not the attachment request was for | 98 // This state contains whether or not the attachment request was for |
98 // newwindow. | 99 // newwindow. |
99 this.deferredAttachState = null; | 100 this.deferredAttachState = null; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 * Resets some state upon reattaching <webview> element to the DOM. | 136 * Resets some state upon reattaching <webview> element to the DOM. |
136 */ | 137 */ |
137 WebViewInternal.prototype.reset = function() { | 138 WebViewInternal.prototype.reset = function() { |
138 // If guestInstanceId is defined then the <webview> has navigated and has | 139 // If guestInstanceId is defined then the <webview> has navigated and has |
139 // already picked up a partition ID. Thus, we need to reset the initialization | 140 // already picked up a partition ID. Thus, we need to reset the initialization |
140 // state. However, it may be the case that beforeFirstNavigation is false BUT | 141 // state. However, it may be the case that beforeFirstNavigation is false BUT |
141 // guestInstanceId has yet to be initialized. This means that we have not | 142 // guestInstanceId has yet to be initialized. This means that we have not |
142 // heard back from createGuest yet. We will not reset the flag in this case so | 143 // heard back from createGuest yet. We will not reset the flag in this case so |
143 // that we don't end up allocating a second guest. | 144 // that we don't end up allocating a second guest. |
144 if (this.guestInstanceId) { | 145 if (this.guestInstanceId) { |
| 146 GuestViewInternal.destroyGuest(this.guestInstanceId); |
145 this.guestInstanceId = undefined; | 147 this.guestInstanceId = undefined; |
146 this.beforeFirstNavigation = true; | 148 this.beforeFirstNavigation = true; |
147 this.validPartitionId = true; | 149 this.validPartitionId = true; |
148 this.partition.validPartitionId = true; | 150 this.partition.validPartitionId = true; |
149 this.contentWindow = null; | 151 this.contentWindow = null; |
150 } | 152 } |
151 this.internalInstanceId = 0; | 153 this.internalInstanceId = 0; |
152 }; | 154 }; |
153 | 155 |
154 // Sets <webview>.request property. | 156 // Sets <webview>.request property. |
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
535 | 537 |
536 /** | 538 /** |
537 * @private | 539 * @private |
538 */ | 540 */ |
539 WebViewInternal.prototype.handleBrowserPluginAttributeMutation = | 541 WebViewInternal.prototype.handleBrowserPluginAttributeMutation = |
540 function(name, oldValue, newValue) { | 542 function(name, oldValue, newValue) { |
541 if (name == 'internalinstanceid' && !oldValue && !!newValue) { | 543 if (name == 'internalinstanceid' && !oldValue && !!newValue) { |
542 this.browserPluginNode.removeAttribute('internalinstanceid'); | 544 this.browserPluginNode.removeAttribute('internalinstanceid'); |
543 this.internalInstanceId = parseInt(newValue); | 545 this.internalInstanceId = parseInt(newValue); |
544 | 546 |
545 if (!this.deferredAttachState) { | |
546 this.parseAttributes(); | |
547 return; | |
548 } | |
549 | |
550 if (!!this.guestInstanceId && this.guestInstanceId != 0) { | 547 if (!!this.guestInstanceId && this.guestInstanceId != 0) { |
551 window.setTimeout(function() { | 548 var isNewWindow = this.deferredAttachState ? |
552 var isNewWindow = this.deferredAttachState ? | 549 this.deferredAttachState.isNewWindow : false; |
553 this.deferredAttachState.isNewWindow : false; | 550 var params = this.buildAttachParams(isNewWindow); |
554 var params = this.buildAttachParams(isNewWindow); | 551 guestViewInternalNatives.AttachGuest( |
555 guestViewInternalNatives.AttachGuest( | 552 this.internalInstanceId, |
556 this.internalInstanceId, | 553 this.guestInstanceId, |
557 this.guestInstanceId, | 554 params, |
558 params, | 555 function(w) { |
559 function(w) { | 556 this.contentWindow = w; |
560 this.contentWindow = w; | 557 }.bind(this) |
561 }.bind(this) | 558 ); |
562 ); | |
563 }.bind(this), 0); | |
564 } | 559 } |
565 | 560 |
566 return; | 561 return; |
567 } | 562 } |
568 }; | 563 }; |
569 | 564 |
570 WebViewInternal.prototype.onSizeChanged = function(webViewEvent) { | 565 WebViewInternal.prototype.onSizeChanged = function(webViewEvent) { |
571 var newWidth = webViewEvent.newWidth; | 566 var newWidth = webViewEvent.newWidth; |
572 var newHeight = webViewEvent.newHeight; | 567 var newHeight = webViewEvent.newHeight; |
573 | 568 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
634 }; | 629 }; |
635 | 630 |
636 WebViewInternal.prototype.hasNavigated = function() { | 631 WebViewInternal.prototype.hasNavigated = function() { |
637 return !this.beforeFirstNavigation; | 632 return !this.beforeFirstNavigation; |
638 }; | 633 }; |
639 | 634 |
640 /** @return {boolean} */ | 635 /** @return {boolean} */ |
641 WebViewInternal.prototype.parseSrcAttribute = function(result) { | 636 WebViewInternal.prototype.parseSrcAttribute = function(result) { |
642 if (!this.partition.validPartitionId) { | 637 if (!this.partition.validPartitionId) { |
643 result.error = ERROR_MSG_INVALID_PARTITION_ATTRIBUTE; | 638 result.error = ERROR_MSG_INVALID_PARTITION_ATTRIBUTE; |
644 return false; | 639 return; |
645 } | 640 } |
646 this.src = this.webviewNode.getAttribute('src'); | 641 this.src = this.webviewNode.getAttribute('src'); |
647 | 642 |
648 if (!this.src) { | 643 if (!this.src) { |
649 return true; | 644 return; |
650 } | |
651 | |
652 if (!this.elementAttached) { | |
653 return true; | |
654 } | 645 } |
655 | 646 |
656 if (!this.hasGuestInstanceID()) { | 647 if (!this.hasGuestInstanceID()) { |
657 if (this.beforeFirstNavigation) { | 648 if (this.beforeFirstNavigation) { |
658 this.beforeFirstNavigation = false; | 649 this.beforeFirstNavigation = false; |
659 this.allocateInstanceId(); | 650 this.createGuest(); |
660 } | 651 } |
661 return true; | 652 return; |
662 } | 653 } |
663 | 654 |
664 // Navigate to this.src. | 655 // Navigate to this.src. |
665 WebView.navigate(this.guestInstanceId, this.src); | 656 WebView.navigate(this.guestInstanceId, this.src); |
666 return true; | 657 return true; |
667 }; | 658 }; |
668 | 659 |
669 /** @return {boolean} */ | 660 /** @return {boolean} */ |
670 WebViewInternal.prototype.parseAttributes = function() { | 661 WebViewInternal.prototype.parseAttributes = function() { |
| 662 if (!this.elementAttached) { |
| 663 return; |
| 664 } |
671 var hasNavigated = this.hasNavigated(); | 665 var hasNavigated = this.hasNavigated(); |
672 var attributeValue = this.webviewNode.getAttribute('partition'); | 666 var attributeValue = this.webviewNode.getAttribute('partition'); |
673 var result = this.partition.fromAttribute(attributeValue, hasNavigated); | 667 var result = this.partition.fromAttribute(attributeValue, hasNavigated); |
674 return this.parseSrcAttribute(result); | 668 this.parseSrcAttribute(result); |
675 }; | 669 }; |
676 | 670 |
677 WebViewInternal.prototype.hasGuestInstanceID = function() { | 671 WebViewInternal.prototype.hasGuestInstanceID = function() { |
678 return this.guestInstanceId != undefined; | 672 return this.guestInstanceId != undefined; |
679 }; | 673 }; |
680 | 674 |
681 WebViewInternal.prototype.allocateInstanceId = function() { | 675 WebViewInternal.prototype.createGuest = function() { |
| 676 if (this.pendingGuestCreation) { |
| 677 return; |
| 678 } |
682 var storagePartitionId = | 679 var storagePartitionId = |
683 this.webviewNode.getAttribute(WEB_VIEW_ATTRIBUTE_PARTITION) || | 680 this.webviewNode.getAttribute(WEB_VIEW_ATTRIBUTE_PARTITION) || |
684 this.webviewNode[WEB_VIEW_ATTRIBUTE_PARTITION]; | 681 this.webviewNode[WEB_VIEW_ATTRIBUTE_PARTITION]; |
685 var params = { | 682 var params = { |
686 'storagePartitionId': storagePartitionId, | 683 'storagePartitionId': storagePartitionId, |
687 }; | 684 }; |
688 GuestViewInternal.createGuest( | 685 GuestViewInternal.createGuest( |
689 'webview', | 686 'webview', |
690 params, | 687 params, |
691 function(guestInstanceId) { | 688 function(guestInstanceId) { |
| 689 this.pendingGuestCreation = false; |
| 690 if (!this.elementAttached) { |
| 691 GuestViewInternal.destroyGuest(this.guestInstanceId); |
| 692 return; |
| 693 } |
692 this.attachWindow(guestInstanceId, false); | 694 this.attachWindow(guestInstanceId, false); |
693 }.bind(this) | 695 }.bind(this) |
694 ); | 696 ); |
| 697 this.pendingGuestCreation = true; |
695 }; | 698 }; |
696 | 699 |
697 WebViewInternal.prototype.onFrameNameChanged = function(name) { | 700 WebViewInternal.prototype.onFrameNameChanged = function(name) { |
698 this.name = name || ''; | 701 this.name = name || ''; |
699 if (this.name === '') { | 702 if (this.name === '') { |
700 this.webviewNode.removeAttribute('name'); | 703 this.webviewNode.removeAttribute('name'); |
701 } else { | 704 } else { |
702 this.webviewNode.setAttribute('name', this.name); | 705 this.webviewNode.setAttribute('name', this.name); |
703 } | 706 } |
704 }; | 707 }; |
705 | 708 |
706 WebViewInternal.prototype.onPluginDestroyed = function() { | |
707 this.reset(); | |
708 }; | |
709 | |
710 WebViewInternal.prototype.dispatchEvent = function(webViewEvent) { | 709 WebViewInternal.prototype.dispatchEvent = function(webViewEvent) { |
711 return this.webviewNode.dispatchEvent(webViewEvent); | 710 return this.webviewNode.dispatchEvent(webViewEvent); |
712 }; | 711 }; |
713 | 712 |
714 /** | 713 /** |
715 * Adds an 'on<event>' property on the webview, which can be used to set/unset | 714 * Adds an 'on<event>' property on the webview, which can be used to set/unset |
716 * an event handler. | 715 * an event handler. |
717 */ | 716 */ |
718 WebViewInternal.prototype.setupEventProperty = function(eventName) { | 717 WebViewInternal.prototype.setupEventProperty = function(eventName) { |
719 var propertyName = 'on' + eventName.toLowerCase(); | 718 var propertyName = 'on' + eventName.toLowerCase(); |
(...skipping 29 matching lines...) Expand all Loading... |
749 this.ignoreNextSrcAttributeChange = true; | 748 this.ignoreNextSrcAttributeChange = true; |
750 this.webviewNode.setAttribute('src', newValue); | 749 this.webviewNode.setAttribute('src', newValue); |
751 } | 750 } |
752 }; | 751 }; |
753 | 752 |
754 WebViewInternal.prototype.onAttach = function(storagePartitionId) { | 753 WebViewInternal.prototype.onAttach = function(storagePartitionId) { |
755 this.webviewNode.setAttribute('partition', storagePartitionId); | 754 this.webviewNode.setAttribute('partition', storagePartitionId); |
756 this.partition.fromAttribute(storagePartitionId, this.hasNavigated()); | 755 this.partition.fromAttribute(storagePartitionId, this.hasNavigated()); |
757 }; | 756 }; |
758 | 757 |
759 | |
760 /** @private */ | 758 /** @private */ |
761 WebViewInternal.prototype.getUserAgent = function() { | 759 WebViewInternal.prototype.getUserAgent = function() { |
762 return this.userAgentOverride || navigator.userAgent; | 760 return this.userAgentOverride || navigator.userAgent; |
763 }; | 761 }; |
764 | 762 |
765 /** @private */ | 763 /** @private */ |
766 WebViewInternal.prototype.isUserAgentOverridden = function() { | 764 WebViewInternal.prototype.isUserAgentOverridden = function() { |
767 return !!this.userAgentOverride && | 765 return !!this.userAgentOverride && |
768 this.userAgentOverride != navigator.userAgent; | 766 this.userAgentOverride != navigator.userAgent; |
769 }; | 767 }; |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1006 | 1004 |
1007 /** | 1005 /** |
1008 * Implemented when the experimental API is available. | 1006 * Implemented when the experimental API is available. |
1009 * @private | 1007 * @private |
1010 */ | 1008 */ |
1011 WebViewInternal.prototype.setupExperimentalContextMenus = function() { | 1009 WebViewInternal.prototype.setupExperimentalContextMenus = function() { |
1012 }; | 1010 }; |
1013 | 1011 |
1014 exports.WebView = WebView; | 1012 exports.WebView = WebView; |
1015 exports.WebViewInternal = WebViewInternal; | 1013 exports.WebViewInternal = WebViewInternal; |
OLD | NEW |