Bug 1329220 - use a fourth browser to deal with print previewing simplified mode, r?jwatt,mconley draft
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Mon, 09 Jan 2017 23:44:15 +0000
changeset 457798 70bd5c8ffd5a5ce89bb892d38ad82c0041c742cf
parent 457797 e5853c043cce75ba89e3d800a181ba1d259e1f70
child 541596 50a3fff967c8c297054f62a6ab7f33d0e5038dfb
push id40900
push userbmo:gijskruitbosch+bugs@gmail.com
push dateMon, 09 Jan 2017 23:44:44 +0000
reviewersjwatt, mconley
bugs1329220
milestone53.0a1
Bug 1329220 - use a fourth browser to deal with print previewing simplified mode, r?jwatt,mconley MozReview-Commit-ID: JxMA3Kk6wnO
browser/base/content/browser.js
browser/base/content/tabbrowser.xml
toolkit/components/printing/content/printPreviewBindings.xml
toolkit/components/printing/content/printUtils.js
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -3322,32 +3322,54 @@ function getPEMString(cert) {
   var wrapped = derb64.replace(/(\S{64}(?!$))/g, "$1\r\n");
   return "-----BEGIN CERTIFICATE-----\r\n"
          + wrapped
          + "\r\n-----END CERTIFICATE-----\r\n";
 }
 
 var PrintPreviewListener = {
   _printPreviewTab: null,
+  _simplifiedPrintPreviewTab: null,
   _tabBeforePrintPreview: null,
   _simplifyPageTab: null,
+  _lastRequestedPrintPreviewTab: null,
+
+  _createPPBrowser() {
+    if (!this._tabBeforePrintPreview) {
+      this._tabBeforePrintPreview = gBrowser.selectedTab;
+    }
+    let browser = this._tabBeforePrintPreview.linkedBrowser;
+    let preferredRemoteType = browser.remoteType;
+    return gBrowser.loadOneTab("about:blank", {
+      inBackground: false,
+      preferredRemoteType,
+      relatedBrowser: browser,
+    });
+  },
 
   getPrintPreviewBrowser() {
     if (!this._printPreviewTab) {
-      let browser = gBrowser.selectedTab.linkedBrowser;
-      let preferredRemoteType = browser.remoteType;
-      this._tabBeforePrintPreview = gBrowser.selectedTab;
-      this._printPreviewTab = gBrowser.loadOneTab("about:blank",
-                                                  { inBackground: false,
-                                                    preferredRemoteType,
-                                                    relatedBrowser: browser });
-      gBrowser.selectedTab = this._printPreviewTab;
-    }
+      this._printPreviewTab = this._createPPBrowser();
+    }
+    gBrowser._allowTabChange = true;
+    this._lastRequestedPrintPreviewTab = gBrowser.selectedTab = this._printPreviewTab;
+    gBrowser._allowTabChange = false;
     return gBrowser.getBrowserForTab(this._printPreviewTab);
   },
+
+  getSimplifiedPrintPreviewBrowser() {
+    if (!this._simplifiedPrintPreviewTab) {
+      this._simplifiedPrintPreviewTab = this._createPPBrowser();
+    }
+    gBrowser._allowTabChange = true;
+    this._lastRequestedPrintPreviewTab = gBrowser.selectedTab = this._simplifiedPrintPreviewTab;
+    gBrowser._allowTabChange = false;
+    return gBrowser.getBrowserForTab(this._simplifiedPrintPreviewTab);
+  },
+
   createSimplifiedBrowser() {
     this._simplifyPageTab = gBrowser.loadOneTab("about:blank",
                                                 { inBackground: true });
     return this.getSimplifiedSourceBrowser();
   },
   getSourceBrowser() {
     return this._tabBeforePrintPreview ?
       this._tabBeforePrintPreview.linkedBrowser : gBrowser.selectedBrowser;
@@ -3357,34 +3379,36 @@ var PrintPreviewListener = {
       gBrowser.getBrowserForTab(this._simplifyPageTab) : null;
   },
   getNavToolbox() {
     return gNavToolbox;
   },
   onEnter() {
     // We might have accidentally switched tabs since the user invoked print
     // preview
-    if (gBrowser.selectedTab != this._printPreviewTab) {
-      gBrowser.selectedTab = this._printPreviewTab;
+    if (gBrowser.selectedTab != this._lastRequestedPrintPreviewTab) {
+      gBrowser.selectedTab = this._lastRequestedPrintPreviewTab;
     }
     gInPrintPreviewMode = true;
     this._toggleAffectedChrome();
   },
   onExit() {
     gBrowser.selectedTab = this._tabBeforePrintPreview;
     this._tabBeforePrintPreview = null;
     gInPrintPreviewMode = false;
     this._toggleAffectedChrome();
-    if (this._simplifyPageTab) {
-      gBrowser.removeTab(this._simplifyPageTab);
-      this._simplifyPageTab = null;
-    }
-    gBrowser.removeTab(this._printPreviewTab);
+    let tabsToRemove = ["_simplifyPageTab", "_printPreviewTab", "_simplifiedPrintPreviewTab"];
+    for (let tabProp of tabsToRemove) {
+      gBrowser.removeTab(this[tabProp]);
+    }
     gBrowser.deactivatePrintPreviewBrowsers();
-    this._printPreviewTab = null;
+    for (let tabProp of tabsToRemove) {
+      this[tabProp] = null;
+    }
+    this._lastRequestedPrintPreviewTab = null;
   },
   _toggleAffectedChrome() {
     gNavToolbox.collapsed = gInPrintPreviewMode;
 
     if (gInPrintPreviewMode)
       this._hideChrome();
     else
       this._showChrome();
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -3217,17 +3217,17 @@
       </method>
 
       <property name="selectedTab">
         <getter>
           return this.mCurrentTab;
         </getter>
         <setter>
           <![CDATA[
-          if (gNavToolbox.collapsed) {
+          if (gNavToolbox.collapsed && !this._allowTabChange) {
             return this.mTabBox.selectedTab;
           }
           // Update the tab
           this.mTabBox.selectedTab = val;
           return val;
           ]]>
         </setter>
       </property>
--- a/toolkit/components/printing/content/printPreviewBindings.xml
+++ b/toolkit/components/printing/content/printPreviewBindings.xml
@@ -164,16 +164,26 @@
           $("navigateHome").label = ltr ? "⏮" : "⏭";
           $("navigatePrevious").label = ltr ? "◂" : "▸";
           $("navigateNext").label = ltr ? "▸" : "◂";
           $("navigateEnd").label = ltr ? "⏭" : "⏮";
         ]]>
         </body>
       </method>
 
+      <method name="destroy">
+        <body>
+        <![CDATA[
+          this.mMessageManager.removeMessageListener("Printing:Preview:UpdatePageCount", this);
+          delete this.mMessageManager;
+          delete this.mPPBrowser;
+        ]]>
+        </body>
+      </method>
+
       <method name="doPageSetup">
         <body>
         <![CDATA[
           /* import-globals-from printUtils.js */
           var didOK = PrintUtils.showPageSetup();
           if (didOK) {
             // the changes that effect the UI
             this.updateToolbar();
--- a/toolkit/components/printing/content/printUtils.js
+++ b/toolkit/components/printing/content/printUtils.js
@@ -160,21 +160,31 @@ var PrintUtils = {
    *
    * @param aListenerObj
    *        An object that defines the following functions:
    *
    *        getPrintPreviewBrowser:
    *          Returns the <xul:browser> to display the print preview in. This
    *          <xul:browser> must have its type attribute set to "content".
    *
+   *        getSimplifiedPrintPreviewBrowser:
+   *          Returns the <xul:browser> to display the simplified print preview
+   *          in. This <xul:browser> must have its type attribute set to
+   *          "content".
+   *
    *        getSourceBrowser:
    *          Returns the <xul:browser> that contains the document being
    *          printed. This <xul:browser> must have its type attribute set to
    *          "content".
    *
+   *        getSimplifiedSourceBrowser:
+   *          Returns the <xul:browser> that contains the simplified version
+   *          of the document being printed. This <xul:browser> must have its
+   *          type attribute set to "content".
+   *
    *        getNavToolbox:
    *          Returns the primary toolbox for this window.
    *
    *        onEnter:
    *          Called upon entering print preview.
    *
    *        onExit:
    *          Called upon exiting print preview.
@@ -197,17 +207,19 @@ var PrintUtils = {
       // Here we log telemetry data for when the user enters print preview.
       this.logTelemetry("PRINT_PREVIEW_OPENED_COUNT");
     } else {
       // collapse the browser here -- it will be shown in
       // enterPrintPreview; this forces a reflow which fixes display
       // issues in bug 267422.
       // We use the print preview browser as the source browser to avoid
       // re-initializing print preview with a document that might now have changed.
-      this._sourceBrowser = this._listener.getPrintPreviewBrowser();
+      this._sourceBrowser = this._shouldSimplify ?
+        this._listener.getSimplifiedPrintPreviewBrowser() :
+        this._listener.getPrintPreviewBrowser();
       this._sourceBrowser.collapsed = true;
 
       // If the user transits too quickly within preview and we have a pending
       // progress dialog, we will close it before opening a new one.
       if (this._webProgressPP && this._webProgressPP.value) {
         this._webProgressPP.value.onStateChange(null, null,
           Components.interfaces.nsIWebProgressListener.STATE_STOP, 0);
       }
@@ -284,17 +296,17 @@ var PrintUtils = {
                "access to nsIWebBrowserPrint from content.";
     let url = "https://developer.mozilla.org/en-US/docs/Printing_from_a_XUL_App";
     Deprecated.warning(text, url);
 
     if (this.usingRemoteTabs) {
       return {};
     }
 
-    return this._listener.getPrintPreviewBrowser().docShell.printPreview;
+    return this._currentPPBrowser.docShell.printPreview;
   },
 
   get inPrintPreview() {
     return document.getElementById("print-preview-toolbar") != null;
   },
 
   // "private" methods and members. Don't use them.
 
@@ -478,23 +490,39 @@ var PrintUtils = {
       throw Components.results.NS_NOINTERFACE;
     }
   },
 
   setSimplifiedMode(shouldSimplify) {
     this._shouldSimplify = shouldSimplify;
   },
 
+  _ppBrowsers: new Set(),
+  _currentPPBrowser: null,
+
   enterPrintPreview() {
     // Send a message to the print preview browser to initialize
     // print preview. If we happen to have gotten a print preview
     // progress listener from nsIPrintingPromptService.showProgress
     // in printPreview, we add listeners to feed that progress
     // listener.
-    let ppBrowser = this._listener.getPrintPreviewBrowser();
+    let ppBrowser = this._shouldSimplify ?
+      this._listener.getSimplifiedPrintPreviewBrowser() :
+      this._listener.getPrintPreviewBrowser();
+    this._ppBrowsers.add(ppBrowser);
+    // If we're switching from 'normal' print preview to 'simplified' print
+    // preview, we will want to run reader mode against the 'normal' print
+    // preview browser's content:
+    let oldPPBrowser = null;
+    let changingPrintPreviewBrowsers = false;
+    if (ppBrowser != this._currentPPBrowser) {
+      changingPrintPreviewBrowsers = true;
+      oldPPBrowser = this._currentPPBrowser;
+    }
+    this._currentPPBrowser = ppBrowser;
     let mm = ppBrowser.messageManager;
 
     let sendEnterPreviewMessage = function(browser, simplified) {
       mm.sendAsyncMessage("Printing:Preview:Enter", {
         windowID: browser.outerWindowID,
         simplifiedMode: simplified,
       });
     };
@@ -520,17 +548,17 @@ var PrintUtils = {
           sendEnterPreviewMessage(simplifiedBrowser, true);
         });
 
         // Here, we send down a message to simplified browser in order to parse
         // the original page. After we have parsed it, content will tell parent
         // that the document is ready for print previewing.
         spMM.sendAsyncMessage("Printing:Preview:ParseDocument", {
           URL: this._originalURL,
-          windowID: this._sourceBrowser.outerWindowID,
+          windowID: oldPPBrowser.outerWindowID,
         });
 
         // Here we log telemetry data for when the user enters simplify mode.
         this.logTelemetry("PRINT_PREVIEW_SIMPLIFY_PAGE_OPENED_COUNT");
       }
     } else {
       sendEnterPreviewMessage(this._sourceBrowser, false);
     }
@@ -552,16 +580,20 @@ var PrintUtils = {
       }
 
       // Stash the focused element so that we can return to it after exiting
       // print preview.
       gFocusedElement = document.commandDispatcher.focusedElement;
 
       let printPreviewTB = document.getElementById("print-preview-toolbar");
       if (printPreviewTB) {
+        if (changingPrintPreviewBrowsers) {
+          printPreviewTB.destroy();
+          printPreviewTB.initialize(ppBrowser);
+        }
         printPreviewTB.updateToolbar();
         ppBrowser.collapsed = false;
         ppBrowser.focus();
         return;
       }
 
       // Set the original window as an active window so any mozPrintCallbacks can
       // run without delayed setTimeouts.
@@ -608,29 +640,33 @@ var PrintUtils = {
       // on Enter PP Call back
       this._listener.onEnter();
     };
 
     mm.addMessageListener("Printing:Preview:Entered", onEntered);
   },
 
   exitPrintPreview() {
-    let ppBrowser = this._listener.getPrintPreviewBrowser();
-    let browserMM = ppBrowser.messageManager;
-    browserMM.sendAsyncMessage("Printing:Preview:Exit");
+    for (let browser of this._ppBrowsers) {
+      let browserMM = browser.messageManager;
+      browserMM.sendAsyncMessage("Printing:Preview:Exit");
+    }
+    this._ppBrowsers.clear();
+    this._currentPPBrowser = null;
     window.removeEventListener("keydown", this.onKeyDownPP, true);
     window.removeEventListener("keypress", this.onKeyPressPP, true);
 
     // restore the old close handler
     document.documentElement.setAttribute("onclose", this._closeHandlerPP);
     this._closeHandlerPP = null;
 
     // remove the print preview toolbar
     let printPreviewTB = document.getElementById("print-preview-toolbar");
-    this._listener.getNavToolbox().parentNode.removeChild(printPreviewTB);
+    printPreviewTB.destroy();
+    printPreviewTB.remove();
 
     let fm = Components.classes["@mozilla.org/focus-manager;1"]
                        .getService(Components.interfaces.nsIFocusManager);
     if (gFocusedElement)
       fm.setFocus(gFocusedElement, fm.FLAG_NOSCROLL);
     else
       this._sourceBrowser.focus();
     gFocusedElement = null;