| 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 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 307 /** | 311 /** |
| 308 * @private | 312 * @private |
| 309 */ | 313 */ |
| 310 WebViewInternal.prototype.insertCSS = function(var_args) { | 314 WebViewInternal.prototype.insertCSS = function(var_args) { |
| 311 this.validateExecuteCodeCall(); | 315 this.validateExecuteCodeCall(); |
| 312 var args = $Array.concat([this.instanceId, this.src], | 316 var args = $Array.concat([this.instanceId, this.src], |
| 313 $Array.slice(arguments)); | 317 $Array.slice(arguments)); |
| 314 $Function.apply(WebView.insertCSS, null, args); | 318 $Function.apply(WebView.insertCSS, null, args); |
| 315 }; | 319 }; |
| 316 | 320 |
| 321 WebViewInternal.prototype.setupAutoSizeProperties = function() { |
| 322 var self = this; |
| 323 $Array.forEach(AUTO_SIZE_ATTRIBUTES, function(attributeName) { |
| 324 this[attributeName] = this.webviewNode.getAttribute(attributeName); |
| 325 Object.defineProperty(this.webviewNode, attributeName, { |
| 326 get: function() { |
| 327 return self[attributeName]; |
| 328 }, |
| 329 set: function(value) { |
| 330 self.webviewNode.setAttribute(attributeName, value); |
| 331 }, |
| 332 enumerable: true |
| 333 }); |
| 334 }, this); |
| 335 }; |
| 336 |
| 317 /** | 337 /** |
| 318 * @private | 338 * @private |
| 319 */ | 339 */ |
| 320 WebViewInternal.prototype.setupWebviewNodeProperties = function() { | 340 WebViewInternal.prototype.setupWebviewNodeProperties = function() { |
| 321 var ERROR_MSG_CONTENTWINDOW_NOT_AVAILABLE = '<webview>: ' + | 341 var ERROR_MSG_CONTENTWINDOW_NOT_AVAILABLE = '<webview>: ' + |
| 322 'contentWindow is not available at this time. It will become available ' + | 342 'contentWindow is not available at this time. It will become available ' + |
| 323 'when the page has finished loading.'; | 343 'when the page has finished loading.'; |
| 324 | 344 |
| 345 this.setupAutoSizeProperties(); |
| 325 var self = this; | 346 var self = this; |
| 326 var browserPluginNode = this.browserPluginNode; | 347 var browserPluginNode = this.browserPluginNode; |
| 327 // Expose getters and setters for the attributes. | 348 // Expose getters and setters for the attributes. |
| 328 $Array.forEach(WEB_VIEW_ATTRIBUTES, function(attributeName) { | 349 $Array.forEach(WEB_VIEW_ATTRIBUTES, function(attributeName) { |
| 329 Object.defineProperty(this.webviewNode, attributeName, { | 350 Object.defineProperty(this.webviewNode, attributeName, { |
| 330 get: function() { | 351 get: function() { |
| 331 if (browserPluginNode.hasOwnProperty(attributeName)) { | 352 if (browserPluginNode.hasOwnProperty(attributeName)) { |
| 332 return browserPluginNode[attributeName]; | 353 return browserPluginNode[attributeName]; |
| 333 } else { | 354 } else { |
| 334 return browserPluginNode.getAttribute(attributeName); | 355 return browserPluginNode.getAttribute(attributeName); |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 438 /** | 459 /** |
| 439 * @private | 460 * @private |
| 440 */ | 461 */ |
| 441 WebViewInternal.prototype.handleWebviewAttributeMutation = | 462 WebViewInternal.prototype.handleWebviewAttributeMutation = |
| 442 function(name, oldValue, newValue) { | 463 function(name, oldValue, newValue) { |
| 443 // This observer monitors mutations to attributes of the <webview> and | 464 // This observer monitors mutations to attributes of the <webview> and |
| 444 // updates the BrowserPlugin properties accordingly. In turn, updating | 465 // updates the BrowserPlugin properties accordingly. In turn, updating |
| 445 // a BrowserPlugin property will update the corresponding BrowserPlugin | 466 // a BrowserPlugin property will update the corresponding BrowserPlugin |
| 446 // attribute, if necessary. See BrowserPlugin::UpdateDOMAttribute for more | 467 // attribute, if necessary. See BrowserPlugin::UpdateDOMAttribute for more |
| 447 // details. | 468 // details. |
| 448 if (name == 'name') { | 469 if (AUTO_SIZE_ATTRIBUTES.indexOf(name) > -1) { |
| 470 this[name] = newValue; |
| 471 if (!this.instanceId) { |
| 472 return; |
| 473 } |
| 474 // Convert autosize attribute to boolean. |
| 475 var autosize = this.webviewNode.hasAttribute(WEB_VIEW_ATTRIBUTE_AUTOSIZE); |
| 476 WebView.setAutoSize(this.instanceId, { |
| 477 'enableAutoSize': autosize, |
| 478 'min': { |
| 479 'width': parseInt(this.minwidth || 0), |
| 480 'height': parseInt(this.minheight || 0) |
| 481 }, |
| 482 'max': { |
| 483 'width': parseInt(this.maxwidth || 0), |
| 484 'height': parseInt(this.maxheight || 0) |
| 485 } |
| 486 }); |
| 487 return; |
| 488 } else if (name == 'name') { |
| 449 // We treat null attribute (attribute removed) and the empty string as | 489 // We treat null attribute (attribute removed) and the empty string as |
| 450 // one case. | 490 // one case. |
| 451 oldValue = oldValue || ''; | 491 oldValue = oldValue || ''; |
| 452 newValue = newValue || ''; | 492 newValue = newValue || ''; |
| 453 | 493 |
| 454 if (oldValue === newValue) { | 494 if (oldValue === newValue) { |
| 455 return; | 495 return; |
| 456 } | 496 } |
| 457 this.name = newValue; | 497 this.name = newValue; |
| 458 if (!this.instanceId) { | 498 if (!this.instanceId) { |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 543 if (newValue != this.webviewNode.getAttribute(name)) { | 583 if (newValue != this.webviewNode.getAttribute(name)) { |
| 544 this.webviewNode.setAttribute(name, newValue); | 584 this.webviewNode.setAttribute(name, newValue); |
| 545 } | 585 } |
| 546 } else { | 586 } else { |
| 547 // If an attribute is removed from the BrowserPlugin, then remove it | 587 // If an attribute is removed from the BrowserPlugin, then remove it |
| 548 // from the <webview> as well. | 588 // from the <webview> as well. |
| 549 this.webviewNode.removeAttribute(name); | 589 this.webviewNode.removeAttribute(name); |
| 550 } | 590 } |
| 551 }; | 591 }; |
| 552 | 592 |
| 553 WebViewInternal.prototype.onSizeChanged = function(newWidth, newHeight) { | 593 WebViewInternal.prototype.onSizeChanged = function(webViewEvent) { |
| 594 var newWidth = webViewEvent.newWidth; |
| 595 var newHeight = webViewEvent.newHeight; |
| 596 |
| 554 var node = this.webviewNode; | 597 var node = this.webviewNode; |
| 555 | 598 |
| 556 var width = node.offsetWidth; | 599 var width = node.offsetWidth; |
| 557 var height = node.offsetHeight; | 600 var height = node.offsetHeight; |
| 558 | 601 |
| 559 // Check the current bounds to make sure we do not resize <webview> | 602 // Check the current bounds to make sure we do not resize <webview> |
| 560 // outside of current constraints. | 603 // outside of current constraints. |
| 561 var maxWidth; | 604 var maxWidth; |
| 562 if (node.hasAttribute(WEB_VIEW_ATTRIBUTE_MAXWIDTH) && | 605 if (node.hasAttribute(WEB_VIEW_ATTRIBUTE_MAXWIDTH) && |
| 563 node[WEB_VIEW_ATTRIBUTE_MAXWIDTH]) { | 606 node[WEB_VIEW_ATTRIBUTE_MAXWIDTH]) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 588 if (node.hasAttribute(WEB_VIEW_ATTRIBUTE_MINHEIGHT) && | 631 if (node.hasAttribute(WEB_VIEW_ATTRIBUTE_MINHEIGHT) && |
| 589 node[WEB_VIEW_ATTRIBUTE_MINHEIGHT]) { | 632 node[WEB_VIEW_ATTRIBUTE_MINHEIGHT]) { |
| 590 minHeight = node[WEB_VIEW_ATTRIBUTE_MINHEIGHT]; | 633 minHeight = node[WEB_VIEW_ATTRIBUTE_MINHEIGHT]; |
| 591 } else { | 634 } else { |
| 592 minHeight = height; | 635 minHeight = height; |
| 593 } | 636 } |
| 594 if (minHeight > maxHeight) { | 637 if (minHeight > maxHeight) { |
| 595 minHeight = maxHeight; | 638 minHeight = maxHeight; |
| 596 } | 639 } |
| 597 | 640 |
| 598 if (newWidth >= minWidth && | 641 if (!this.webviewNode.hasAttribute(WEB_VIEW_ATTRIBUTE_AUTOSIZE) || |
| 599 newWidth <= maxWidth && | 642 (newWidth >= minWidth && |
| 600 newHeight >= minHeight && | 643 newWidth <= maxWidth && |
| 601 newHeight <= maxHeight) { | 644 newHeight >= minHeight && |
| 645 newHeight <= maxHeight)) { |
| 602 node.style.width = newWidth + 'px'; | 646 node.style.width = newWidth + 'px'; |
| 603 node.style.height = newHeight + 'px'; | 647 node.style.height = newHeight + 'px'; |
| 648 // Only fire the DOM event if the size of the <webview> has actually |
| 649 // changed. |
| 650 this.dispatchEvent(webViewEvent); |
| 604 } | 651 } |
| 605 }; | 652 }; |
| 606 | 653 |
| 607 // Returns true if Browser Plugin bindings is available. | 654 // Returns true if Browser Plugin bindings is available. |
| 608 // Bindings are unavailable if <object> is not in the render tree. | 655 // Bindings are unavailable if <object> is not in the render tree. |
| 609 WebViewInternal.prototype.hasBindings = function() { | 656 WebViewInternal.prototype.hasBindings = function() { |
| 610 return 'function' == typeof this.browserPluginNode[PLUGIN_METHOD_ATTACH]; | 657 return 'function' == typeof this.browserPluginNode[PLUGIN_METHOD_ATTACH]; |
| 611 }; | 658 }; |
| 612 | 659 |
| 613 WebViewInternal.prototype.hasNavigated = function() { | 660 WebViewInternal.prototype.hasNavigated = function() { |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 776 | 823 |
| 777 WebViewInternal.prototype.getZoom = function(callback) { | 824 WebViewInternal.prototype.getZoom = function(callback) { |
| 778 if (!this.instanceId) { | 825 if (!this.instanceId) { |
| 779 return; | 826 return; |
| 780 } | 827 } |
| 781 WebView.getZoom(this.instanceId, callback); | 828 WebView.getZoom(this.instanceId, callback); |
| 782 }; | 829 }; |
| 783 | 830 |
| 784 WebViewInternal.prototype.buildAttachParams = function(isNewWindow) { | 831 WebViewInternal.prototype.buildAttachParams = function(isNewWindow) { |
| 785 var params = { | 832 var params = { |
| 786 'api': 'webview', | 833 'autosize': this.webviewNode.hasAttribute(WEB_VIEW_ATTRIBUTE_AUTOSIZE), |
| 787 'instanceId': this.viewInstanceId, | 834 'instanceId': this.viewInstanceId, |
| 835 'maxheight': parseInt(this.maxheight || 0), |
| 836 'maxwidth': parseInt(this.maxwidth || 0), |
| 837 'minheight': parseInt(this.minheight || 0), |
| 838 'minwidth': parseInt(this.minwidth || 0), |
| 788 'name': this.name, | 839 'name': this.name, |
| 789 // We don't need to navigate new window from here. | 840 // We don't need to navigate new window from here. |
| 790 'src': isNewWindow ? undefined : this.src, | 841 'src': isNewWindow ? undefined : this.src, |
| 791 // If we have a partition from the opener, that will also be already | 842 // If we have a partition from the opener, that will also be already |
| 792 // set via this.onAttach(). | 843 // set via this.onAttach(). |
| 793 'storagePartitionId': this.partition.toAttribute(), | 844 'storagePartitionId': this.partition.toAttribute(), |
| 794 'userAgentOverride': this.userAgentOverride | 845 'userAgentOverride': this.userAgentOverride |
| 795 }; | 846 }; |
| 796 return params; | 847 return params; |
| 797 }; | 848 }; |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 962 }; | 1013 }; |
| 963 | 1014 |
| 964 /** | 1015 /** |
| 965 * Implemented when the experimental API is available. | 1016 * Implemented when the experimental API is available. |
| 966 * @private | 1017 * @private |
| 967 */ | 1018 */ |
| 968 WebViewInternal.prototype.setupExperimentalContextMenus = function() {}; | 1019 WebViewInternal.prototype.setupExperimentalContextMenus = function() {}; |
| 969 | 1020 |
| 970 exports.WebView = WebView; | 1021 exports.WebView = WebView; |
| 971 exports.WebViewInternal = WebViewInternal; | 1022 exports.WebViewInternal = WebViewInternal; |
| OLD | NEW |