Bug 1936774 - [remote] Prototype parent process NavigationListener r=webdriver-reviewers,Sasha
Depends on D245945 Differential Revision: https://phabricator.services.mozilla.com/D245946
This commit is contained in:
@@ -3918,6 +3918,9 @@ pref("services.common.log.logger.tokenserverclient", "Debug");
|
|||||||
// Enable retrying to execute commands in the child process in case the
|
// Enable retrying to execute commands in the child process in case the
|
||||||
// JSWindowActor gets destroyed.
|
// JSWindowActor gets destroyed.
|
||||||
pref("remote.retry-on-abort", true);
|
pref("remote.retry-on-abort", true);
|
||||||
|
|
||||||
|
// Enable the NavigationManager using parent process WebProgress listeners
|
||||||
|
pref("remote.experimental-parent-navigation.enabled", false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Enable the JSON View tool (an inspector for application/json documents).
|
// Enable the JSON View tool (an inspector for application/json documents).
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ remote.jar:
|
|||||||
content/shared/listeners/NavigationListener.sys.mjs (shared/listeners/NavigationListener.sys.mjs)
|
content/shared/listeners/NavigationListener.sys.mjs (shared/listeners/NavigationListener.sys.mjs)
|
||||||
content/shared/listeners/NetworkEventRecord.sys.mjs (shared/listeners/NetworkEventRecord.sys.mjs)
|
content/shared/listeners/NetworkEventRecord.sys.mjs (shared/listeners/NetworkEventRecord.sys.mjs)
|
||||||
content/shared/listeners/NetworkListener.sys.mjs (shared/listeners/NetworkListener.sys.mjs)
|
content/shared/listeners/NetworkListener.sys.mjs (shared/listeners/NetworkListener.sys.mjs)
|
||||||
|
content/shared/listeners/ParentWebProgressListener.sys.mjs (shared/listeners/ParentWebProgressListener.sys.mjs)
|
||||||
content/shared/listeners/PromptListener.sys.mjs (shared/listeners/PromptListener.sys.mjs)
|
content/shared/listeners/PromptListener.sys.mjs (shared/listeners/PromptListener.sys.mjs)
|
||||||
|
|
||||||
# JSWindowActors
|
# JSWindowActors
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
import { EventEmitter } from "resource://gre/modules/EventEmitter.sys.mjs";
|
import { EventEmitter } from "resource://gre/modules/EventEmitter.sys.mjs";
|
||||||
|
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
|
||||||
|
|
||||||
const lazy = {};
|
const lazy = {};
|
||||||
|
|
||||||
@@ -11,6 +12,8 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
|||||||
"chrome://remote/content/shared/listeners/BrowsingContextListener.sys.mjs",
|
"chrome://remote/content/shared/listeners/BrowsingContextListener.sys.mjs",
|
||||||
generateUUID: "chrome://remote/content/shared/UUID.sys.mjs",
|
generateUUID: "chrome://remote/content/shared/UUID.sys.mjs",
|
||||||
Log: "chrome://remote/content/shared/Log.sys.mjs",
|
Log: "chrome://remote/content/shared/Log.sys.mjs",
|
||||||
|
ParentWebProgressListener:
|
||||||
|
"chrome://remote/content/shared/listeners/ParentWebProgressListener.sys.mjs",
|
||||||
PromptListener:
|
PromptListener:
|
||||||
"chrome://remote/content/shared/listeners/PromptListener.sys.mjs",
|
"chrome://remote/content/shared/listeners/PromptListener.sys.mjs",
|
||||||
registerWebProgressListenerActor:
|
registerWebProgressListenerActor:
|
||||||
@@ -23,6 +26,13 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
|||||||
|
|
||||||
ChromeUtils.defineLazyGetter(lazy, "logger", () => lazy.Log.get());
|
ChromeUtils.defineLazyGetter(lazy, "logger", () => lazy.Log.get());
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyPreferenceGetter(
|
||||||
|
lazy,
|
||||||
|
"useParentWebProgressListener",
|
||||||
|
"remote.experimental-parent-navigation.enabled",
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {object} BrowsingContextDetails
|
* @typedef {object} BrowsingContextDetails
|
||||||
* @property {string} browsingContextId - The browsing context id.
|
* @property {string} browsingContextId - The browsing context id.
|
||||||
@@ -71,6 +81,7 @@ class NavigationRegistry extends EventEmitter {
|
|||||||
#contextListener;
|
#contextListener;
|
||||||
#managers;
|
#managers;
|
||||||
#navigations;
|
#navigations;
|
||||||
|
#parentWebProgressListener;
|
||||||
#promptListener;
|
#promptListener;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -82,6 +93,10 @@ class NavigationRegistry extends EventEmitter {
|
|||||||
// Maps navigable id to NavigationInfo.
|
// Maps navigable id to NavigationInfo.
|
||||||
this.#navigations = new Map();
|
this.#navigations = new Map();
|
||||||
|
|
||||||
|
if (lazy.useParentWebProgressListener) {
|
||||||
|
this.#parentWebProgressListener = new lazy.ParentWebProgressListener();
|
||||||
|
}
|
||||||
|
|
||||||
this.#contextListener = new lazy.BrowsingContextListener();
|
this.#contextListener = new lazy.BrowsingContextListener();
|
||||||
this.#contextListener.on("attached", this.#onContextAttached);
|
this.#contextListener.on("attached", this.#onContextAttached);
|
||||||
this.#contextListener.on("discarded", this.#onContextDiscarded);
|
this.#contextListener.on("discarded", this.#onContextDiscarded);
|
||||||
@@ -121,7 +136,11 @@ class NavigationRegistry extends EventEmitter {
|
|||||||
*/
|
*/
|
||||||
startMonitoring(listener) {
|
startMonitoring(listener) {
|
||||||
if (this.#managers.size == 0) {
|
if (this.#managers.size == 0) {
|
||||||
lazy.registerWebProgressListenerActor();
|
if (lazy.useParentWebProgressListener) {
|
||||||
|
this.#parentWebProgressListener.startListening();
|
||||||
|
} else {
|
||||||
|
lazy.registerWebProgressListenerActor();
|
||||||
|
}
|
||||||
this.#contextListener.startListening();
|
this.#contextListener.startListening();
|
||||||
this.#promptListener.startListening();
|
this.#promptListener.startListening();
|
||||||
}
|
}
|
||||||
@@ -142,7 +161,11 @@ class NavigationRegistry extends EventEmitter {
|
|||||||
if (this.#managers.size == 0) {
|
if (this.#managers.size == 0) {
|
||||||
this.#contextListener.stopListening();
|
this.#contextListener.stopListening();
|
||||||
this.#promptListener.stopListening();
|
this.#promptListener.stopListening();
|
||||||
lazy.unregisterWebProgressListenerActor();
|
if (lazy.useParentWebProgressListener) {
|
||||||
|
this.#parentWebProgressListener.stopListening();
|
||||||
|
} else {
|
||||||
|
lazy.unregisterWebProgressListenerActor();
|
||||||
|
}
|
||||||
// Clear the map.
|
// Clear the map.
|
||||||
this.#navigations = new Map();
|
this.#navigations = new Map();
|
||||||
}
|
}
|
||||||
|
|||||||
352
remote/shared/listeners/ParentWebProgressListener.sys.mjs
Normal file
352
remote/shared/listeners/ParentWebProgressListener.sys.mjs
Normal file
@@ -0,0 +1,352 @@
|
|||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
const lazy = {};
|
||||||
|
|
||||||
|
ChromeUtils.defineESModuleGetters(lazy, {
|
||||||
|
BrowsingContextListener:
|
||||||
|
"chrome://remote/content/shared/listeners/BrowsingContextListener.sys.mjs",
|
||||||
|
isInitialDocument:
|
||||||
|
"chrome://remote/content/shared/messagehandler/transports/BrowsingContextUtils.sys.mjs",
|
||||||
|
Log: "chrome://remote/content/shared/Log.sys.mjs",
|
||||||
|
notifyFragmentNavigated:
|
||||||
|
"chrome://remote/content/shared/NavigationManager.sys.mjs",
|
||||||
|
notifySameDocumentChanged:
|
||||||
|
"chrome://remote/content/shared/NavigationManager.sys.mjs",
|
||||||
|
notifyNavigationFailed:
|
||||||
|
"chrome://remote/content/shared/NavigationManager.sys.mjs",
|
||||||
|
notifyNavigationStarted:
|
||||||
|
"chrome://remote/content/shared/NavigationManager.sys.mjs",
|
||||||
|
notifyNavigationStopped:
|
||||||
|
"chrome://remote/content/shared/NavigationManager.sys.mjs",
|
||||||
|
TabManager: "chrome://remote/content/shared/TabManager.sys.mjs",
|
||||||
|
truncate: "chrome://remote/content/shared/Format.sys.mjs",
|
||||||
|
});
|
||||||
|
|
||||||
|
ChromeUtils.defineLazyGetter(lazy, "logger", () => lazy.Log.get());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not to be confused with the WebProgressListenerParent which is the parent
|
||||||
|
* actor for the WebProgressListener JSWindow actor pair.
|
||||||
|
*
|
||||||
|
* The ParentWebProgressListener is a listener that supports monitoring
|
||||||
|
* navigations for the NavigationManager entirely from the parent process.
|
||||||
|
*
|
||||||
|
* The NavigationManager will either use the WebProgressListener JSWindow actors
|
||||||
|
* or this listener, depending on the value of the hidden preference
|
||||||
|
* remote.experimental-parent-navigation.enabled.
|
||||||
|
*
|
||||||
|
* This listener does not implement the same interface as our other listeners
|
||||||
|
* and is designed to be instantiated only once from the NavigationRegistry
|
||||||
|
* singleton.
|
||||||
|
*
|
||||||
|
* Once we remove the WebProgressListener JS Window actors and only use this
|
||||||
|
* listener, we may update it for consistency with the rest of the codebase but
|
||||||
|
* in the meantime, the goal is to avoid the impact on the existing
|
||||||
|
* implementation used by default.
|
||||||
|
*/
|
||||||
|
export class ParentWebProgressListener {
|
||||||
|
#contextListener;
|
||||||
|
#listener;
|
||||||
|
#listening;
|
||||||
|
#monitoredWebProgress;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.#monitoredWebProgress = new Map();
|
||||||
|
|
||||||
|
this.#contextListener = new lazy.BrowsingContextListener();
|
||||||
|
this.#contextListener.on("attached", this.#onContextAttached);
|
||||||
|
this.#contextListener.on("discarded", this.#onContextDiscarded);
|
||||||
|
|
||||||
|
this.#listener = {
|
||||||
|
onLocationChange: this.#onLocationChange,
|
||||||
|
onStateChange: this.#onStateChange,
|
||||||
|
QueryInterface: ChromeUtils.generateQI([
|
||||||
|
"nsIWebProgressListener",
|
||||||
|
"nsISupportsWeakReference",
|
||||||
|
]),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
get listening() {
|
||||||
|
return this.#listening;
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy() {
|
||||||
|
this.stopListening();
|
||||||
|
this.#contextListener.destroy();
|
||||||
|
this.#monitoredWebProgress = new Map();
|
||||||
|
}
|
||||||
|
|
||||||
|
#onLocationChange = (progress, request, location, flags) => {
|
||||||
|
if (flags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT) {
|
||||||
|
const context = progress.browsingContext;
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
contextDetails: { context },
|
||||||
|
url: location.spec,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (location.hasRef) {
|
||||||
|
// If the target URL contains a hash, handle the navigation as a
|
||||||
|
// fragment navigation.
|
||||||
|
this.#trace(
|
||||||
|
lazy.truncate`Location=fragmentNavigated: ${location.spec}`,
|
||||||
|
context.id
|
||||||
|
);
|
||||||
|
|
||||||
|
lazy.notifyFragmentNavigated(payload);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#trace(
|
||||||
|
lazy.truncate`Location=sameDocumentChanged: ${location.spec}`,
|
||||||
|
context.id
|
||||||
|
);
|
||||||
|
|
||||||
|
lazy.notifySameDocumentChanged(payload);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#onStateChange = (progress, request, stateFlags, status) => {
|
||||||
|
const context = progress.browsingContext;
|
||||||
|
const targetURI = this.#getTargetURI(request);
|
||||||
|
|
||||||
|
const isBindingAborted = status == Cr.NS_BINDING_ABORTED;
|
||||||
|
const isStart = !!(stateFlags & Ci.nsIWebProgressListener.STATE_START);
|
||||||
|
const isStop = !!(stateFlags & Ci.nsIWebProgressListener.STATE_STOP);
|
||||||
|
|
||||||
|
if (lazy.Log.isTraceLevelOrMore) {
|
||||||
|
const isNetwork = !!(
|
||||||
|
stateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK
|
||||||
|
);
|
||||||
|
this.#trace(
|
||||||
|
`Loading state: flags: ${stateFlags}, status: ${status}, ` +
|
||||||
|
` isStart: ${isStart}, isStop: ${isStop}, isNetwork: ${isNetwork},` +
|
||||||
|
` isBindingAborted: ${isBindingAborted},` +
|
||||||
|
lazy.truncate` targetURI: ${targetURI?.spec}`,
|
||||||
|
context.id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = targetURI?.spec;
|
||||||
|
|
||||||
|
const isInitialDocument = lazy.isInitialDocument(context);
|
||||||
|
if (isInitialDocument && url === "about:blank") {
|
||||||
|
this.#trace("Skip initial navigation to about:blank", context.id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (isStart) {
|
||||||
|
lazy.notifyNavigationStarted({
|
||||||
|
contextDetails: { context },
|
||||||
|
url,
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isStop && !isBindingAborted) {
|
||||||
|
const errorName = ChromeUtils.getXPCOMErrorName(status);
|
||||||
|
if (this.#isContentBlocked(errorName)) {
|
||||||
|
lazy.notifyNavigationFailed({
|
||||||
|
contextDetails: { context },
|
||||||
|
errorName,
|
||||||
|
status,
|
||||||
|
url,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
lazy.notifyNavigationStopped({
|
||||||
|
contextDetails: { context },
|
||||||
|
status,
|
||||||
|
url,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (e.name === "InvalidStateError") {
|
||||||
|
// We'll arrive here if we no longer have our manager, so we can
|
||||||
|
// just swallow this error.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
startListening() {
|
||||||
|
if (this.#listening) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#contextListener.startListening();
|
||||||
|
// Start listening for navigation on all existing contexts.
|
||||||
|
this.#getAllBrowsingContexts().forEach(browsingContext =>
|
||||||
|
this.#startWatchingBrowsingContextNavigation(browsingContext)
|
||||||
|
);
|
||||||
|
|
||||||
|
this.#listening = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
stopListening() {
|
||||||
|
if (!this.#listening) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#contextListener.stopListening();
|
||||||
|
for (const webProgress of this.#monitoredWebProgress.keys()) {
|
||||||
|
try {
|
||||||
|
webProgress.removeProgressListener(
|
||||||
|
this.#listener,
|
||||||
|
Ci.nsIWebProgress.NOTIFY_STATE_ALL
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
this.#trace(`Failed to remove the progress listener`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.#monitoredWebProgress = new Map();
|
||||||
|
|
||||||
|
this.#listening = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#getAllBrowsingContexts() {
|
||||||
|
return lazy.TabManager.browsers.flatMap(browser =>
|
||||||
|
browser.browsingContext.getAllBrowsingContextsInSubtree()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#getTargetURI(request) {
|
||||||
|
try {
|
||||||
|
return request.QueryInterface(Ci.nsIChannel).originalURI;
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
#isContentBlocked(blockedReason) {
|
||||||
|
return [
|
||||||
|
// If content is blocked with e.g. CSP meta tag.
|
||||||
|
"NS_ERROR_CONTENT_BLOCKED",
|
||||||
|
// If a resource load was blocked because of the CSP header.
|
||||||
|
"NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION",
|
||||||
|
// If a resource load was blocked because of the Cross-Origin-Embedder-Policy header.
|
||||||
|
"NS_ERROR_DOM_COEP_FAILED",
|
||||||
|
// If a resource load was blocked because of the X-Frame-Options header.
|
||||||
|
"NS_ERROR_XFO_VIOLATION",
|
||||||
|
].includes(blockedReason);
|
||||||
|
}
|
||||||
|
|
||||||
|
#onContextAttached = async (eventName, data) => {
|
||||||
|
const { browsingContext } = data;
|
||||||
|
this.#startWatchingBrowsingContextNavigation(browsingContext);
|
||||||
|
};
|
||||||
|
|
||||||
|
#onContextDiscarded = async (eventName, data = {}) => {
|
||||||
|
const { browsingContext } = data;
|
||||||
|
|
||||||
|
this.#stopWatchingBrowsingContextNavigation(browsingContext);
|
||||||
|
};
|
||||||
|
|
||||||
|
#startWatchingBrowsingContextNavigation(browsingContext) {
|
||||||
|
if (browsingContext.parent) {
|
||||||
|
// Frame contexts will be monitored through the webprogress listener of
|
||||||
|
// the top window.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#trace(
|
||||||
|
`Start watching updates for browsing context`,
|
||||||
|
browsingContext.id
|
||||||
|
);
|
||||||
|
|
||||||
|
const webProgress = browsingContext.webProgress;
|
||||||
|
if (!webProgress) {
|
||||||
|
this.#trace(
|
||||||
|
`No web progress attached to this browsing context, bailing out`,
|
||||||
|
browsingContext.id
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.#monitoredWebProgress.has(webProgress)) {
|
||||||
|
this.#trace(
|
||||||
|
`The web progress was not monitored yet, adding a progress listener`,
|
||||||
|
browsingContext.id
|
||||||
|
);
|
||||||
|
this.#monitoredWebProgress.set(webProgress, new Set());
|
||||||
|
webProgress.addProgressListener(
|
||||||
|
this.#listener,
|
||||||
|
Ci.nsIWebProgress.NOTIFY_ALL
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#monitoredWebProgress.get(webProgress).add(browsingContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
#stopWatchingBrowsingContextNavigation(browsingContext) {
|
||||||
|
if (browsingContext.parent) {
|
||||||
|
// Frame contexts will be monitored through the webprogress listener of
|
||||||
|
// the top window.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#trace(
|
||||||
|
`Stop watching updates for browsing context`,
|
||||||
|
browsingContext.id
|
||||||
|
);
|
||||||
|
|
||||||
|
const webProgress = browsingContext.webProgress;
|
||||||
|
if (!webProgress) {
|
||||||
|
this.#trace(
|
||||||
|
`No web progress attached to this browsing context, bailing out`,
|
||||||
|
browsingContext.id
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const contexts = this.#monitoredWebProgress.get(webProgress);
|
||||||
|
if (!contexts) {
|
||||||
|
this.#trace(
|
||||||
|
`No browsing context tracked for the web progress, bailing out`,
|
||||||
|
browsingContext.id
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
contexts.delete(browsingContext);
|
||||||
|
if (!contexts.size) {
|
||||||
|
this.#trace(
|
||||||
|
`All browsing contexts for this web progress deleted, removing the progress listener`,
|
||||||
|
browsingContext.id
|
||||||
|
);
|
||||||
|
try {
|
||||||
|
webProgress.removeProgressListener(
|
||||||
|
this.#listener,
|
||||||
|
Ci.nsIWebProgress.NOTIFY_STATE_ALL
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
this.#trace(
|
||||||
|
`Failed to remove the progress listener`,
|
||||||
|
browsingContext.id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#trace(
|
||||||
|
`Removing the web progress from monitored web progress`,
|
||||||
|
browsingContext.id
|
||||||
|
);
|
||||||
|
this.#monitoredWebProgress.delete(webProgress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#trace(message, contextId = null) {
|
||||||
|
if (contextId !== null) {
|
||||||
|
lazy.logger.trace(
|
||||||
|
`${this.constructor.name} ${message} [context=${contextId}]`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
lazy.logger.trace(`${this.constructor.name} ${message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -41,6 +41,7 @@ add_task(async function test_navigationManager() {
|
|||||||
);
|
);
|
||||||
is(navigation.url, testUrl, "Navigation has the expected URL");
|
is(navigation.url, testUrl, "Navigation has the expected URL");
|
||||||
|
|
||||||
|
await BrowserTestUtils.waitForCondition(() => events.length === 2);
|
||||||
is(events.length, 2, "Received 2 navigation events");
|
is(events.length, 2, "Received 2 navigation events");
|
||||||
is(events[0].name, "navigation-started");
|
is(events[0].name, "navigation-started");
|
||||||
is(events[1].name, "navigation-stopped");
|
is(events[1].name, "navigation-stopped");
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ add_task(async function test_simpleNavigation() {
|
|||||||
is(events.length, 0, "No event recorded");
|
is(events.length, 0, "No event recorded");
|
||||||
|
|
||||||
await loadURL(browser, SECOND_URL);
|
await loadURL(browser, SECOND_URL);
|
||||||
|
await BrowserTestUtils.waitForCondition(() => events.length === 2);
|
||||||
|
|
||||||
const firstNavigation = navigationManager.getNavigationForBrowsingContext(
|
const firstNavigation = navigationManager.getNavigationForBrowsingContext(
|
||||||
browser.browsingContext
|
browser.browsingContext
|
||||||
@@ -56,6 +57,7 @@ add_task(async function test_simpleNavigation() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await loadURL(browser, THIRD_URL);
|
await loadURL(browser, THIRD_URL);
|
||||||
|
await BrowserTestUtils.waitForCondition(() => events.length === 4);
|
||||||
|
|
||||||
const secondNavigation = navigationManager.getNavigationForBrowsingContext(
|
const secondNavigation = navigationManager.getNavigationForBrowsingContext(
|
||||||
browser.browsingContext
|
browser.browsingContext
|
||||||
@@ -109,6 +111,7 @@ add_task(async function test_loadTwoTabsSimultaneously() {
|
|||||||
|
|
||||||
info("Wait for the tabs to load");
|
info("Wait for the tabs to load");
|
||||||
await Promise.all([onLoad1, onLoad2]);
|
await Promise.all([onLoad1, onLoad2]);
|
||||||
|
await BrowserTestUtils.waitForCondition(() => events.length === 4);
|
||||||
|
|
||||||
is(events.length, 4, "Recorded 4 navigation events");
|
is(events.length, 4, "Recorded 4 navigation events");
|
||||||
|
|
||||||
@@ -132,6 +135,7 @@ add_task(async function test_loadTwoTabsSimultaneously() {
|
|||||||
BrowserTestUtils.reloadTab(tab1),
|
BrowserTestUtils.reloadTab(tab1),
|
||||||
BrowserTestUtils.reloadTab(tab2),
|
BrowserTestUtils.reloadTab(tab2),
|
||||||
]);
|
]);
|
||||||
|
await BrowserTestUtils.waitForCondition(() => events.length === 8);
|
||||||
|
|
||||||
is(events.length, 8, "Recorded 8 navigation events");
|
is(events.length, 8, "Recorded 8 navigation events");
|
||||||
|
|
||||||
@@ -156,6 +160,19 @@ add_task(async function test_loadTwoTabsSimultaneously() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
add_task(async function test_loadPageWithIframes() {
|
add_task(async function test_loadPageWithIframes() {
|
||||||
|
if (
|
||||||
|
Services.prefs.getBoolPref(
|
||||||
|
"remote.experimental-parent-navigation.enabled",
|
||||||
|
false
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
todo(
|
||||||
|
false,
|
||||||
|
"The ParentWebProgressListener misses events from same process iframes"
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const events = [];
|
const events = [];
|
||||||
const onEvent = (name, data) => events.push({ name, data });
|
const onEvent = (name, data) => events.push({ name, data });
|
||||||
|
|
||||||
@@ -170,6 +187,7 @@ add_task(async function test_loadPageWithIframes() {
|
|||||||
const tab = addTab(gBrowser, testUrl);
|
const tab = addTab(gBrowser, testUrl);
|
||||||
const browser = tab.linkedBrowser;
|
const browser = tab.linkedBrowser;
|
||||||
await BrowserTestUtils.browserLoaded(browser, false, testUrl);
|
await BrowserTestUtils.browserLoaded(browser, false, testUrl);
|
||||||
|
await BrowserTestUtils.waitForCondition(() => events.length === 8);
|
||||||
|
|
||||||
is(events.length, 8, "Recorded 8 navigation events");
|
is(events.length, 8, "Recorded 8 navigation events");
|
||||||
const contexts = browser.browsingContext.getAllBrowsingContextsInSubtree();
|
const contexts = browser.browsingContext.getAllBrowsingContextsInSubtree();
|
||||||
@@ -188,6 +206,7 @@ add_task(async function test_loadPageWithIframes() {
|
|||||||
assertUniqueNavigationIds(...navigations);
|
assertUniqueNavigationIds(...navigations);
|
||||||
|
|
||||||
await BrowserTestUtils.reloadTab(tab);
|
await BrowserTestUtils.reloadTab(tab);
|
||||||
|
await BrowserTestUtils.waitForCondition(() => events.length === 16);
|
||||||
|
|
||||||
is(events.length, 16, "Recorded 8 additional navigation events");
|
is(events.length, 16, "Recorded 8 additional navigation events");
|
||||||
const newContexts = browser.browsingContext.getAllBrowsingContextsInSubtree();
|
const newContexts = browser.browsingContext.getAllBrowsingContextsInSubtree();
|
||||||
@@ -210,6 +229,19 @@ add_task(async function test_loadPageWithIframes() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
add_task(async function test_loadPageWithCoop() {
|
add_task(async function test_loadPageWithCoop() {
|
||||||
|
if (
|
||||||
|
Services.prefs.getBoolPref(
|
||||||
|
"remote.experimental-parent-navigation.enabled",
|
||||||
|
false
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
todo(
|
||||||
|
false,
|
||||||
|
"The ParentWebProgressListener misses navigation stopped for coop navigation"
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const tab = addTab(gBrowser, FIRST_COOP_URL);
|
const tab = addTab(gBrowser, FIRST_COOP_URL);
|
||||||
const browser = tab.linkedBrowser;
|
const browser = tab.linkedBrowser;
|
||||||
await BrowserTestUtils.browserLoaded(browser, false, FIRST_COOP_URL);
|
await BrowserTestUtils.browserLoaded(browser, false, FIRST_COOP_URL);
|
||||||
@@ -225,6 +257,7 @@ add_task(async function test_loadPageWithCoop() {
|
|||||||
|
|
||||||
const navigableId = TabManager.getIdForBrowser(browser);
|
const navigableId = TabManager.getIdForBrowser(browser);
|
||||||
await loadURL(browser, SECOND_COOP_URL);
|
await loadURL(browser, SECOND_COOP_URL);
|
||||||
|
await BrowserTestUtils.waitForCondition(() => events.length === 2);
|
||||||
|
|
||||||
const coopNavigation = navigationManager.getNavigationForBrowsingContext(
|
const coopNavigation = navigationManager.getNavigationForBrowsingContext(
|
||||||
browser.browsingContext
|
browser.browsingContext
|
||||||
@@ -286,6 +319,7 @@ add_task(async function test_sameDocumentNavigation() {
|
|||||||
// complete.
|
// complete.
|
||||||
info("Perform a regular navigation");
|
info("Perform a regular navigation");
|
||||||
await loadURL(browser, url);
|
await loadURL(browser, url);
|
||||||
|
await BrowserTestUtils.waitForCondition(() => events.length === 3);
|
||||||
|
|
||||||
const regularNavigation = navigationManager.getNavigationForBrowsingContext(
|
const regularNavigation = navigationManager.getNavigationForBrowsingContext(
|
||||||
browser.browsingContext
|
browser.browsingContext
|
||||||
|
|||||||
@@ -50,9 +50,18 @@ add_task(async function testDocumentOpenWriteClose() {
|
|||||||
info("Reload the page, which should trigger a navigation");
|
info("Reload the page, which should trigger a navigation");
|
||||||
await loadURL(browser, url);
|
await loadURL(browser, url);
|
||||||
|
|
||||||
// See Bug 1844517.
|
if (
|
||||||
// document.open/write/close is identical to same-url + same-hash navigations.
|
Services.prefs.getBoolPref(
|
||||||
todo_is(events.length, 2, "Recorded navigation events");
|
"remote.experimental-parent-navigation.enabled",
|
||||||
|
false
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
is(events.length, 2, "Recorded navigation events");
|
||||||
|
} else {
|
||||||
|
// See Bug 1844517.
|
||||||
|
// document.open/write/close is identical to same-url + same-hash navigations.
|
||||||
|
todo_is(events.length, 2, "Recorded navigation events");
|
||||||
|
}
|
||||||
|
|
||||||
navigationManager.off("fragment-navigated", onEvent);
|
navigationManager.off("fragment-navigated", onEvent);
|
||||||
navigationManager.off("navigation-started", onEvent);
|
navigationManager.off("navigation-started", onEvent);
|
||||||
|
|||||||
Reference in New Issue
Block a user