OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // This module implements Webview (<webview>) as a custom element that wraps a | 5 // This module implements Webview (<webview>) as a custom element that wraps a |
6 // BrowserPlugin object element. The object element is hidden within | 6 // BrowserPlugin object element. The object element is hidden within |
7 // the shadow DOM of the Webview element. | 7 // the shadow DOM of the Webview element. |
8 | 8 |
9 var DocumentNatives = requireNative('document_natives'); | 9 var DocumentNatives = requireNative('document_natives'); |
10 var GuestViewInternal = | 10 var GuestViewInternal = |
11 require('binding').Binding.create('guestViewInternal').generate(); | 11 require('binding').Binding.create('guestViewInternal').generate(); |
12 var IdGenerator = requireNative('id_generator'); | 12 var IdGenerator = requireNative('id_generator'); |
13 // TODO(lazyboy): Rename this to WebViewInternal and call WebViewInternal | 13 // TODO(lazyboy): Rename this to WebViewInternal and call WebViewInternal |
14 // something else. | 14 // something else. |
15 var WebView = require('webViewInternal').WebView; | 15 var WebView = require('webViewInternal').WebView; |
16 var WebViewEvents = require('webViewEvents').WebViewEvents; | 16 var WebViewEvents = require('webViewEvents').WebViewEvents; |
17 | 17 |
| 18 var WEB_VIEW_ATTRIBUTE_AUTOSIZE = 'autosize'; |
18 var WEB_VIEW_ATTRIBUTE_MAXHEIGHT = 'maxheight'; | 19 var WEB_VIEW_ATTRIBUTE_MAXHEIGHT = 'maxheight'; |
19 var WEB_VIEW_ATTRIBUTE_MAXWIDTH = 'maxwidth'; | 20 var WEB_VIEW_ATTRIBUTE_MAXWIDTH = 'maxwidth'; |
20 var WEB_VIEW_ATTRIBUTE_MINHEIGHT = 'minheight'; | 21 var WEB_VIEW_ATTRIBUTE_MINHEIGHT = 'minheight'; |
21 var WEB_VIEW_ATTRIBUTE_MINWIDTH = 'minwidth'; | 22 var WEB_VIEW_ATTRIBUTE_MINWIDTH = 'minwidth'; |
| 23 var AUTO_SIZE_ATTRIBUTES = [ |
| 24 WEB_VIEW_ATTRIBUTE_AUTOSIZE, |
| 25 WEB_VIEW_ATTRIBUTE_MAXHEIGHT, |
| 26 WEB_VIEW_ATTRIBUTE_MAXWIDTH, |
| 27 WEB_VIEW_ATTRIBUTE_MINHEIGHT, |
| 28 WEB_VIEW_ATTRIBUTE_MINWIDTH |
| 29 ]; |
| 30 |
22 var WEB_VIEW_ATTRIBUTE_PARTITION = 'partition'; | 31 var WEB_VIEW_ATTRIBUTE_PARTITION = 'partition'; |
23 | 32 |
24 var PLUGIN_METHOD_ATTACH = '-internal-attach'; | 33 var PLUGIN_METHOD_ATTACH = '-internal-attach'; |
25 | 34 |
26 var ERROR_MSG_ALREADY_NAVIGATED = | 35 var ERROR_MSG_ALREADY_NAVIGATED = |
27 'The object has already navigated, so its partition cannot be changed.'; | 36 'The object has already navigated, so its partition cannot be changed.'; |
28 var ERROR_MSG_INVALID_PARTITION_ATTRIBUTE = 'Invalid partition attribute.'; | 37 var ERROR_MSG_INVALID_PARTITION_ATTRIBUTE = 'Invalid partition attribute.'; |
29 | 38 |
30 /** @type {Array.<string>} */ | 39 /** @type {Array.<string>} */ |
31 var WEB_VIEW_ATTRIBUTES = [ | 40 var WEB_VIEW_ATTRIBUTES = [ |
32 'allowtransparency', | 41 'allowtransparency', |
33 'autosize', | |
34 WEB_VIEW_ATTRIBUTE_MINHEIGHT, | |
35 WEB_VIEW_ATTRIBUTE_MINWIDTH, | |
36 WEB_VIEW_ATTRIBUTE_MAXHEIGHT, | |
37 WEB_VIEW_ATTRIBUTE_MAXWIDTH | |
38 ]; | 42 ]; |
39 | 43 |
40 /** @class representing state of storage partition. */ | 44 /** @class representing state of storage partition. */ |
41 function Partition() { | 45 function Partition() { |
42 this.validPartitionId = true; | 46 this.validPartitionId = true; |
43 this.persistStorage = false; | 47 this.persistStorage = false; |
44 this.storagePartitionId = ''; | 48 this.storagePartitionId = ''; |
45 }; | 49 }; |
46 | 50 |
47 Partition.prototype.toAttribute = function() { | 51 Partition.prototype.toAttribute = function() { |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 /** | 312 /** |
309 * @private | 313 * @private |
310 */ | 314 */ |
311 WebViewInternal.prototype.insertCSS = function(var_args) { | 315 WebViewInternal.prototype.insertCSS = function(var_args) { |
312 this.validateExecuteCodeCall(); | 316 this.validateExecuteCodeCall(); |
313 var args = $Array.concat([this.instanceId, this.src], | 317 var args = $Array.concat([this.instanceId, this.src], |
314 $Array.slice(arguments)); | 318 $Array.slice(arguments)); |
315 $Function.apply(WebView.insertCSS, null, args); | 319 $Function.apply(WebView.insertCSS, null, args); |
316 }; | 320 }; |
317 | 321 |
| 322 WebViewInternal.prototype.setupAutoSizeProperties = function() { |
| 323 var self = this; |
| 324 $Array.forEach(AUTO_SIZE_ATTRIBUTES, function(attributeName) { |
| 325 this[attributeName] = this.webviewNode.getAttribute(attributeName); |
| 326 Object.defineProperty(this.webviewNode, attributeName, { |
| 327 get: function() { |
| 328 return self[attributeName]; |
| 329 }, |
| 330 set: function(value) { |
| 331 self.webviewNode.setAttribute(attributeName, value); |
| 332 }, |
| 333 enumerable: true |
| 334 }); |
| 335 }, this); |
| 336 }; |
| 337 |
318 /** | 338 /** |
319 * @private | 339 * @private |
320 */ | 340 */ |
321 WebViewInternal.prototype.setupWebviewNodeProperties = function() { | 341 WebViewInternal.prototype.setupWebviewNodeProperties = function() { |
322 var ERROR_MSG_CONTENTWINDOW_NOT_AVAILABLE = '<webview>: ' + | 342 var ERROR_MSG_CONTENTWINDOW_NOT_AVAILABLE = '<webview>: ' + |
323 'contentWindow is not available at this time. It will become available ' + | 343 'contentWindow is not available at this time. It will become available ' + |
324 'when the page has finished loading.'; | 344 'when the page has finished loading.'; |
325 | 345 |
| 346 this.setupAutoSizeProperties(); |
326 var self = this; | 347 var self = this; |
327 var browserPluginNode = this.browserPluginNode; | 348 var browserPluginNode = this.browserPluginNode; |
328 // Expose getters and setters for the attributes. | 349 // Expose getters and setters for the attributes. |
329 $Array.forEach(WEB_VIEW_ATTRIBUTES, function(attributeName) { | 350 $Array.forEach(WEB_VIEW_ATTRIBUTES, function(attributeName) { |
330 Object.defineProperty(this.webviewNode, attributeName, { | 351 Object.defineProperty(this.webviewNode, attributeName, { |
331 get: function() { | 352 get: function() { |
332 if (browserPluginNode.hasOwnProperty(attributeName)) { | 353 if (browserPluginNode.hasOwnProperty(attributeName)) { |
333 return browserPluginNode[attributeName]; | 354 return browserPluginNode[attributeName]; |
334 } else { | 355 } else { |
335 return browserPluginNode.getAttribute(attributeName); | 356 return browserPluginNode.getAttribute(attributeName); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
439 /** | 460 /** |
440 * @private | 461 * @private |
441 */ | 462 */ |
442 WebViewInternal.prototype.handleWebviewAttributeMutation = | 463 WebViewInternal.prototype.handleWebviewAttributeMutation = |
443 function(name, oldValue, newValue) { | 464 function(name, oldValue, newValue) { |
444 // This observer monitors mutations to attributes of the <webview> and | 465 // This observer monitors mutations to attributes of the <webview> and |
445 // updates the BrowserPlugin properties accordingly. In turn, updating | 466 // updates the BrowserPlugin properties accordingly. In turn, updating |
446 // a BrowserPlugin property will update the corresponding BrowserPlugin | 467 // a BrowserPlugin property will update the corresponding BrowserPlugin |
447 // attribute, if necessary. See BrowserPlugin::UpdateDOMAttribute for more | 468 // attribute, if necessary. See BrowserPlugin::UpdateDOMAttribute for more |
448 // details. | 469 // details. |
449 if (name == 'name') { | 470 if (AUTO_SIZE_ATTRIBUTES.indexOf(name) > -1) { |
| 471 this[name] = newValue; |
| 472 if (!this.instanceId) { |
| 473 return; |
| 474 } |
| 475 // Convert autosize attribute to boolean. |
| 476 var autosize = this.webviewNode.hasAttribute(WEB_VIEW_ATTRIBUTE_AUTOSIZE); |
| 477 GuestViewInternal.setAutoSize(this.instanceId, { |
| 478 'enableAutoSize': autosize, |
| 479 'min': { |
| 480 'width': parseInt(this.minwidth || 0), |
| 481 'height': parseInt(this.minheight || 0) |
| 482 }, |
| 483 'max': { |
| 484 'width': parseInt(this.maxwidth || 0), |
| 485 'height': parseInt(this.maxheight || 0) |
| 486 } |
| 487 }); |
| 488 return; |
| 489 } else if (name == 'name') { |
450 // We treat null attribute (attribute removed) and the empty string as | 490 // We treat null attribute (attribute removed) and the empty string as |
451 // one case. | 491 // one case. |
452 oldValue = oldValue || ''; | 492 oldValue = oldValue || ''; |
453 newValue = newValue || ''; | 493 newValue = newValue || ''; |
454 | 494 |
455 if (oldValue === newValue) { | 495 if (oldValue === newValue) { |
456 return; | 496 return; |
457 } | 497 } |
458 this.name = newValue; | 498 this.name = newValue; |
459 if (!this.instanceId) { | 499 if (!this.instanceId) { |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
544 if (newValue != this.webviewNode.getAttribute(name)) { | 584 if (newValue != this.webviewNode.getAttribute(name)) { |
545 this.webviewNode.setAttribute(name, newValue); | 585 this.webviewNode.setAttribute(name, newValue); |
546 } | 586 } |
547 } else { | 587 } else { |
548 // If an attribute is removed from the BrowserPlugin, then remove it | 588 // If an attribute is removed from the BrowserPlugin, then remove it |
549 // from the <webview> as well. | 589 // from the <webview> as well. |
550 this.webviewNode.removeAttribute(name); | 590 this.webviewNode.removeAttribute(name); |
551 } | 591 } |
552 }; | 592 }; |
553 | 593 |
554 WebViewInternal.prototype.onSizeChanged = function(newWidth, newHeight) { | 594 WebViewInternal.prototype.onSizeChanged = function(webViewEvent) { |
| 595 var newWidth = webViewEvent.newWidth; |
| 596 var newHeight = webViewEvent.newHeight; |
| 597 |
555 var node = this.webviewNode; | 598 var node = this.webviewNode; |
556 | 599 |
557 var width = node.offsetWidth; | 600 var width = node.offsetWidth; |
558 var height = node.offsetHeight; | 601 var height = node.offsetHeight; |
559 | 602 |
560 // Check the current bounds to make sure we do not resize <webview> | 603 // Check the current bounds to make sure we do not resize <webview> |
561 // outside of current constraints. | 604 // outside of current constraints. |
562 var maxWidth; | 605 var maxWidth; |
563 if (node.hasAttribute(WEB_VIEW_ATTRIBUTE_MAXWIDTH) && | 606 if (node.hasAttribute(WEB_VIEW_ATTRIBUTE_MAXWIDTH) && |
564 node[WEB_VIEW_ATTRIBUTE_MAXWIDTH]) { | 607 node[WEB_VIEW_ATTRIBUTE_MAXWIDTH]) { |
(...skipping 24 matching lines...) Expand all Loading... |
589 if (node.hasAttribute(WEB_VIEW_ATTRIBUTE_MINHEIGHT) && | 632 if (node.hasAttribute(WEB_VIEW_ATTRIBUTE_MINHEIGHT) && |
590 node[WEB_VIEW_ATTRIBUTE_MINHEIGHT]) { | 633 node[WEB_VIEW_ATTRIBUTE_MINHEIGHT]) { |
591 minHeight = node[WEB_VIEW_ATTRIBUTE_MINHEIGHT]; | 634 minHeight = node[WEB_VIEW_ATTRIBUTE_MINHEIGHT]; |
592 } else { | 635 } else { |
593 minHeight = height; | 636 minHeight = height; |
594 } | 637 } |
595 if (minHeight > maxHeight) { | 638 if (minHeight > maxHeight) { |
596 minHeight = maxHeight; | 639 minHeight = maxHeight; |
597 } | 640 } |
598 | 641 |
599 if (newWidth >= minWidth && | 642 if (!this.webviewNode.hasAttribute(WEB_VIEW_ATTRIBUTE_AUTOSIZE) || |
600 newWidth <= maxWidth && | 643 (newWidth >= minWidth && |
601 newHeight >= minHeight && | 644 newWidth <= maxWidth && |
602 newHeight <= maxHeight) { | 645 newHeight >= minHeight && |
| 646 newHeight <= maxHeight)) { |
603 node.style.width = newWidth + 'px'; | 647 node.style.width = newWidth + 'px'; |
604 node.style.height = newHeight + 'px'; | 648 node.style.height = newHeight + 'px'; |
| 649 // Only fire the DOM event if the size of the <webview> has actually |
| 650 // changed. |
| 651 this.dispatchEvent(webViewEvent); |
605 } | 652 } |
606 }; | 653 }; |
607 | 654 |
608 // Returns true if Browser Plugin bindings is available. | 655 // Returns true if Browser Plugin bindings is available. |
609 // Bindings are unavailable if <object> is not in the render tree. | 656 // Bindings are unavailable if <object> is not in the render tree. |
610 WebViewInternal.prototype.hasBindings = function() { | 657 WebViewInternal.prototype.hasBindings = function() { |
611 return 'function' == typeof this.browserPluginNode[PLUGIN_METHOD_ATTACH]; | 658 return 'function' == typeof this.browserPluginNode[PLUGIN_METHOD_ATTACH]; |
612 }; | 659 }; |
613 | 660 |
614 WebViewInternal.prototype.hasNavigated = function() { | 661 WebViewInternal.prototype.hasNavigated = function() { |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
781 | 828 |
782 WebViewInternal.prototype.getZoom = function(callback) { | 829 WebViewInternal.prototype.getZoom = function(callback) { |
783 if (!this.instanceId) { | 830 if (!this.instanceId) { |
784 return; | 831 return; |
785 } | 832 } |
786 WebView.getZoom(this.instanceId, callback); | 833 WebView.getZoom(this.instanceId, callback); |
787 }; | 834 }; |
788 | 835 |
789 WebViewInternal.prototype.buildAttachParams = function(isNewWindow) { | 836 WebViewInternal.prototype.buildAttachParams = function(isNewWindow) { |
790 var params = { | 837 var params = { |
791 'api': 'webview', | 838 'autosize': this.webviewNode.hasAttribute(WEB_VIEW_ATTRIBUTE_AUTOSIZE), |
792 'instanceId': this.viewInstanceId, | 839 'instanceId': this.viewInstanceId, |
| 840 'maxheight': parseInt(this.maxheight || 0), |
| 841 'maxwidth': parseInt(this.maxwidth || 0), |
| 842 'minheight': parseInt(this.minheight || 0), |
| 843 'minwidth': parseInt(this.minwidth || 0), |
793 'name': this.name, | 844 'name': this.name, |
794 // We don't need to navigate new window from here. | 845 // We don't need to navigate new window from here. |
795 'src': isNewWindow ? undefined : this.src, | 846 'src': isNewWindow ? undefined : this.src, |
796 // If we have a partition from the opener, that will also be already | 847 // If we have a partition from the opener, that will also be already |
797 // set via this.onAttach(). | 848 // set via this.onAttach(). |
798 'storagePartitionId': this.partition.toAttribute(), | 849 'storagePartitionId': this.partition.toAttribute(), |
799 'userAgentOverride': this.userAgentOverride | 850 'userAgentOverride': this.userAgentOverride |
800 }; | 851 }; |
801 return params; | 852 return params; |
802 }; | 853 }; |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
972 }; | 1023 }; |
973 | 1024 |
974 /** | 1025 /** |
975 * Implemented when the experimental API is available. | 1026 * Implemented when the experimental API is available. |
976 * @private | 1027 * @private |
977 */ | 1028 */ |
978 WebViewInternal.prototype.setupExperimentalContextMenus = function() {}; | 1029 WebViewInternal.prototype.setupExperimentalContextMenus = function() {}; |
979 | 1030 |
980 exports.WebView = WebView; | 1031 exports.WebView = WebView; |
981 exports.WebViewInternal = WebViewInternal; | 1032 exports.WebViewInternal = WebViewInternal; |
OLD | NEW |