commit fc11ba2f78f97a71f9900f7a3934ef4fbe6b8e5e
parent a6dba4a5db827a1d723bc4ae7d97f0a82000cfff
Author: Alexandra Borovova <aborovova@mozilla.com>
Date: Tue, 23 Dec 2025 12:51:16 +0000
Bug 1964905 - Add "owningBrowsingContext" to "DOMModalDialogClosed" event details. r=Gijs
Differential Revision: https://phabricator.services.mozilla.com/D276819
Diffstat:
2 files changed, 104 insertions(+), 26 deletions(-)
diff --git a/browser/actors/PromptParent.sys.mjs b/browser/actors/PromptParent.sys.mjs
@@ -156,6 +156,14 @@ export class PromptParent extends JSWindowActorParent {
throw new Error(`Cannot ${modal_type}-prompt without a browser!`);
}
+ const closingEventDetails =
+ args.modalType === Services.prompt.MODAL_TYPE_CONTENT
+ ? {
+ owningBrowsingContext: this.browsingContext,
+ promptType: args.inPermitUnload ? "beforeunload" : args.promptType,
+ }
+ : null;
+
let win;
// If we are a chrome actor we can use the associated chrome win.
@@ -287,27 +295,20 @@ export class PromptParent extends JSWindowActorParent {
win,
"DOMModalDialogClosed",
browsingContext.embedderElement,
- this.getClosingEventDetail(args)
+ closingEventDetails
+ ? {
+ ...closingEventDetails,
+ areLeaving: args.ok,
+ // If a prompt was not accepted, do not return the prompt value.
+ value: args.ok ? args.value : null,
+ }
+ : null
);
}
}
return args;
}
- getClosingEventDetail(args) {
- let details =
- args.modalType === Services.prompt.MODAL_TYPE_CONTENT
- ? {
- areLeaving: args.ok,
- promptType: args.inPermitUnload ? "beforeunload" : args.promptType,
- // If a prompt was not accepted, do not return the prompt value.
- value: args.ok ? args.value : null,
- }
- : null;
-
- return details;
- }
-
getOpenEventDetail(args) {
let details =
args.modalType === Services.prompt.MODAL_TYPE_CONTENT
diff --git a/browser/base/content/test/tabPrompts/browser_prompt_close_event.js b/browser/base/content/test/tabPrompts/browser_prompt_close_event.js
@@ -21,24 +21,23 @@ const BEFOREUNLOAD_URL = BUILDER_URL + encodeURI(BEFOREUNLOAD_MARKUP);
/**
* Execute the provided script content by generating a dynamic script tag and
- * inserting it in the page for the current selected browser.
+ * inserting it in the page for the provided browser.
*
* @param {string} script
* The script to execute.
+ * @param {Browser} browser
+ * The browser element where the script has to be to executed.
+ * Defaults to a current selected browser.
* @returns {Promise}
* A promise that resolves when the script node was added and removed from
* the content page.
*/
-function createScriptNode(script) {
- return SpecialPowers.spawn(
- gBrowser.selectedBrowser,
- [script],
- function (_script) {
- const scriptTag = content.document.createElement("script");
- scriptTag.append(content.document.createTextNode(_script));
- content.document.body.append(scriptTag);
- }
- );
+function createScriptNode(script, browser = gBrowser.selectedBrowser) {
+ return SpecialPowers.spawn(browser, [script], function (_script) {
+ const scriptTag = content.document.createElement("script");
+ scriptTag.append(content.document.createTextNode(_script));
+ content.document.body.append(scriptTag);
+ });
}
add_task(async function test_close_prompt_event_detail_prompt_types() {
@@ -103,6 +102,11 @@ add_task(async function test_close_prompt_event_detail_beforeunload() {
"beforeunload",
"Received correct `promptType` value in the event detail"
);
+ is(
+ closedEvent.detail.owningBrowsingContext,
+ browser.browsingContext,
+ "Received correct `owningBrowsingContext` value in the event detail"
+ );
if (leavePage) {
await BrowserTestUtils.browserLoaded(browser, false, "about:blank");
@@ -153,6 +157,11 @@ add_task(
defaultValue,
"Received correct `value` value in the event detail"
);
+ is(
+ closedEvent.detail.owningBrowsingContext,
+ gBrowser.selectedBrowser.browsingContext,
+ "Received correct `owningBrowsingContext` value in the event detail"
+ );
}
);
@@ -194,6 +203,11 @@ add_task(
amendedValue,
"Received correct `value` value in the event detail"
);
+ is(
+ closedEvent.detail.owningBrowsingContext,
+ gBrowser.selectedBrowser.browsingContext,
+ "Received correct `owningBrowsingContext` value in the event detail"
+ );
}
);
@@ -232,6 +246,11 @@ add_task(
null,
"Received correct `value` value in the event detail"
);
+ is(
+ closedEvent.detail.owningBrowsingContext,
+ gBrowser.selectedBrowser.browsingContext,
+ "Received correct `owningBrowsingContext` value in the event detail"
+ );
}
);
@@ -273,5 +292,63 @@ add_task(
null,
"Received correct `value` value in the event detail"
);
+ is(
+ closedEvent.detail.owningBrowsingContext,
+ gBrowser.selectedBrowser.browsingContext,
+ "Received correct `owningBrowsingContext` value in the event detail"
+ );
}
);
+
+add_task(async function test_close_prompt_event_detail_in_iframe() {
+ const IFRAME_HTML = `
+ <!doctype html>
+ <html>
+ <head>
+ <meta charset=utf8>
+ </head>
+ <body>
+ <h1>Iframe</h1>
+ </body>
+ </html>`;
+
+ const PAGE_WITH_IFRAME = `
+ <html>
+ <head>
+ </head>
+ <body>
+ <iframe src='${BUILDER_URL + encodeURI(IFRAME_HTML)}'></iframe>
+ </body>
+ </html>
+ `;
+
+ await BrowserTestUtils.withNewTab(
+ BUILDER_URL + encodeURI(PAGE_WITH_IFRAME),
+ async function (browser) {
+ const iframeBrowsingContext = browser.browsingContext.children[0];
+
+ const closed = BrowserTestUtils.waitForEvent(
+ window,
+ "DOMModalDialogClosed"
+ );
+
+ const promptPromise = BrowserTestUtils.promiseAlertDialogOpen();
+ await createScriptNode(
+ `setTimeout(() => window.alert('test'))`,
+ iframeBrowsingContext
+ );
+ const promptWin = await promptPromise;
+
+ info("accepting prompt with default value.");
+ promptWin.document.querySelector("dialog").acceptDialog();
+
+ const closedEvent = await closed;
+
+ is(
+ closedEvent.detail.owningBrowsingContext,
+ iframeBrowsingContext,
+ "Received correct `owningBrowsingContext` value in the event detail"
+ );
+ }
+ );
+});