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:
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"
+ );
+ });
+});