|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
|
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 "use strict"; |
|
6 |
|
7 this.EXPORTED_SYMBOLS = ["PageStyle"]; |
|
8 |
|
9 const Ci = Components.interfaces; |
|
10 |
|
11 /** |
|
12 * The external API exported by this module. |
|
13 */ |
|
14 this.PageStyle = Object.freeze({ |
|
15 collect: function (docShell, frameTree) { |
|
16 return PageStyleInternal.collect(docShell, frameTree); |
|
17 }, |
|
18 |
|
19 restore: function (docShell, frameList, pageStyle) { |
|
20 PageStyleInternal.restore(docShell, frameList, pageStyle); |
|
21 }, |
|
22 |
|
23 restoreTree: function (docShell, data) { |
|
24 PageStyleInternal.restoreTree(docShell, data); |
|
25 } |
|
26 }); |
|
27 |
|
28 // Signifies that author style level is disabled for the page. |
|
29 const NO_STYLE = "_nostyle"; |
|
30 |
|
31 let PageStyleInternal = { |
|
32 /** |
|
33 * Collects the selected style sheet sets for all reachable frames. |
|
34 */ |
|
35 collect: function (docShell, frameTree) { |
|
36 let result = frameTree.map(({document: doc}) => { |
|
37 let style; |
|
38 |
|
39 if (doc) { |
|
40 // http://dev.w3.org/csswg/cssom/#persisting-the-selected-css-style-sheet-set |
|
41 style = doc.selectedStyleSheetSet || doc.lastStyleSheetSet; |
|
42 } |
|
43 |
|
44 return style ? {pageStyle: style} : null; |
|
45 }); |
|
46 |
|
47 let markupDocumentViewer = |
|
48 docShell.contentViewer.QueryInterface(Ci.nsIMarkupDocumentViewer); |
|
49 |
|
50 if (markupDocumentViewer.authorStyleDisabled) { |
|
51 result = result || {}; |
|
52 result.disabled = true; |
|
53 } |
|
54 |
|
55 return result && Object.keys(result).length ? result : null; |
|
56 }, |
|
57 |
|
58 /** |
|
59 * Restore the selected style sheet of all the frames in frameList |
|
60 * to match |pageStyle|. |
|
61 * @param docShell the root docshell of all the frames |
|
62 * @param frameList a list of [frame, data] pairs, where frame is a |
|
63 * DOM window and data is the session restore data associated with |
|
64 * it. |
|
65 * @param pageStyle the title of the style sheet to apply |
|
66 */ |
|
67 restore: function (docShell, frameList, pageStyle) { |
|
68 let disabled = pageStyle == NO_STYLE; |
|
69 |
|
70 let markupDocumentViewer = |
|
71 docShell.contentViewer.QueryInterface(Ci.nsIMarkupDocumentViewer); |
|
72 markupDocumentViewer.authorStyleDisabled = disabled; |
|
73 |
|
74 for (let [frame, data] of frameList) { |
|
75 Array.forEach(frame.document.styleSheets, function(aSS) { |
|
76 aSS.disabled = aSS.title && aSS.title != pageStyle; |
|
77 }); |
|
78 } |
|
79 }, |
|
80 |
|
81 /** |
|
82 * Restores pageStyle data for the current frame hierarchy starting at the |
|
83 * |docShell's| current DOMWindow using the given pageStyle |data|. |
|
84 * |
|
85 * Warning: If the current frame hierarchy doesn't match that of the given |
|
86 * |data| object we will silently discard data for unreachable frames. We may |
|
87 * as well assign page styles to the wrong frames if some were reordered or |
|
88 * removed. |
|
89 * |
|
90 * @param docShell (nsIDocShell) |
|
91 * @param data (object) |
|
92 * { |
|
93 * disabled: true, // when true, author styles will be disabled |
|
94 * pageStyle: "Dusk", |
|
95 * children: [ |
|
96 * null, |
|
97 * {pageStyle: "Mozilla", children: [ ... ]} |
|
98 * ] |
|
99 * } |
|
100 */ |
|
101 restoreTree: function (docShell, data) { |
|
102 let disabled = data.disabled || false; |
|
103 let markupDocumentViewer = |
|
104 docShell.contentViewer.QueryInterface(Ci.nsIMarkupDocumentViewer); |
|
105 markupDocumentViewer.authorStyleDisabled = disabled; |
|
106 |
|
107 function restoreFrame(root, data) { |
|
108 if (data.hasOwnProperty("pageStyle")) { |
|
109 root.document.selectedStyleSheetSet = data.pageStyle; |
|
110 } |
|
111 |
|
112 if (!data.hasOwnProperty("children")) { |
|
113 return; |
|
114 } |
|
115 |
|
116 let frames = root.frames; |
|
117 data.children.forEach((child, index) => { |
|
118 if (child && index < frames.length) { |
|
119 restoreFrame(frames[index], child); |
|
120 } |
|
121 }); |
|
122 } |
|
123 |
|
124 let ifreq = docShell.QueryInterface(Ci.nsIInterfaceRequestor); |
|
125 restoreFrame(ifreq.getInterface(Ci.nsIDOMWindow), data); |
|
126 } |
|
127 }; |