Bug 1892905 - [devtools] Ensure tracing DOM Events for same-process iframe. r=devtools-reviewers,nchevobbe

The previous patch explicitly prevents spawning JavaScriptTracer for same-process iframe,
as the JavaScriptTracer can only be spawn once per thread.
But then the JavaScriptTracer should ensure tracking DOM Events for these same-process iframe globals.
`DebuggerNotificationObserver` requires to connect to each individual WindowGlobal.
Connecting to the top WindowGlobal isn't enough to receive DOM Events for children WindowGlobals.

Differential Revision: https://phabricator.services.mozilla.com/D208468
This commit is contained in:
Alexandre Poirot 2024-04-25 11:26:23 +00:00
parent bafa6d1966
commit aa60c9f40e
2 changed files with 76 additions and 0 deletions

View File

@ -12,6 +12,19 @@ add_task(async function () {
const dbg = await initDebugger("doc-scripts.html");
// Add an iframe before starting the tracer to later check for key event on it
const preExistingIframeBrowsingContext = await SpecialPowers.spawn(
gBrowser.selectedBrowser,
[],
async function () {
const iframe = content.document.createElement("iframe");
iframe.src = `data:text/html,<input type="text" value="pre existing iframe" onkeydown="console.log('keydown')" />`;
content.document.body.appendChild(iframe);
await new Promise(resolve => (iframe.onload = resolve));
return iframe.contentWindow.browsingContext;
}
);
info("Enable the tracing");
await clickElement(dbg, "trace");
@ -55,6 +68,38 @@ add_task(async function () {
await hasConsoleMessage(dbg, "DOM | click");
await hasConsoleMessage(dbg, "λ simple");
const iframeBrowsingContext = await SpecialPowers.spawn(
gBrowser.selectedBrowser,
[],
async function () {
const iframe = content.document.createElement("iframe");
iframe.src = `data:text/html,<input type="text" value="new iframe" onkeypress="console.log('keypress')" />`;
content.document.body.appendChild(iframe);
await new Promise(resolve => (iframe.onload = resolve));
iframe.contentWindow.document.querySelector("input").focus();
return iframe.contentWindow.browsingContext;
}
);
await BrowserTestUtils.synthesizeKey("x", {}, iframeBrowsingContext);
await hasConsoleMessage(dbg, "DOM | keypress");
await hasConsoleMessage(dbg, "λ onkeypress");
await SpecialPowers.spawn(
preExistingIframeBrowsingContext,
[],
async function () {
content.document.querySelector("input").focus();
}
);
await BrowserTestUtils.synthesizeKey(
"x",
{},
preExistingIframeBrowsingContext
);
await hasConsoleMessage(dbg, "DOM | keydown");
await hasConsoleMessage(dbg, "λ onkeydown");
// Test Blackboxing
info("Clear the console from previous traces");
const { hud } = await dbg.toolbox.getPanel("webconsole");

View File

@ -312,6 +312,37 @@ class JavaScriptTracer {
this.debuggerNotificationObserver.addListener(this.eventListener);
this.debuggerNotificationObserver.connect(this.tracedGlobal);
// When we are tracing a document, also ensure connecting to all its children iframe globals.
// If we don't, Debugger API would fire onEnterFrame for their JavaScript code,
// but DOM Events wouldn't be notified by DebuggerNotificationObserver.
if (!isWorker && this.tracedGlobal instanceof Ci.nsIDOMWindow) {
const { browserId } = this.tracedGlobal.browsingContext;
// Keep track of any future global
this.dbg.onNewGlobalObject = g => {
try {
const win = g.unsafeDereference();
// only process globals relating to documents, and which are within the debugged tab
if (
win instanceof Ci.nsIDOMWindow &&
win.browsingContext.browserId == browserId
) {
this.dbg.addDebuggee(g);
this.debuggerNotificationObserver.connect(win);
}
} catch (e) {}
};
// Register all, already existing children
for (const browsingContext of this.tracedGlobal.browsingContext.getAllBrowsingContextsInSubtree()) {
try {
// Only consider children which run in the same process, and exposes their window object
if (browsingContext.window) {
this.dbg.addDebuggee(browsingContext.window);
this.debuggerNotificationObserver.connect(browsingContext.window);
}
} catch (e) {}
}
}
this.currentDOMEvent = null;
}