Bug 1094312: Properly destroy browsers when switching between remote and non-remove pages and override the default destroy method in remote-browser.xml. r=mconley

In some cases removing an element from a document doesn't call its XBL
constructor. tabbrowser knows this and so calls a destroy method on browser
elements when removing them.

When remote-browser was added we forgot to add a specific destroy method so the
base browser binding's would be used. This would mean remote-browsers aren't
being destroyed correctly.

Also when we switch from remote to non-remote browsers or vice versa we don't
call the destroy method at all so sometimes the browser isn't destroyed properly
and observer notifications get fired on dead browser elements.

--HG--
extra : rebase_source : d54ca85d912fdd736495c500910ff51fb5e15b6a
This commit is contained in:
Dave Townsend 2014-12-29 17:09:52 -08:00
parent ca0f5ff5a7
commit 87c71b8022
2 changed files with 38 additions and 3 deletions

View File

@ -1466,6 +1466,8 @@
let index = tab._tPos;
let filter = this.mTabFilters[index];
aBrowser.webProgress.removeProgressListener(filter);
// Make sure the browser is destroyed so it unregisters from observer notifications
aBrowser.destroy();
// Change the "remote" attribute.
let parent = aBrowser.parentNode;

View File

@ -19,6 +19,11 @@
readonly="true">
<getter><![CDATA[
if (!this._securityUI) {
// Don't attempt to create the remote web progress if the
// messageManager has already gone away
if (!this.messageManager)
return null;
let jsm = "resource://gre/modules/RemoteSecurityUI.jsm";
let RemoteSecurityUI = Components.utils.import(jsm, {}).RemoteSecurityUI;
this._securityUI = new RemoteSecurityUI();
@ -40,6 +45,8 @@
]]></body>
</method>
<field name="_controller">null</field>
<field name="_remoteWebNavigation">null</field>
<property name="webNavigation"
@ -52,8 +59,13 @@
<getter>
<![CDATA[
if (!this._remoteWebProgress) {
// Don't attempt to create the remote web progress if the
// messageManager has already gone away
if (!this.messageManager)
return null;
let jsm = "resource://gre/modules/RemoteWebProgress.jsm";
let RemoteWebProgressManager = Cu.import(jsm, {}).RemoteWebProgressManager;
let { RemoteWebProgressManager } = Cu.import(jsm, {});
this._remoteWebProgressManager = new RemoteWebProgressManager(this);
this._remoteWebProgress = this._remoteWebProgressManager.topLevelWebProgress;
}
@ -67,8 +79,13 @@
<property name="finder" readonly="true">
<getter><![CDATA[
if (!this._remoteFinder) {
// Don't attempt to create the remote web progress if the
// messageManager has already gone away
if (!this.messageManager)
return null;
let jsm = "resource://gre/modules/RemoteFinder.jsm";
let RemoteFinder = Cu.import(jsm, {}).RemoteFinder;
let { RemoteFinder } = Cu.import(jsm, {});
this._remoteFinder = new RemoteFinder(this);
}
return this._remoteFinder;
@ -206,6 +223,8 @@
</setter>
</property>
<field name="mDestroyed">false</field>
<constructor>
<![CDATA[
/*
@ -246,10 +265,24 @@
<destructor>
<![CDATA[
Services.obs.removeObserver(this, "ask-children-to-exit-fullscreen");
this.destroy();
]]>
</destructor>
<!-- This is necessary because the destructor doesn't always get called when
we are removed from a tabbrowser. This will be explicitly called by tabbrowser -->
<method name="destroy">
<body><![CDATA[
if (this.mDestroyed)
return;
this.mDestroyed = true;
this.controllers.removeController(this._controller);
Services.obs.removeObserver(this, "ask-children-to-exit-fullscreen");
]]></body>
</method>
<method name="receiveMessage">
<parameter name="aMessage"/>
<body><![CDATA[