|
1 /* Any copyright is dedicated to the Public Domain. |
|
2 * http://creativecommons.org/publicdomain/zero/1.0/ */ |
|
3 |
|
4 "use strict"; |
|
5 |
|
6 const URL = ROOT + "browser_frametree_sample.html"; |
|
7 const URL_FRAMESET = ROOT + "browser_frametree_sample_frameset.html"; |
|
8 |
|
9 /** |
|
10 * This ensures that loading a page normally, aborting a page load, reloading |
|
11 * a page, navigating using the bfcache, and ignoring frames that were |
|
12 * created dynamically work as expect. We expect the frame tree to be reset |
|
13 * when a page starts loading and we also expect a valid frame tree to exist |
|
14 * when it has stopped loading. |
|
15 */ |
|
16 add_task(function test_frametree() { |
|
17 const FRAME_TREE_SINGLE = { href: URL }; |
|
18 const FRAME_TREE_FRAMESET = { |
|
19 href: URL_FRAMESET, |
|
20 children: [{href: URL}, {href: URL}, {href: URL}] |
|
21 }; |
|
22 |
|
23 // Create a tab with a single frame. |
|
24 let tab = gBrowser.addTab(URL); |
|
25 let browser = tab.linkedBrowser; |
|
26 yield promiseNewFrameTree(browser); |
|
27 yield checkFrameTree(browser, FRAME_TREE_SINGLE, |
|
28 "loading a page resets and creates the frame tree correctly"); |
|
29 |
|
30 // Load the frameset and create two frames dynamically, the first on |
|
31 // DOMContentLoaded and the second on load. |
|
32 yield sendMessage(browser, "ss-test:createDynamicFrames", {id: "frames", url: URL}); |
|
33 browser.loadURI(URL_FRAMESET); |
|
34 yield promiseNewFrameTree(browser); |
|
35 yield checkFrameTree(browser, FRAME_TREE_FRAMESET, |
|
36 "dynamic frames created on or after the load event are ignored"); |
|
37 |
|
38 // Go back to the previous single-frame page. There will be no load event as |
|
39 // the page is still in the bfcache. We thus make sure this type of navigation |
|
40 // resets the frame tree. |
|
41 browser.goBack(); |
|
42 yield promiseNewFrameTree(browser); |
|
43 yield checkFrameTree(browser, FRAME_TREE_SINGLE, |
|
44 "loading from bfache resets and creates the frame tree correctly"); |
|
45 |
|
46 // Load the frameset again but abort the load early. |
|
47 // The frame tree should still be reset and created. |
|
48 browser.loadURI(URL_FRAMESET); |
|
49 executeSoon(() => browser.stop()); |
|
50 yield promiseNewFrameTree(browser); |
|
51 |
|
52 // Load the frameset and check the tree again. |
|
53 yield sendMessage(browser, "ss-test:createDynamicFrames", {id: "frames", url: URL}); |
|
54 browser.loadURI(URL_FRAMESET); |
|
55 yield promiseNewFrameTree(browser); |
|
56 yield checkFrameTree(browser, FRAME_TREE_FRAMESET, |
|
57 "reloading a page resets and creates the frame tree correctly"); |
|
58 |
|
59 // Cleanup. |
|
60 gBrowser.removeTab(tab); |
|
61 }); |
|
62 |
|
63 /** |
|
64 * This test ensures that we ignore frames that were created dynamically at or |
|
65 * after the load event. SessionStore can't handle these and will not restore |
|
66 * or collect any data for them. |
|
67 */ |
|
68 add_task(function test_frametree_dynamic() { |
|
69 // The frame tree as expected. The first two frames are static |
|
70 // and the third one was created on DOMContentLoaded. |
|
71 const FRAME_TREE = { |
|
72 href: URL_FRAMESET, |
|
73 children: [{href: URL}, {href: URL}, {href: URL}] |
|
74 }; |
|
75 const FRAME_TREE_REMOVED = { |
|
76 href: URL_FRAMESET, |
|
77 children: [{href: URL}, {href: URL}] |
|
78 }; |
|
79 |
|
80 // Add an empty tab for a start. |
|
81 let tab = gBrowser.addTab("about:blank"); |
|
82 let browser = tab.linkedBrowser; |
|
83 yield promiseBrowserLoaded(browser); |
|
84 |
|
85 // Create dynamic frames on "DOMContentLoaded" and on "load". |
|
86 yield sendMessage(browser, "ss-test:createDynamicFrames", {id: "frames", url: URL}); |
|
87 browser.loadURI(URL_FRAMESET); |
|
88 yield promiseNewFrameTree(browser); |
|
89 |
|
90 // Check that the frame tree does not contain the frame created on "load". |
|
91 // The two static frames and the one created on DOMContentLoaded must be in |
|
92 // the tree. |
|
93 yield checkFrameTree(browser, FRAME_TREE, |
|
94 "frame tree contains first four frames"); |
|
95 |
|
96 // Remove the last frame in the frameset. |
|
97 yield sendMessage(browser, "ss-test:removeLastFrame", {id: "frames"}); |
|
98 // Check that the frame tree didn't change. |
|
99 yield checkFrameTree(browser, FRAME_TREE, |
|
100 "frame tree contains first four frames"); |
|
101 |
|
102 // Remove the last frame in the frameset. |
|
103 yield sendMessage(browser, "ss-test:removeLastFrame", {id: "frames"}); |
|
104 // Check that the frame tree excludes the removed frame. |
|
105 yield checkFrameTree(browser, FRAME_TREE_REMOVED, |
|
106 "frame tree contains first three frames"); |
|
107 |
|
108 // Cleanup. |
|
109 gBrowser.removeTab(tab); |
|
110 }); |
|
111 |
|
112 /** |
|
113 * Checks whether the current frame hierarchy of a given |browser| matches the |
|
114 * |expected| frame hierarchy. |
|
115 */ |
|
116 function checkFrameTree(browser, expected, msg) { |
|
117 return sendMessage(browser, "ss-test:mapFrameTree").then(tree => { |
|
118 is(JSON.stringify(tree), JSON.stringify(expected), msg); |
|
119 }); |
|
120 } |
|
121 |
|
122 /** |
|
123 * Returns a promise that will be resolved when the given |browser| has loaded |
|
124 * and we received messages saying that its frame tree has been reset and |
|
125 * recollected. |
|
126 */ |
|
127 function promiseNewFrameTree(browser) { |
|
128 let reset = promiseContentMessage(browser, "ss-test:onFrameTreeCollected"); |
|
129 let collect = promiseContentMessage(browser, "ss-test:onFrameTreeCollected"); |
|
130 return Promise.all([reset, collect]); |
|
131 } |