Closed
Bug 1124122
Opened 11 years ago
Closed 6 years ago
Event suppression doesn't seem to work with postMessage
Categories
(DevTools :: Debugger, defect, P3)
DevTools
Debugger
Tracking
(firefox69 fixed)
RESOLVED
FIXED
Firefox 69
Tracking | Status | |
---|---|---|
firefox69 | --- | fixed |
People
(Reporter: shu, Assigned: bhackett1024)
References
(Blocks 1 open bug)
Details
(Whiteboard: [debugger-mvp] [devtools-platform])
Attachments
(2 files)
I'm running into a case where debugger; statements are not hit until after quite a bit. Preliminary debugging shows that the onDebuggerStatement hook is actually being hit, but we are unable to pause because the ThreadActor.state is already "paused" from the initial pause.
Debuggee JS shouldn't be able to run during this time -- best guess after talking with Eddy and Panos on IRC is that event suppression isn't working right for iframes.
Reporter | ||
Updated•11 years ago
|
Summary: Event suppression doesn't seem to work with iframes when pushing nested event loops → Event suppression doesn't seem to work with postMessage
Reporter | ||
Comment 1•11 years ago
|
||
The iframe was a red herring. It's really postMessages being pumped even with event suppression. If you run this test with the debugger open and check the console, one should notice several "AFTER DEBUGGER" messages being hit before we actually pause in the Debugger on the |debugger;| statement.
Updated•11 years ago
|
Component: Developer Tools → Developer Tools: Debugger
Comment 2•11 years ago
|
||
(In reply to Shu-yu Guo [:shu] from comment #0)
> best guess after
> talking with Eddy and Panos on IRC is that event suppression isn't working
> right for iframes.
Made a test page to verify this:
http://htmlpad.org/paused-iframes/
Opening the debugger and hitting pause will stop execution in both iframe and parent window (=timeout is suspended). Double-clicking on the iframe won't select the text (=events are suppressed). So the iframe was indeed a red herring.
Reporter | ||
Comment 3•11 years ago
|
||
So the problem, as best as I understand, after talking with mrbkap, is this:
The frontend's "pushThreadPause" mechanism is fundamentally broken.
We attempt to pause debuggee code by 1) suppressing events on the content window and 2) suppressing timeouts on the content window. Afterwards, we spin a nested event loop, with the intention of processing debugger chrome code. The event loop itself isn't intrinsically hierarchical. A nested event loop still pumps the *same* message loop. Indeed, there's a single message loop per process.
Neither 1) nor 2) above actually pauses the debuggee code. Things like postMessage slip through, as do other things on the message loop that aren't events that event suppression in 1) above suppresses. This means that we simply do not have a guarantee that debuggee code does not run while the frontend debugger is visually paused.
I guess a new DOM API is needed that tells a document to just "stop", so all messages on it are enqueued and saved up somewhere. This is tricky, as mrbkap pointed out, because we also have to consider all other similarly-origined windows. Those other windows can hold CCWs to functions inside our "stopped" document, and can thus invoke code in our debuggee document directly.
I think this should be high priority, because it erodes confidence in users. Imagine if you started up gdb and your breakpoints just don't hit for the first 2s. How can you trust in the rest of the toolkit?
Reporter | ||
Comment 4•11 years ago
|
||
Most realistic way forward, since per-document message queues is pretty much shangri-la, is to add a new API to suppress and resume postMessage events. The current event suppression on the pres shell (or was it something else?) basically only suppresses focus events.
Comment 5•11 years ago
|
||
(In reply to Shu-yu Guo [:shu] from comment #3)
> Neither 1) nor 2) above actually pauses the debuggee code. Things like
> postMessage slip through, as do other things on the message loop that aren't
> events that event suppression in 1) above suppresses. This means that we
> simply do not have a guarantee that debuggee code does not run while the
> frontend debugger is visually paused.
So, there are basically 2 ways that we can enter script in a given compartment:
(1) The system enters script (event dispatch, postmessage, etc)
(2) Script from another compartment invokes script in the given compartment via a cross-compartment wrapper (possibly indirectly via property manipulation).
I recently implemented an API that is supposed to handle (1), and is used by addons like NoScript, called BlockScriptForGlobal/UnblockScriptForGlobal. The debugger should almost use that instead of doing manual event supporession. And if there are holes in it (e.g. postMessage), we should fix it.
If (2) is a problem, we could solve it at the wrapper layer by temporarily sealing off all incoming wrappers while the debugger is paused.
I can't find the debugger's event suppression code, but it should almost certainly use the proper XPConnect API if it isn't already. Shu, are you interested in digging into this? I can help you out if so.
Flags: needinfo?(shu)
Reporter | ||
Comment 6•11 years ago
|
||
(In reply to Bobby Holley (Busy with media, don't ask for DOM/JS/XPConnect things) from comment #5)
> (In reply to Shu-yu Guo [:shu] from comment #3)
> > Neither 1) nor 2) above actually pauses the debuggee code. Things like
> > postMessage slip through, as do other things on the message loop that aren't
> > events that event suppression in 1) above suppresses. This means that we
> > simply do not have a guarantee that debuggee code does not run while the
> > frontend debugger is visually paused.
>
> So, there are basically 2 ways that we can enter script in a given
> compartment:
> (1) The system enters script (event dispatch, postmessage, etc)
> (2) Script from another compartment invokes script in the given compartment
> via a cross-compartment wrapper (possibly indirectly via property
> manipulation).
>
> I recently implemented an API that is supposed to handle (1), and is used by
> addons like NoScript, called BlockScriptForGlobal/UnblockScriptForGlobal.
> The debugger should almost use that instead of doing manual event
> supporession. And if there are holes in it (e.g. postMessage), we should fix
> it.
>
> If (2) is a problem, we could solve it at the wrapper layer by temporarily
> sealing off all incoming wrappers while the debugger is paused.
>
> I can't find the debugger's event suppression code, but it should almost
> certainly use the proper XPConnect API if it isn't already. Shu, are you
> interested in digging into this? I can help you out if so.
Sure, I can fix this if the new API is suitable. Does BlockScriptForGlobal *delay* the events until the Unblock call or does it discard them? The debugger needs them delayed.
Flags: needinfo?(shu)
Comment 7•11 years ago
|
||
(In reply to Shu-yu Guo [:shu] from comment #6)
> Sure, I can fix this if the new API is suitable. Does BlockScriptForGlobal
> *delay* the events until the Unblock call or does it discard them? The
> debugger needs them delayed.
It discards them - so if that isn't good enough, we need another story. But it probably makes sense to coordinate the APIs, because callsites checking whether script can run should be the same.
I think it makes sense to add another predicate to xpc::Scriptability called ::Delayed(). If caller support delaying execution, they can check ::Delayed() if ::Allowed() returns false.
For edge cases where delaying isn't supported, do we want to default to running script, or to not running it? I'm assuming the latter, but we should think about that.
Comment 8•11 years ago
|
||
(In reply to Bobby Holley (Busy with media, don't ask for DOM/JS/XPConnect things) from comment #5)
> I can't find the debugger's event suppression code, but it should almost
> certainly use the proper XPConnect API if it isn't already.
The debugger actors call preNest() to pause execution before entering a nested event loop:
https://dxr.mozilla.org/mozilla-central/search?tree=mozilla-central&q=preNest
BTA_preNest is the most common one, used when debugging a tab in Firefox desktop.
Reporter | ||
Updated•10 years ago
|
Whiteboard: [devtools-platform]
Updated•7 years ago
|
Product: Firefox → DevTools
Updated•7 years ago
|
Blocks: dbg-r2c-q1
Updated•6 years ago
|
Whiteboard: [devtools-platform] → [debugger-mvp] [devtools-platform]
Comment 9•6 years ago
|
||
I can still reproduce this bug:
Here are my STR:
- Load http://janodvarko.cz/tests/bugzilla/1124122/
- Open DevTools Toolbox and Browser Console
- Reload the page
- You should see 99
AFTER DEBUGGER
logs in the Browser Console before breaking at thedebugger
statement
ER:
Debugger breaks on the debugger
statement immediatelly.
AR:
The debugger
statement is hit many times, but doesn't break the debugger.
Honza
Priority: -- → P2
Updated•6 years ago
|
Priority: P2 → P3
Updated•6 years ago
|
Assignee: nobody → bhackett1024
Assignee | ||
Comment 10•6 years ago
|
||
Updated•6 years ago
|
Status: NEW → ASSIGNED
Comment 11•6 years ago
|
||
Pushed by bhackett@mozilla.com:
https://hg.mozilla.org/integration/mozilla-inbound/rev/51440617724b
Suppress postMessage events on a window's document when event handling is suppressed, r=smaug.
Comment 12•6 years ago
|
||
bugherder |
Status: ASSIGNED → RESOLVED
Closed: 6 years ago
status-firefox69:
--- → fixed
Resolution: --- → FIXED
Target Milestone: --- → Firefox 69
You need to log in
before you can comment on or make changes to this bug.
Description
•