/* -*- 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", {}); }, };