Backed out 2 changesets (bug 1936774) as requested by Julian. CLOSED TREE
Backed out changeset 35f43832e05c (bug 1936774) Backed out changeset 842565c0705e (bug 1936774)
This commit is contained in:
@@ -3918,9 +3918,6 @@ pref("services.common.log.logger.tokenserverclient", "Debug");
|
||||
// Enable retrying to execute commands in the child process in case the
|
||||
// JSWindowActor gets destroyed.
|
||||
pref("remote.retry-on-abort", true);
|
||||
|
||||
// Enable the NavigationManager using parent process WebProgress listeners
|
||||
pref("remote.experimental-parent-navigation.enabled", false);
|
||||
#endif
|
||||
|
||||
// Enable the JSON View tool (an inspector for application/json documents).
|
||||
|
||||
@@ -53,13 +53,12 @@ remote.jar:
|
||||
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/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)
|
||||
|
||||
# JSWindowActors
|
||||
content/shared/js-window-actors/WebProgressListenerActor.sys.mjs (shared/js-window-actors/WebProgressListenerActor.sys.mjs)
|
||||
content/shared/js-window-actors/WebProgressListenerChild.sys.mjs (shared/js-window-actors/WebProgressListenerChild.sys.mjs)
|
||||
content/shared/js-window-actors/WebProgressListenerParent.sys.mjs (shared/js-window-actors/WebProgressListenerParent.sys.mjs)
|
||||
content/shared/js-window-actors/NavigationListenerActor.sys.mjs (shared/js-window-actors/NavigationListenerActor.sys.mjs)
|
||||
content/shared/js-window-actors/NavigationListenerChild.sys.mjs (shared/js-window-actors/NavigationListenerChild.sys.mjs)
|
||||
content/shared/js-window-actors/NavigationListenerParent.sys.mjs (shared/js-window-actors/NavigationListenerParent.sys.mjs)
|
||||
|
||||
# shared modules (messagehandler architecture)
|
||||
content/shared/messagehandler/Errors.sys.mjs (shared/messagehandler/Errors.sys.mjs)
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import { EventEmitter } from "resource://gre/modules/EventEmitter.sys.mjs";
|
||||
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
|
||||
|
||||
const lazy = {};
|
||||
|
||||
@@ -12,27 +11,18 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
||||
"chrome://remote/content/shared/listeners/BrowsingContextListener.sys.mjs",
|
||||
generateUUID: "chrome://remote/content/shared/UUID.sys.mjs",
|
||||
Log: "chrome://remote/content/shared/Log.sys.mjs",
|
||||
ParentWebProgressListener:
|
||||
"chrome://remote/content/shared/listeners/ParentWebProgressListener.sys.mjs",
|
||||
PromptListener:
|
||||
"chrome://remote/content/shared/listeners/PromptListener.sys.mjs",
|
||||
registerWebProgressListenerActor:
|
||||
"chrome://remote/content/shared/js-window-actors/WebProgressListenerActor.sys.mjs",
|
||||
registerNavigationListenerActor:
|
||||
"chrome://remote/content/shared/js-window-actors/NavigationListenerActor.sys.mjs",
|
||||
TabManager: "chrome://remote/content/shared/TabManager.sys.mjs",
|
||||
truncate: "chrome://remote/content/shared/Format.sys.mjs",
|
||||
unregisterWebProgressListenerActor:
|
||||
"chrome://remote/content/shared/js-window-actors/WebProgressListenerActor.sys.mjs",
|
||||
unregisterNavigationListenerActor:
|
||||
"chrome://remote/content/shared/js-window-actors/NavigationListenerActor.sys.mjs",
|
||||
});
|
||||
|
||||
ChromeUtils.defineLazyGetter(lazy, "logger", () => lazy.Log.get());
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
lazy,
|
||||
"useParentWebProgressListener",
|
||||
"remote.experimental-parent-navigation.enabled",
|
||||
false
|
||||
);
|
||||
|
||||
/**
|
||||
* @typedef {object} BrowsingContextDetails
|
||||
* @property {string} browsingContextId - The browsing context id.
|
||||
@@ -56,20 +46,20 @@ XPCOMUtils.defineLazyPreferenceGetter(
|
||||
* The NavigationRegistry is responsible for monitoring all navigations happening
|
||||
* in the browser.
|
||||
*
|
||||
* It relies on a JSWindowActor pair called WebProgressListener{Parent|Child},
|
||||
* It relies on a JSWindowActor pair called NavigationListener{Parent|Child},
|
||||
* found under remote/shared/js-window-actors. As a simple overview, the
|
||||
* WebProgressListenerChild will monitor navigations in all window globals using
|
||||
* NavigationListenerChild will monitor navigations in all window globals using
|
||||
* content process WebProgressListener, and will forward each relevant update to
|
||||
* the WebProgressListenerParent
|
||||
* the NavigationListenerParent
|
||||
*
|
||||
* The NavigationRegistry singleton holds the map of navigations, from navigable
|
||||
* to NavigationInfo. It will also be called by WebProgressListenerParent
|
||||
* to NavigationInfo. It will also be called by NavigationListenerParent
|
||||
* whenever a navigation event happens.
|
||||
*
|
||||
* This singleton is not exported outside of this class, and consumers instead
|
||||
* need to use the NavigationManager class. The NavigationRegistry keeps track
|
||||
* of how many NavigationListener instances are currently listening in order to
|
||||
* know if the WebProgressListenerActor should be registered or not.
|
||||
* know if the NavigationListenerActor should be registered or not.
|
||||
*
|
||||
* The NavigationRegistry exposes an API to retrieve the current or last
|
||||
* navigation for a given navigable, and also forwards events to notify about
|
||||
@@ -81,7 +71,6 @@ class NavigationRegistry extends EventEmitter {
|
||||
#contextListener;
|
||||
#managers;
|
||||
#navigations;
|
||||
#parentWebProgressListener;
|
||||
#promptListener;
|
||||
|
||||
constructor() {
|
||||
@@ -93,10 +82,6 @@ class NavigationRegistry extends EventEmitter {
|
||||
// Maps navigable id to NavigationInfo.
|
||||
this.#navigations = new Map();
|
||||
|
||||
if (lazy.useParentWebProgressListener) {
|
||||
this.#parentWebProgressListener = new lazy.ParentWebProgressListener();
|
||||
}
|
||||
|
||||
this.#contextListener = new lazy.BrowsingContextListener();
|
||||
this.#contextListener.on("attached", this.#onContextAttached);
|
||||
this.#contextListener.on("discarded", this.#onContextDiscarded);
|
||||
@@ -131,16 +116,12 @@ class NavigationRegistry extends EventEmitter {
|
||||
|
||||
/**
|
||||
* Start monitoring navigations in all browsing contexts. This will register
|
||||
* the WebProgressListener JSWindowActor and will initialize them in all
|
||||
* the NavigationListener JSWindowActor and will initialize them in all
|
||||
* existing browsing contexts.
|
||||
*/
|
||||
startMonitoring(listener) {
|
||||
if (this.#managers.size == 0) {
|
||||
if (lazy.useParentWebProgressListener) {
|
||||
this.#parentWebProgressListener.startListening();
|
||||
} else {
|
||||
lazy.registerWebProgressListenerActor();
|
||||
}
|
||||
lazy.registerNavigationListenerActor();
|
||||
this.#contextListener.startListening();
|
||||
this.#promptListener.startListening();
|
||||
}
|
||||
@@ -149,7 +130,7 @@ class NavigationRegistry extends EventEmitter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop monitoring navigations. This will unregister the WebProgressListener
|
||||
* Stop monitoring navigations. This will unregister the NavigationListener
|
||||
* JSWindowActor and clear the information collected about navigations so far.
|
||||
*/
|
||||
stopMonitoring(listener) {
|
||||
@@ -161,11 +142,7 @@ class NavigationRegistry extends EventEmitter {
|
||||
if (this.#managers.size == 0) {
|
||||
this.#contextListener.stopListening();
|
||||
this.#promptListener.stopListening();
|
||||
if (lazy.useParentWebProgressListener) {
|
||||
this.#parentWebProgressListener.stopListening();
|
||||
} else {
|
||||
lazy.unregisterWebProgressListenerActor();
|
||||
}
|
||||
lazy.unregisterNavigationListenerActor();
|
||||
// Clear the map.
|
||||
this.#navigations = new Map();
|
||||
}
|
||||
@@ -173,10 +150,10 @@ class NavigationRegistry extends EventEmitter {
|
||||
|
||||
/**
|
||||
* Called when a fragment navigation is recorded from the
|
||||
* WebProgressListener actors.
|
||||
* NavigationListener actors.
|
||||
*
|
||||
* This entry point is only intended to be called from
|
||||
* WebProgressListenerParent, to avoid setting up observers or listeners,
|
||||
* NavigationListenerParent, to avoid setting up observers or listeners,
|
||||
* which are unnecessary since NavigationManager has to be a singleton.
|
||||
*
|
||||
* @param {object} data
|
||||
@@ -210,10 +187,10 @@ class NavigationRegistry extends EventEmitter {
|
||||
}
|
||||
/**
|
||||
* Called when a same-document navigation is recorded from the
|
||||
* WebProgressListener actors.
|
||||
* NavigationListener actors.
|
||||
*
|
||||
* This entry point is only intended to be called from
|
||||
* WebProgressListenerParent, to avoid setting up observers or listeners,
|
||||
* NavigationListenerParent, to avoid setting up observers or listeners,
|
||||
* which are unnecessary since NavigationManager has to be a singleton.
|
||||
*
|
||||
* @param {object} data
|
||||
@@ -249,10 +226,10 @@ class NavigationRegistry extends EventEmitter {
|
||||
|
||||
/**
|
||||
* Called when a navigation-failed event is recorded from the
|
||||
* WebProgressListener actors.
|
||||
* NavigationListener actors.
|
||||
*
|
||||
* This entry point is only intended to be called from
|
||||
* WebProgressListenerParent, to avoid setting up observers or listeners,
|
||||
* NavigationListenerParent, to avoid setting up observers or listeners,
|
||||
* which are unnecessary since NavigationManager has to be a singleton.
|
||||
*
|
||||
* @param {object} data
|
||||
@@ -306,10 +283,10 @@ class NavigationRegistry extends EventEmitter {
|
||||
|
||||
/**
|
||||
* Called when a navigation-started event is recorded from the
|
||||
* WebProgressListener actors.
|
||||
* NavigationListener actors.
|
||||
*
|
||||
* This entry point is only intended to be called from
|
||||
* WebProgressListenerParent, to avoid setting up observers or listeners,
|
||||
* NavigationListenerParent, to avoid setting up observers or listeners,
|
||||
* which are unnecessary since NavigationManager has to be a singleton.
|
||||
*
|
||||
* @param {object} data
|
||||
@@ -409,7 +386,7 @@ class NavigationRegistry extends EventEmitter {
|
||||
|
||||
/**
|
||||
* Called when a navigation-stopped event is recorded from the
|
||||
* WebProgressListener actors.
|
||||
* NavigationListener actors.
|
||||
*
|
||||
* @param {object} data
|
||||
* @param {BrowsingContextDetails} data.contextDetails
|
||||
@@ -624,7 +601,7 @@ const navigationRegistry = new NavigationRegistry();
|
||||
/**
|
||||
* See NavigationRegistry.notifyHashChanged.
|
||||
*
|
||||
* This entry point is only intended to be called from WebProgressListenerParent,
|
||||
* This entry point is only intended to be called from NavigationListenerParent,
|
||||
* to avoid setting up observers or listeners, which are unnecessary since
|
||||
* NavigationRegistry has to be a singleton.
|
||||
*/
|
||||
@@ -635,7 +612,7 @@ export function notifyFragmentNavigated(data) {
|
||||
/**
|
||||
* See NavigationRegistry.notifySameDocumentChanged.
|
||||
*
|
||||
* This entry point is only intended to be called from WebProgressListenerParent,
|
||||
* This entry point is only intended to be called from NavigationListenerParent,
|
||||
* to avoid setting up observers or listeners, which are unnecessary since
|
||||
* NavigationRegistry has to be a singleton.
|
||||
*/
|
||||
@@ -646,7 +623,7 @@ export function notifySameDocumentChanged(data) {
|
||||
/**
|
||||
* See NavigationRegistry.notifyNavigationFailed.
|
||||
*
|
||||
* This entry point is only intended to be called from WebProgressListenerParent,
|
||||
* This entry point is only intended to be called from NavigationListenerParent,
|
||||
* to avoid setting up observers or listeners, which are unnecessary since
|
||||
* NavigationRegistry has to be a singleton.
|
||||
*/
|
||||
@@ -657,7 +634,7 @@ export function notifyNavigationFailed(data) {
|
||||
/**
|
||||
* See NavigationRegistry.notifyNavigationStarted.
|
||||
*
|
||||
* This entry point is only intended to be called from WebProgressListenerParent,
|
||||
* This entry point is only intended to be called from NavigationListenerParent,
|
||||
* to avoid setting up observers or listeners, which are unnecessary since
|
||||
* NavigationRegistry has to be a singleton.
|
||||
*/
|
||||
@@ -668,7 +645,7 @@ export function notifyNavigationStarted(data) {
|
||||
/**
|
||||
* See NavigationRegistry.notifyNavigationStopped.
|
||||
*
|
||||
* This entry point is only intended to be called from WebProgressListenerParent,
|
||||
* This entry point is only intended to be called from NavigationListenerParent,
|
||||
* to avoid setting up observers or listeners, which are unnecessary since
|
||||
* NavigationRegistry has to be a singleton.
|
||||
*/
|
||||
|
||||
@@ -12,29 +12,29 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
||||
ChromeUtils.defineLazyGetter(lazy, "logger", () => lazy.Log.get());
|
||||
|
||||
let registered = false;
|
||||
export function isWebProgressListenerActorRegistered() {
|
||||
export function isNavigationListenerActorRegistered() {
|
||||
return registered;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the WebProgressListener actor that will keep track of all ongoing
|
||||
* Register the NavigationListener actor that will keep track of all ongoing
|
||||
* navigations.
|
||||
*/
|
||||
export function registerWebProgressListenerActor() {
|
||||
export function registerNavigationListenerActor() {
|
||||
if (registered) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
ChromeUtils.registerWindowActor("WebProgressListener", {
|
||||
ChromeUtils.registerWindowActor("NavigationListener", {
|
||||
kind: "JSWindowActor",
|
||||
parent: {
|
||||
esModuleURI:
|
||||
"chrome://remote/content/shared/js-window-actors/WebProgressListenerParent.sys.mjs",
|
||||
"chrome://remote/content/shared/js-window-actors/NavigationListenerParent.sys.mjs",
|
||||
},
|
||||
child: {
|
||||
esModuleURI:
|
||||
"chrome://remote/content/shared/js-window-actors/WebProgressListenerChild.sys.mjs",
|
||||
"chrome://remote/content/shared/js-window-actors/NavigationListenerChild.sys.mjs",
|
||||
events: {
|
||||
DOMWindowCreated: {},
|
||||
},
|
||||
@@ -44,7 +44,7 @@ export function registerWebProgressListenerActor() {
|
||||
});
|
||||
registered = true;
|
||||
|
||||
// Ensure the WebProgress listener is started in existing contexts.
|
||||
// Ensure the navigation listener is started in existing contexts.
|
||||
for (const browser of lazy.TabManager.browsers) {
|
||||
if (!browser?.browsingContext) {
|
||||
continue;
|
||||
@@ -56,7 +56,7 @@ export function registerWebProgressListenerActor() {
|
||||
}
|
||||
|
||||
context.currentWindowGlobal
|
||||
.getActor("WebProgressListener")
|
||||
.getActor("NavigationListener")
|
||||
// Note that "createActor" is not explicitly referenced in the child
|
||||
// actor, this is only used to trigger the creation of the actor.
|
||||
.sendAsyncMessage("createActor");
|
||||
@@ -64,17 +64,17 @@ export function registerWebProgressListenerActor() {
|
||||
}
|
||||
} catch (e) {
|
||||
if (e.name === "NotSupportedError") {
|
||||
lazy.logger.warn(`WebProgressListener actor is already registered!`);
|
||||
lazy.logger.warn(`NavigationListener actor is already registered!`);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function unregisterWebProgressListenerActor() {
|
||||
export function unregisterNavigationListenerActor() {
|
||||
if (!registered) {
|
||||
return;
|
||||
}
|
||||
ChromeUtils.unregisterWindowActor("WebProgressListener");
|
||||
ChromeUtils.unregisterWindowActor("NavigationListener");
|
||||
registered = false;
|
||||
}
|
||||
@@ -11,7 +11,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
||||
|
||||
ChromeUtils.defineLazyGetter(lazy, "logger", () => lazy.Log.get());
|
||||
|
||||
export class WebProgressListenerChild extends JSWindowActorChild {
|
||||
export class NavigationListenerChild extends JSWindowActorChild {
|
||||
#listener;
|
||||
#webProgress;
|
||||
|
||||
@@ -116,7 +116,7 @@ export class WebProgressListenerChild extends JSWindowActorChild {
|
||||
);
|
||||
|
||||
this.sendAsyncMessage(
|
||||
"WebProgressListenerChild:fragmentNavigated",
|
||||
"NavigationListenerChild:fragmentNavigated",
|
||||
payload
|
||||
);
|
||||
return;
|
||||
@@ -128,7 +128,7 @@ export class WebProgressListenerChild extends JSWindowActorChild {
|
||||
);
|
||||
|
||||
this.sendAsyncMessage(
|
||||
"WebProgressListenerChild:sameDocumentChanged",
|
||||
"NavigationListenerChild:sameDocumentChanged",
|
||||
payload
|
||||
);
|
||||
}
|
||||
@@ -157,7 +157,7 @@ export class WebProgressListenerChild extends JSWindowActorChild {
|
||||
|
||||
try {
|
||||
if (isStart) {
|
||||
this.sendAsyncMessage("WebProgressListenerChild:navigationStarted", {
|
||||
this.sendAsyncMessage("NavigationListenerChild:navigationStarted", {
|
||||
contextDetails: this.#getBrowsingContextDetails(context),
|
||||
url: targetURI?.spec,
|
||||
});
|
||||
@@ -169,7 +169,7 @@ export class WebProgressListenerChild extends JSWindowActorChild {
|
||||
// Skip NS_BINDING_ABORTED state changes as this can happen during a
|
||||
// browsing context + process change and we should get the real stop state
|
||||
// change from the correct process later.
|
||||
this.sendAsyncMessage("WebProgressListenerChild:navigationStopped", {
|
||||
this.sendAsyncMessage("NavigationListenerChild:navigationStopped", {
|
||||
contextDetails: this.#getBrowsingContextDetails(context),
|
||||
status,
|
||||
url: targetURI?.spec,
|
||||
@@ -20,7 +20,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
||||
|
||||
ChromeUtils.defineLazyGetter(lazy, "logger", () => lazy.Log.get());
|
||||
|
||||
export class WebProgressListenerParent extends JSWindowActorParent {
|
||||
export class NavigationListenerParent extends JSWindowActorParent {
|
||||
async receiveMessage(message) {
|
||||
const { data, name } = message;
|
||||
|
||||
@@ -31,19 +31,19 @@ export class WebProgressListenerParent extends JSWindowActorParent {
|
||||
};
|
||||
|
||||
switch (name) {
|
||||
case "WebProgressListenerChild:fragmentNavigated": {
|
||||
case "NavigationListenerChild:fragmentNavigated": {
|
||||
lazy.notifyFragmentNavigated(payload);
|
||||
break;
|
||||
}
|
||||
case "WebProgressListenerChild:sameDocumentChanged": {
|
||||
case "NavigationListenerChild:sameDocumentChanged": {
|
||||
lazy.notifySameDocumentChanged(payload);
|
||||
break;
|
||||
}
|
||||
case "WebProgressListenerChild:navigationStarted": {
|
||||
case "NavigationListenerChild:navigationStarted": {
|
||||
lazy.notifyNavigationStarted(payload);
|
||||
break;
|
||||
}
|
||||
case "WebProgressListenerChild:navigationStopped": {
|
||||
case "NavigationListenerChild:navigationStopped": {
|
||||
const errorName = ChromeUtils.getXPCOMErrorName(data.status);
|
||||
if (this.#isContentBlocked(errorName)) {
|
||||
payload.errorName = errorName;
|
||||
@@ -1,352 +0,0 @@
|
||||
/* 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,7 +41,6 @@ add_task(async function test_navigationManager() {
|
||||
);
|
||||
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[0].name, "navigation-started");
|
||||
is(events[1].name, "navigation-stopped");
|
||||
|
||||
@@ -41,7 +41,6 @@ add_task(async function test_simpleNavigation() {
|
||||
is(events.length, 0, "No event recorded");
|
||||
|
||||
await loadURL(browser, SECOND_URL);
|
||||
await BrowserTestUtils.waitForCondition(() => events.length === 2);
|
||||
|
||||
const firstNavigation = navigationManager.getNavigationForBrowsingContext(
|
||||
browser.browsingContext
|
||||
@@ -57,7 +56,6 @@ add_task(async function test_simpleNavigation() {
|
||||
);
|
||||
|
||||
await loadURL(browser, THIRD_URL);
|
||||
await BrowserTestUtils.waitForCondition(() => events.length === 4);
|
||||
|
||||
const secondNavigation = navigationManager.getNavigationForBrowsingContext(
|
||||
browser.browsingContext
|
||||
@@ -111,7 +109,6 @@ add_task(async function test_loadTwoTabsSimultaneously() {
|
||||
|
||||
info("Wait for the tabs to load");
|
||||
await Promise.all([onLoad1, onLoad2]);
|
||||
await BrowserTestUtils.waitForCondition(() => events.length === 4);
|
||||
|
||||
is(events.length, 4, "Recorded 4 navigation events");
|
||||
|
||||
@@ -135,7 +132,6 @@ add_task(async function test_loadTwoTabsSimultaneously() {
|
||||
BrowserTestUtils.reloadTab(tab1),
|
||||
BrowserTestUtils.reloadTab(tab2),
|
||||
]);
|
||||
await BrowserTestUtils.waitForCondition(() => events.length === 8);
|
||||
|
||||
is(events.length, 8, "Recorded 8 navigation events");
|
||||
|
||||
@@ -160,19 +156,6 @@ add_task(async function test_loadTwoTabsSimultaneously() {
|
||||
});
|
||||
|
||||
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 onEvent = (name, data) => events.push({ name, data });
|
||||
|
||||
@@ -187,7 +170,6 @@ add_task(async function test_loadPageWithIframes() {
|
||||
const tab = addTab(gBrowser, testUrl);
|
||||
const browser = tab.linkedBrowser;
|
||||
await BrowserTestUtils.browserLoaded(browser, false, testUrl);
|
||||
await BrowserTestUtils.waitForCondition(() => events.length === 8);
|
||||
|
||||
is(events.length, 8, "Recorded 8 navigation events");
|
||||
const contexts = browser.browsingContext.getAllBrowsingContextsInSubtree();
|
||||
@@ -206,7 +188,6 @@ add_task(async function test_loadPageWithIframes() {
|
||||
assertUniqueNavigationIds(...navigations);
|
||||
|
||||
await BrowserTestUtils.reloadTab(tab);
|
||||
await BrowserTestUtils.waitForCondition(() => events.length === 16);
|
||||
|
||||
is(events.length, 16, "Recorded 8 additional navigation events");
|
||||
const newContexts = browser.browsingContext.getAllBrowsingContextsInSubtree();
|
||||
@@ -229,19 +210,6 @@ add_task(async function test_loadPageWithIframes() {
|
||||
});
|
||||
|
||||
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 browser = tab.linkedBrowser;
|
||||
await BrowserTestUtils.browserLoaded(browser, false, FIRST_COOP_URL);
|
||||
@@ -257,7 +225,6 @@ add_task(async function test_loadPageWithCoop() {
|
||||
|
||||
const navigableId = TabManager.getIdForBrowser(browser);
|
||||
await loadURL(browser, SECOND_COOP_URL);
|
||||
await BrowserTestUtils.waitForCondition(() => events.length === 2);
|
||||
|
||||
const coopNavigation = navigationManager.getNavigationForBrowsingContext(
|
||||
browser.browsingContext
|
||||
@@ -319,7 +286,6 @@ add_task(async function test_sameDocumentNavigation() {
|
||||
// complete.
|
||||
info("Perform a regular navigation");
|
||||
await loadURL(browser, url);
|
||||
await BrowserTestUtils.waitForCondition(() => events.length === 3);
|
||||
|
||||
const regularNavigation = navigationManager.getNavigationForBrowsingContext(
|
||||
browser.browsingContext
|
||||
|
||||
@@ -50,18 +50,9 @@ add_task(async function testDocumentOpenWriteClose() {
|
||||
info("Reload the page, which should trigger a navigation");
|
||||
await loadURL(browser, url);
|
||||
|
||||
if (
|
||||
Services.prefs.getBoolPref(
|
||||
"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");
|
||||
}
|
||||
// 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("navigation-started", onEvent);
|
||||
|
||||
Reference in New Issue
Block a user