michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: "use strict"; michael@0: michael@0: this.EXPORTED_SYMBOLS = ["PageStyle"]; michael@0: michael@0: const Ci = Components.interfaces; michael@0: michael@0: /** michael@0: * The external API exported by this module. michael@0: */ michael@0: this.PageStyle = Object.freeze({ michael@0: collect: function (docShell, frameTree) { michael@0: return PageStyleInternal.collect(docShell, frameTree); michael@0: }, michael@0: michael@0: restore: function (docShell, frameList, pageStyle) { michael@0: PageStyleInternal.restore(docShell, frameList, pageStyle); michael@0: }, michael@0: michael@0: restoreTree: function (docShell, data) { michael@0: PageStyleInternal.restoreTree(docShell, data); michael@0: } michael@0: }); michael@0: michael@0: // Signifies that author style level is disabled for the page. michael@0: const NO_STYLE = "_nostyle"; michael@0: michael@0: let PageStyleInternal = { michael@0: /** michael@0: * Collects the selected style sheet sets for all reachable frames. michael@0: */ michael@0: collect: function (docShell, frameTree) { michael@0: let result = frameTree.map(({document: doc}) => { michael@0: let style; michael@0: michael@0: if (doc) { michael@0: // http://dev.w3.org/csswg/cssom/#persisting-the-selected-css-style-sheet-set michael@0: style = doc.selectedStyleSheetSet || doc.lastStyleSheetSet; michael@0: } michael@0: michael@0: return style ? {pageStyle: style} : null; michael@0: }); michael@0: michael@0: let markupDocumentViewer = michael@0: docShell.contentViewer.QueryInterface(Ci.nsIMarkupDocumentViewer); michael@0: michael@0: if (markupDocumentViewer.authorStyleDisabled) { michael@0: result = result || {}; michael@0: result.disabled = true; michael@0: } michael@0: michael@0: return result && Object.keys(result).length ? result : null; michael@0: }, michael@0: michael@0: /** michael@0: * Restore the selected style sheet of all the frames in frameList michael@0: * to match |pageStyle|. michael@0: * @param docShell the root docshell of all the frames michael@0: * @param frameList a list of [frame, data] pairs, where frame is a michael@0: * DOM window and data is the session restore data associated with michael@0: * it. michael@0: * @param pageStyle the title of the style sheet to apply michael@0: */ michael@0: restore: function (docShell, frameList, pageStyle) { michael@0: let disabled = pageStyle == NO_STYLE; michael@0: michael@0: let markupDocumentViewer = michael@0: docShell.contentViewer.QueryInterface(Ci.nsIMarkupDocumentViewer); michael@0: markupDocumentViewer.authorStyleDisabled = disabled; michael@0: michael@0: for (let [frame, data] of frameList) { michael@0: Array.forEach(frame.document.styleSheets, function(aSS) { michael@0: aSS.disabled = aSS.title && aSS.title != pageStyle; michael@0: }); michael@0: } michael@0: }, michael@0: michael@0: /** michael@0: * Restores pageStyle data for the current frame hierarchy starting at the michael@0: * |docShell's| current DOMWindow using the given pageStyle |data|. michael@0: * michael@0: * Warning: If the current frame hierarchy doesn't match that of the given michael@0: * |data| object we will silently discard data for unreachable frames. We may michael@0: * as well assign page styles to the wrong frames if some were reordered or michael@0: * removed. michael@0: * michael@0: * @param docShell (nsIDocShell) michael@0: * @param data (object) michael@0: * { michael@0: * disabled: true, // when true, author styles will be disabled michael@0: * pageStyle: "Dusk", michael@0: * children: [ michael@0: * null, michael@0: * {pageStyle: "Mozilla", children: [ ... ]} michael@0: * ] michael@0: * } michael@0: */ michael@0: restoreTree: function (docShell, data) { michael@0: let disabled = data.disabled || false; michael@0: let markupDocumentViewer = michael@0: docShell.contentViewer.QueryInterface(Ci.nsIMarkupDocumentViewer); michael@0: markupDocumentViewer.authorStyleDisabled = disabled; michael@0: michael@0: function restoreFrame(root, data) { michael@0: if (data.hasOwnProperty("pageStyle")) { michael@0: root.document.selectedStyleSheetSet = data.pageStyle; michael@0: } michael@0: michael@0: if (!data.hasOwnProperty("children")) { michael@0: return; michael@0: } michael@0: michael@0: let frames = root.frames; michael@0: data.children.forEach((child, index) => { michael@0: if (child && index < frames.length) { michael@0: restoreFrame(frames[index], child); michael@0: } michael@0: }); michael@0: } michael@0: michael@0: let ifreq = docShell.QueryInterface(Ci.nsIInterfaceRequestor); michael@0: restoreFrame(ifreq.getInterface(Ci.nsIDOMWindow), data); michael@0: } michael@0: };