Closed Bug 2063548 Opened 13 days ago Closed 12 days ago

swapBrowsers() throws a TypeError because TabProgressListener isn't reachable as a window property

Categories

(Firefox :: Tabbed Browser, defect)

defect

Tracking

()

RESOLVED FIXED
156 Branch
Tracking Status
firefox156 --- fixed

People

(Reporter: dao, Assigned: dao)

References

Details

Attachments

(2 files)

Tabbrowser.swapBrowsers() restores the swapped-in tab's progress listener with:

tabListener = new otherTabBrowser.documentGlobal.TabProgressListener(...)

(browser/components/tabbrowser/content/tabbrowser.js:6727, where documentGlobal is the tab's window.)

But class TabProgressListener is declared inside the file's private block scope ({ // start private scope for Tabbrowser, line 5), so it is a lexical binding in that block and never becomes a property of the window. documentGlobal.TabProgressListener is therefore undefined and the call throws a TypeError. There is no other definition of TabProgressListener in browser/ or toolkit/, and this fails for same-window swaps just as it does for cross-window ones.

The path is reachable from nsIBrowser::swapBrowsers via browser-custom-element.mjs, which forwards to Tabbrowser.swapBrowsers() when both browsers are attached to a tabbrowser. NewTabPagePreloading doesn't hit it, since the preloaded browser has no tabbrowser and falls through to swapDocShells(). There appears to be no test coverage for the affected path. swapBrowsersAndCloseOther() is unaffected; it doesn't construct a listener.

Plan: rather than exposing the class on the window, make TabProgressListener window-agnostic and construct it directly. Its body relies on the constructing realm's globals -- roughly 50 bare gBrowser references plus gURLBar, PrivateBrowsingUtils.isWindowPrivate(window) and AIWindow.isAIWindowActive(window) -- which is what documentGlobal.TabProgressListener was reaching for, so simply constructing the local class first would trade the TypeError for a listener driving the wrong window's tabbrowser. So:

  1. Derive the tabbrowser and window from this._tab / this._browser, which the constructor already receives, and drop the bare window globals.
  2. Replace the construction at 6727 with new TabProgressListener(...).

Both steps are prerequisites for bug 2049770, which needs the class free of window closures anyway, and step 2 is the shape the shared module wants -- nothing to undo at move time. Bug 2049770 also removes the interim wrinkle that a listener constructed in one window for another window's tab keeps the constructing window's global alive, since the shared class lives in the system realm.

TabProgressListener is declared inside the file's private block scope, so it
never was a property of the window and swapBrowsers threw a TypeError where it
should have restored the tab's progress listener. Asking the owning tabbrowser
for the listener keeps it in the realm of the window whose tab it serves, so it
resolves that window's globals and doesn't keep the swapping window alive.

The test drives the swap through nsIBrowser::swapBrowsers, the path that reaches
this code, and checks both the listener's realm and that it notifies its own
window.

Assignee: nobody → dao+bmo
Status: NEW → ASSIGNED

The timer was scheduled by the window the tab is adopted from, so clearing the
id against the adopting window's timers leaves it pending and can cancel an
unrelated timer of the same id.

Pushed by dgottwald@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/936ee9782c6f https://hg.mozilla.org/integration/autoland/rev/af0ec50a215c Create the swapped-in tab's progress listener in its own window. r=jsudiaman,tabbrowser-reviewers https://github.com/mozilla-firefox/firefox/commit/914c5a4d038f https://hg.mozilla.org/integration/autoland/rev/cc05575d8e79 Cancel the adopted tab's soundplaying timer in its own window. r=jsudiaman,tabbrowser-reviewers
Status: ASSIGNED → RESOLVED
Closed: 12 days ago
Resolution: --- → FIXED
Target Milestone: --- → 156 Branch
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: