tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 9026728fa30aaece52f6ad550e4ea1e1d1affd6b
parent 592042b39f61a9caec42d6b4bec6791673a23095
Author: Simon Knott <info@simonknott.de>
Date:   Wed, 22 Oct 2025 08:29:28 +0000

Bug 1993703 - Make browserContext.forceOffline emit "offline" event on window r=necko-reviewers,valentin,dom-core,edgar

Differential Revision: https://phabricator.services.mozilla.com/D268266

Diffstat:
Mdocshell/base/BrowsingContext.cpp | 16++++++++++++++++
Mdocshell/base/BrowsingContext.h | 2++
Mdom/base/nsGlobalWindowInner.cpp | 6+++++-
Mnetwerk/test/browser/browser_test_offline_tab.js | 26++++++++++++++++++++++++++
4 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/docshell/base/BrowsingContext.cpp b/docshell/base/BrowsingContext.cpp @@ -4208,6 +4208,22 @@ void BrowsingContext::DidSet(FieldIndex<IDX_IsUnderHiddenEmbedderElement>, } } +void BrowsingContext::DidSet(FieldIndex<IDX_ForceOffline>, bool aOldValue) { + const bool newValue = ForceOffline(); + if (newValue == aOldValue) { + return; + } + PreOrderWalk([&](BrowsingContext* aBrowsingContext) { + if (RefPtr<WindowContext> windowContext = + aBrowsingContext->GetCurrentWindowContext()) { + if (nsCOMPtr<nsPIDOMWindowInner> window = + windowContext->GetInnerWindow()) { + nsGlobalWindowInner::Cast(window)->FireOfflineStatusEventIfChanged(); + } + } + }); +} + bool BrowsingContext::IsPopupAllowed() { for (auto* context = GetCurrentWindowContext(); context; context = context->GetParentWindowContext()) { diff --git a/docshell/base/BrowsingContext.h b/docshell/base/BrowsingContext.h @@ -1446,6 +1446,8 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache { void DidSet(FieldIndex<IDX_IsUnderHiddenEmbedderElement>, bool aOldValue); + void DidSet(FieldIndex<IDX_ForceOffline>, bool aOldValue); + // Allow if the process attemping to set field is the same as the owning // process. Deprecated. New code that might use this should generally be moved // to WindowContext or be settable only by the parent process. diff --git a/dom/base/nsGlobalWindowInner.cpp b/dom/base/nsGlobalWindowInner.cpp @@ -4939,8 +4939,12 @@ already_AddRefed<CacheStorage> nsGlobalWindowInner::GetCaches( void nsGlobalWindowInner::FireOfflineStatusEventIfChanged() { if (!IsCurrentInnerWindow()) return; + bool isOffline = + NS_IsOffline() || + (GetBrowsingContext() && GetBrowsingContext()->Top()->GetForceOffline()); + // Don't fire an event if the status hasn't changed - if (mWasOffline == NS_IsOffline()) { + if (mWasOffline == isOffline) { return; } diff --git a/netwerk/test/browser/browser_test_offline_tab.js b/netwerk/test/browser/browser_test_offline_tab.js @@ -34,3 +34,29 @@ add_task(async function test_set_tab_online() { }); }); }); + +add_task(async function test_set_tab_offline_events() { + await BrowserTestUtils.withNewTab("https://example.com", async browser => { + await SpecialPowers.spawn(browser, [], async () => { + content.events = []; + content.window.addEventListener("offline", () => + content.events.push("offline") + ); + content.window.addEventListener("online", () => + content.events.push("online") + ); + }); + gBrowser.selectedBrowser.browsingContext.forceOffline = true; + Assert.deepEqual( + await SpecialPowers.spawn(browser, [], async () => content.events), + ["offline"], + "events should be fired" + ); + gBrowser.selectedBrowser.browsingContext.forceOffline = false; + Assert.deepEqual( + await SpecialPowers.spawn(browser, [], async () => content.events), + ["offline", "online"], + "events should be fired" + ); + }); +});