diff --git a/devtools/client/framework/test/browser.ini b/devtools/client/framework/test/browser.ini
index 4e07f04796df..bbca8b0c4ca4 100644
--- a/devtools/client/framework/test/browser.ini
+++ b/devtools/client/framework/test/browser.ini
@@ -159,7 +159,6 @@ run-if = e10s
[browser_toolbox_window_reload_target_force.js]
[browser_toolbox_window_shortcuts.js]
[browser_toolbox_window_title_changes.js]
-skip-if = fission
[browser_toolbox_window_title_frame_select.js]
fail-if = fission
[browser_toolbox_zoom.js]
diff --git a/devtools/client/framework/test/browser_toolbox_window_title_changes.js b/devtools/client/framework/test/browser_toolbox_window_title_changes.js
index 0bcac7f49ab1..0222159a079b 100644
--- a/devtools/client/framework/test/browser_toolbox_window_title_changes.js
+++ b/devtools/client/framework/test/browser_toolbox_window_title_changes.js
@@ -5,121 +5,93 @@ requestLongerTimeout(5);
var { Toolbox } = require("devtools/client/framework/toolbox");
-function test() {
- const URL_1 = "data:text/plain;charset=UTF-8,abcde";
- const URL_2 = "data:text/plain;charset=UTF-8,12345";
- const URL_3 = URL_ROOT + "browser_toolbox_window_title_changes_page.html";
+const NAME_1 = "";
+const NAME_2 = "Toolbox test for title update";
+const NAME_3 = NAME_2;
+const NAME_4 = "Toolbox test for another title update";
- const TOOL_ID_1 = "webconsole";
- const TOOL_ID_2 = "jsdebugger";
+const URL_1 = "data:text/plain;charset=UTF-8,abcde";
+const URL_2 = URL_ROOT_ORG + "browser_toolbox_window_title_changes_page.html";
+const URL_3 = URL_ROOT_COM + "browser_toolbox_window_title_changes_page.html";
+const URL_4 = `http://example.com/document-builder.sjs?html=
${NAME_4}Hello`;
- const NAME_1 = "";
- const NAME_2 = "";
- const NAME_3 = "Toolbox test for title update";
+add_task(async function test() {
+ await addTab(URL_1);
- let toolbox;
- let panel;
-
- addTab(URL_1).then(async function() {
- const tab = gBrowser.selectedTab;
- gDevTools
- .showToolboxForTab(tab, { hostType: Toolbox.HostType.BOTTOM })
- .then(function(aToolbox) {
- toolbox = aToolbox;
- })
- .then(() => toolbox.selectTool(TOOL_ID_1))
-
- // undock toolbox and check title
- .then(() => {
- // We have to first switch the host in order to spawn the new top level window
- // on which we are going to listen from title change event
- return toolbox
- .switchHost(Toolbox.HostType.WINDOW)
- .then(() => waitForTitleChange(toolbox));
- })
- .then(checkTitle.bind(null, NAME_1, URL_1, "toolbox undocked"))
-
- // switch to different tool and check title
- .then(async () => {
- const onTitleChanged = waitForTitleChange(toolbox);
- panel = await toolbox.selectTool(TOOL_ID_2);
- return onTitleChanged;
- })
- .then(checkTitle.bind(null, NAME_1, URL_1, "tool changed"))
-
- // navigate to different local url and check title
- .then(async function() {
- const onTitleChanged = waitForTitleChange(toolbox);
- const waitForReloaded = panel.once("reloaded");
- await navigateTo(URL_2);
- await waitForReloaded;
- return onTitleChanged;
- })
- .then(checkTitle.bind(null, NAME_2, URL_2, "url changed"))
-
- // navigate to a real url and check title
- .then(async () => {
- const onTitleChanged = waitForTitleChange(toolbox);
- const waitForReloaded = panel.once("reloaded");
- await navigateTo(URL_3);
- await waitForReloaded;
- return onTitleChanged;
- })
- .then(checkTitle.bind(null, NAME_3, URL_3, "url changed"))
-
- // destroy toolbox, create new one hosted in a window (with a
- // different tool id), and check title
- .then(function() {
- // Give the tools a chance to handle the navigation event before
- // destroying the toolbox.
- executeSoon(function() {
- toolbox
- .destroy()
- .then(async function() {
- // After destroying the toolbox, open a new one.
- return gDevTools.showToolboxForTab(tab, {
- hostType: Toolbox.HostType.WINDOW,
- });
- })
- .then(function(aToolbox) {
- toolbox = aToolbox;
- })
- .then(() => {
- const onTitleChanged = waitForTitleChange(toolbox);
- toolbox.selectTool(TOOL_ID_1);
- return onTitleChanged;
- })
- .then(
- checkTitle.bind(
- null,
- NAME_3,
- URL_3,
- "toolbox destroyed and recreated"
- )
- )
-
- // clean up
- .then(() => toolbox.destroy())
- .then(function() {
- toolbox = null;
- gBrowser.removeCurrentTab();
- Services.prefs.clearUserPref("devtools.toolbox.host");
- Services.prefs.clearUserPref("devtools.toolbox.selectedTool");
- Services.prefs.clearUserPref("devtools.toolbox.sideEnabled");
- finish();
- });
- });
- });
+ const tab = gBrowser.selectedTab;
+ let toolbox = await gDevTools.showToolboxForTab(tab, {
+ hostType: Toolbox.HostType.BOTTOM,
});
+ await toolbox.selectTool("webconsole");
+
+ info("Undock toolbox and check title");
+ // We have to first switch the host in order to spawn the new top level window
+ // on which we are going to listen from title change event
+ await toolbox.switchHost(Toolbox.HostType.WINDOW);
+ await checkTitle(NAME_1, URL_1, "toolbox undocked");
+
+ info("switch to different tool and check title again");
+ await toolbox.selectTool("jsdebugger");
+ await checkTitle(NAME_1, URL_1, "tool changed");
+
+ info("navigate to different local url and check title");
+
+ await navigateTo(URL_2);
+ info("wait for title change");
+ await checkTitle(NAME_2, URL_2, "url changed");
+
+ info("navigate to a real url and check title");
+ await navigateTo(URL_3);
+
+ info("wait for title change");
+ await checkTitle(NAME_3, URL_3, "url changed");
+
+ info("navigate to another page on the same domain");
+ await navigateTo(URL_4);
+ await checkTitle(NAME_4, URL_4, "title changed");
+
+ info(
+ "destroy toolbox, create new one hosted in a window (with a different tool id), and check title"
+ );
+ // Give the tools a chance to handle the navigation event before
+ // destroying the toolbox.
+ await new Promise(resolve => executeSoon(resolve));
+ await toolbox.destroy();
+
+ // After destroying the toolbox, open a new one.
+ toolbox = await gDevTools.showToolboxForTab(tab, {
+ hostType: Toolbox.HostType.WINDOW,
+ });
+ toolbox.selectTool("webconsole");
+ await checkTitle(NAME_4, URL_4, "toolbox destroyed and recreated");
+
+ info("clean up");
+ await toolbox.destroy();
+ gBrowser.removeCurrentTab();
+ Services.prefs.clearUserPref("devtools.toolbox.host");
+ Services.prefs.clearUserPref("devtools.toolbox.selectedTool");
+ Services.prefs.clearUserPref("devtools.toolbox.sideEnabled");
+});
+
+function getExpectedTitle(name, url) {
+ if (name) {
+ return `Developer Tools — ${name} — ${url}`;
+ }
+ return `Developer Tools — ${url}`;
}
-function checkTitle(name, url, context) {
- const win = Services.wm.getMostRecentWindow("devtools:toolbox");
- let expectedTitle;
- if (name) {
- expectedTitle = `Developer Tools — ${name} — ${url}`;
- } else {
- expectedTitle = `Developer Tools — ${url}`;
- }
- is(win.document.title, expectedTitle, context);
+async function checkTitle(name, url, context) {
+ info("Check title - " + context);
+ await waitFor(
+ () => getToolboxWindowTitle() === getExpectedTitle(name, url),
+ `Didn't get the expected title ("${getExpectedTitle(name, url)}"`,
+ 200,
+ 50
+ );
+ const expectedTitle = getExpectedTitle(name, url);
+ is(getToolboxWindowTitle(), expectedTitle, context);
+}
+
+function getToolboxWindowTitle() {
+ return Services.wm.getMostRecentWindow("devtools:toolbox").document.title;
}
diff --git a/devtools/client/framework/toolbox.js b/devtools/client/framework/toolbox.js
index 80f5397c28c8..231b1126761e 100644
--- a/devtools/client/framework/toolbox.js
+++ b/devtools/client/framework/toolbox.js
@@ -330,7 +330,6 @@ function Toolbox(
this._onResumedState = this._onResumedState.bind(this);
this._onTargetAvailable = this._onTargetAvailable.bind(this);
this._onTargetDestroyed = this._onTargetDestroyed.bind(this);
- this._onNavigate = this._onNavigate.bind(this);
this._onResourceAvailable = this._onResourceAvailable.bind(this);
this._onResourceUpdated = this._onResourceUpdated.bind(this);
@@ -696,7 +695,6 @@ Toolbox.prototype = {
// Attach to a new top-level target.
// For now, register these event listeners only on the top level target
targetFront.on("will-navigate", this._onWillNavigate);
- targetFront.on("navigate", this._onNavigate);
targetFront.on("frame-update", this._updateFrames);
targetFront.on("inspect-object", this._onInspectObject);
}
@@ -732,7 +730,6 @@ Toolbox.prototype = {
if (targetFront.isTopLevel) {
this.target.off("inspect-object", this._onInspectObject);
this.target.off("will-navigate", this._onWillNavigate);
- this.target.off("navigate", this._onNavigate);
this.target.off("frame-update", this._updateFrames);
}
@@ -801,10 +798,10 @@ Toolbox.prototype = {
this._onTargetDestroyed
);
- // Watch for console API messages, errors and network events in order to populate
- // the error count icon in the toolbox.
const onResourcesWatched = this.resourceCommand.watchResources(
[
+ // Watch for console API messages, errors and network events in order to populate
+ // the error count icon in the toolbox.
this.resourceCommand.TYPES.CONSOLE_MESSAGE,
this.resourceCommand.TYPES.ERROR_MESSAGE,
// Independently of watching network event resources for the error count icon,
@@ -813,6 +810,7 @@ Toolbox.prototype = {
// for network events across the lifetime of the various panels, so stopping
// the resource command from clearing out its cache of network event resources.
this.resourceCommand.TYPES.NETWORK_EVENT,
+ this.resourceCommand.TYPES.DOCUMENT_EVENT,
],
{
onAvailable: this._onResourceAvailable,
@@ -3762,6 +3760,7 @@ Toolbox.prototype = {
this.resourceCommand.TYPES.CONSOLE_MESSAGE,
this.resourceCommand.TYPES.ERROR_MESSAGE,
this.resourceCommand.TYPES.NETWORK_EVENT,
+ this.resourceCommand.TYPES.DOCUMENT_EVENT,
],
{ onAvailable: this._onResourceAvailable }
);
@@ -4279,14 +4278,6 @@ Toolbox.prototype = {
return id;
},
- /**
- * Fired when the user navigates to another page.
- */
- _onNavigate: function() {
- this._refreshHostTitle();
- this._setDebugTargetData();
- },
-
/**
* Sets basic information on the DebugTargetInfo component
*/
@@ -4325,6 +4316,24 @@ Toolbox.prototype = {
errors = 0;
}
}
+
+ if (
+ resource.resourceType === this.resourceCommand.TYPES.DOCUMENT_EVENT &&
+ resource?.targetFront.isTopLevel &&
+ !resource.isFrameSwitching &&
+ // `url` is set on the targetFront when we receive dom-loading, and `title` when
+ // `dom-interactive` is received. Here we're only updating the window title in
+ // the "newer" event.
+ resource.name === "dom-interactive"
+ ) {
+ // the targetFront title and url are update on dom-interactive, so delay refreshing
+ // the host title a bit in order for the event listener in targetCommand to be
+ // executed.
+ setTimeout(() => {
+ this._refreshHostTitle();
+ }, 0);
+ this._setDebugTargetData();
+ }
}
this.setErrorCount(errors);