Bug 1313933 - Explicitly bypass history when loading RDM UI. r=ochameau draft
authorJ. Ryan Stinnett <jryans@gmail.com>
Fri, 27 Jan 2017 16:03:04 -0600
changeset 467533 957f65ae6c97f27041b15d0790f8991da4be9747
parent 467532 271f1b04981006e936ae71e12e24f6646fadac25
child 543711 50074e510172232fe88313fa27085581f9e8be1e
push id43204
push userbmo:jryans@gmail.com
push dateFri, 27 Jan 2017 23:02:24 +0000
reviewersochameau
bugs1313933
milestone54.0a1
Bug 1313933 - Explicitly bypass history when loading RDM UI. r=ochameau By using `LOAD_FLAGS_BYPASS_HISTORY`, we can tell session history explicitly to ignore the entry for the container UI (which is meant to remain hidden from the user). This allows us to remove the horrible racy hack that attempted to have the same effect. MozReview-Commit-ID: LnhJpO9UbNI
devtools/client/responsive.html/browser/swap.js
devtools/client/responsive.html/browser/tunnel.js
--- a/devtools/client/responsive.html/browser/swap.js
+++ b/devtools/client/responsive.html/browser/swap.js
@@ -1,14 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
+const { Ci } = require("chrome");
 const promise = require("promise");
 const { Task } = require("devtools/shared/task");
 const { tunnelToInnerBrowser } = require("./tunnel");
 
 /**
  * Swap page content from an existing tab into a new browser within a container
  * page.  Page state is preserved by using `swapFrameLoaders`, just like when
  * you move a tab to a new window.  This provides a seamless transition for the
@@ -53,21 +54,26 @@ function swapToInnerBrowser({ tab, conta
 
     start: Task.async(function* () {
       tab.isResponsiveDesignMode = true;
 
       // Freeze navigation temporarily to avoid "blinking" in the location bar.
       freezeNavigationState(tab);
 
       // 1. Create a temporary, hidden tab to load the tool UI.
-      let containerTab = gBrowser.addTab(containerURL, {
+      let containerTab = gBrowser.addTab("about:blank", {
         skipAnimation: true,
+        forceNotRemote: true,
       });
       gBrowser.hideTab(containerTab);
       let containerBrowser = containerTab.linkedBrowser;
+      // Prevent the `containerURL` from ending up in the tab's history.
+      containerBrowser.loadURIWithFlags(containerURL, {
+        flags: Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_HISTORY,
+      });
 
       // Copy tab listener state flags to container tab.  Each tab gets its own tab
       // listener and state flags which cache document loading progress.  The state flags
       // are checked when switching tabs to update the browser UI.  The later step of
       // `swapBrowsersAndCloseOther` will fold the state back into the main tab.
       let stateFlags = gBrowser._tabListeners.get(tab).mStateFlags;
       gBrowser._tabListeners.get(containerTab).mStateFlags = stateFlags;
 
--- a/devtools/client/responsive.html/browser/tunnel.js
+++ b/devtools/client/responsive.html/browser/tunnel.js
@@ -2,17 +2,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const { Ci } = require("chrome");
 const Services = require("Services");
 const { Task } = require("devtools/shared/task");
-const DevToolsUtils = require("devtools/shared/DevToolsUtils");
 const { BrowserElementWebNavigation } = require("./web-navigation");
 const { getStack } = require("devtools/shared/platform/stack");
 
 // A symbol used to hold onto the frame loader from the outer browser while tunneling.
 const FRAME_LOADER = Symbol("devtools/responsive/frame-loader");
 
 function debug(msg) {
   // console.log(msg);
@@ -122,17 +121,18 @@ function tunnelToInnerBrowser(outer, inn
       });
 
       // The `permanentKey` property on a <xul:browser> is used to index into various maps
       // held by the session store.  When you swap content around with
       // `_swapBrowserDocShells`, these keys are also swapped so they follow the content.
       // This means the key that matches the content is on the inner browser.  Since we
       // want the browser UI to believe the page content is part of the outer browser, we
       // copy the content's `permanentKey` up to the outer browser.
-      copyPermanentKey(outer, inner);
+      debug("Copy inner permanentKey to outer browser");
+      outer.permanentKey = inner.permanentKey;
 
       // Replace the outer browser's native messageManager with a message manager tunnel
       // which we can use to route messages of interest to the inner browser instead.
       // Note: The _actual_ messageManager accessible from
       // `browser.frameLoader.messageManager` is not overridable and is left unchanged.
       // Only the XBL getter `browser.messageManager` is overridden.  Browser UI code
       // always uses this getter instead of `browser.frameLoader.messageManager` directly,
       // so this has the effect of overriding the message manager for browser UI code.
@@ -299,43 +299,16 @@ function tunnelToInnerBrowser(outer, inn
       gBrowser = null;
     },
 
   };
 }
 
 exports.tunnelToInnerBrowser = tunnelToInnerBrowser;
 
-function copyPermanentKey(outer, inner) {
-  // When we're in the process of swapping content around, we end up receiving a
-  // SessionStore:update message which lists the container page that is loaded into the
-  // outer browser (that we're hiding the inner browser within) as part of its history.
-  // We want SessionStore's view of the history for our tab to only have the page content
-  // of the inner browser, so we want to hide this message from SessionStore, but we have
-  // no direct mechanism to do so.  As a workaround, we wait until the one errant message
-  // has gone by, and then we copy the permanentKey after that, since the permanentKey is
-  // what SessionStore uses to identify each browser.
-  let outerMM = outer[FRAME_LOADER].messageManager;
-  let onHistoryEntry = message => {
-    let data = message.data.data;
-    let history = data.history || data.historychange;
-    if (!history || !history.entries) {
-      // Wait for a message that contains history data
-      return;
-    }
-    outerMM.removeMessageListener("SessionStore:update", onHistoryEntry);
-    debug("Got session update for outer browser");
-    DevToolsUtils.executeSoon(() => {
-      debug("Copy inner permanentKey to outer browser");
-      outer.permanentKey = inner.permanentKey;
-    });
-  };
-  outerMM.addMessageListener("SessionStore:update", onHistoryEntry);
-}
-
 /**
  * This module allows specific messages of interest to be directed from the
  * outer browser to the inner browser (and vice versa) in a targetted fashion
  * without having to touch the original code paths that use them.
  */
 function MessageManagerTunnel(outer, inner) {
   if (outer.isRemoteBrowser) {
     throw new Error("The outer browser must be non-remote.");