Chromium Code Reviews| Index: chrome/renderer/resources/extensions/web_view.js |
| diff --git a/chrome/renderer/resources/extensions/web_view.js b/chrome/renderer/resources/extensions/web_view.js |
| index a21a4ab5de093d81d49fac130a7dfa38f2ef5398..5f0cb6e5890750dd02b98e6c8e56e03c63127b90 100644 |
| --- a/chrome/renderer/resources/extensions/web_view.js |
| +++ b/chrome/renderer/resources/extensions/web_view.js |
| @@ -14,6 +14,7 @@ var IdGenerator = requireNative('id_generator'); |
| // something else. |
| var WebView = require('webViewInternal').WebView; |
| var WebViewEvents = require('webViewEvents').WebViewEvents; |
| +var guestViewInternalNatives = requireNative('guest_view_internal'); |
| var WEB_VIEW_ATTRIBUTE_AUTOSIZE = 'autosize'; |
| var WEB_VIEW_ATTRIBUTE_MAXHEIGHT = 'maxheight'; |
| @@ -30,8 +31,6 @@ var AUTO_SIZE_ATTRIBUTES = [ |
| var WEB_VIEW_ATTRIBUTE_PARTITION = 'partition'; |
| -var PLUGIN_METHOD_ATTACH = '-internal-attach'; |
| - |
| var ERROR_MSG_ALREADY_NAVIGATED = |
| 'The object has already navigated, so its partition cannot be changed.'; |
| var ERROR_MSG_INVALID_PARTITION_ATTRIBUTE = 'Invalid partition attribute.'; |
| @@ -149,18 +148,27 @@ WebViewInternal.prototype.createBrowserPluginNode = function() { |
| return browserPluginNode; |
| }; |
| -WebViewInternal.prototype.getInstanceId = function() { |
| - return this.instanceId; |
| +WebViewInternal.prototype.getGuestInstanceId = function() { |
| + return this.guestInstanceId; |
| }; |
| /** |
| * Resets some state upon reattaching <webview> element to the DOM. |
| */ |
| -WebViewInternal.prototype.resetUponReattachment = function() { |
| - this.instanceId = undefined; |
| - this.beforeFirstNavigation = true; |
| - this.validPartitionId = true; |
| - this.partition.validPartitionId = true; |
| +WebViewInternal.prototype.reset = function() { |
| + // If guestInstanceId is defined then the <webview> has navigated and has |
| + // already picked up a partition ID. Thus, we need to reset the initialization |
| + // state. However, it may be the case that beforeFirstNavigation is false BUT |
| + // guestInstanceId has yet to be initialized. This means that we have not |
| + // heard back from createGuest yet. We will not reset the flag in this case so |
| + // that we don't end up allocating a second guest. |
| + if (this.guestInstanceId) { |
| + this.guestInstanceId = undefined; |
| + this.beforeFirstNavigation = true; |
| + this.validPartitionId = true; |
| + this.partition.validPartitionId = true; |
| + } |
| + this.internalInstanceId = 0; |
| }; |
| // Sets <webview>.request property. |
| @@ -227,10 +235,10 @@ WebViewInternal.prototype.canGoForward = function() { |
| * @private |
| */ |
| WebViewInternal.prototype.clearData = function() { |
| - if (!this.instanceId) { |
| + if (!this.guestInstanceId) { |
| return; |
| } |
| - var args = $Array.concat([this.instanceId], $Array.slice(arguments)); |
| + var args = $Array.concat([this.guestInstanceId], $Array.slice(arguments)); |
| $Function.apply(WebView.clearData, null, args); |
| }; |
| @@ -245,10 +253,10 @@ WebViewInternal.prototype.getProcessId = function() { |
| * @private |
| */ |
| WebViewInternal.prototype.go = function(relativeIndex) { |
| - if (!this.instanceId) { |
| + if (!this.guestInstanceId) { |
| return; |
| } |
| - WebView.go(this.instanceId, relativeIndex); |
| + WebView.go(this.guestInstanceId, relativeIndex); |
| }; |
| /** |
| @@ -262,30 +270,30 @@ WebViewInternal.prototype.print = function() { |
| * @private |
| */ |
| WebViewInternal.prototype.reload = function() { |
| - if (!this.instanceId) { |
| + if (!this.guestInstanceId) { |
| return; |
| } |
| - WebView.reload(this.instanceId); |
| + WebView.reload(this.guestInstanceId); |
| }; |
| /** |
| * @private |
| */ |
| WebViewInternal.prototype.stop = function() { |
| - if (!this.instanceId) { |
| + if (!this.guestInstanceId) { |
| return; |
| } |
| - WebView.stop(this.instanceId); |
| + WebView.stop(this.guestInstanceId); |
| }; |
| /** |
| * @private |
| */ |
| WebViewInternal.prototype.terminate = function() { |
| - if (!this.instanceId) { |
| + if (!this.guestInstanceId) { |
| return; |
| } |
| - WebView.terminate(this.instanceId); |
| + WebView.terminate(this.guestInstanceId); |
| }; |
| /** |
| @@ -294,7 +302,7 @@ WebViewInternal.prototype.terminate = function() { |
| WebViewInternal.prototype.validateExecuteCodeCall = function() { |
| var ERROR_MSG_CANNOT_INJECT_SCRIPT = '<webview>: ' + |
| 'Script cannot be injected into content until the page has loaded.'; |
| - if (!this.instanceId) { |
| + if (!this.guestInstanceId) { |
| throw new Error(ERROR_MSG_CANNOT_INJECT_SCRIPT); |
| } |
| }; |
| @@ -304,7 +312,7 @@ WebViewInternal.prototype.validateExecuteCodeCall = function() { |
| */ |
| WebViewInternal.prototype.executeScript = function(var_args) { |
| this.validateExecuteCodeCall(); |
| - var args = $Array.concat([this.instanceId, this.src], |
| + var args = $Array.concat([this.guestInstanceId, this.src], |
| $Array.slice(arguments)); |
| $Function.apply(WebView.executeScript, null, args); |
| }; |
| @@ -314,7 +322,7 @@ WebViewInternal.prototype.executeScript = function(var_args) { |
| */ |
| WebViewInternal.prototype.insertCSS = function(var_args) { |
| this.validateExecuteCodeCall(); |
| - var args = $Array.concat([this.instanceId, this.src], |
| + var args = $Array.concat([this.guestInstanceId, this.src], |
| $Array.slice(arguments)); |
| $Function.apply(WebView.insertCSS, null, args); |
| }; |
| @@ -469,12 +477,12 @@ WebViewInternal.prototype.handleWebviewAttributeMutation = |
| // details. |
| if (AUTO_SIZE_ATTRIBUTES.indexOf(name) > -1) { |
| this[name] = newValue; |
| - if (!this.instanceId) { |
| + if (!this.guestInstanceId) { |
| return; |
| } |
| // Convert autosize attribute to boolean. |
| var autosize = this.webviewNode.hasAttribute(WEB_VIEW_ATTRIBUTE_AUTOSIZE); |
| - GuestViewInternal.setAutoSize(this.instanceId, { |
| + GuestViewInternal.setAutoSize(this.guestInstanceId, { |
| 'enableAutoSize': autosize, |
| 'min': { |
| 'width': parseInt(this.minwidth || 0), |
| @@ -496,10 +504,10 @@ WebViewInternal.prototype.handleWebviewAttributeMutation = |
| return; |
| } |
| this.name = newValue; |
| - if (!this.instanceId) { |
| + if (!this.guestInstanceId) { |
| return; |
| } |
| - WebView.setName(this.instanceId, newValue); |
| + WebView.setName(this.guestInstanceId, newValue); |
| return; |
| } else if (name == 'src') { |
| // We treat null attribute (attribute removed) and the empty string as |
| @@ -552,20 +560,20 @@ WebViewInternal.prototype.handleWebviewAttributeMutation = |
| */ |
| WebViewInternal.prototype.handleBrowserPluginAttributeMutation = |
| function(name, oldValue, newValue) { |
| - if (name == 'internalbindings' && !oldValue && newValue) { |
| - this.browserPluginNode.removeAttribute('internalbindings'); |
| - |
| - if (this.deferredAttachState) { |
| - var self = this; |
| - // A setTimeout is necessary for the binding to be initialized properly. |
| + if (name == 'internalinstanceid' && !oldValue && !!newValue) { |
| + this.browserPluginNode.removeAttribute('internalinstanceid'); |
| + this.internalInstanceId = parseInt(newValue); |
| + if (this.deferredAttachState && !!this.guestInstanceId && |
| + this.guestInstanceId != 0) { |
| window.setTimeout(function() { |
| - if (self.hasBindings()) { |
| - var params = self.buildAttachParams( |
| - self.deferredAttachState.isNewWindow); |
| - self.browserPluginNode[PLUGIN_METHOD_ATTACH](self.instanceId, params); |
| - self.deferredAttachState = null; |
| - } |
| - }, 0); |
| + var isNewWindow = this.deferredAttachState ? |
| + this.deferredAttachState.isNewWindow : false; |
| + var params = this.buildAttachParams(isNewWindow); |
| + guestViewInternalNatives.AttachGuest( |
| + this.internalInstanceId, |
| + this.guestInstanceId, |
| + params); |
| + }.bind(this), 0); |
| } |
| return; |
| } |
| @@ -652,10 +660,9 @@ WebViewInternal.prototype.onSizeChanged = function(webViewEvent) { |
| } |
| }; |
| -// Returns true if Browser Plugin bindings is available. |
| -// Bindings are unavailable if <object> is not in the render tree. |
| -WebViewInternal.prototype.hasBindings = function() { |
| - return 'function' == typeof this.browserPluginNode[PLUGIN_METHOD_ATTACH]; |
| +// Returns if <object> is in the render tree. |
| +WebViewInternal.prototype.isPluginInRenderTree = function() { |
| + return !!this.internalInstanceId && this.internalInstanceId != 0; |
| }; |
| WebViewInternal.prototype.hasNavigated = function() { |
| @@ -687,7 +694,7 @@ WebViewInternal.prototype.parseSrcAttribute = function(result) { |
| } |
| // Navigate to this.src. |
| - WebView.navigate(this.instanceId, this.src); |
| + WebView.navigate(this.guestInstanceId, this.src); |
| return true; |
| }; |
| @@ -700,7 +707,7 @@ WebViewInternal.prototype.parseAttributes = function() { |
| }; |
| WebViewInternal.prototype.hasGuestInstanceID = function() { |
| - return this.instanceId != undefined; |
| + return this.guestInstanceId != undefined; |
| }; |
| WebViewInternal.prototype.allocateInstanceId = function() { |
| @@ -714,10 +721,10 @@ WebViewInternal.prototype.allocateInstanceId = function() { |
| GuestViewInternal.createGuest( |
| 'webview', |
| params, |
| - function(instanceId) { |
| + function(guestInstanceId) { |
| // TODO(lazyboy): Make sure this.autoNavigate_ stuff correctly updated |
| // |self.src| at this point. |
| - self.attachWindow(instanceId, false); |
| + self.attachWindow(guestInstanceId, false); |
| }); |
| }; |
| @@ -794,43 +801,43 @@ WebViewInternal.prototype.isUserAgentOverridden = function() { |
| /** @private */ |
| WebViewInternal.prototype.setUserAgentOverride = function(userAgentOverride) { |
| this.userAgentOverride = userAgentOverride; |
| - if (!this.instanceId) { |
| + if (!this.guestInstanceId) { |
| // If we are not attached yet, then we will pick up the user agent on |
| // attachment. |
| return; |
| } |
| - WebView.overrideUserAgent(this.instanceId, userAgentOverride); |
| + WebView.overrideUserAgent(this.guestInstanceId, userAgentOverride); |
| }; |
| /** @private */ |
| WebViewInternal.prototype.find = function(search_text, options, callback) { |
| - if (!this.instanceId) { |
| + if (!this.guestInstanceId) { |
| return; |
| } |
| - WebView.find(this.instanceId, search_text, options, callback); |
| + WebView.find(this.guestInstanceId, search_text, options, callback); |
| }; |
| /** @private */ |
| WebViewInternal.prototype.stopFinding = function(action) { |
| - if (!this.instanceId) { |
| + if (!this.guestInstanceId) { |
| return; |
| } |
| - WebView.stopFinding(this.instanceId, action); |
| + WebView.stopFinding(this.guestInstanceId, action); |
| }; |
| /** @private */ |
| WebViewInternal.prototype.setZoom = function(zoomFactor, callback) { |
| - if (!this.instanceId) { |
| + if (!this.guestInstanceId) { |
| return; |
| } |
| - WebView.setZoom(this.instanceId, zoomFactor, callback); |
| + WebView.setZoom(this.guestInstanceId, zoomFactor, callback); |
| }; |
| WebViewInternal.prototype.getZoom = function(callback) { |
| - if (!this.instanceId) { |
| + if (!this.guestInstanceId) { |
| return; |
| } |
| - WebView.getZoom(this.instanceId, callback); |
| + WebView.getZoom(this.guestInstanceId, callback); |
| }; |
| WebViewInternal.prototype.buildAttachParams = function(isNewWindow) { |
| @@ -852,19 +859,21 @@ WebViewInternal.prototype.buildAttachParams = function(isNewWindow) { |
| return params; |
| }; |
| -WebViewInternal.prototype.attachWindow = function(instanceId, isNewWindow) { |
| - this.instanceId = instanceId; |
| +WebViewInternal.prototype.attachWindow = function(guestInstanceId, |
| + isNewWindow) { |
| + this.guestInstanceId = guestInstanceId; |
| var params = this.buildAttachParams(isNewWindow); |
| - if (!this.hasBindings()) { |
| - // No bindings means that the plugin isn't there (display: none), we defer |
| - // attachWindow in this case. |
| + if (!this.isPluginInRenderTree()) { |
| this.deferredAttachState = {isNewWindow: isNewWindow}; |
| return false; |
| } |
| this.deferredAttachState = null; |
| - return this.browserPluginNode[PLUGIN_METHOD_ATTACH](this.instanceId, params); |
| + return guestViewInternalNatives.AttachGuest( |
| + this.internalInstanceId, |
| + this.guestInstanceId, |
| + params); |
| }; |
| // Registers browser plugin <object> custom element. |
| @@ -873,6 +882,7 @@ function registerBrowserPluginElement() { |
| proto.createdCallback = function() { |
| this.setAttribute('type', 'application/browser-plugin'); |
| + this.setAttribute('id', 'browser-plugin-' + IdGenerator.GetNextId()); |
|
Fady Samuel
2014/08/13 22:24:39
Note to self: Remove this.
|
| // The <object> node fills in the <webview> container. |
| this.style.width = '100%'; |
| this.style.height = '100%'; |
| @@ -923,6 +933,7 @@ function registerWebViewElement() { |
| return; |
| } |
| internal.elementAttached = false; |
| + internal.reset(); |
| }; |
| proto.attachedCallback = function() { |
| @@ -932,7 +943,6 @@ function registerWebViewElement() { |
| } |
| if (!internal.elementAttached) { |
| internal.elementAttached = true; |
| - internal.resetUponReattachment(); |
| internal.parseAttributes(); |
| } |
| }; |
| @@ -1019,7 +1029,7 @@ WebViewInternal.prototype.maybeHandleContextMenu = function(e, webViewEvent) { |
| // Setting |params| = undefined will show the context menu unmodified, hence |
| // the 'contextmenu' API is disabled for stable channel. |
| var params = undefined; |
| - WebView.showContextMenu(this.instanceId, requestId, params); |
| + WebView.showContextMenu(this.guestInstanceId, requestId, params); |
| }; |
| /** |