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 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 // newwindow. | 100 // newwindow. |
101 this.deferredAttachState = null; | 101 this.deferredAttachState = null; |
102 | 102 |
103 // on* Event handlers. | 103 // on* Event handlers. |
104 this.on = {}; | 104 this.on = {}; |
105 | 105 |
106 this.browserPluginNode = this.createBrowserPluginNode(); | 106 this.browserPluginNode = this.createBrowserPluginNode(); |
107 var shadowRoot = this.webviewNode.createShadowRoot(); | 107 var shadowRoot = this.webviewNode.createShadowRoot(); |
108 this.partition = new Partition(); | 108 this.partition = new Partition(); |
109 | 109 |
110 this.setupWebviewNodeAttributes(); | 110 this.setupWebViewSrcAttributeMutationObserver(); |
111 this.setupFocusPropagation(); | 111 this.setupFocusPropagation(); |
112 this.setupWebviewNodeProperties(); | 112 this.setupWebviewNodeProperties(); |
113 | 113 |
114 this.viewInstanceId = IdGenerator.GetNextId(); | 114 this.viewInstanceId = IdGenerator.GetNextId(); |
115 | 115 |
116 new WebViewEvents(this, this.viewInstanceId); | 116 new WebViewEvents(this, this.viewInstanceId); |
117 | 117 |
118 shadowRoot.appendChild(this.browserPluginNode); | 118 shadowRoot.appendChild(this.browserPluginNode); |
119 } | 119 } |
120 | 120 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 }; | 162 }; |
163 | 163 |
164 WebViewInternal.prototype.setupFocusPropagation = function() { | 164 WebViewInternal.prototype.setupFocusPropagation = function() { |
165 if (!this.webviewNode.hasAttribute('tabIndex')) { | 165 if (!this.webviewNode.hasAttribute('tabIndex')) { |
166 // <webview> needs a tabIndex in order to be focusable. | 166 // <webview> needs a tabIndex in order to be focusable. |
167 // TODO(fsamuel): It would be nice to avoid exposing a tabIndex attribute | 167 // TODO(fsamuel): It would be nice to avoid exposing a tabIndex attribute |
168 // to allow <webview> to be focusable. | 168 // to allow <webview> to be focusable. |
169 // See http://crbug.com/231664. | 169 // See http://crbug.com/231664. |
170 this.webviewNode.setAttribute('tabIndex', -1); | 170 this.webviewNode.setAttribute('tabIndex', -1); |
171 } | 171 } |
172 var self = this; | |
173 this.webviewNode.addEventListener('focus', function(e) { | 172 this.webviewNode.addEventListener('focus', function(e) { |
174 // Focus the BrowserPlugin when the <webview> takes focus. | 173 // Focus the BrowserPlugin when the <webview> takes focus. |
175 this.browserPluginNode.focus(); | 174 this.browserPluginNode.focus(); |
176 }.bind(this)); | 175 }.bind(this)); |
177 this.webviewNode.addEventListener('blur', function(e) { | 176 this.webviewNode.addEventListener('blur', function(e) { |
178 // Blur the BrowserPlugin when the <webview> loses focus. | 177 // Blur the BrowserPlugin when the <webview> loses focus. |
179 this.browserPluginNode.blur(); | 178 this.browserPluginNode.blur(); |
180 }.bind(this)); | 179 }.bind(this)); |
181 }; | 180 }; |
182 | 181 |
183 // Navigates to the previous history entry. | 182 // Validation helper function for executeScript() and insertCSS(). |
184 WebViewInternal.prototype.back = function(callback) { | |
185 return this.go(-1, callback); | |
186 }; | |
187 | |
188 // Navigates to the subsequent history entry. | |
189 WebViewInternal.prototype.forward = function(callback) { | |
190 return this.go(1, callback); | |
191 }; | |
192 | |
193 // Returns whether there is a previous history entry to navigate to. | |
194 WebViewInternal.prototype.canGoBack = function() { | |
195 return this.entryCount > 1 && this.currentEntryIndex > 0; | |
196 }; | |
197 | |
198 // Returns whether there is a subsequent history entry to navigate to. | |
199 WebViewInternal.prototype.canGoForward = function() { | |
200 return this.currentEntryIndex >= 0 && | |
201 this.currentEntryIndex < (this.entryCount - 1); | |
202 }; | |
203 | |
204 // Clears browsing data for the WebView partition. | |
205 WebViewInternal.prototype.clearData = function() { | |
206 if (!this.guestInstanceId) { | |
207 return; | |
208 } | |
209 var args = $Array.concat([this.guestInstanceId], $Array.slice(arguments)); | |
210 $Function.apply(WebView.clearData, null, args); | |
211 }; | |
212 | |
213 // Returns Chrome's internal process ID for the guest web page's current | |
214 // process. | |
215 WebViewInternal.prototype.getProcessId = function() { | |
216 return this.processId; | |
217 }; | |
218 | |
219 // Navigates to a history entry using a history index relative to the current | |
220 // navigation. | |
221 WebViewInternal.prototype.go = function(relativeIndex, callback) { | |
222 if (!this.guestInstanceId) { | |
223 return; | |
224 } | |
225 WebView.go(this.guestInstanceId, relativeIndex, callback); | |
226 }; | |
227 | |
228 // Prints the contents of the webview. | |
229 WebViewInternal.prototype.print = function() { | |
230 this.executeScript({code: 'window.print();'}); | |
231 }; | |
232 | |
233 // Reloads the current top-level page. | |
234 WebViewInternal.prototype.reload = function() { | |
235 if (!this.guestInstanceId) { | |
236 return; | |
237 } | |
238 WebView.reload(this.guestInstanceId); | |
239 }; | |
240 | |
241 // Stops loading the current navigation if one is in progress. | |
242 WebViewInternal.prototype.stop = function() { | |
243 if (!this.guestInstanceId) { | |
244 return; | |
245 } | |
246 WebView.stop(this.guestInstanceId); | |
247 }; | |
248 | |
249 // Forcibly kills the guest web page's renderer process. | |
250 WebViewInternal.prototype.terminate = function() { | |
251 if (!this.guestInstanceId) { | |
252 return; | |
253 } | |
254 WebView.terminate(this.guestInstanceId); | |
255 }; | |
256 | |
257 WebViewInternal.prototype.validateExecuteCodeCall = function() { | 183 WebViewInternal.prototype.validateExecuteCodeCall = function() { |
258 if (!this.guestInstanceId) { | 184 if (!this.guestInstanceId) { |
259 throw new Error(ERROR_MSG_CANNOT_INJECT_SCRIPT); | 185 throw new Error(ERROR_MSG_CANNOT_INJECT_SCRIPT); |
260 } | 186 } |
261 }; | 187 }; |
262 | 188 |
263 // Injects JavaScript code into the guest page. | |
264 WebViewInternal.prototype.executeScript = function(var_args) { | |
265 this.validateExecuteCodeCall(); | |
266 var webview_src = this.src; | |
267 if (this.baseUrlForDataUrl != '') { | |
268 webview_src = this.baseUrlForDataUrl; | |
269 } | |
270 var args = $Array.concat([this.guestInstanceId, webview_src], | |
271 $Array.slice(arguments)); | |
272 $Function.apply(WebView.executeScript, null, args); | |
273 }; | |
274 | |
275 // Injects CSS into the guest page. | |
276 WebViewInternal.prototype.insertCSS = function(var_args) { | |
277 this.validateExecuteCodeCall(); | |
278 var webview_src = this.src; | |
279 if (this.baseUrlForDataUrl != '') { | |
280 webview_src = this.baseUrlForDataUrl; | |
281 } | |
282 var args = $Array.concat([this.guestInstanceId, webview_src], | |
283 $Array.slice(arguments)); | |
284 $Function.apply(WebView.insertCSS, null, args); | |
285 }; | |
286 | |
287 WebViewInternal.prototype.setupAutoSizeProperties = function() { | 189 WebViewInternal.prototype.setupAutoSizeProperties = function() { |
288 $Array.forEach(AUTO_SIZE_ATTRIBUTES, function(attributeName) { | 190 $Array.forEach(AUTO_SIZE_ATTRIBUTES, function(attributeName) { |
289 this[attributeName] = this.webviewNode.getAttribute(attributeName); | 191 this[attributeName] = this.webviewNode.getAttribute(attributeName); |
290 Object.defineProperty(this.webviewNode, attributeName, { | 192 Object.defineProperty(this.webviewNode, attributeName, { |
291 get: function() { | 193 get: function() { |
292 return this[attributeName]; | 194 return this[attributeName]; |
293 }.bind(this), | 195 }.bind(this), |
294 set: function(value) { | 196 set: function(value) { |
295 this.webviewNode.setAttribute(attributeName, value); | 197 this.webviewNode.setAttribute(attributeName, value); |
296 }.bind(this), | 198 }.bind(this), |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
357 return this.src; | 259 return this.src; |
358 }.bind(this), | 260 }.bind(this), |
359 set: function(value) { | 261 set: function(value) { |
360 this.webviewNode.setAttribute('src', value); | 262 this.webviewNode.setAttribute('src', value); |
361 }.bind(this), | 263 }.bind(this), |
362 // No setter. | 264 // No setter. |
363 enumerable: true | 265 enumerable: true |
364 }); | 266 }); |
365 }; | 267 }; |
366 | 268 |
367 WebViewInternal.prototype.setupWebviewNodeAttributes = function() { | |
368 this.setupWebViewSrcAttributeMutationObserver(); | |
369 }; | |
370 | |
371 // The purpose of this mutation observer is to catch assignment to the src | 269 // The purpose of this mutation observer is to catch assignment to the src |
372 // attribute without any changes to its value. This is useful in the case | 270 // attribute without any changes to its value. This is useful in the case |
373 // where the webview guest has crashed and navigating to the same address | 271 // where the webview guest has crashed and navigating to the same address |
374 // spawns off a new process. | 272 // spawns off a new process. |
375 WebViewInternal.prototype.setupWebViewSrcAttributeMutationObserver = | 273 WebViewInternal.prototype.setupWebViewSrcAttributeMutationObserver = |
376 function() { | 274 function() { |
377 this.srcAndPartitionObserver = new MutationObserver(function(mutations) { | 275 this.srcAndPartitionObserver = new MutationObserver(function(mutations) { |
378 $Array.forEach(mutations, function(mutation) { | 276 $Array.forEach(mutations, function(mutation) { |
379 var oldValue = mutation.oldValue; | 277 var oldValue = mutation.oldValue; |
380 var newValue = this.webviewNode.getAttribute(mutation.attributeName); | 278 var newValue = this.webviewNode.getAttribute(mutation.attributeName); |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
585 if (!this.partition.validPartitionId) { | 483 if (!this.partition.validPartitionId) { |
586 result.error = ERROR_MSG_INVALID_PARTITION_ATTRIBUTE; | 484 result.error = ERROR_MSG_INVALID_PARTITION_ATTRIBUTE; |
587 return; | 485 return; |
588 } | 486 } |
589 this.src = this.webviewNode.getAttribute('src'); | 487 this.src = this.webviewNode.getAttribute('src'); |
590 | 488 |
591 if (!this.src) { | 489 if (!this.src) { |
592 return; | 490 return; |
593 } | 491 } |
594 | 492 |
595 if (!this.hasGuestInstanceID()) { | 493 if (this.guestInstanceId == undefined) { |
596 if (this.beforeFirstNavigation) { | 494 if (this.beforeFirstNavigation) { |
597 this.beforeFirstNavigation = false; | 495 this.beforeFirstNavigation = false; |
598 this.createGuest(); | 496 this.createGuest(); |
599 } | 497 } |
600 return; | 498 return; |
601 } | 499 } |
602 | 500 |
603 // Navigate to |this.src|. | 501 // Navigate to |this.src|. |
604 WebView.navigate(this.guestInstanceId, this.src); | 502 WebView.navigate(this.guestInstanceId, this.src); |
605 return true; | |
606 }; | 503 }; |
607 | 504 |
608 WebViewInternal.prototype.parseAttributes = function() { | 505 WebViewInternal.prototype.parseAttributes = function() { |
609 if (!this.elementAttached) { | 506 if (!this.elementAttached) { |
610 return; | 507 return; |
611 } | 508 } |
612 var hasNavigated = this.hasNavigated(); | 509 var hasNavigated = this.hasNavigated(); |
613 var attributeValue = this.webviewNode.getAttribute('partition'); | 510 var attributeValue = this.webviewNode.getAttribute('partition'); |
614 var result = this.partition.fromAttribute(attributeValue, hasNavigated); | 511 var result = this.partition.fromAttribute(attributeValue, hasNavigated); |
615 this.parseSrcAttribute(result); | 512 this.parseSrcAttribute(result); |
616 }; | 513 }; |
617 | 514 |
618 WebViewInternal.prototype.hasGuestInstanceID = function() { | |
619 return this.guestInstanceId != undefined; | |
620 }; | |
621 | |
622 WebViewInternal.prototype.createGuest = function() { | 515 WebViewInternal.prototype.createGuest = function() { |
623 if (this.pendingGuestCreation) { | 516 if (this.pendingGuestCreation) { |
624 return; | 517 return; |
625 } | 518 } |
626 var storagePartitionId = | 519 var storagePartitionId = |
627 this.webviewNode.getAttribute(WEB_VIEW_ATTRIBUTE_PARTITION) || | 520 this.webviewNode.getAttribute(WEB_VIEW_ATTRIBUTE_PARTITION) || |
628 this.webviewNode[WEB_VIEW_ATTRIBUTE_PARTITION]; | 521 this.webviewNode[WEB_VIEW_ATTRIBUTE_PARTITION]; |
629 var params = { | 522 var params = { |
630 'storagePartitionId': storagePartitionId | 523 'storagePartitionId': storagePartitionId |
631 }; | 524 }; |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
693 this.ignoreNextSrcAttributeChange = true; | 586 this.ignoreNextSrcAttributeChange = true; |
694 this.webviewNode.setAttribute('src', newValue); | 587 this.webviewNode.setAttribute('src', newValue); |
695 } | 588 } |
696 }; | 589 }; |
697 | 590 |
698 WebViewInternal.prototype.onAttach = function(storagePartitionId) { | 591 WebViewInternal.prototype.onAttach = function(storagePartitionId) { |
699 this.webviewNode.setAttribute('partition', storagePartitionId); | 592 this.webviewNode.setAttribute('partition', storagePartitionId); |
700 this.partition.fromAttribute(storagePartitionId, this.hasNavigated()); | 593 this.partition.fromAttribute(storagePartitionId, this.hasNavigated()); |
701 }; | 594 }; |
702 | 595 |
| 596 WebViewInternal.prototype.buildAttachParams = function(isNewWindow) { |
| 597 var params = { |
| 598 'allowtransparency': this.allowtransparency || false, |
| 599 'autosize': this.webviewNode.hasAttribute(WEB_VIEW_ATTRIBUTE_AUTOSIZE), |
| 600 'instanceId': this.viewInstanceId, |
| 601 'maxheight': parseInt(this.maxheight || 0), |
| 602 'maxwidth': parseInt(this.maxwidth || 0), |
| 603 'minheight': parseInt(this.minheight || 0), |
| 604 'minwidth': parseInt(this.minwidth || 0), |
| 605 'name': this.name, |
| 606 // We don't need to navigate new window from here. |
| 607 'src': isNewWindow ? undefined : this.src, |
| 608 // If we have a partition from the opener, that will also be already |
| 609 // set via this.onAttach(). |
| 610 'storagePartitionId': this.partition.toAttribute(), |
| 611 'userAgentOverride': this.userAgentOverride |
| 612 }; |
| 613 return params; |
| 614 }; |
| 615 |
| 616 WebViewInternal.prototype.attachWindow = function(guestInstanceId, |
| 617 isNewWindow) { |
| 618 this.guestInstanceId = guestInstanceId; |
| 619 var params = this.buildAttachParams(isNewWindow); |
| 620 |
| 621 if (!this.isPluginInRenderTree()) { |
| 622 this.deferredAttachState = {isNewWindow: isNewWindow}; |
| 623 return true; |
| 624 } |
| 625 |
| 626 this.deferredAttachState = null; |
| 627 return guestViewInternalNatives.AttachGuest( |
| 628 this.internalInstanceId, |
| 629 this.guestInstanceId, |
| 630 params, function(w) { |
| 631 this.contentWindow = w; |
| 632 }.bind(this) |
| 633 ); |
| 634 }; |
| 635 |
| 636 // ----------------------------------------------------------------------------- |
| 637 // Public-facing API methods. |
| 638 |
| 639 |
| 640 // Navigates to the previous history entry. |
| 641 WebViewInternal.prototype.back = function(callback) { |
| 642 return this.go(-1, callback); |
| 643 }; |
| 644 |
| 645 // Returns whether there is a previous history entry to navigate to. |
| 646 WebViewInternal.prototype.canGoBack = function() { |
| 647 return this.entryCount > 1 && this.currentEntryIndex > 0; |
| 648 }; |
| 649 |
| 650 // Returns whether there is a subsequent history entry to navigate to. |
| 651 WebViewInternal.prototype.canGoForward = function() { |
| 652 return this.currentEntryIndex >= 0 && |
| 653 this.currentEntryIndex < (this.entryCount - 1); |
| 654 }; |
| 655 |
| 656 // Clears browsing data for the WebView partition. |
| 657 WebViewInternal.prototype.clearData = function() { |
| 658 if (!this.guestInstanceId) { |
| 659 return; |
| 660 } |
| 661 var args = $Array.concat([this.guestInstanceId], $Array.slice(arguments)); |
| 662 $Function.apply(WebView.clearData, null, args); |
| 663 }; |
| 664 |
| 665 // Injects JavaScript code into the guest page. |
| 666 WebViewInternal.prototype.executeScript = function(var_args) { |
| 667 this.validateExecuteCodeCall(); |
| 668 var webviewSrc = this.src; |
| 669 if (this.baseUrlForDataUrl != '') { |
| 670 webviewSrc = this.baseUrlForDataUrl; |
| 671 } |
| 672 var args = $Array.concat([this.guestInstanceId, webviewSrc], |
| 673 $Array.slice(arguments)); |
| 674 $Function.apply(WebView.executeScript, null, args); |
| 675 }; |
| 676 |
| 677 // Initiates a find-in-page request. |
| 678 WebViewInternal.prototype.find = function(search_text, options, callback) { |
| 679 if (!this.guestInstanceId) { |
| 680 return; |
| 681 } |
| 682 WebView.find(this.guestInstanceId, search_text, options, callback); |
| 683 }; |
| 684 |
| 685 // Navigates to the subsequent history entry. |
| 686 WebViewInternal.prototype.forward = function(callback) { |
| 687 return this.go(1, callback); |
| 688 }; |
| 689 |
| 690 // Returns Chrome's internal process ID for the guest web page's current |
| 691 // process. |
| 692 WebViewInternal.prototype.getProcessId = function() { |
| 693 return this.processId; |
| 694 }; |
| 695 |
703 // Returns the user agent string used by the webview for guest page requests. | 696 // Returns the user agent string used by the webview for guest page requests. |
704 WebViewInternal.prototype.getUserAgent = function() { | 697 WebViewInternal.prototype.getUserAgent = function() { |
705 return this.userAgentOverride || navigator.userAgent; | 698 return this.userAgentOverride || navigator.userAgent; |
706 }; | 699 }; |
707 | 700 |
| 701 // Gets the current zoom factor. |
| 702 WebViewInternal.prototype.getZoom = function(callback) { |
| 703 if (!this.guestInstanceId) { |
| 704 return; |
| 705 } |
| 706 WebView.getZoom(this.guestInstanceId, callback); |
| 707 }; |
| 708 |
| 709 // Navigates to a history entry using a history index relative to the current |
| 710 // navigation. |
| 711 WebViewInternal.prototype.go = function(relativeIndex, callback) { |
| 712 if (!this.guestInstanceId) { |
| 713 return; |
| 714 } |
| 715 WebView.go(this.guestInstanceId, relativeIndex, callback); |
| 716 }; |
| 717 |
| 718 // Injects CSS into the guest page. |
| 719 WebViewInternal.prototype.insertCSS = function(var_args) { |
| 720 this.validateExecuteCodeCall(); |
| 721 var webviewSrc = this.src; |
| 722 if (this.baseUrlForDataUrl != '') { |
| 723 webviewSrc = this.baseUrlForDataUrl; |
| 724 } |
| 725 var args = $Array.concat([this.guestInstanceId, webviewSrc], |
| 726 $Array.slice(arguments)); |
| 727 $Function.apply(WebView.insertCSS, null, args); |
| 728 }; |
| 729 |
708 // Indicates whether or not the webview's user agent string has been overridden. | 730 // Indicates whether or not the webview's user agent string has been overridden. |
709 WebViewInternal.prototype.isUserAgentOverridden = function() { | 731 WebViewInternal.prototype.isUserAgentOverridden = function() { |
710 return !!this.userAgentOverride && | 732 return !!this.userAgentOverride && |
711 this.userAgentOverride != navigator.userAgent; | 733 this.userAgentOverride != navigator.userAgent; |
712 }; | 734 }; |
713 | 735 |
| 736 // Prints the contents of the webview. |
| 737 WebViewInternal.prototype.print = function() { |
| 738 this.executeScript({code: 'window.print();'}); |
| 739 }; |
| 740 |
| 741 // Reloads the current top-level page. |
| 742 WebViewInternal.prototype.reload = function() { |
| 743 if (!this.guestInstanceId) { |
| 744 return; |
| 745 } |
| 746 WebView.reload(this.guestInstanceId); |
| 747 }; |
| 748 |
714 // Override the user agent string used by the webview for guest page requests. | 749 // Override the user agent string used by the webview for guest page requests. |
715 WebViewInternal.prototype.setUserAgentOverride = function(userAgentOverride) { | 750 WebViewInternal.prototype.setUserAgentOverride = function(userAgentOverride) { |
716 this.userAgentOverride = userAgentOverride; | 751 this.userAgentOverride = userAgentOverride; |
717 if (!this.guestInstanceId) { | 752 if (!this.guestInstanceId) { |
718 // If we are not attached yet, then we will pick up the user agent on | 753 // If we are not attached yet, then we will pick up the user agent on |
719 // attachment. | 754 // attachment. |
720 return; | 755 return; |
721 } | 756 } |
722 WebView.overrideUserAgent(this.guestInstanceId, userAgentOverride); | 757 WebView.overrideUserAgent(this.guestInstanceId, userAgentOverride); |
723 }; | 758 }; |
724 | 759 |
725 // Initiates a find-in-page request. | 760 // Changes the zoom factor of the page. |
726 WebViewInternal.prototype.find = function(search_text, options, callback) { | 761 WebViewInternal.prototype.setZoom = function(zoomFactor, callback) { |
727 if (!this.guestInstanceId) { | 762 if (!this.guestInstanceId) { |
728 return; | 763 return; |
729 } | 764 } |
730 WebView.find(this.guestInstanceId, search_text, options, callback); | 765 WebView.setZoom(this.guestInstanceId, zoomFactor, callback); |
| 766 }; |
| 767 |
| 768 // Stops loading the current navigation if one is in progress. |
| 769 WebViewInternal.prototype.stop = function() { |
| 770 if (!this.guestInstanceId) { |
| 771 return; |
| 772 } |
| 773 WebView.stop(this.guestInstanceId); |
731 }; | 774 }; |
732 | 775 |
733 // Ends the current find session. | 776 // Ends the current find session. |
734 WebViewInternal.prototype.stopFinding = function(action) { | 777 WebViewInternal.prototype.stopFinding = function(action) { |
735 if (!this.guestInstanceId) { | 778 if (!this.guestInstanceId) { |
736 return; | 779 return; |
737 } | 780 } |
738 WebView.stopFinding(this.guestInstanceId, action); | 781 WebView.stopFinding(this.guestInstanceId, action); |
739 }; | 782 }; |
740 | 783 |
741 // Changes the zoom factor of the page. | 784 // Forcibly kills the guest web page's renderer process. |
742 WebViewInternal.prototype.setZoom = function(zoomFactor, callback) { | 785 WebViewInternal.prototype.terminate = function() { |
743 if (!this.guestInstanceId) { | 786 if (!this.guestInstanceId) { |
744 return; | 787 return; |
745 } | 788 } |
746 WebView.setZoom(this.guestInstanceId, zoomFactor, callback); | 789 WebView.terminate(this.guestInstanceId); |
747 }; | 790 }; |
748 | 791 |
749 // Gets the current zoom factor. | 792 // ----------------------------------------------------------------------------- |
750 WebViewInternal.prototype.getZoom = function(callback) { | |
751 if (!this.guestInstanceId) { | |
752 return; | |
753 } | |
754 WebView.getZoom(this.guestInstanceId, callback); | |
755 }; | |
756 | |
757 WebViewInternal.prototype.buildAttachParams = function(isNewWindow) { | |
758 var params = { | |
759 'allowtransparency': this.allowtransparency || false, | |
760 'autosize': this.webviewNode.hasAttribute(WEB_VIEW_ATTRIBUTE_AUTOSIZE), | |
761 'instanceId': this.viewInstanceId, | |
762 'maxheight': parseInt(this.maxheight || 0), | |
763 'maxwidth': parseInt(this.maxwidth || 0), | |
764 'minheight': parseInt(this.minheight || 0), | |
765 'minwidth': parseInt(this.minwidth || 0), | |
766 'name': this.name, | |
767 // We don't need to navigate new window from here. | |
768 'src': isNewWindow ? undefined : this.src, | |
769 // If we have a partition from the opener, that will also be already | |
770 // set via this.onAttach(). | |
771 'storagePartitionId': this.partition.toAttribute(), | |
772 'userAgentOverride': this.userAgentOverride | |
773 }; | |
774 return params; | |
775 }; | |
776 | |
777 WebViewInternal.prototype.attachWindow = function(guestInstanceId, | |
778 isNewWindow) { | |
779 this.guestInstanceId = guestInstanceId; | |
780 var params = this.buildAttachParams(isNewWindow); | |
781 | |
782 if (!this.isPluginInRenderTree()) { | |
783 this.deferredAttachState = {isNewWindow: isNewWindow}; | |
784 return true; | |
785 } | |
786 | |
787 this.deferredAttachState = null; | |
788 return guestViewInternalNatives.AttachGuest( | |
789 this.internalInstanceId, | |
790 this.guestInstanceId, | |
791 params, function(w) { | |
792 this.contentWindow = w; | |
793 }.bind(this) | |
794 ); | |
795 }; | |
796 | 793 |
797 // Registers browser plugin <object> custom element. | 794 // Registers browser plugin <object> custom element. |
798 function registerBrowserPluginElement() { | 795 function registerBrowserPluginElement() { |
799 var proto = Object.create(HTMLObjectElement.prototype); | 796 var proto = Object.create(HTMLObjectElement.prototype); |
800 | 797 |
801 proto.createdCallback = function() { | 798 proto.createdCallback = function() { |
802 this.setAttribute('type', 'application/browser-plugin'); | 799 this.setAttribute('type', 'application/browser-plugin'); |
803 this.setAttribute('id', 'browser-plugin-' + IdGenerator.GetNextId()); | 800 this.setAttribute('id', 'browser-plugin-' + IdGenerator.GetNextId()); |
804 // The <object> node fills in the <webview> container. | 801 // The <object> node fills in the <webview> container. |
805 this.style.width = '100%'; | 802 this.style.width = '100%'; |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
861 } | 858 } |
862 if (!internal.elementAttached) { | 859 if (!internal.elementAttached) { |
863 internal.elementAttached = true; | 860 internal.elementAttached = true; |
864 internal.parseAttributes(); | 861 internal.parseAttributes(); |
865 } | 862 } |
866 }; | 863 }; |
867 | 864 |
868 // Public-facing API methods. | 865 // Public-facing API methods. |
869 var methods = [ | 866 var methods = [ |
870 'back', | 867 'back', |
871 'find', | |
872 'forward', | |
873 'canGoBack', | 868 'canGoBack', |
874 'canGoForward', | 869 'canGoForward', |
875 'clearData', | 870 'clearData', |
| 871 'executeScript', |
| 872 'find', |
| 873 'forward', |
876 'getProcessId', | 874 'getProcessId', |
| 875 'getUserAgent', |
877 'getZoom', | 876 'getZoom', |
878 'go', | 877 'go', |
| 878 'insertCSS', |
| 879 'isUserAgentOverridden', |
879 'print', | 880 'print', |
880 'reload', | 881 'reload', |
| 882 'setUserAgentOverride', |
881 'setZoom', | 883 'setZoom', |
882 'stop', | 884 'stop', |
883 'stopFinding', | 885 'stopFinding', |
884 'terminate', | 886 'terminate' |
885 'executeScript', | |
886 'insertCSS', | |
887 'getUserAgent', | |
888 'isUserAgentOverridden', | |
889 'setUserAgentOverride' | |
890 ]; | 887 ]; |
891 | 888 |
892 // Add the experimental API methods, if available. | 889 // Add the experimental API methods, if available. |
893 var experimentalMethods = | 890 var experimentalMethods = |
894 WebViewInternal.maybeGetExperimentalAPIs(); | 891 WebViewInternal.maybeGetExperimentalAPIs(); |
895 methods = $Array.concat(methods, experimentalMethods); | 892 methods = $Array.concat(methods, experimentalMethods); |
896 | 893 |
897 // Forward proto.foo* method calls to WebViewInternal.foo*. | 894 // Forward proto.foo* method calls to WebViewInternal.foo*. |
898 var createHandler = function(m) { | 895 var createHandler = function(m) { |
899 return function(var_args) { | 896 return function(var_args) { |
(...skipping 30 matching lines...) Expand all Loading... |
930 WebViewInternal.prototype.maybeGetChromeWebViewEvents = function() {}; | 927 WebViewInternal.prototype.maybeGetChromeWebViewEvents = function() {}; |
931 | 928 |
932 // Implemented when the experimental WebView API is available. | 929 // Implemented when the experimental WebView API is available. |
933 WebViewInternal.maybeGetExperimentalAPIs = function() {}; | 930 WebViewInternal.maybeGetExperimentalAPIs = function() {}; |
934 WebViewInternal.prototype.maybeGetExperimentalEvents = function() {}; | 931 WebViewInternal.prototype.maybeGetExperimentalEvents = function() {}; |
935 WebViewInternal.prototype.setupExperimentalContextMenus = function() {}; | 932 WebViewInternal.prototype.setupExperimentalContextMenus = function() {}; |
936 | 933 |
937 // Exports. | 934 // Exports. |
938 exports.WebView = WebView; | 935 exports.WebView = WebView; |
939 exports.WebViewInternal = WebViewInternal; | 936 exports.WebViewInternal = WebViewInternal; |
OLD | NEW |