gecko-dev/docshell/test/browser/browser_browsingContext_iframeWebProgress.js
Julian Descottes 4a716fd605 Bug 1963189 - Forward WebProgress events directly from nsDocShell to BrowsingContextWebProgress, r=smaug,webdriver-reviewers,extension-reviewers,robwu,jdescottes
Prior to this change, all web progress events fired by nsDocLoader
were bubbled to the toplevel in-process nsDocShell instance, then
captured by web progress listener. This listener would filter the
notifications (using nsBrowserStatusFilter), then send them either
directly to the BrowsingContextWebProgress, or via. PBrowser to the
BrowsingContextWebProgress.

Unfortunately, these events are modified as they are bubbled (e.g.
changing the progress flags to remove STATE_IS_NETWORK), which combined
with the filtering from nsBrowserStatusFilter led to some strange
behaviour in the notifications.

This change skips the in-content bubbling by directly propagating events
from the nsDocShell they were fired on to the corresponding
BrowsingContextWebProgress, and then performing the bubbling within the
parent process.

The one major exception to this is OnProgressChange, which relies on
nsDocLoader's handling on aCurTotalProgress and aMaxTotalProgress.
Because of that, these listeners continue to capture progress
notifications exclusively on the toplevel BrowsingContext, and do not
handle out-of-process iframes.

Differential Revision: https://phabricator.services.mozilla.com/D249651
2025-05-29 21:43:41 +00:00

59 lines
1.8 KiB
JavaScript

/* 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/. */
function getPageURL(domain) {
// The iframe in file_browsingContext_iframeWebProgress.html is hardcoded to
// point to example.com
return (
getRootDirectory(gTestPath).replace(
"chrome://mochitests/content",
`https://${domain}`
) + "file_browsingContext_iframeWebProgress.html"
);
}
const SAME_ORIGIN_IFRAME_PAGE = getPageURL("example.com");
const CROSS_ORIGIN_IFRAME_PAGE = getPageURL("example.org");
add_task(async function testReloadCrossOriginIframePage() {
await testReloadPageWithIframe(CROSS_ORIGIN_IFRAME_PAGE);
});
add_task(async function testReloadSameOriginIframePage() {
await testReloadPageWithIframe(SAME_ORIGIN_IFRAME_PAGE);
});
async function testReloadPageWithIframe(url) {
const tab = BrowserTestUtils.addTab(gBrowser, url);
const browser = tab.linkedBrowser;
await BrowserTestUtils.browserLoaded(browser, false, url);
const onStateChangeEvents = [];
const listener = {
QueryInterface: ChromeUtils.generateQI([
"nsIWebProgressListener",
"nsISupportsWeakReference",
]),
onStateChange(webProgress, request, flags) {
if (flags & Ci.nsIWebProgressListener.STATE_START) {
onStateChangeEvents.push(
request.QueryInterface(Ci.nsIChannel).originalURI
);
}
},
};
browser.browsingContext.webProgress.addProgressListener(
listener,
Ci.nsIWebProgress.NOTIFY_STATE_WINDOW
);
BrowserTestUtils.reloadTab(tab);
await BrowserTestUtils.waitForCondition(
() => onStateChangeEvents.length == 2
);
is(onStateChangeEvents.length, 2);
gBrowser.removeTab(tab);
}