Bug 1296785 - Make view-source in a new window work correctly
This patch also makes sure that we correctly grab a weak reference to the
related window instead of just setting a "relatedBrowser" property directly on
the JS object (which shadows the XBL property getter).
MozReview-Commit-ID: IQeIoSHKKbb
--- a/toolkit/components/viewsource/ViewSourceBrowser.jsm
+++ b/toolkit/components/viewsource/ViewSourceBrowser.jsm
@@ -181,16 +181,18 @@ ViewSourceBrowser.prototype = {
* The line number to focus on once the source is loaded.
*/
loadViewSource({ URL, browser, outerWindowID, lineNumber }) {
if (!URL) {
throw new Error("Must supply a URL when opening view source.");
}
if (browser) {
+ this.browser.relatedBrowser = browser;
+
// If we're dealing with a remote browser, then the browser
// for view source needs to be remote as well.
this.updateBrowserRemoteness(browser.isRemoteBrowser);
} else if (outerWindowID) {
throw new Error("Must supply the browser if passing the outerWindowID");
}
this.sendAsyncMessage("ViewSource:LoadSource",
--- a/toolkit/components/viewsource/content/viewSource.js
+++ b/toolkit/components/viewsource/content/viewSource.js
@@ -670,22 +670,32 @@ ViewSourceChrome.prototype = {
updateBrowserRemoteness(shouldBeRemote) {
if (this.browser.isRemoteBrowser == shouldBeRemote) {
return;
}
let parentNode = this.browser.parentNode;
let nextSibling = this.browser.nextSibling;
+ // XX Removing and re-adding the browser from and to the DOM strips its
+ // XBL properties. Save and restore relatedBrowser. Note that when we
+ // restore relatedBrowser, there won't yet be a binding or setter. This
+ // works in conjunction with the hack in <xul:browser>'s constructor to
+ // re-get the weak reference to it.
+ let relatedBrowser = this.browser.relatedBrowser;
+
this.browser.remove();
if (shouldBeRemote) {
this.browser.setAttribute("remote", "true");
} else {
this.browser.removeAttribute("remote");
}
+
+ this.browser.relatedBrowser = relatedBrowser;
+
// If nextSibling was null, this will put the browser at
// the end of the list.
parentNode.insertBefore(this.browser, nextSibling);
if (shouldBeRemote) {
// We're going to send a message down to the remote browser
// to load the source content - however, in order for the
// contentWindowAsCPOW and contentDocumentAsCPOW values on
--- a/toolkit/content/widgets/browser.xml
+++ b/toolkit/content/widgets/browser.xml
@@ -895,16 +895,26 @@
Components.utils.reportError(e);
}
try {
var securityUI = this.securityUI;
}
catch (e) {
}
+ // XXX tabbrowser.js sets "relatedBrowser" as a direct property on
+ // some browsers before they are put into a DOM (and get a binding).
+ // This hack makes sure that we hold a weak reference to the other
+ // browser (and go through the proper getter and setter).
+ if (this.hasOwnProperty("relatedBrowser")) {
+ var relatedBrowser = this.relatedBrowser;
+ delete this.relatedBrowser;
+ this.relatedBrowser = relatedBrowser;
+ }
+
if (!this.isRemoteBrowser) {
this.addEventListener("pagehide", this.onPageHide, true);
}
if (this.messageManager) {
this.messageManager.addMessageListener("PopupBlocking:UpdateBlockedPopups", this);
this.messageManager.addMessageListener("Autoscroll:Start", this);
this.messageManager.addMessageListener("Autoscroll:Cancel", this);