Commit 617e4fc4 authored by ericzeng's avatar ericzeng Committed by Commit bot

Implement <extensionoptions> deferred attach logic

Due to how the browser plugin is created, it is possible for the
<extensionoptions> element to attempt to attach to the embedder before
the browser plugin has bindings. This occurs when an ExtensionOptions object
gets an extension id and creates a guest, but has not yet been added
to the DOM. Use the deferred attach logic from <webview> so that if this
case occurs, wait until the browser plugin gets its bindings before
trying to attach the guest view.

BUG=386838

Review URL: https://codereview.chromium.org/457653003

Cr-Commit-Position: refs/heads/master@{#292215}
parent 9a44f044
......@@ -35,29 +35,31 @@ function ExtensionOptionsInternal(extensionoptionsNode) {
// the event is fired from here instead of through
// extension_options_events.js.
this.setupEventProperty('createfailed');
new ExtensionOptionsEvents(this, this.viewInstanceId);
this.setupNodeProperties();
if (this.parseExtensionAttribute())
this.init();
this.parseExtensionAttribute();
// Once the browser plugin has been created, the guest view will be created
// and attached. See handleBrowserPluginAttributeMutation().
this.browserPluginNode = this.createBrowserPluginNode();
var shadowRoot = this.extensionoptionsNode.createShadowRoot();
shadowRoot.appendChild(this.browserPluginNode);
};
ExtensionOptionsInternal.prototype.attachWindow = function(guestInstanceId) {
this.guestInstanceId = guestInstanceId;
var params = {
'autosize': this.autosize,
'instanceId': this.viewInstanceId,
'maxheight': parseInt(this.maxheight || 0),
'maxwidth': parseInt(this.maxwidth || 0),
'minheight': parseInt(this.minheight || 0),
'minwidth': parseInt(this.minwidth || 0)
};
ExtensionOptionsInternal.prototype.attachWindow = function() {
return guestViewInternalNatives.AttachGuest(
parseInt(this.browserPluginNode.getAttribute('internalinstanceid')),
guestInstanceId,
params);
this.internalInstanceId,
this.guestInstanceId,
{
'autosize': this.autosize,
'instanceId': this.viewInstanceId,
'maxheight': parseInt(this.maxheight || 0),
'maxwidth': parseInt(this.maxwidth || 0),
'minheight': parseInt(this.minheight || 0),
'minwidth': parseInt(this.minwidth || 0)
});
};
ExtensionOptionsInternal.prototype.createBrowserPluginNode = function() {
......@@ -81,7 +83,8 @@ ExtensionOptionsInternal.prototype.createGuest = function() {
var createFailedEvent = new Event('createfailed', { bubbles: true });
this.dispatchEvent(createFailedEvent);
} else {
this.attachWindow(guestInstanceId);
this.guestInstanceId = guestInstanceId;
this.attachWindow();
}
}.bind(this));
};
......@@ -101,11 +104,18 @@ ExtensionOptionsInternal.prototype.handleExtensionOptionsAttributeMutation =
if (oldValue === newValue)
return;
if (name == 'extension') {
if (name == 'extension' && !oldValue && newValue) {
this.extensionId = newValue;
// Create new guest view if one hasn't been created for this element.
if (!this.guestInstanceId && this.parseExtensionAttribute())
this.init();
// If the browser plugin is not ready then don't create the guest until
// it is ready (in handleBrowserPluginAttributeMutation).
if (!this.internalInstanceId)
return;
// If a guest view does not exist then create one.
if (!this.guestInstanceId) {
this.createGuest();
return;
}
// TODO(ericzeng): Implement navigation to another guest view if we want
// that functionality.
} else if (AUTO_SIZE_ATTRIBUTES.hasOwnProperty(name) > -1) {
......@@ -129,15 +139,15 @@ ExtensionOptionsInternal.prototype.handleExtensionOptionsAttributeMutation =
}
};
ExtensionOptionsInternal.prototype.init = function() {
if (this.initCalled)
return;
ExtensionOptionsInternal.prototype.handleBrowserPluginAttributeMutation =
function(name, oldValue, newValue) {
if (name == 'internalinstanceid' && !oldValue && !!newValue) {
this.internalInstanceId = parseInt(newValue);
this.browserPluginNode.removeAttribute('internalinstanceid');
if (this.extensionId)
this.createGuest();
this.initCalled = true;
this.browserPluginNode = this.createBrowserPluginNode();
var shadowRoot = this.extensionoptionsNode.createShadowRoot();
shadowRoot.appendChild(this.browserPluginNode);
this.createGuest();
}
};
ExtensionOptionsInternal.prototype.onSizeChanged =
......@@ -292,6 +302,14 @@ function registerBrowserPluginElement() {
this.style.height = '100%';
};
proto.attributeChangedCallback = function(name, oldValue, newValue) {
var internal = privates(this).internal;
if (!internal) {
return;
}
internal.handleBrowserPluginAttributeMutation(name, oldValue, newValue);
};
proto.attachedCallback = function() {
// Load the plugin immediately.
var unused = this.nonExistentAttribute;
......@@ -299,7 +317,7 @@ function registerBrowserPluginElement() {
ExtensionOptionsInternal.BrowserPlugin =
DocumentNatives.RegisterElement('extensionoptionsplugin',
{extends: 'object', prototype: proto});
{extends: 'object', prototype: proto});
delete proto.createdCallback;
delete proto.attachedCallback;
delete proto.detachedCallback;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment