diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
commit | 43a97878ce14b72f0981164f87f2e35e14151312 (patch) | |
tree | 620249daf56c0258faa40cbdcf9cfba06de2a846 /browser/actors/PageStyleChild.jsm | |
parent | Initial commit. (diff) | |
download | firefox-43a97878ce14b72f0981164f87f2e35e14151312.tar.xz firefox-43a97878ce14b72f0981164f87f2e35e14151312.zip |
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'browser/actors/PageStyleChild.jsm')
-rw-r--r-- | browser/actors/PageStyleChild.jsm | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/browser/actors/PageStyleChild.jsm b/browser/actors/PageStyleChild.jsm new file mode 100644 index 0000000000..a45e0a422f --- /dev/null +++ b/browser/actors/PageStyleChild.jsm @@ -0,0 +1,178 @@ +/* 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/. */ +"use strict"; + +var EXPORTED_SYMBOLS = ["PageStyleChild"]; + +class PageStyleChild extends JSWindowActorChild { + handleEvent(event) { + // On page show, tell the parent all of the stylesheets this document has. + if (event.type == "pageshow") { + // If we are in the topmost browsing context, + // delete the stylesheets from the previous page. + if (this.browsingContext.top === this.browsingContext) { + this.sendAsyncMessage("PageStyle:Clear"); + } + + let window = event.target.ownerGlobal; + window.requestIdleCallback(() => { + if (!window || window.closed) { + return; + } + let filteredStyleSheets = this._collectStyleSheets(window); + this.sendAsyncMessage("PageStyle:Add", { + filteredStyleSheets, + authorStyleDisabled: this.docShell.contentViewer.authorStyleDisabled, + preferredStyleSheetSet: this.document.preferredStyleSheetSet, + }); + }); + } + } + + receiveMessage(msg) { + switch (msg.name) { + // Sent when the page's enabled style sheet is changed. + case "PageStyle:Switch": + if (this.browsingContext.top == this.browsingContext) { + this.browsingContext.authorStyleDisabledDefault = false; + } + this.docShell.contentViewer.authorStyleDisabled = false; + this._switchStylesheet(msg.data.title); + break; + // Sent when "No Style" is chosen. + case "PageStyle:Disable": + if (this.browsingContext.top == this.browsingContext) { + this.browsingContext.authorStyleDisabledDefault = true; + } + this.docShell.contentViewer.authorStyleDisabled = true; + break; + } + } + + /** + * Returns links that would represent stylesheets once loaded. + */ + _collectLinks(document) { + let result = []; + for (let link of document.querySelectorAll("link")) { + if (link.namespaceURI !== "http://www.w3.org/1999/xhtml") { + continue; + } + let isStyleSheet = Array.from(link.relList).some( + r => r.toLowerCase() == "stylesheet" + ); + if (!isStyleSheet) { + continue; + } + if (!link.href) { + continue; + } + result.push(link); + } + return result; + } + + /** + * Switch the stylesheet so that only the sheet with the given title is enabled. + */ + _switchStylesheet(title) { + let document = this.document; + let docStyleSheets = Array.from(document.styleSheets); + let links; + + // Does this doc contain a stylesheet with this title? + // If not, it's a subframe's stylesheet that's being changed, + // so no need to disable stylesheets here. + let docContainsStyleSheet = !title; + if (title) { + links = this._collectLinks(document); + docContainsStyleSheet = + docStyleSheets.some(sheet => sheet.title == title) || + links.some(link => link.title == title); + } + + for (let sheet of docStyleSheets) { + if (sheet.title) { + if (docContainsStyleSheet) { + sheet.disabled = sheet.title !== title; + } + } else if (sheet.disabled) { + sheet.disabled = false; + } + } + + // If there's no title, we just need to disable potentially-enabled + // stylesheets via document.styleSheets, so no need to deal with links + // there. + // + // We don't want to enable <link rel="stylesheet" disabled> without title + // that were not enabled before. + if (title) { + for (let link of links) { + if (link.title == title && link.disabled) { + link.disabled = false; + } + } + } + } + + /** + * Get the stylesheets that have a title (and thus can be switched) in this + * webpage. + * + * @param content The window object for the page. + */ + _collectStyleSheets(content) { + let result = []; + let document = content.document; + + for (let sheet of document.styleSheets) { + let title = sheet.title; + if (!title) { + // Sheets without a title are not alternates. + continue; + } + + // Skip any stylesheets that don't match the screen media type. + let media = sheet.media.mediaText; + if (media && !content.matchMedia(media).matches) { + continue; + } + + // We skip links here, see below. + if ( + sheet.href && + sheet.ownerNode && + sheet.ownerNode.nodeName.toLowerCase() == "link" + ) { + continue; + } + + let disabled = sheet.disabled; + result.push({ title, disabled }); + } + + // This is tricky, because we can't just rely on document.styleSheets, as + // `<link disabled>` makes the sheet don't appear there at all. + for (let link of this._collectLinks(document)) { + let title = link.title; + if (!title) { + continue; + } + + let media = link.media; + if (media && !content.matchMedia(media).matches) { + continue; + } + + let disabled = + link.disabled || + !!link.sheet?.disabled || + document.preferredStyleSheetSet != title; + result.push({ title, disabled }); + } + + return result; + } +} |