Chromium Code Reviews| 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 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 = 'Invalid partition attribute.'; | |
| 24 | 30 |
| 25 /** @type {Array.<string>} */ | 31 /** @type {Array.<string>} */ |
| 26 var WEB_VIEW_ATTRIBUTES = [ | 32 var WEB_VIEW_ATTRIBUTES = [ |
| 27 'allowtransparency', | 33 'allowtransparency', |
| 28 'autosize', | 34 'autosize', |
| 29 'partition', | |
| 30 WEB_VIEW_ATTRIBUTE_MINHEIGHT, | 35 WEB_VIEW_ATTRIBUTE_MINHEIGHT, |
| 31 WEB_VIEW_ATTRIBUTE_MINWIDTH, | 36 WEB_VIEW_ATTRIBUTE_MINWIDTH, |
| 32 WEB_VIEW_ATTRIBUTE_MAXHEIGHT, | 37 WEB_VIEW_ATTRIBUTE_MAXHEIGHT, |
| 33 WEB_VIEW_ATTRIBUTE_MAXWIDTH | 38 WEB_VIEW_ATTRIBUTE_MAXWIDTH |
| 34 ]; | 39 ]; |
| 35 | 40 |
| 41 /** @class representing state of storage partition. */ | |
| 42 function Partition() { | |
| 43 this.validPartitionId = true; | |
| 44 this.persist_storage_ = false; | |
| 45 this.storage_partition_id = ''; | |
| 46 }; | |
| 47 | |
| 48 Partition.prototype.toAttribute = function() { | |
| 49 if (!this.validPartitionId) { | |
| 50 return ''; | |
| 51 } | |
| 52 return (this.persist_storage_ ? 'persist:' : '') + this.storage_partition_id; | |
| 53 }; | |
| 54 | |
| 55 Partition.prototype.fromAttribute = function(value, hasNavigated) { | |
| 56 var result = {}; | |
| 57 if (hasNavigated) { | |
| 58 result.error = ERROR_MSG_ALREADY_NAVIGATED; | |
| 59 return result; | |
| 60 } | |
| 61 if (!value) { | |
| 62 value = ''; | |
| 63 } | |
| 64 | |
| 65 var LEN = 'persist:'.length; | |
| 66 if (value.substr(0, LEN) == 'persist:') { | |
| 67 value = value.substr(LEN); | |
| 68 if (!value) { | |
| 69 this.validPartitionId = false; | |
| 70 result.error = ERROR_MSG_INVALID_PARTITION_ATTRIBUTE; | |
| 71 return result; | |
| 72 } | |
| 73 this.persist_storage_ = true; | |
| 74 } else { | |
| 75 this.persist_storage_ = false; | |
| 76 } | |
| 77 | |
| 78 this.storage_partition_id = value; | |
| 79 return result; | |
| 80 }; | |
| 81 | |
| 36 var CreateEvent = function(name) { | 82 var CreateEvent = function(name) { |
| 37 var eventOpts = {supportsListeners: true, supportsFilters: true}; | 83 var eventOpts = {supportsListeners: true, supportsFilters: true}; |
| 38 return new EventBindings.Event(name, undefined, eventOpts); | 84 return new EventBindings.Event(name, undefined, eventOpts); |
| 39 }; | 85 }; |
| 40 | 86 |
| 41 // WEB_VIEW_EVENTS is a map of stable <webview> DOM event names to their | 87 // WEB_VIEW_EVENTS is a map of stable <webview> DOM event names to their |
| 42 // associated extension event descriptor objects. | 88 // associated extension event descriptor objects. |
| 43 // An event listener will be attached to the extension event |evt| specified in | 89 // An event listener will be attached to the extension event |evt| specified in |
| 44 // the descriptor. | 90 // the descriptor. |
| 45 // |fields| specifies the public-facing fields in the DOM event that are | 91 // |fields| specifies the public-facing fields in the DOM event that are |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 169 // Implemented when the experimental API is available. | 215 // Implemented when the experimental API is available. |
| 170 WebViewInternal.maybeRegisterExperimentalAPIs = function(proto) {} | 216 WebViewInternal.maybeRegisterExperimentalAPIs = function(proto) {} |
| 171 | 217 |
| 172 /** | 218 /** |
| 173 * @constructor | 219 * @constructor |
| 174 */ | 220 */ |
| 175 function WebViewInternal(webviewNode) { | 221 function WebViewInternal(webviewNode) { |
| 176 privates(webviewNode).internal = this; | 222 privates(webviewNode).internal = this; |
| 177 this.webviewNode = webviewNode; | 223 this.webviewNode = webviewNode; |
| 178 this.attached = false; | 224 this.attached = false; |
| 225 | |
| 226 this.beforeFirstNavigation = true; | |
| 227 this.validPartitionId = true; | |
| 228 | |
| 179 this.browserPluginNode = this.createBrowserPluginNode(); | 229 this.browserPluginNode = this.createBrowserPluginNode(); |
| 180 var shadowRoot = this.webviewNode.createShadowRoot(); | 230 var shadowRoot = this.webviewNode.createShadowRoot(); |
| 181 shadowRoot.appendChild(this.browserPluginNode); | 231 shadowRoot.appendChild(this.browserPluginNode); |
| 182 | 232 |
| 183 this.setupWebviewNodeAttributes(); | 233 this.setupWebviewNodeAttributes(); |
| 184 this.setupFocusPropagation(); | 234 this.setupFocusPropagation(); |
| 185 this.setupWebviewNodeProperties(); | 235 this.setupWebviewNodeProperties(); |
| 236 | |
| 237 this.viewInstanceId = IdGenerator.GetNextId(); | |
| 238 | |
| 239 //this.allocateInstanceId(); | |
|
Fady Samuel
2014/06/04 04:54:18
Remove this?
| |
| 240 this.partition = new Partition(); | |
| 241 this.parseAttributes(); | |
| 242 | |
| 186 this.setupWebviewNodeEvents(); | 243 this.setupWebviewNodeEvents(); |
| 187 } | 244 } |
| 188 | 245 |
| 189 /** | 246 /** |
| 190 * @private | 247 * @private |
| 191 */ | 248 */ |
| 192 WebViewInternal.prototype.createBrowserPluginNode = function() { | 249 WebViewInternal.prototype.createBrowserPluginNode = function() { |
| 193 // We create BrowserPlugin as a custom element in order to observe changes | 250 // We create BrowserPlugin as a custom element in order to observe changes |
| 194 // to attributes synchronously. | 251 // to attributes synchronously. |
| 195 var browserPluginNode = new WebViewInternal.BrowserPlugin(); | 252 var browserPluginNode = new WebViewInternal.BrowserPlugin(); |
| 196 privates(browserPluginNode).internal = this; | 253 privates(browserPluginNode).internal = this; |
| 197 | 254 |
| 198 var ALL_ATTRIBUTES = WEB_VIEW_ATTRIBUTES.concat(['src']); | 255 $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 | 256 // Only copy attributes that have been assigned values, rather than copying |
| 201 // a series of undefined attributes to BrowserPlugin. | 257 // a series of undefined attributes to BrowserPlugin. |
| 202 if (this.webviewNode.hasAttribute(attributeName)) { | 258 if (this.webviewNode.hasAttribute(attributeName)) { |
| 203 browserPluginNode.setAttribute( | 259 browserPluginNode.setAttribute( |
| 204 attributeName, this.webviewNode.getAttribute(attributeName)); | 260 attributeName, this.webviewNode.getAttribute(attributeName)); |
| 205 } else if (this.webviewNode[attributeName]){ | 261 } else if (this.webviewNode[attributeName]){ |
| 206 // Reading property using has/getAttribute does not work on | 262 // Reading property using has/getAttribute does not work on |
| 207 // document.DOMContentLoaded event (but works on | 263 // document.DOMContentLoaded event (but works on |
| 208 // window.DOMContentLoaded event). | 264 // window.DOMContentLoaded event). |
| 209 // So copy from property if copying from attribute fails. | 265 // So copy from property if copying from attribute fails. |
| 210 browserPluginNode.setAttribute( | 266 browserPluginNode.setAttribute( |
| 211 attributeName, this.webviewNode[attributeName]); | 267 attributeName, this.webviewNode[attributeName]); |
| 212 } | 268 } |
| 213 }, this); | 269 }, this); |
| 214 | 270 |
| 215 return browserPluginNode; | 271 return browserPluginNode; |
| 216 }; | 272 }; |
| 217 | 273 |
| 218 /** | 274 /** |
| 219 * @private | 275 * @private |
| 276 * Resets some state upon re-attaching <webview> element to the DOM. | |
| 277 */ | |
| 278 WebViewInternal.prototype.resetUponReattachment = function() { | |
| 279 this.instanceId = undefined; | |
| 280 this.beforeFirstNavigation = true; | |
| 281 this.validPartitionId = true; | |
| 282 this.partition.validPartitionId = true; | |
| 283 }; | |
| 284 | |
| 285 /** | |
| 286 * @private | |
| 220 */ | 287 */ |
| 221 WebViewInternal.prototype.setupFocusPropagation = function() { | 288 WebViewInternal.prototype.setupFocusPropagation = function() { |
| 222 if (!this.webviewNode.hasAttribute('tabIndex')) { | 289 if (!this.webviewNode.hasAttribute('tabIndex')) { |
| 223 // <webview> needs a tabIndex in order to be focusable. | 290 // <webview> needs a tabIndex in order to be focusable. |
| 224 // TODO(fsamuel): It would be nice to avoid exposing a tabIndex attribute | 291 // TODO(fsamuel): It would be nice to avoid exposing a tabIndex attribute |
| 225 // to allow <webview> to be focusable. | 292 // to allow <webview> to be focusable. |
| 226 // See http://crbug.com/231664. | 293 // See http://crbug.com/231664. |
| 227 this.webviewNode.setAttribute('tabIndex', -1); | 294 this.webviewNode.setAttribute('tabIndex', -1); |
| 228 } | 295 } |
| 229 var self = this; | 296 var self = this; |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 return self.partition.toAttribute(); | |
| 472 }, | |
| 473 set: function(value) { | |
| 474 var result = self.partition.fromAttribute(value, self.hasNavigated()); | |
| 475 if (result.error) { | |
| 476 throw result.error; | |
| 477 } | |
| 478 self.webviewNode.setAttribute('partition', value); | |
| 479 }, | |
| 480 enumerable: true | |
| 481 }); | |
| 482 | |
| 402 // We cannot use {writable: true} property descriptor because we want a | 483 // We cannot use {writable: true} property descriptor because we want a |
| 403 // dynamic getter value. | 484 // dynamic getter value. |
| 404 Object.defineProperty(this.webviewNode, 'contentWindow', { | 485 Object.defineProperty(this.webviewNode, 'contentWindow', { |
| 405 get: function() { | 486 get: function() { |
| 406 if (browserPluginNode.contentWindow) | 487 if (browserPluginNode.contentWindow) |
| 407 return browserPluginNode.contentWindow; | 488 return browserPluginNode.contentWindow; |
| 408 window.console.error(ERROR_MSG_CONTENTWINDOW_NOT_AVAILABLE); | 489 window.console.error(ERROR_MSG_CONTENTWINDOW_NOT_AVAILABLE); |
| 409 }, | 490 }, |
| 410 // No setter. | 491 // No setter. |
| 411 enumerable: true | 492 enumerable: true |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 422 /** | 503 /** |
| 423 * @private | 504 * @private |
| 424 */ | 505 */ |
| 425 WebViewInternal.prototype.setupWebViewSrcAttributeMutationObserver = | 506 WebViewInternal.prototype.setupWebViewSrcAttributeMutationObserver = |
| 426 function() { | 507 function() { |
| 427 // The purpose of this mutation observer is to catch assignment to the src | 508 // 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 | 509 // 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 | 510 // where the webview guest has crashed and navigating to the same address |
| 430 // spawns off a new process. | 511 // spawns off a new process. |
| 431 var self = this; | 512 var self = this; |
| 432 this.srcObserver = new MutationObserver(function(mutations) { | 513 this.srcAndPartitionObserver = new MutationObserver(function(mutations) { |
| 433 $Array.forEach(mutations, function(mutation) { | 514 $Array.forEach(mutations, function(mutation) { |
| 434 var oldValue = mutation.oldValue; | 515 var oldValue = mutation.oldValue; |
| 435 var newValue = self.webviewNode.getAttribute(mutation.attributeName); | 516 var newValue = self.webviewNode.getAttribute(mutation.attributeName); |
| 436 if (oldValue != newValue) { | 517 if (oldValue != newValue) { |
| 437 return; | 518 return; |
| 438 } | 519 } |
| 439 self.handleWebviewAttributeMutation( | 520 self.handleWebviewAttributeMutation( |
| 440 mutation.attributeName, oldValue, newValue); | 521 mutation.attributeName, oldValue, newValue); |
| 441 }); | 522 }); |
| 442 }); | 523 }); |
| 443 var params = { | 524 var params = { |
| 444 attributes: true, | 525 attributes: true, |
| 445 attributeOldValue: true, | 526 attributeOldValue: true, |
| 446 attributeFilter: ['src'] | 527 attributeFilter: ['src', 'partition'] |
| 447 }; | 528 }; |
| 448 this.srcObserver.observe(this.webviewNode, params); | 529 this.srcAndPartitionObserver.observe(this.webviewNode, params); |
| 449 }; | 530 }; |
| 450 | 531 |
| 451 /** | 532 /** |
| 452 * @private | 533 * @private |
| 453 */ | 534 */ |
| 454 WebViewInternal.prototype.handleWebviewAttributeMutation = | 535 WebViewInternal.prototype.handleWebviewAttributeMutation = |
| 455 function(name, oldValue, newValue) { | 536 function(name, oldValue, newValue) { |
| 456 // This observer monitors mutations to attributes of the <webview> and | 537 // This observer monitors mutations to attributes of the <webview> and |
| 457 // updates the BrowserPlugin properties accordingly. In turn, updating | 538 // updates the BrowserPlugin properties accordingly. In turn, updating |
| 458 // a BrowserPlugin property will update the corresponding BrowserPlugin | 539 // a BrowserPlugin property will update the corresponding BrowserPlugin |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 485 // src attribute changes normally initiate a navigation. We suppress | 566 // src attribute changes normally initiate a navigation. We suppress |
| 486 // the next src attribute handler call to avoid reloading the page | 567 // the next src attribute handler call to avoid reloading the page |
| 487 // on every guest-initiated navigation. | 568 // on every guest-initiated navigation. |
| 488 this.ignoreNextSrcAttributeChange = true; | 569 this.ignoreNextSrcAttributeChange = true; |
| 489 this.webviewNode.setAttribute('src', oldValue); | 570 this.webviewNode.setAttribute('src', oldValue); |
| 490 return; | 571 return; |
| 491 } | 572 } |
| 492 this.src = newValue; | 573 this.src = newValue; |
| 493 if (this.ignoreNextSrcAttributeChange) { | 574 if (this.ignoreNextSrcAttributeChange) { |
| 494 // Don't allow the src mutation observer to see this change. | 575 // Don't allow the src mutation observer to see this change. |
| 495 this.srcObserver.takeRecords(); | 576 this.srcAndPartitionObserver.takeRecords(); |
| 496 this.ignoreNextSrcAttributeChange = false; | 577 this.ignoreNextSrcAttributeChange = false; |
| 497 return; | 578 return; |
| 498 } | 579 } |
| 580 var result = {}; | |
| 581 this.parseSrcAttribute(result); | |
| 582 | |
| 583 if (result.error) { | |
| 584 throw result.error; | |
| 585 } | |
| 586 } else if (name == 'partition') { | |
| 587 // Note that throwing error here won't synchronously propagate. | |
| 588 this.partition.fromAttribute(newValue, this.hasNavigated()); | |
| 499 } | 589 } |
| 590 | |
| 591 // No <webview> -> <object> mutation propagation for these attributes. | |
| 592 if (name == 'src' || name == 'partition') { | |
| 593 return; | |
| 594 } | |
| 595 | |
| 500 if (this.browserPluginNode.hasOwnProperty(name)) { | 596 if (this.browserPluginNode.hasOwnProperty(name)) { |
| 501 this.browserPluginNode[name] = newValue; | 597 this.browserPluginNode[name] = newValue; |
| 502 } else { | 598 } else { |
| 503 this.browserPluginNode.setAttribute(name, newValue); | 599 this.browserPluginNode.setAttribute(name, newValue); |
| 504 } | 600 } |
| 505 }; | 601 }; |
| 506 | 602 |
| 507 /** | 603 /** |
| 508 * @private | 604 * @private |
| 509 */ | 605 */ |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 590 if (webViewEvent.newWidth >= minWidth && | 686 if (webViewEvent.newWidth >= minWidth && |
| 591 webViewEvent.newWidth <= maxWidth && | 687 webViewEvent.newWidth <= maxWidth && |
| 592 webViewEvent.newHeight >= minHeight && | 688 webViewEvent.newHeight >= minHeight && |
| 593 webViewEvent.newHeight <= maxHeight) { | 689 webViewEvent.newHeight <= maxHeight) { |
| 594 node.style.width = webViewEvent.newWidth + 'px'; | 690 node.style.width = webViewEvent.newWidth + 'px'; |
| 595 node.style.height = webViewEvent.newHeight + 'px'; | 691 node.style.height = webViewEvent.newHeight + 'px'; |
| 596 } | 692 } |
| 597 node.dispatchEvent(webViewEvent); | 693 node.dispatchEvent(webViewEvent); |
| 598 }; | 694 }; |
| 599 | 695 |
| 696 WebViewInternal.prototype.hasNavigated = function() { | |
| 697 return !this.beforeFirstNavigation; | |
| 698 }; | |
| 699 | |
| 700 /** @return {boolean} */ | |
| 701 WebViewInternal.prototype.parseSrcAttribute = function(result) { | |
| 702 if (!this.partition.validPartitionId) { | |
| 703 result.error = ERROR_MSG_INVALID_PARTITION_ATTRIBUTE; | |
| 704 return false; | |
| 705 } | |
| 706 this.src = this.webviewNode.getAttribute('src'); | |
| 707 | |
| 708 if (!this.src) { | |
| 709 return true; | |
| 710 } | |
| 711 | |
| 712 if (!this.hasGuestInstanceID()) { | |
| 713 if (this.beforeFirstNavigation) { | |
| 714 this.beforeFirstNavigation = false; | |
| 715 this.allocateInstanceId(); | |
| 716 } | |
| 717 return true; | |
| 718 } | |
| 719 | |
| 720 // Navigate to this.src. | |
| 721 WebView.navigate(this.instanceId, this.src); | |
| 722 return true; | |
| 723 }; | |
| 724 | |
| 725 /** @return {boolean} */ | |
| 726 WebViewInternal.prototype.parseAttributes = function() { | |
| 727 var hasNavigated = this.hasNavigated(); | |
| 728 var attributeValue = this.webviewNode.getAttribute('partition'); | |
| 729 var result = this.partition.fromAttribute(attributeValue, hasNavigated); | |
| 730 return this.parseSrcAttribute(result); | |
| 731 }; | |
| 732 | |
| 733 WebViewInternal.prototype.hasGuestInstanceID = function() { | |
| 734 return this.instanceId != undefined; | |
| 735 }; | |
| 736 | |
| 737 WebViewInternal.prototype.allocateInstanceId = function() { | |
| 738 // Parse .src and .partition. | |
| 739 var self = this; | |
| 740 GuestView.allocateInstanceId( | |
| 741 function(instanceId) { | |
| 742 self.instanceId = instanceId; | |
| 743 // TODO(lazyboy): Make sure this.autoNavigate_ stuff correctly updated | |
| 744 // |self.src| at this point. | |
| 745 self.attachWindowAndSetUpEvents(self.instanceId, self.src); | |
| 746 }); | |
| 747 }; | |
| 748 | |
| 600 /** | 749 /** |
| 601 * @private | 750 * @private |
| 602 */ | 751 */ |
| 603 WebViewInternal.prototype.setupWebviewNodeEvents = function() { | 752 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(); | 753 this.setupWebRequestEvents(); |
| 613 this.setupExperimentalContextMenus_(); | 754 this.setupExperimentalContextMenus_(); |
| 614 | 755 |
| 615 this.on = {}; | 756 this.on = {}; |
| 616 var events = self.getEvents(); | 757 var events = this.getEvents(); |
| 617 for (var eventName in events) { | 758 for (var eventName in events) { |
| 618 this.setupEventProperty(eventName); | 759 this.setupEventProperty(eventName); |
| 619 } | 760 } |
| 620 }; | 761 }; |
| 621 | 762 |
| 622 /** | 763 /** |
| 623 * @private | 764 * @private |
| 624 */ | 765 */ |
| 625 WebViewInternal.prototype.setupNameAttribute = function() { | 766 WebViewInternal.prototype.setupNameAttribute = function() { |
| 626 var self = this; | 767 var self = this; |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 838 validateCall(); | 979 validateCall(); |
| 839 if (!webview || !webview.tagName || webview.tagName != 'WEBVIEW') | 980 if (!webview || !webview.tagName || webview.tagName != 'WEBVIEW') |
| 840 throw new Error(ERROR_MSG_WEBVIEW_EXPECTED); | 981 throw new Error(ERROR_MSG_WEBVIEW_EXPECTED); |
| 841 // Attach happens asynchronously to give the tagWatcher an opportunity | 982 // 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 | 983 // to pick up the new webview before attach operates on it, if it hasn't |
| 843 // been attached to the DOM already. | 984 // been attached to the DOM already. |
| 844 // Note: Any subsequent errors cannot be exceptions because they happen | 985 // Note: Any subsequent errors cannot be exceptions because they happen |
| 845 // asynchronously. | 986 // asynchronously. |
| 846 setTimeout(function() { | 987 setTimeout(function() { |
| 847 var webViewInternal = privates(webview).internal; | 988 var webViewInternal = privates(webview).internal; |
| 989 if (event.storagePartitionId) { | |
| 990 webViewInternal.webviewNode.setAttribute('partition', | |
| 991 event.storagePartitionId); | |
| 992 var partition = new Partition(); | |
| 993 partition.fromAttribute(event.storagePartitionId, | |
| 994 webViewInternal.hasNavigated()); | |
| 995 webViewInternal.partition = partition; | |
| 996 } | |
| 997 | |
| 848 var attached = | 998 var attached = |
| 849 webViewInternal.attachWindowAndSetUpEvents(event.windowId); | 999 webViewInternal.attachWindowAndSetUpEvents( |
| 1000 event.windowId, undefined, event.storagePartitionId); | |
| 850 | 1001 |
| 851 if (!attached) { | 1002 if (!attached) { |
| 852 window.console.error(ERROR_MSG_NEWWINDOW_UNABLE_TO_ATTACH); | 1003 window.console.error(ERROR_MSG_NEWWINDOW_UNABLE_TO_ATTACH); |
| 853 } | 1004 } |
| 854 // If the object being passed into attach is not a valid <webview> | 1005 // 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 | 1006 // 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 | 1007 // was rejected. The permission API plumbing is used here to clean |
| 857 // up the state created for the new window if attaching fails. | 1008 // up the state created for the new window if attaching fails. |
| 858 WebView.setPermission( | 1009 WebView.setPermission( |
| 859 self.instanceId, requestId, attached ? 'allow' : 'deny'); | 1010 self.instanceId, requestId, attached ? 'allow' : 'deny'); |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1093 this.userAgentOverride = userAgentOverride; | 1244 this.userAgentOverride = userAgentOverride; |
| 1094 if (!this.instanceId) { | 1245 if (!this.instanceId) { |
| 1095 // If we are not attached yet, then we will pick up the user agent on | 1246 // If we are not attached yet, then we will pick up the user agent on |
| 1096 // attachment. | 1247 // attachment. |
| 1097 return; | 1248 return; |
| 1098 } | 1249 } |
| 1099 WebView.overrideUserAgent(this.instanceId, userAgentOverride); | 1250 WebView.overrideUserAgent(this.instanceId, userAgentOverride); |
| 1100 }; | 1251 }; |
| 1101 | 1252 |
| 1102 /** @private */ | 1253 /** @private */ |
| 1103 WebViewInternal.prototype.attachWindowAndSetUpEvents = function(instanceId) { | 1254 WebViewInternal.prototype.attachWindowAndSetUpEvents = function( |
| 1255 instanceId, opt_src, opt_partitionId) { | |
| 1104 this.instanceId = instanceId; | 1256 this.instanceId = instanceId; |
| 1257 // If we have a partition from the opener, use that instead. | |
| 1258 var storagePartitionId = | |
| 1259 opt_partitionId || | |
| 1260 this.webviewNode.getAttribute(WEB_VIEW_ATTRIBUTE_PARTITION) || | |
| 1261 this.webviewNode[WEB_VIEW_ATTRIBUTE_PARTITION]; | |
| 1105 var params = { | 1262 var params = { |
| 1106 'api': 'webview', | 1263 'api': 'webview', |
| 1107 'instanceId': this.viewInstanceId, | 1264 'instanceId': this.viewInstanceId, |
| 1108 'name': this.name | 1265 'name': this.name, |
| 1266 'src': opt_src, | |
| 1267 'storagePartitionId': storagePartitionId, | |
| 1268 'userAgentOverride': this.userAgentOverride | |
| 1109 }; | 1269 }; |
| 1110 if (this.userAgentOverride) { | |
| 1111 params['userAgentOverride'] = this.userAgentOverride; | |
| 1112 } | |
| 1113 this.setupNameAttribute(); | 1270 this.setupNameAttribute(); |
| 1114 var events = this.getEvents(); | 1271 var events = this.getEvents(); |
| 1115 for (var eventName in events) { | 1272 for (var eventName in events) { |
| 1116 this.setupEvent(eventName, events[eventName]); | 1273 this.setupEvent(eventName, events[eventName]); |
| 1117 } | 1274 } |
| 1118 | 1275 |
| 1119 return this.browserPluginNode['-internal-attach'](this.instanceId, params); | 1276 return this.browserPluginNode['-internal-attach'](this.instanceId, params); |
| 1120 }; | 1277 }; |
| 1121 | 1278 |
| 1122 // Registers browser plugin <object> custom element. | 1279 // Registers browser plugin <object> custom element. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1154 } | 1311 } |
| 1155 | 1312 |
| 1156 // Registers <webview> custom element. | 1313 // Registers <webview> custom element. |
| 1157 function registerWebViewElement() { | 1314 function registerWebViewElement() { |
| 1158 var proto = Object.create(HTMLElement.prototype); | 1315 var proto = Object.create(HTMLElement.prototype); |
| 1159 | 1316 |
| 1160 proto.createdCallback = function() { | 1317 proto.createdCallback = function() { |
| 1161 new WebViewInternal(this); | 1318 new WebViewInternal(this); |
| 1162 }; | 1319 }; |
| 1163 | 1320 |
| 1321 proto.customElementDetached = false; | |
| 1322 | |
| 1164 proto.attributeChangedCallback = function(name, oldValue, newValue) { | 1323 proto.attributeChangedCallback = function(name, oldValue, newValue) { |
| 1165 var internal = privates(this).internal; | 1324 var internal = privates(this).internal; |
| 1166 if (!internal) { | 1325 if (!internal) { |
| 1167 return; | 1326 return; |
| 1168 } | 1327 } |
| 1169 internal.handleWebviewAttributeMutation(name, oldValue, newValue); | 1328 internal.handleWebviewAttributeMutation(name, oldValue, newValue); |
| 1170 }; | 1329 }; |
| 1171 | 1330 |
| 1331 proto.detachedCallback = function() { | |
| 1332 this.customElementDetached = true; | |
| 1333 }; | |
| 1334 | |
| 1335 proto.attachedCallback = function() { | |
| 1336 if (this.customElementDetached) { | |
| 1337 var webViewInternal = privates(this).internal; | |
| 1338 webViewInternal.resetUponReattachment(); | |
| 1339 webViewInternal.allocateInstanceId(); | |
| 1340 } | |
| 1341 this.customElementDetached = false; | |
| 1342 }; | |
| 1343 | |
| 1172 proto.back = function() { | 1344 proto.back = function() { |
| 1173 this.go(-1); | 1345 this.go(-1); |
| 1174 }; | 1346 }; |
| 1175 | 1347 |
| 1176 proto.forward = function() { | 1348 proto.forward = function() { |
| 1177 this.go(1); | 1349 this.go(1); |
| 1178 }; | 1350 }; |
| 1179 | 1351 |
| 1180 proto.canGoBack = function() { | 1352 proto.canGoBack = function() { |
| 1181 return privates(this).internal.canGoBack(); | 1353 return privates(this).internal.canGoBack(); |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1285 | 1457 |
| 1286 /** | 1458 /** |
| 1287 * Implemented when the experimental API is available. | 1459 * Implemented when the experimental API is available. |
| 1288 * @private | 1460 * @private |
| 1289 */ | 1461 */ |
| 1290 WebViewInternal.prototype.setupExperimentalContextMenus_ = function() {}; | 1462 WebViewInternal.prototype.setupExperimentalContextMenus_ = function() {}; |
| 1291 | 1463 |
| 1292 exports.WebView = WebView; | 1464 exports.WebView = WebView; |
| 1293 exports.WebViewInternal = WebViewInternal; | 1465 exports.WebViewInternal = WebViewInternal; |
| 1294 exports.CreateEvent = CreateEvent; | 1466 exports.CreateEvent = CreateEvent; |
| OLD | NEW |