Bug 1068400 - Restore toolbox when switching from in-parent-process to OOP tab. r=jryans
MozReview-Commit-ID: K51gp7PavC7
--- a/devtools/client/framework/target.js
+++ b/devtools/client/framework/target.js
@@ -9,24 +9,26 @@ const promise = require("promise");
const defer = require("devtools/shared/defer");
const EventEmitter = require("devtools/shared/event-emitter");
const Services = require("Services");
const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
loader.lazyRequireGetter(this, "DebuggerServer", "devtools/server/main", true);
loader.lazyRequireGetter(this, "DebuggerClient",
"devtools/shared/client/main", true);
+loader.lazyRequireGetter(this, "gDevTools",
+ "devtools/client/framework/devtools", true);
const targets = new WeakMap();
const promiseTargets = new WeakMap();
/**
* Functions for creating Targets
*/
-exports.TargetFactory = {
+const TargetFactory = exports.TargetFactory = {
/**
* Construct a Target
* @param {XULTab} tab
* The tab to use in creating a new target.
*
* @return A target object
*/
forTab: function (tab) {
@@ -449,29 +451,31 @@ TabTarget.prototype = {
* Listen to the different events.
*/
_setupListeners: function () {
this._webProgressListener = new TabWebProgressListener(this);
this.tab.linkedBrowser.addProgressListener(this._webProgressListener);
this.tab.addEventListener("TabClose", this);
this.tab.parentNode.addEventListener("TabSelect", this);
this.tab.ownerDocument.defaultView.addEventListener("unload", this);
+ this.tab.addEventListener("TabRemotenessChange", this);
},
/**
* Teardown event listeners.
*/
_teardownListeners: function () {
if (this._webProgressListener) {
this._webProgressListener.destroy();
}
this._tab.ownerDocument.defaultView.removeEventListener("unload", this);
this._tab.removeEventListener("TabClose", this);
this._tab.parentNode.removeEventListener("TabSelect", this);
+ this._tab.removeEventListener("TabRemotenessChange", this);
},
/**
* Setup listeners for remote debugging, updating existing ones as necessary.
*/
_setupRemoteListeners: function () {
this.client.addListener("closed", this.destroy);
@@ -543,19 +547,48 @@ TabTarget.prototype = {
break;
case "TabSelect":
if (this.tab.selected) {
this.emit("visible", event);
} else {
this.emit("hidden", event);
}
break;
+ case "TabRemotenessChange":
+ this.onRemotenessChange();
+ break;
}
},
+ // Automatically respawn the toolbox when the tab changes between being
+ // loaded within the parent process and loaded from a content process.
+ // Process change can go in both ways.
+ onRemotenessChange: function () {
+ // Responsive design do a crazy dance around tabs and triggers
+ // remotenesschange events. But we should ignore them as at the end
+ // the content doesn't change its remoteness.
+ if (this._tab.isReponsiveDesignMode) {
+ return;
+ }
+
+ // Save a reference to the tab as it will be nullified on destroy
+ let tab = this._tab;
+ let onToolboxDestroyed = (event, target) => {
+ if (target != this) {
+ return;
+ }
+ gDevTools.off("toolbox-destroyed", target);
+
+ // Recreate a fresh target instance as the current one is now destroyed
+ let newTarget = TargetFactory.forTab(tab);
+ gDevTools.showToolbox(newTarget);
+ };
+ gDevTools.on("toolbox-destroyed", onToolboxDestroyed);
+ },
+
/**
* Target is not alive anymore.
*/
destroy: function () {
// If several things call destroy then we give them all the same
// destruction promise so we're sure to destroy only once
if (this._destroyer) {
return this._destroyer.promise;
--- a/devtools/client/framework/test/browser.ini
+++ b/devtools/client/framework/test/browser.ini
@@ -56,16 +56,18 @@ skip-if = true # Bug 1177463 - Temporari
[browser_toolbox_options_disable_buttons.js]
[browser_toolbox_options_disable_cache-01.js]
[browser_toolbox_options_disable_cache-02.js]
[browser_toolbox_options_disable_js.js]
[browser_toolbox_options_enable_serviceworkers_testing.js]
# [browser_toolbox_raise.js] # Bug 962258
# skip-if = os == "win"
[browser_toolbox_ready.js]
+[browser_toolbox_remoteness_change.js]
+run-if = e10s
[browser_toolbox_select_event.js]
skip-if = e10s # Bug 1069044 - destroyInspector may hang during shutdown
[browser_toolbox_selected_tool_unavailable.js]
[browser_toolbox_sidebar.js]
[browser_toolbox_sidebar_events.js]
[browser_toolbox_sidebar_existing_tabs.js]
[browser_toolbox_sidebar_overflow_menu.js]
[browser_toolbox_split_console.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/framework/test/browser_toolbox_remoteness_change.js
@@ -0,0 +1,42 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+var {Toolbox} = require("devtools/client/framework/toolbox");
+
+const URL_1 = "about:robots";
+const URL_2 = "data:text/html;charset=UTF-8," +
+ encodeURIComponent("<div id=\"remote-page\">foo</div>");
+
+add_task(function* () {
+ info("Open a tab on a URL supporting only running in parent process");
+ let tab = yield addTab(URL_1);
+ is(tab.linkedBrowser.currentURI.spec, URL_1, "We really are on the expected document");
+ is(tab.linkedBrowser.getAttribute("remote"), "", "And running in parent process");
+
+ let toolbox = yield openToolboxForTab(tab);
+
+ let onToolboxDestroyed = toolbox.once("destroyed");
+ let onToolboxCreated = gDevTools.once("toolbox-created");
+
+ info("Navigate to a URL supporting remote process");
+ let onLoaded = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
+ gBrowser.loadURI(URL_2);
+ yield onLoaded;
+
+ is(tab.linkedBrowser.getAttribute("remote"), "true", "Navigated to a data: URI and switching to remote");
+
+ info("Waiting for the toolbox to be destroyed");
+ yield onToolboxDestroyed;
+
+ info("Waiting for a new toolbox to be created");
+ toolbox = yield onToolboxCreated;
+
+ info("Waiting for the new toolbox to be ready");
+ yield toolbox.once("ready");
+
+ info("Veryify we are inspecting the new document");
+ let console = yield toolbox.selectTool("webconsole");
+ let { jsterm } = console.hud;
+ let url = yield jsterm.execute("document.location.href");
+ is(url.textContent, URL_2, "The console inspects the second document");
+});
--- a/devtools/client/responsive.html/browser/swap.js
+++ b/devtools/client/responsive.html/browser/swap.js
@@ -47,16 +47,18 @@ function swapToInnerBrowser({ tab, conta
bubbles: true,
});
from.dispatchEvent(event);
};
return {
start: Task.async(function* () {
+ tab.isReponsiveDesignMode = 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, {
skipAnimation: true,
});
gBrowser.hideTab(containerTab);
@@ -145,16 +147,18 @@ function swapToInnerBrowser({ tab, conta
dispatchDevToolsBrowserSwap(contentBrowser, tab.linkedBrowser);
gBrowser.swapBrowsersAndCloseOther(tab, contentTab);
gBrowser = null;
// The focus manager seems to get a little dizzy after all this swapping. If a
// content element had been focused inside the viewport before stopping, it will
// have lost focus. Activate the frame to restore expected focus.
tab.linkedBrowser.frameLoader.activateRemoteFrame();
+
+ delete tab.isReponsiveDesignMode;
},
};
}
/**
* Browser navigation properties we'll freeze temporarily to avoid "blinking" in the
* location bar, etc. caused by the containerURL peeking through before the swap is