diff options
Diffstat (limited to 'browser/base/content/browser-pagestyle.js')
-rw-r--r-- | browser/base/content/browser-pagestyle.js | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/browser/base/content/browser-pagestyle.js b/browser/base/content/browser-pagestyle.js new file mode 100644 index 0000000000..4266ffd69e --- /dev/null +++ b/browser/base/content/browser-pagestyle.js @@ -0,0 +1,125 @@ +/* -*- 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", {}); + }, +}; |