1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/browser/components/sessionstore/src/PageStyle.jsm Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,127 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 +* License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.6 +* You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +"use strict"; 1.9 + 1.10 +this.EXPORTED_SYMBOLS = ["PageStyle"]; 1.11 + 1.12 +const Ci = Components.interfaces; 1.13 + 1.14 +/** 1.15 + * The external API exported by this module. 1.16 + */ 1.17 +this.PageStyle = Object.freeze({ 1.18 + collect: function (docShell, frameTree) { 1.19 + return PageStyleInternal.collect(docShell, frameTree); 1.20 + }, 1.21 + 1.22 + restore: function (docShell, frameList, pageStyle) { 1.23 + PageStyleInternal.restore(docShell, frameList, pageStyle); 1.24 + }, 1.25 + 1.26 + restoreTree: function (docShell, data) { 1.27 + PageStyleInternal.restoreTree(docShell, data); 1.28 + } 1.29 +}); 1.30 + 1.31 +// Signifies that author style level is disabled for the page. 1.32 +const NO_STYLE = "_nostyle"; 1.33 + 1.34 +let PageStyleInternal = { 1.35 + /** 1.36 + * Collects the selected style sheet sets for all reachable frames. 1.37 + */ 1.38 + collect: function (docShell, frameTree) { 1.39 + let result = frameTree.map(({document: doc}) => { 1.40 + let style; 1.41 + 1.42 + if (doc) { 1.43 + // http://dev.w3.org/csswg/cssom/#persisting-the-selected-css-style-sheet-set 1.44 + style = doc.selectedStyleSheetSet || doc.lastStyleSheetSet; 1.45 + } 1.46 + 1.47 + return style ? {pageStyle: style} : null; 1.48 + }); 1.49 + 1.50 + let markupDocumentViewer = 1.51 + docShell.contentViewer.QueryInterface(Ci.nsIMarkupDocumentViewer); 1.52 + 1.53 + if (markupDocumentViewer.authorStyleDisabled) { 1.54 + result = result || {}; 1.55 + result.disabled = true; 1.56 + } 1.57 + 1.58 + return result && Object.keys(result).length ? result : null; 1.59 + }, 1.60 + 1.61 + /** 1.62 + * Restore the selected style sheet of all the frames in frameList 1.63 + * to match |pageStyle|. 1.64 + * @param docShell the root docshell of all the frames 1.65 + * @param frameList a list of [frame, data] pairs, where frame is a 1.66 + * DOM window and data is the session restore data associated with 1.67 + * it. 1.68 + * @param pageStyle the title of the style sheet to apply 1.69 + */ 1.70 + restore: function (docShell, frameList, pageStyle) { 1.71 + let disabled = pageStyle == NO_STYLE; 1.72 + 1.73 + let markupDocumentViewer = 1.74 + docShell.contentViewer.QueryInterface(Ci.nsIMarkupDocumentViewer); 1.75 + markupDocumentViewer.authorStyleDisabled = disabled; 1.76 + 1.77 + for (let [frame, data] of frameList) { 1.78 + Array.forEach(frame.document.styleSheets, function(aSS) { 1.79 + aSS.disabled = aSS.title && aSS.title != pageStyle; 1.80 + }); 1.81 + } 1.82 + }, 1.83 + 1.84 + /** 1.85 + * Restores pageStyle data for the current frame hierarchy starting at the 1.86 + * |docShell's| current DOMWindow using the given pageStyle |data|. 1.87 + * 1.88 + * Warning: If the current frame hierarchy doesn't match that of the given 1.89 + * |data| object we will silently discard data for unreachable frames. We may 1.90 + * as well assign page styles to the wrong frames if some were reordered or 1.91 + * removed. 1.92 + * 1.93 + * @param docShell (nsIDocShell) 1.94 + * @param data (object) 1.95 + * { 1.96 + * disabled: true, // when true, author styles will be disabled 1.97 + * pageStyle: "Dusk", 1.98 + * children: [ 1.99 + * null, 1.100 + * {pageStyle: "Mozilla", children: [ ... ]} 1.101 + * ] 1.102 + * } 1.103 + */ 1.104 + restoreTree: function (docShell, data) { 1.105 + let disabled = data.disabled || false; 1.106 + let markupDocumentViewer = 1.107 + docShell.contentViewer.QueryInterface(Ci.nsIMarkupDocumentViewer); 1.108 + markupDocumentViewer.authorStyleDisabled = disabled; 1.109 + 1.110 + function restoreFrame(root, data) { 1.111 + if (data.hasOwnProperty("pageStyle")) { 1.112 + root.document.selectedStyleSheetSet = data.pageStyle; 1.113 + } 1.114 + 1.115 + if (!data.hasOwnProperty("children")) { 1.116 + return; 1.117 + } 1.118 + 1.119 + let frames = root.frames; 1.120 + data.children.forEach((child, index) => { 1.121 + if (child && index < frames.length) { 1.122 + restoreFrame(frames[index], child); 1.123 + } 1.124 + }); 1.125 + } 1.126 + 1.127 + let ifreq = docShell.QueryInterface(Ci.nsIInterfaceRequestor); 1.128 + restoreFrame(ifreq.getInterface(Ci.nsIDOMWindow), data); 1.129 + } 1.130 +};