|
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 = ["ScrollPosition"]; |
|
8 |
|
9 const Ci = Components.interfaces; |
|
10 |
|
11 /** |
|
12 * It provides methods to collect and restore scroll positions for single |
|
13 * frames and frame trees. |
|
14 * |
|
15 * This is a child process module. |
|
16 */ |
|
17 this.ScrollPosition = Object.freeze({ |
|
18 /** |
|
19 * Collects scroll position data for any given |frame| in the frame hierarchy. |
|
20 * |
|
21 * @param frame (DOMWindow) |
|
22 * |
|
23 * @return {scroll: "x,y"} e.g. {scroll: "100,200"} |
|
24 * Returns null when there is no scroll data we want to store for the |
|
25 * given |frame|. |
|
26 */ |
|
27 collect: function (frame) { |
|
28 let ifreq = frame.QueryInterface(Ci.nsIInterfaceRequestor); |
|
29 let utils = ifreq.getInterface(Ci.nsIDOMWindowUtils); |
|
30 let scrollX = {}, scrollY = {}; |
|
31 utils.getScrollXY(false /* no layout flush */, scrollX, scrollY); |
|
32 |
|
33 if (scrollX.value || scrollY.value) { |
|
34 return {scroll: scrollX.value + "," + scrollY.value}; |
|
35 } |
|
36 |
|
37 return null; |
|
38 }, |
|
39 |
|
40 /** |
|
41 * Restores scroll position data for any given |frame| in the frame hierarchy. |
|
42 * |
|
43 * @param frame (DOMWindow) |
|
44 * @param value (object, see collect()) |
|
45 */ |
|
46 restore: function (frame, value) { |
|
47 let match; |
|
48 |
|
49 if (value && (match = /(\d+),(\d+)/.exec(value))) { |
|
50 frame.scrollTo(match[1], match[2]); |
|
51 } |
|
52 }, |
|
53 |
|
54 /** |
|
55 * Restores scroll position data for the current frame hierarchy starting at |
|
56 * |root| using the given scroll position |data|. |
|
57 * |
|
58 * If the given |root| frame's hierarchy doesn't match that of the given |
|
59 * |data| object we will silently discard data for unreachable frames. We |
|
60 * may as well assign scroll positions to the wrong frames if some were |
|
61 * reordered or removed. |
|
62 * |
|
63 * @param root (DOMWindow) |
|
64 * @param data (object) |
|
65 * { |
|
66 * scroll: "100,200", |
|
67 * children: [ |
|
68 * {scroll: "100,200"}, |
|
69 * null, |
|
70 * {scroll: "200,300", children: [ ... ]} |
|
71 * ] |
|
72 * } |
|
73 */ |
|
74 restoreTree: function (root, data) { |
|
75 if (data.hasOwnProperty("scroll")) { |
|
76 this.restore(root, data.scroll); |
|
77 } |
|
78 |
|
79 if (!data.hasOwnProperty("children")) { |
|
80 return; |
|
81 } |
|
82 |
|
83 let frames = root.frames; |
|
84 data.children.forEach((child, index) => { |
|
85 if (child && index < frames.length) { |
|
86 this.restoreTree(frames[index], child); |
|
87 } |
|
88 }); |
|
89 } |
|
90 }); |