fune/browser/base/content/browser-pagestyle.js
Gijs Kruitbosch e3c02a0ba0 Bug 1842141 - fix page style no style menu checked state after reloads or same-origin navigations, r=mconley
The issue here is that authorStyleDisabledDefault persists on the BrowsingContext.
This means it stays set/unset if the BC navigates same-origin (including
reloads). But the actor was keeping its own copy, on the actor, and the actor
gets destroyed in those circumstances, leading to the frontend and the internal
state no longer being in sync.

This patch addresses this by no longer keeping our own state and just reading
the browsingcontext's field directly.

This is a tiny bit hackish because technically, whether this is the 'default'
is not the same as whether the author style is actually disabled, but in
practice the child actor always sets the two at the same time, and it is
the simpler fix (vs. trying to mirror state to the parent some more).

Differential Revision: https://phabricator.services.mozilla.com/D183188
2023-07-11 22:36:31 +00:00

125 lines
4.1 KiB
JavaScript

/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* eslint-env mozilla/browser-window */
var gPageStyleMenu = {
_getStyleSheetInfo(browser) {
let actor =
browser.browsingContext.currentWindowGlobal?.getActor("PageStyle");
let styleSheetInfo;
if (actor) {
styleSheetInfo = actor.getSheetInfo();
} else {
// Fallback if the actor is missing or we don't have a window global.
// It's unlikely things will work well but let's be optimistic,
// rather than throwing exceptions immediately.
styleSheetInfo = {
filteredStyleSheets: [],
preferredStyleSheetSet: true,
};
}
return styleSheetInfo;
},
fillPopup(menuPopup) {
let styleSheetInfo = this._getStyleSheetInfo(gBrowser.selectedBrowser);
var noStyle = menuPopup.firstElementChild;
var persistentOnly = noStyle.nextElementSibling;
var sep = persistentOnly.nextElementSibling;
while (sep.nextElementSibling) {
menuPopup.removeChild(sep.nextElementSibling);
}
let styleSheets = styleSheetInfo.filteredStyleSheets;
var currentStyleSheets = {};
var styleDisabled =
!!gBrowser.selectedBrowser.browsingContext?.authorStyleDisabledDefault;
var haveAltSheets = false;
var altStyleSelected = false;
for (let currentStyleSheet of styleSheets) {
if (!currentStyleSheet.disabled) {
altStyleSelected = true;
}
haveAltSheets = true;
let lastWithSameTitle = null;
if (currentStyleSheet.title in currentStyleSheets) {
lastWithSameTitle = currentStyleSheets[currentStyleSheet.title];
}
if (!lastWithSameTitle) {
let menuItem = document.createXULElement("menuitem");
menuItem.setAttribute("type", "radio");
menuItem.setAttribute("label", currentStyleSheet.title);
menuItem.setAttribute("data", currentStyleSheet.title);
menuItem.setAttribute(
"checked",
!currentStyleSheet.disabled && !styleDisabled
);
menuItem.setAttribute(
"oncommand",
"gPageStyleMenu.switchStyleSheet(this.getAttribute('data'));"
);
menuPopup.appendChild(menuItem);
currentStyleSheets[currentStyleSheet.title] = menuItem;
} else if (currentStyleSheet.disabled) {
lastWithSameTitle.removeAttribute("checked");
}
}
noStyle.setAttribute("checked", styleDisabled);
persistentOnly.setAttribute("checked", !altStyleSelected && !styleDisabled);
persistentOnly.hidden = styleSheetInfo.preferredStyleSheetSet
? haveAltSheets
: false;
sep.hidden = (noStyle.hidden && persistentOnly.hidden) || !haveAltSheets;
},
/**
* Send a message to all PageStyleParents by walking the BrowsingContext tree.
* @param message
* The string message to send to each PageStyleChild.
* @param data
* The data to send to each PageStyleChild within the message.
*/
_sendMessageToAll(message, data) {
let contextsToVisit = [gBrowser.selectedBrowser.browsingContext];
while (contextsToVisit.length) {
let currentContext = contextsToVisit.pop();
let global = currentContext.currentWindowGlobal;
if (!global) {
continue;
}
let actor = global.getActor("PageStyle");
actor.sendAsyncMessage(message, data);
contextsToVisit.push(...currentContext.children);
}
},
/**
* Switch the stylesheet of all documents in the current browser.
* @param title The title of the stylesheet to switch to.
*/
switchStyleSheet(title) {
let sheetData = this._getStyleSheetInfo(gBrowser.selectedBrowser);
for (let sheet of sheetData.filteredStyleSheets) {
sheet.disabled = sheet.title !== title;
}
this._sendMessageToAll("PageStyle:Switch", { title });
},
/**
* Disable all stylesheets. Called with View > Page Style > No Style.
*/
disableStyle() {
this._sendMessageToAll("PageStyle:Disable", {});
},
};