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 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 var guestViewInternalNatives = requireNative('guest_view_internal'); | |
| 17 | 18 |
| 18 var WEB_VIEW_ATTRIBUTE_AUTOSIZE = 'autosize'; | 19 var WEB_VIEW_ATTRIBUTE_AUTOSIZE = 'autosize'; |
| 19 var WEB_VIEW_ATTRIBUTE_MAXHEIGHT = 'maxheight'; | 20 var WEB_VIEW_ATTRIBUTE_MAXHEIGHT = 'maxheight'; |
| 20 var WEB_VIEW_ATTRIBUTE_MAXWIDTH = 'maxwidth'; | 21 var WEB_VIEW_ATTRIBUTE_MAXWIDTH = 'maxwidth'; |
| 21 var WEB_VIEW_ATTRIBUTE_MINHEIGHT = 'minheight'; | 22 var WEB_VIEW_ATTRIBUTE_MINHEIGHT = 'minheight'; |
| 22 var WEB_VIEW_ATTRIBUTE_MINWIDTH = 'minwidth'; | 23 var WEB_VIEW_ATTRIBUTE_MINWIDTH = 'minwidth'; |
| 23 var AUTO_SIZE_ATTRIBUTES = [ | 24 var AUTO_SIZE_ATTRIBUTES = [ |
| 24 WEB_VIEW_ATTRIBUTE_AUTOSIZE, | 25 WEB_VIEW_ATTRIBUTE_AUTOSIZE, |
| 25 WEB_VIEW_ATTRIBUTE_MAXHEIGHT, | 26 WEB_VIEW_ATTRIBUTE_MAXHEIGHT, |
| 26 WEB_VIEW_ATTRIBUTE_MAXWIDTH, | 27 WEB_VIEW_ATTRIBUTE_MAXWIDTH, |
| 27 WEB_VIEW_ATTRIBUTE_MINHEIGHT, | 28 WEB_VIEW_ATTRIBUTE_MINHEIGHT, |
| 28 WEB_VIEW_ATTRIBUTE_MINWIDTH | 29 WEB_VIEW_ATTRIBUTE_MINWIDTH |
| 29 ]; | 30 ]; |
| 30 | 31 |
| 31 var WEB_VIEW_ATTRIBUTE_PARTITION = 'partition'; | 32 var WEB_VIEW_ATTRIBUTE_PARTITION = 'partition'; |
| 32 | 33 |
| 33 var PLUGIN_METHOD_ATTACH = '-internal-attach'; | |
| 34 | |
| 35 var ERROR_MSG_ALREADY_NAVIGATED = | 34 var ERROR_MSG_ALREADY_NAVIGATED = |
| 36 'The object has already navigated, so its partition cannot be changed.'; | 35 'The object has already navigated, so its partition cannot be changed.'; |
| 37 var ERROR_MSG_INVALID_PARTITION_ATTRIBUTE = 'Invalid partition attribute.'; | 36 var ERROR_MSG_INVALID_PARTITION_ATTRIBUTE = 'Invalid partition attribute.'; |
| 38 | 37 |
| 39 /** @type {Array.<string>} */ | 38 /** @type {Array.<string>} */ |
| 40 var WEB_VIEW_ATTRIBUTES = [ | 39 var WEB_VIEW_ATTRIBUTES = [ |
| 41 'allowtransparency', | 40 'allowtransparency', |
| 42 ]; | 41 ]; |
| 43 | 42 |
| 44 /** @class representing state of storage partition. */ | 43 /** @class representing state of storage partition. */ |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 142 // window.DOMContentLoaded event). | 141 // window.DOMContentLoaded event). |
| 143 // So copy from property if copying from attribute fails. | 142 // So copy from property if copying from attribute fails. |
| 144 browserPluginNode.setAttribute( | 143 browserPluginNode.setAttribute( |
| 145 attributeName, this.webviewNode[attributeName]); | 144 attributeName, this.webviewNode[attributeName]); |
| 146 } | 145 } |
| 147 }, this); | 146 }, this); |
| 148 | 147 |
| 149 return browserPluginNode; | 148 return browserPluginNode; |
| 150 }; | 149 }; |
| 151 | 150 |
| 152 WebViewInternal.prototype.getInstanceId = function() { | 151 WebViewInternal.prototype.getGuestInstanceId = function() { |
| 153 return this.instanceId; | 152 return this.guestInstanceId; |
| 154 }; | 153 }; |
| 155 | 154 |
| 156 /** | 155 /** |
| 157 * Resets some state upon reattaching <webview> element to the DOM. | 156 * Resets some state upon reattaching <webview> element to the DOM. |
| 158 */ | 157 */ |
| 159 WebViewInternal.prototype.resetUponReattachment = function() { | 158 WebViewInternal.prototype.reset = function() { |
| 160 this.instanceId = undefined; | 159 // If guestInstanceId is defined then the <webview> has navigated and has |
| 161 this.beforeFirstNavigation = true; | 160 // already picked up a partition ID. Thus, we need to reset the initialization |
| 162 this.validPartitionId = true; | 161 // state. However, it may be the case that beforeFirstNavigation is false BUT |
| 163 this.partition.validPartitionId = true; | 162 // guestInstanceId has yet to be initialized. This means that we have not |
| 163 // heard back from createGuest yet. We will not reset the flag in this case so | |
| 164 // that we don't end up allocating a second guest. | |
| 165 if (this.guestInstanceId) { | |
| 166 this.guestInstanceId = undefined; | |
| 167 this.beforeFirstNavigation = true; | |
| 168 this.validPartitionId = true; | |
| 169 this.partition.validPartitionId = true; | |
| 170 } | |
| 171 this.internalInstanceId = 0; | |
| 164 }; | 172 }; |
| 165 | 173 |
| 166 // Sets <webview>.request property. | 174 // Sets <webview>.request property. |
| 167 WebViewInternal.prototype.setRequestPropertyOnWebViewNode = function(request) { | 175 WebViewInternal.prototype.setRequestPropertyOnWebViewNode = function(request) { |
| 168 Object.defineProperty( | 176 Object.defineProperty( |
| 169 this.webviewNode, | 177 this.webviewNode, |
| 170 'request', | 178 'request', |
| 171 { | 179 { |
| 172 value: request, | 180 value: request, |
| 173 enumerable: true | 181 enumerable: true |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 220 */ | 228 */ |
| 221 WebViewInternal.prototype.canGoForward = function() { | 229 WebViewInternal.prototype.canGoForward = function() { |
| 222 return this.currentEntryIndex >= 0 && | 230 return this.currentEntryIndex >= 0 && |
| 223 this.currentEntryIndex < (this.entryCount - 1); | 231 this.currentEntryIndex < (this.entryCount - 1); |
| 224 }; | 232 }; |
| 225 | 233 |
| 226 /** | 234 /** |
| 227 * @private | 235 * @private |
| 228 */ | 236 */ |
| 229 WebViewInternal.prototype.clearData = function() { | 237 WebViewInternal.prototype.clearData = function() { |
| 230 if (!this.instanceId) { | 238 if (!this.guestInstanceId) { |
| 231 return; | 239 return; |
| 232 } | 240 } |
| 233 var args = $Array.concat([this.instanceId], $Array.slice(arguments)); | 241 var args = $Array.concat([this.guestInstanceId], $Array.slice(arguments)); |
| 234 $Function.apply(WebView.clearData, null, args); | 242 $Function.apply(WebView.clearData, null, args); |
| 235 }; | 243 }; |
| 236 | 244 |
| 237 /** | 245 /** |
| 238 * @private | 246 * @private |
| 239 */ | 247 */ |
| 240 WebViewInternal.prototype.getProcessId = function() { | 248 WebViewInternal.prototype.getProcessId = function() { |
| 241 return this.processId; | 249 return this.processId; |
| 242 }; | 250 }; |
| 243 | 251 |
| 244 /** | 252 /** |
| 245 * @private | 253 * @private |
| 246 */ | 254 */ |
| 247 WebViewInternal.prototype.go = function(relativeIndex) { | 255 WebViewInternal.prototype.go = function(relativeIndex) { |
| 248 if (!this.instanceId) { | 256 if (!this.guestInstanceId) { |
| 249 return; | 257 return; |
| 250 } | 258 } |
| 251 WebView.go(this.instanceId, relativeIndex); | 259 WebView.go(this.guestInstanceId, relativeIndex); |
| 252 }; | 260 }; |
| 253 | 261 |
| 254 /** | 262 /** |
| 255 * @private | 263 * @private |
| 256 */ | 264 */ |
| 257 WebViewInternal.prototype.print = function() { | 265 WebViewInternal.prototype.print = function() { |
| 258 this.executeScript({code: 'window.print();'}); | 266 this.executeScript({code: 'window.print();'}); |
| 259 }; | 267 }; |
| 260 | 268 |
| 261 /** | 269 /** |
| 262 * @private | 270 * @private |
| 263 */ | 271 */ |
| 264 WebViewInternal.prototype.reload = function() { | 272 WebViewInternal.prototype.reload = function() { |
| 265 if (!this.instanceId) { | 273 if (!this.guestInstanceId) { |
| 266 return; | 274 return; |
| 267 } | 275 } |
| 268 WebView.reload(this.instanceId); | 276 WebView.reload(this.guestInstanceId); |
| 269 }; | 277 }; |
| 270 | 278 |
| 271 /** | 279 /** |
| 272 * @private | 280 * @private |
| 273 */ | 281 */ |
| 274 WebViewInternal.prototype.stop = function() { | 282 WebViewInternal.prototype.stop = function() { |
| 275 if (!this.instanceId) { | 283 if (!this.guestInstanceId) { |
| 276 return; | 284 return; |
| 277 } | 285 } |
| 278 WebView.stop(this.instanceId); | 286 WebView.stop(this.guestInstanceId); |
| 279 }; | 287 }; |
| 280 | 288 |
| 281 /** | 289 /** |
| 282 * @private | 290 * @private |
| 283 */ | 291 */ |
| 284 WebViewInternal.prototype.terminate = function() { | 292 WebViewInternal.prototype.terminate = function() { |
| 285 if (!this.instanceId) { | 293 if (!this.guestInstanceId) { |
| 286 return; | 294 return; |
| 287 } | 295 } |
| 288 WebView.terminate(this.instanceId); | 296 WebView.terminate(this.guestInstanceId); |
| 289 }; | 297 }; |
| 290 | 298 |
| 291 /** | 299 /** |
| 292 * @private | 300 * @private |
| 293 */ | 301 */ |
| 294 WebViewInternal.prototype.validateExecuteCodeCall = function() { | 302 WebViewInternal.prototype.validateExecuteCodeCall = function() { |
| 295 var ERROR_MSG_CANNOT_INJECT_SCRIPT = '<webview>: ' + | 303 var ERROR_MSG_CANNOT_INJECT_SCRIPT = '<webview>: ' + |
| 296 'Script cannot be injected into content until the page has loaded.'; | 304 'Script cannot be injected into content until the page has loaded.'; |
| 297 if (!this.instanceId) { | 305 if (!this.guestInstanceId) { |
| 298 throw new Error(ERROR_MSG_CANNOT_INJECT_SCRIPT); | 306 throw new Error(ERROR_MSG_CANNOT_INJECT_SCRIPT); |
| 299 } | 307 } |
| 300 }; | 308 }; |
| 301 | 309 |
| 302 /** | 310 /** |
| 303 * @private | 311 * @private |
| 304 */ | 312 */ |
| 305 WebViewInternal.prototype.executeScript = function(var_args) { | 313 WebViewInternal.prototype.executeScript = function(var_args) { |
| 306 this.validateExecuteCodeCall(); | 314 this.validateExecuteCodeCall(); |
| 307 var args = $Array.concat([this.instanceId, this.src], | 315 var args = $Array.concat([this.guestInstanceId, this.src], |
| 308 $Array.slice(arguments)); | 316 $Array.slice(arguments)); |
| 309 $Function.apply(WebView.executeScript, null, args); | 317 $Function.apply(WebView.executeScript, null, args); |
| 310 }; | 318 }; |
| 311 | 319 |
| 312 /** | 320 /** |
| 313 * @private | 321 * @private |
| 314 */ | 322 */ |
| 315 WebViewInternal.prototype.insertCSS = function(var_args) { | 323 WebViewInternal.prototype.insertCSS = function(var_args) { |
| 316 this.validateExecuteCodeCall(); | 324 this.validateExecuteCodeCall(); |
| 317 var args = $Array.concat([this.instanceId, this.src], | 325 var args = $Array.concat([this.guestInstanceId, this.src], |
| 318 $Array.slice(arguments)); | 326 $Array.slice(arguments)); |
| 319 $Function.apply(WebView.insertCSS, null, args); | 327 $Function.apply(WebView.insertCSS, null, args); |
| 320 }; | 328 }; |
| 321 | 329 |
| 322 WebViewInternal.prototype.setupAutoSizeProperties = function() { | 330 WebViewInternal.prototype.setupAutoSizeProperties = function() { |
| 323 var self = this; | 331 var self = this; |
| 324 $Array.forEach(AUTO_SIZE_ATTRIBUTES, function(attributeName) { | 332 $Array.forEach(AUTO_SIZE_ATTRIBUTES, function(attributeName) { |
| 325 this[attributeName] = this.webviewNode.getAttribute(attributeName); | 333 this[attributeName] = this.webviewNode.getAttribute(attributeName); |
| 326 Object.defineProperty(this.webviewNode, attributeName, { | 334 Object.defineProperty(this.webviewNode, attributeName, { |
| 327 get: function() { | 335 get: function() { |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 462 */ | 470 */ |
| 463 WebViewInternal.prototype.handleWebviewAttributeMutation = | 471 WebViewInternal.prototype.handleWebviewAttributeMutation = |
| 464 function(name, oldValue, newValue) { | 472 function(name, oldValue, newValue) { |
| 465 // This observer monitors mutations to attributes of the <webview> and | 473 // This observer monitors mutations to attributes of the <webview> and |
| 466 // updates the BrowserPlugin properties accordingly. In turn, updating | 474 // updates the BrowserPlugin properties accordingly. In turn, updating |
| 467 // a BrowserPlugin property will update the corresponding BrowserPlugin | 475 // a BrowserPlugin property will update the corresponding BrowserPlugin |
| 468 // attribute, if necessary. See BrowserPlugin::UpdateDOMAttribute for more | 476 // attribute, if necessary. See BrowserPlugin::UpdateDOMAttribute for more |
| 469 // details. | 477 // details. |
| 470 if (AUTO_SIZE_ATTRIBUTES.indexOf(name) > -1) { | 478 if (AUTO_SIZE_ATTRIBUTES.indexOf(name) > -1) { |
| 471 this[name] = newValue; | 479 this[name] = newValue; |
| 472 if (!this.instanceId) { | 480 if (!this.guestInstanceId) { |
| 473 return; | 481 return; |
| 474 } | 482 } |
| 475 // Convert autosize attribute to boolean. | 483 // Convert autosize attribute to boolean. |
| 476 var autosize = this.webviewNode.hasAttribute(WEB_VIEW_ATTRIBUTE_AUTOSIZE); | 484 var autosize = this.webviewNode.hasAttribute(WEB_VIEW_ATTRIBUTE_AUTOSIZE); |
| 477 GuestViewInternal.setAutoSize(this.instanceId, { | 485 GuestViewInternal.setAutoSize(this.guestInstanceId, { |
| 478 'enableAutoSize': autosize, | 486 'enableAutoSize': autosize, |
| 479 'min': { | 487 'min': { |
| 480 'width': parseInt(this.minwidth || 0), | 488 'width': parseInt(this.minwidth || 0), |
| 481 'height': parseInt(this.minheight || 0) | 489 'height': parseInt(this.minheight || 0) |
| 482 }, | 490 }, |
| 483 'max': { | 491 'max': { |
| 484 'width': parseInt(this.maxwidth || 0), | 492 'width': parseInt(this.maxwidth || 0), |
| 485 'height': parseInt(this.maxheight || 0) | 493 'height': parseInt(this.maxheight || 0) |
| 486 } | 494 } |
| 487 }); | 495 }); |
| 488 return; | 496 return; |
| 489 } else if (name == 'name') { | 497 } else if (name == 'name') { |
| 490 // We treat null attribute (attribute removed) and the empty string as | 498 // We treat null attribute (attribute removed) and the empty string as |
| 491 // one case. | 499 // one case. |
| 492 oldValue = oldValue || ''; | 500 oldValue = oldValue || ''; |
| 493 newValue = newValue || ''; | 501 newValue = newValue || ''; |
| 494 | 502 |
| 495 if (oldValue === newValue) { | 503 if (oldValue === newValue) { |
| 496 return; | 504 return; |
| 497 } | 505 } |
| 498 this.name = newValue; | 506 this.name = newValue; |
| 499 if (!this.instanceId) { | 507 if (!this.guestInstanceId) { |
| 500 return; | 508 return; |
| 501 } | 509 } |
| 502 WebView.setName(this.instanceId, newValue); | 510 WebView.setName(this.guestInstanceId, newValue); |
| 503 return; | 511 return; |
| 504 } else if (name == 'src') { | 512 } else if (name == 'src') { |
| 505 // We treat null attribute (attribute removed) and the empty string as | 513 // We treat null attribute (attribute removed) and the empty string as |
| 506 // one case. | 514 // one case. |
| 507 oldValue = oldValue || ''; | 515 oldValue = oldValue || ''; |
| 508 newValue = newValue || ''; | 516 newValue = newValue || ''; |
| 509 // Once we have navigated, we don't allow clearing the src attribute. | 517 // Once we have navigated, we don't allow clearing the src attribute. |
| 510 // Once <webview> enters a navigated state, it cannot be return back to a | 518 // Once <webview> enters a navigated state, it cannot be return back to a |
| 511 // placeholder state. | 519 // placeholder state. |
| 512 if (newValue == '' && oldValue != '') { | 520 if (newValue == '' && oldValue != '') { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 545 } else { | 553 } else { |
| 546 this.browserPluginNode.setAttribute(name, newValue); | 554 this.browserPluginNode.setAttribute(name, newValue); |
| 547 } | 555 } |
| 548 }; | 556 }; |
| 549 | 557 |
| 550 /** | 558 /** |
| 551 * @private | 559 * @private |
| 552 */ | 560 */ |
| 553 WebViewInternal.prototype.handleBrowserPluginAttributeMutation = | 561 WebViewInternal.prototype.handleBrowserPluginAttributeMutation = |
| 554 function(name, oldValue, newValue) { | 562 function(name, oldValue, newValue) { |
| 555 if (name == 'internalbindings' && !oldValue && newValue) { | 563 if (name == 'internalinstanceid' && !oldValue && !!newValue) { |
| 556 this.browserPluginNode.removeAttribute('internalbindings'); | 564 this.browserPluginNode.removeAttribute('internalinstanceid'); |
| 557 | 565 this.internalInstanceId = parseInt(newValue); |
| 558 if (this.deferredAttachState) { | 566 if (this.deferredAttachState && !!this.guestInstanceId && |
| 559 var self = this; | 567 this.guestInstanceId != 0) { |
| 560 // A setTimeout is necessary for the binding to be initialized properly. | |
| 561 window.setTimeout(function() { | 568 window.setTimeout(function() { |
| 562 if (self.hasBindings()) { | 569 var isNewWindow = this.deferredAttachState ? |
| 563 var params = self.buildAttachParams( | 570 this.deferredAttachState.isNewWindow : false; |
| 564 self.deferredAttachState.isNewWindow); | 571 var params = this.buildAttachParams(isNewWindow); |
| 565 self.browserPluginNode[PLUGIN_METHOD_ATTACH](self.instanceId, params); | 572 guestViewInternalNatives.AttachGuest( |
| 566 self.deferredAttachState = null; | 573 this.internalInstanceId, |
| 567 } | 574 this.guestInstanceId, |
| 568 }, 0); | 575 params); |
| 576 }.bind(this), 0); | |
| 569 } | 577 } |
| 570 return; | 578 return; |
| 571 } | 579 } |
| 572 | 580 |
| 573 // This observer monitors mutations to attributes of the BrowserPlugin and | 581 // This observer monitors mutations to attributes of the BrowserPlugin and |
| 574 // updates the <webview> attributes accordingly. | 582 // updates the <webview> attributes accordingly. |
| 575 // |newValue| is null if the attribute |name| has been removed. | 583 // |newValue| is null if the attribute |name| has been removed. |
| 576 if (newValue != null) { | 584 if (newValue != null) { |
| 577 // Update the <webview> attribute to match the BrowserPlugin attribute. | 585 // Update the <webview> attribute to match the BrowserPlugin attribute. |
| 578 // Note: Calling setAttribute on <webview> will trigger its mutation | 586 // Note: Calling setAttribute on <webview> will trigger its mutation |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 645 newHeight >= minHeight && | 653 newHeight >= minHeight && |
| 646 newHeight <= maxHeight)) { | 654 newHeight <= maxHeight)) { |
| 647 node.style.width = newWidth + 'px'; | 655 node.style.width = newWidth + 'px'; |
| 648 node.style.height = newHeight + 'px'; | 656 node.style.height = newHeight + 'px'; |
| 649 // Only fire the DOM event if the size of the <webview> has actually | 657 // Only fire the DOM event if the size of the <webview> has actually |
| 650 // changed. | 658 // changed. |
| 651 this.dispatchEvent(webViewEvent); | 659 this.dispatchEvent(webViewEvent); |
| 652 } | 660 } |
| 653 }; | 661 }; |
| 654 | 662 |
| 655 // Returns true if Browser Plugin bindings is available. | 663 // Returns if <object> is in the render tree. |
| 656 // Bindings are unavailable if <object> is not in the render tree. | 664 WebViewInternal.prototype.isPluginInRenderTree = function() { |
| 657 WebViewInternal.prototype.hasBindings = function() { | 665 return !!this.internalInstanceId && this.internalInstanceId != 0; |
| 658 return 'function' == typeof this.browserPluginNode[PLUGIN_METHOD_ATTACH]; | |
| 659 }; | 666 }; |
| 660 | 667 |
| 661 WebViewInternal.prototype.hasNavigated = function() { | 668 WebViewInternal.prototype.hasNavigated = function() { |
| 662 return !this.beforeFirstNavigation; | 669 return !this.beforeFirstNavigation; |
| 663 }; | 670 }; |
| 664 | 671 |
| 665 /** @return {boolean} */ | 672 /** @return {boolean} */ |
| 666 WebViewInternal.prototype.parseSrcAttribute = function(result) { | 673 WebViewInternal.prototype.parseSrcAttribute = function(result) { |
| 667 if (!this.partition.validPartitionId) { | 674 if (!this.partition.validPartitionId) { |
| 668 result.error = ERROR_MSG_INVALID_PARTITION_ATTRIBUTE; | 675 result.error = ERROR_MSG_INVALID_PARTITION_ATTRIBUTE; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 680 | 687 |
| 681 if (!this.hasGuestInstanceID()) { | 688 if (!this.hasGuestInstanceID()) { |
| 682 if (this.beforeFirstNavigation) { | 689 if (this.beforeFirstNavigation) { |
| 683 this.beforeFirstNavigation = false; | 690 this.beforeFirstNavigation = false; |
| 684 this.allocateInstanceId(); | 691 this.allocateInstanceId(); |
| 685 } | 692 } |
| 686 return true; | 693 return true; |
| 687 } | 694 } |
| 688 | 695 |
| 689 // Navigate to this.src. | 696 // Navigate to this.src. |
| 690 WebView.navigate(this.instanceId, this.src); | 697 WebView.navigate(this.guestInstanceId, this.src); |
| 691 return true; | 698 return true; |
| 692 }; | 699 }; |
| 693 | 700 |
| 694 /** @return {boolean} */ | 701 /** @return {boolean} */ |
| 695 WebViewInternal.prototype.parseAttributes = function() { | 702 WebViewInternal.prototype.parseAttributes = function() { |
| 696 var hasNavigated = this.hasNavigated(); | 703 var hasNavigated = this.hasNavigated(); |
| 697 var attributeValue = this.webviewNode.getAttribute('partition'); | 704 var attributeValue = this.webviewNode.getAttribute('partition'); |
| 698 var result = this.partition.fromAttribute(attributeValue, hasNavigated); | 705 var result = this.partition.fromAttribute(attributeValue, hasNavigated); |
| 699 return this.parseSrcAttribute(result); | 706 return this.parseSrcAttribute(result); |
| 700 }; | 707 }; |
| 701 | 708 |
| 702 WebViewInternal.prototype.hasGuestInstanceID = function() { | 709 WebViewInternal.prototype.hasGuestInstanceID = function() { |
| 703 return this.instanceId != undefined; | 710 return this.guestInstanceId != undefined; |
| 704 }; | 711 }; |
| 705 | 712 |
| 706 WebViewInternal.prototype.allocateInstanceId = function() { | 713 WebViewInternal.prototype.allocateInstanceId = function() { |
| 707 var storagePartitionId = | 714 var storagePartitionId = |
| 708 this.webviewNode.getAttribute(WEB_VIEW_ATTRIBUTE_PARTITION) || | 715 this.webviewNode.getAttribute(WEB_VIEW_ATTRIBUTE_PARTITION) || |
| 709 this.webviewNode[WEB_VIEW_ATTRIBUTE_PARTITION]; | 716 this.webviewNode[WEB_VIEW_ATTRIBUTE_PARTITION]; |
| 710 var params = { | 717 var params = { |
| 711 'storagePartitionId': storagePartitionId, | 718 'storagePartitionId': storagePartitionId, |
| 712 }; | 719 }; |
| 713 var self = this; | 720 var self = this; |
| 714 GuestViewInternal.createGuest( | 721 GuestViewInternal.createGuest( |
| 715 'webview', | 722 'webview', |
| 716 params, | 723 params, |
| 717 function(instanceId) { | 724 function(guestInstanceId) { |
| 718 // TODO(lazyboy): Make sure this.autoNavigate_ stuff correctly updated | 725 // TODO(lazyboy): Make sure this.autoNavigate_ stuff correctly updated |
| 719 // |self.src| at this point. | 726 // |self.src| at this point. |
| 720 self.attachWindow(instanceId, false); | 727 self.attachWindow(guestInstanceId, false); |
| 721 }); | 728 }); |
| 722 }; | 729 }; |
| 723 | 730 |
| 724 WebViewInternal.prototype.onFrameNameChanged = function(name) { | 731 WebViewInternal.prototype.onFrameNameChanged = function(name) { |
| 725 this.name = name || ''; | 732 this.name = name || ''; |
| 726 if (this.name === '') { | 733 if (this.name === '') { |
| 727 this.webviewNode.removeAttribute('name'); | 734 this.webviewNode.removeAttribute('name'); |
| 728 } else { | 735 } else { |
| 729 this.webviewNode.setAttribute('name', this.name); | 736 this.webviewNode.setAttribute('name', this.name); |
| 730 } | 737 } |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 787 | 794 |
| 788 /** @private */ | 795 /** @private */ |
| 789 WebViewInternal.prototype.isUserAgentOverridden = function() { | 796 WebViewInternal.prototype.isUserAgentOverridden = function() { |
| 790 return !!this.userAgentOverride && | 797 return !!this.userAgentOverride && |
| 791 this.userAgentOverride != navigator.userAgent; | 798 this.userAgentOverride != navigator.userAgent; |
| 792 }; | 799 }; |
| 793 | 800 |
| 794 /** @private */ | 801 /** @private */ |
| 795 WebViewInternal.prototype.setUserAgentOverride = function(userAgentOverride) { | 802 WebViewInternal.prototype.setUserAgentOverride = function(userAgentOverride) { |
| 796 this.userAgentOverride = userAgentOverride; | 803 this.userAgentOverride = userAgentOverride; |
| 797 if (!this.instanceId) { | 804 if (!this.guestInstanceId) { |
| 798 // If we are not attached yet, then we will pick up the user agent on | 805 // If we are not attached yet, then we will pick up the user agent on |
| 799 // attachment. | 806 // attachment. |
| 800 return; | 807 return; |
| 801 } | 808 } |
| 802 WebView.overrideUserAgent(this.instanceId, userAgentOverride); | 809 WebView.overrideUserAgent(this.guestInstanceId, userAgentOverride); |
| 803 }; | 810 }; |
| 804 | 811 |
| 805 /** @private */ | 812 /** @private */ |
| 806 WebViewInternal.prototype.find = function(search_text, options, callback) { | 813 WebViewInternal.prototype.find = function(search_text, options, callback) { |
| 807 if (!this.instanceId) { | 814 if (!this.guestInstanceId) { |
| 808 return; | 815 return; |
| 809 } | 816 } |
| 810 WebView.find(this.instanceId, search_text, options, callback); | 817 WebView.find(this.guestInstanceId, search_text, options, callback); |
| 811 }; | 818 }; |
| 812 | 819 |
| 813 /** @private */ | 820 /** @private */ |
| 814 WebViewInternal.prototype.stopFinding = function(action) { | 821 WebViewInternal.prototype.stopFinding = function(action) { |
| 815 if (!this.instanceId) { | 822 if (!this.guestInstanceId) { |
| 816 return; | 823 return; |
| 817 } | 824 } |
| 818 WebView.stopFinding(this.instanceId, action); | 825 WebView.stopFinding(this.guestInstanceId, action); |
| 819 }; | 826 }; |
| 820 | 827 |
| 821 /** @private */ | 828 /** @private */ |
| 822 WebViewInternal.prototype.setZoom = function(zoomFactor, callback) { | 829 WebViewInternal.prototype.setZoom = function(zoomFactor, callback) { |
| 823 if (!this.instanceId) { | 830 if (!this.guestInstanceId) { |
| 824 return; | 831 return; |
| 825 } | 832 } |
| 826 WebView.setZoom(this.instanceId, zoomFactor, callback); | 833 WebView.setZoom(this.guestInstanceId, zoomFactor, callback); |
| 827 }; | 834 }; |
| 828 | 835 |
| 829 WebViewInternal.prototype.getZoom = function(callback) { | 836 WebViewInternal.prototype.getZoom = function(callback) { |
| 830 if (!this.instanceId) { | 837 if (!this.guestInstanceId) { |
| 831 return; | 838 return; |
| 832 } | 839 } |
| 833 WebView.getZoom(this.instanceId, callback); | 840 WebView.getZoom(this.guestInstanceId, callback); |
| 834 }; | 841 }; |
| 835 | 842 |
| 836 WebViewInternal.prototype.buildAttachParams = function(isNewWindow) { | 843 WebViewInternal.prototype.buildAttachParams = function(isNewWindow) { |
| 837 var params = { | 844 var params = { |
| 838 'autosize': this.webviewNode.hasAttribute(WEB_VIEW_ATTRIBUTE_AUTOSIZE), | 845 'autosize': this.webviewNode.hasAttribute(WEB_VIEW_ATTRIBUTE_AUTOSIZE), |
| 839 'instanceId': this.viewInstanceId, | 846 'instanceId': this.viewInstanceId, |
| 840 'maxheight': parseInt(this.maxheight || 0), | 847 'maxheight': parseInt(this.maxheight || 0), |
| 841 'maxwidth': parseInt(this.maxwidth || 0), | 848 'maxwidth': parseInt(this.maxwidth || 0), |
| 842 'minheight': parseInt(this.minheight || 0), | 849 'minheight': parseInt(this.minheight || 0), |
| 843 'minwidth': parseInt(this.minwidth || 0), | 850 'minwidth': parseInt(this.minwidth || 0), |
| 844 'name': this.name, | 851 'name': this.name, |
| 845 // We don't need to navigate new window from here. | 852 // We don't need to navigate new window from here. |
| 846 'src': isNewWindow ? undefined : this.src, | 853 'src': isNewWindow ? undefined : this.src, |
| 847 // If we have a partition from the opener, that will also be already | 854 // If we have a partition from the opener, that will also be already |
| 848 // set via this.onAttach(). | 855 // set via this.onAttach(). |
| 849 'storagePartitionId': this.partition.toAttribute(), | 856 'storagePartitionId': this.partition.toAttribute(), |
| 850 'userAgentOverride': this.userAgentOverride | 857 'userAgentOverride': this.userAgentOverride |
| 851 }; | 858 }; |
| 852 return params; | 859 return params; |
| 853 }; | 860 }; |
| 854 | 861 |
| 855 WebViewInternal.prototype.attachWindow = function(instanceId, isNewWindow) { | 862 WebViewInternal.prototype.attachWindow = function(guestInstanceId, |
| 856 this.instanceId = instanceId; | 863 isNewWindow) { |
| 864 this.guestInstanceId = guestInstanceId; | |
| 857 var params = this.buildAttachParams(isNewWindow); | 865 var params = this.buildAttachParams(isNewWindow); |
| 858 | 866 |
| 859 if (!this.hasBindings()) { | 867 if (!this.isPluginInRenderTree()) { |
| 860 // No bindings means that the plugin isn't there (display: none), we defer | |
| 861 // attachWindow in this case. | |
| 862 this.deferredAttachState = {isNewWindow: isNewWindow}; | 868 this.deferredAttachState = {isNewWindow: isNewWindow}; |
| 863 return false; | 869 return false; |
| 864 } | 870 } |
| 865 | 871 |
| 866 this.deferredAttachState = null; | 872 this.deferredAttachState = null; |
| 867 return this.browserPluginNode[PLUGIN_METHOD_ATTACH](this.instanceId, params); | 873 return guestViewInternalNatives.AttachGuest( |
| 874 this.internalInstanceId, | |
| 875 this.guestInstanceId, | |
| 876 params); | |
| 868 }; | 877 }; |
| 869 | 878 |
| 870 // Registers browser plugin <object> custom element. | 879 // Registers browser plugin <object> custom element. |
| 871 function registerBrowserPluginElement() { | 880 function registerBrowserPluginElement() { |
| 872 var proto = Object.create(HTMLObjectElement.prototype); | 881 var proto = Object.create(HTMLObjectElement.prototype); |
| 873 | 882 |
| 874 proto.createdCallback = function() { | 883 proto.createdCallback = function() { |
| 875 this.setAttribute('type', 'application/browser-plugin'); | 884 this.setAttribute('type', 'application/browser-plugin'); |
| 885 this.setAttribute('id', 'browser-plugin-' + IdGenerator.GetNextId()); | |
|
Fady Samuel
2014/08/13 22:24:39
Note to self: Remove this.
| |
| 876 // The <object> node fills in the <webview> container. | 886 // The <object> node fills in the <webview> container. |
| 877 this.style.width = '100%'; | 887 this.style.width = '100%'; |
| 878 this.style.height = '100%'; | 888 this.style.height = '100%'; |
| 879 }; | 889 }; |
| 880 | 890 |
| 881 proto.attributeChangedCallback = function(name, oldValue, newValue) { | 891 proto.attributeChangedCallback = function(name, oldValue, newValue) { |
| 882 var internal = privates(this).internal; | 892 var internal = privates(this).internal; |
| 883 if (!internal) { | 893 if (!internal) { |
| 884 return; | 894 return; |
| 885 } | 895 } |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 916 } | 926 } |
| 917 internal.handleWebviewAttributeMutation(name, oldValue, newValue); | 927 internal.handleWebviewAttributeMutation(name, oldValue, newValue); |
| 918 }; | 928 }; |
| 919 | 929 |
| 920 proto.detachedCallback = function() { | 930 proto.detachedCallback = function() { |
| 921 var internal = privates(this).internal; | 931 var internal = privates(this).internal; |
| 922 if (!internal) { | 932 if (!internal) { |
| 923 return; | 933 return; |
| 924 } | 934 } |
| 925 internal.elementAttached = false; | 935 internal.elementAttached = false; |
| 936 internal.reset(); | |
| 926 }; | 937 }; |
| 927 | 938 |
| 928 proto.attachedCallback = function() { | 939 proto.attachedCallback = function() { |
| 929 var internal = privates(this).internal; | 940 var internal = privates(this).internal; |
| 930 if (!internal) { | 941 if (!internal) { |
| 931 return; | 942 return; |
| 932 } | 943 } |
| 933 if (!internal.elementAttached) { | 944 if (!internal.elementAttached) { |
| 934 internal.elementAttached = true; | 945 internal.elementAttached = true; |
| 935 internal.resetUponReattachment(); | |
| 936 internal.parseAttributes(); | 946 internal.parseAttributes(); |
| 937 } | 947 } |
| 938 }; | 948 }; |
| 939 | 949 |
| 940 var methods = [ | 950 var methods = [ |
| 941 'back', | 951 'back', |
| 942 'find', | 952 'find', |
| 943 'forward', | 953 'forward', |
| 944 'canGoBack', | 954 'canGoBack', |
| 945 'canGoForward', | 955 'canGoForward', |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1012 * Calls to show contextmenu right away instead of dispatching a 'contextmenu' | 1022 * Calls to show contextmenu right away instead of dispatching a 'contextmenu' |
| 1013 * event. | 1023 * event. |
| 1014 * This will be overridden in web_view_experimental.js to implement contextmenu | 1024 * This will be overridden in web_view_experimental.js to implement contextmenu |
| 1015 * API. | 1025 * API. |
| 1016 */ | 1026 */ |
| 1017 WebViewInternal.prototype.maybeHandleContextMenu = function(e, webViewEvent) { | 1027 WebViewInternal.prototype.maybeHandleContextMenu = function(e, webViewEvent) { |
| 1018 var requestId = e.requestId; | 1028 var requestId = e.requestId; |
| 1019 // Setting |params| = undefined will show the context menu unmodified, hence | 1029 // Setting |params| = undefined will show the context menu unmodified, hence |
| 1020 // the 'contextmenu' API is disabled for stable channel. | 1030 // the 'contextmenu' API is disabled for stable channel. |
| 1021 var params = undefined; | 1031 var params = undefined; |
| 1022 WebView.showContextMenu(this.instanceId, requestId, params); | 1032 WebView.showContextMenu(this.guestInstanceId, requestId, params); |
| 1023 }; | 1033 }; |
| 1024 | 1034 |
| 1025 /** | 1035 /** |
| 1026 * Implemented when the experimental API is available. | 1036 * Implemented when the experimental API is available. |
| 1027 * @private | 1037 * @private |
| 1028 */ | 1038 */ |
| 1029 WebViewInternal.prototype.setupExperimentalContextMenus = function() {}; | 1039 WebViewInternal.prototype.setupExperimentalContextMenus = function() {}; |
| 1030 | 1040 |
| 1031 exports.WebView = WebView; | 1041 exports.WebView = WebView; |
| 1032 exports.WebViewInternal = WebViewInternal; | 1042 exports.WebViewInternal = WebViewInternal; |
| OLD | NEW |