Closed Bug 2003810 Opened 2 months ago Closed 15 days ago

Unable to re-open devtools: Permission denied to access property "isChromeWindow" on cross-origin object

Categories

(DevTools :: Inspector, defect, P2)

defect

Tracking

(firefox-esr140 unaffected, firefox146 wontfix, firefox147 verified, firefox148 verified, firefox149 verified)

VERIFIED FIXED
149 Branch
Tracking Status
firefox-esr140 --- unaffected
firefox146 --- wontfix
firefox147 --- verified
firefox148 --- verified
firefox149 --- verified

People

(Reporter: jdescottes, Assigned: ochameau)

References

(Blocks 1 open bug, Regressed 2 open bugs, Regression)

Details

(Keywords: regression)

Attachments

(1 file, 1 obsolete file)

STRs:

Spotted this while testing other random reload bugs with the inspector. I tried with other pages using cross origin iframes, but I can't reproduce it outside of the page linked above for now.

The console is filled with

JavaScript error: resource://devtools/server/actors/inspector/node-picker.js, line 152: SecurityError: Permission denied to access property "isChromeWindow" on cross-origin object

Note: the bug is also triggered if instead of reloading, you start from about:blank (or any other page), press cmd+shift+c and then navigate to the page above.

Severity: -- → S3
Flags: needinfo?(nchevobbe)
Priority: -- → P2
See Also: → 2005348

When the page is reloaded, a picker gets created for a target whose window is about:blank
Some times after that, the picker gets destroyed, but this time the target window is https://instaread.co/player?article=…

What seems to work is to keep a reference of the document we add the suppressed event listener on, and use that again to remove the event listener. What we could also do is make setSuppressedEventListener accept an AbortSignal, since we're already passing one from an AbortController for the other listener we're setting

https://searchfox.org/firefox-main/rev/929fb12c1318659f24965f2908dec6e5fd56d9d9/devtools/server/actors/inspector/node-picker.js#424,461,463-464,467,470-471,474

this.#eventListenersAbortController = new AbortController();
...
  target.addEventListener(type, this._preventContentEvent, {
...
    signal: this.#eventListenersAbortController.signal,
  });
...
  target.addEventListener(type, handler, {
...
    signal: this.#eventListenersAbortController.signal,
  });
...
this._setSuppressedEventListener(this._onSuppressedEvent);

That's probably just a banda-id though, given we get a similar exception from Bug 2005348, and we should understand why the window is seen as a cross origin object.

Flags: needinfo?(nchevobbe)

Looks like this comes from Bug 1989056, if I remove https://searchfox.org/firefox-main/rev/929fb12c1318659f24965f2908dec6e5fd56d9d9/devtools/server/actors/targets/window-global.js#384-388

Object.defineProperty(this, "window", {
  value: this.window,
  configurable: false,
  writable: false,
});

then I don't see the error anymore

Keywords: regression
Regressed by: 1989056

Set release status flags based on info from the regressing bug 1989056

:ochameau, since you are the author of the regressor, bug 1989056, could you take a look?

For more information, please visit BugBot documentation.

Flags: needinfo?(poirot.alex)

This all relates to the better handle breakpoints once the navigation start, for example to pause when the unload event fires.
Bug 1989056 is the actual regressor, but the issues started with bug 1903980.
Before that older bug, we were destroying the target actor before we started navigating away and especially before the related window object starts throwing.

As said in comment 2, we get the following exception first:

DOMException: Permission denied to access property "document" on cross-origin object
    _setSuppressedEventListener resource://devtools/server/actors/inspector/node-picker.js:399
    _stopPickerListeners resource://devtools/server/actors/inspector/node-picker.js:487
    _stopPicking resource://devtools/server/actors/inspector/node-picker.js:531
    cancelPick resource://devtools/server/actors/inspector/node-picker.js:546
    destroy resource://devtools/server/actors/inspector/node-picker.js:579
    [...]
    destroy resource://devtools/server/actors/targets/window-global.js:864

which prevents unregistering the NodePicker listeners, because we throw before aborting the AbortController.
https://searchfox.org/firefox-main/rev/7d8644b9d4470a675bf670c2dc7664cc01f14ece/devtools/server/actors/inspector/node-picker.js#477-483

_stopPickerListeners() {
  this._setSuppressedEventListener(null); // <======= throw here

  if (this.#eventListenersAbortController) {
    this.#eventListenersAbortController.abort(); // <== avoids unregistering the listeners
    this.#eventListenersAbortController = null;
  }

It throws because targetActor.window is a cross origin remote proxy:
https://searchfox.org/firefox-main/rev/7d8644b9d4470a675bf670c2dc7664cc01f14ece/devtools/server/actors/inspector/node-picker.js#391-392

_setSuppressedEventListener(callback) {
  if (!this._targetActor?.window?.document) {

We are seeing a surge of "cross origin exceptions" most likely because of about:blank changes (bug 543435).
The target actor involved in this exception is starting with about:blank document and the exception happens when this same target actor's window refers to the instaread.co iframe location.

Ideally, all actors should now be careful about the late stage of target actor lifecycle where the related window may no longer be usable.
May be WindowGlobalTargetActor should return a null window when we already navigated to a cross origin / cross process document?

Flags: needinfo?(poirot.alex)

When the target actor and the node picker are being destroyed for an <iframe>,
their related window may already have navigated to a new document.
This is to support late stage breakpoint, like pause on unload.

Because of this, the window may refer to another origin, running in another process.
When this happens almost all access to window attributes will throw a cross origin exception.

Assignee: nobody → poirot.alex
Status: NEW → ASSIGNED
Depends on: 2007539

This prevents having to special case the "isRemoteProxy" edgecase in all actors.

Duplicate of this bug: 2005348
Duplicate of this bug: 2008458
Attachment #9534695 - Attachment description: WIP: Bug 2003810 - [devtools] Nullify WindowGlobalTarget actor when the underlying WindowGlobal navigated to another origin and process. → Bug 2003810 - [devtools] Nullify WindowGlobalTarget actor when the underlying WindowGlobal navigated to another origin and process. r=#devtools
Attachment #9534572 - Attachment is obsolete: true
Pushed by apoirot@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/662cd20e49ad https://hg.mozilla.org/integration/autoland/rev/85a2a68f7a26 [devtools] Nullify WindowGlobalTarget actor when the underlying WindowGlobal navigated to another origin and process. r=devtools-reviewers,jdescottes
Regressions: 2011549
Regressions: 2011566
Status: ASSIGNED → RESOLVED
Closed: 15 days ago
Resolution: --- → FIXED
Target Milestone: --- → 149 Branch

Probably worth considering at least a Beta uplift (maybe Release too?) given the dupes this is picking up. WDYT?

Flags: needinfo?(poirot.alex)
Flags: in-testsuite+

Comment on attachment 9534695 [details]
Bug 2003810 - [devtools] Nullify WindowGlobalTarget actor when the underlying WindowGlobal navigated to another origin and process. r=#devtools

Beta/Release Uplift Approval Request

  • User impact if declined/Reason for urgency: DevTools crashes on opening, if the page has some iframe navigating during the load. But it can be reopened by closing and reopening.
  • Is this code covered by automated tests?: Yes
  • Has the fix been verified in Nightly?: No
  • Needs manual test from QE?: Yes
  • If yes, steps to reproduce: STR from comment 0
  • List of other uplifts needed: Bug 2007539
  • Risk to taking this patch: Medium
  • Why is the change risky/not risky? (and alternatives if risky): I had a more conservative patch, but this was highlighting all the other possible similar crash elsewhere in the codebase.
    This new patch is less conservative, but tentatively address all these cases of cross origin exceptions. To the cost of possibly introducing new kind of "this.window" is undefined exception...
    Now... we were getting more and more of these reports, so the balance is still possibly positive in favor of pushing this patch.
  • String changes made/needed: no
  • Is Android affected?: No
Flags: needinfo?(poirot.alex)
Attachment #9534695 - Flags: approval-mozilla-beta?

Comment on attachment 9534695 [details]
Bug 2003810 - [devtools] Nullify WindowGlobalTarget actor when the underlying WindowGlobal navigated to another origin and process. r=#devtools

Approved for 148.0b7

Attachment #9534695 - Flags: approval-mozilla-beta? → approval-mozilla-beta+
See Also: 2005348
Duplicate of this bug: 2012155
Duplicate of this bug: 2005620
Flags: qe-verify+
QA Whiteboard: [uplift][qa-ver-needed-c149/b148]

Hello! I have reproduced the issue with Firefox 147.0a1 (2025-12-04) on Windows 11. After following the steps from comment 0 or comment 1, the developer tools can no longer be opened using Ctrl+ Shift+ C or Ctrl+ Shift+ I keyboard shortcuts.
The web console and browser console are successfully opened with Firefox 148.0b7 and 149.0a1 (2026-01-27) on Windows 11, macOS 26 and Ubuntu 24 by following the same steps.

Has STR: --- → yes
QA Whiteboard: [uplift][qa-ver-needed-c149/b148] → [uplift][qa-ver-done-c149/b148]
Flags: qe-verify+

Comment on attachment 9534695 [details]
Bug 2003810 - [devtools] Nullify WindowGlobalTarget actor when the underlying WindowGlobal navigated to another origin and process. r=#devtools

Beta/Release Uplift Approval Request

  • User impact if declined/Reason for urgency: Looking at the number of duplicates, it looks like it is pretty common to have devtools to crash on opening. You can always close and reopen, as it is a race condition, they will likely work on the second try. But still a frustrating experience.
  • Is this code covered by automated tests?: Yes
  • Has the fix been verified in Nightly?: Yes
  • Needs manual test from QE?: No
  • If yes, steps to reproduce:
  • List of other uplifts needed: Bug 2007539
  • Risk to taking this patch: Low
  • Why is the change risky/not risky? (and alternatives if risky): After some more thoughts, I didn't realize that the final patch was actually quite conservative. So the risk is lower than I thought on the uplift request for beta.

I thought I made the call to always nullify the window attribute, but instead I nullified it only if we may get into this race condition:
https://searchfox.org/firefox-main/rev/0fc599421fc27ac61c501f277cb440777f85b18a/devtools/server/actors/targets/window-global.js#809-818

// In case the window already navigated to another origin,
// which is possibly in another process, nullify window
// as most, if not all attributes would throw.
if (Cu.isRemoteProxy(this.window)) {
  Object.defineProperty(this, "window", {
    value: null,
    configurable: true,
    writable: false,
  });
}
  • String changes made/needed:
  • Is Android affected?: No
Attachment #9534695 - Flags: approval-mozilla-release?

Note that the test added by this changeset almost permafails on linux tsan. If that's a concern for the uplift, we might also want to take https://phabricator.services.mozilla.com/D281159

Comment on attachment 9534695 [details]
Bug 2003810 - [devtools] Nullify WindowGlobalTarget actor when the underlying WindowGlobal navigated to another origin and process. r=#devtools

Approved for 147.0.3

Attachment #9534695 - Flags: approval-mozilla-release? → approval-mozilla-release+

The web console and browser console are successfully opened with Firefox 147.0.3 on Windows 11, macOS 26 and Ubuntu 24 by following the steps from comment 0 and comment 1.

Status: RESOLVED → VERIFIED
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: