Bug 1296785 - Make view-source in a new window work correctly draft
authorBlake Kaplan <mrbkap@gmail.com>
Fri, 19 Aug 2016 16:26:13 -0700
changeset 403568 6afb7cdf16f9da1c575d40394d8d4761a5252e75
parent 403386 8ef9629d8f90d6507b1bad01146b14101de79174
child 528935 1c37aa1865c8c0b90b40fcce4d0cfbd6333c6c1d
push id26943
push usermrbkap@mozilla.com
push dateFri, 19 Aug 2016 23:42:34 +0000
bugs1296785
milestone51.0a1
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
toolkit/components/viewsource/ViewSourceBrowser.jsm
toolkit/components/viewsource/content/viewSource.js
toolkit/content/widgets/browser.xml
--- 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);