Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* Any copyright is dedicated to the Public Domain.
2 * http://creativecommons.org/publicdomain/zero/1.0/ */
4 "use strict";
6 const INITIAL_VALUE = "browser_broadcast.js-initial-value-" + Date.now();
8 /**
9 * This test ensures we won't lose tab data queued in the content script when
10 * closing a tab.
11 */
12 add_task(function flush_on_tabclose() {
13 let tab = yield createTabWithStorageData(["http://example.com"]);
14 let browser = tab.linkedBrowser;
16 yield modifySessionStorage(browser, {test: "on-tab-close"});
17 gBrowser.removeTab(tab);
19 let [{state: {storage}}] = JSON.parse(ss.getClosedTabData(window));
20 is(storage["http://example.com"].test, "on-tab-close",
21 "sessionStorage data has been flushed on TabClose");
22 });
24 /**
25 * This test ensures we won't lose tab data queued in the content script when
26 * the application tries to quit.
27 */
28 add_task(function flush_on_quit_requested() {
29 let tab = yield createTabWithStorageData(["http://example.com"]);
30 let browser = tab.linkedBrowser;
32 yield modifySessionStorage(browser, {test: "on-quit-requested"});
34 // Note that sending quit-application-requested should not interfere with
35 // other tests and code. We're just notifying about a shutdown request but
36 // we will not send quit-application-granted. Observers will thus assume
37 // that some other observer has canceled the request.
38 sendQuitApplicationRequested();
40 let {storage} = JSON.parse(ss.getTabState(tab));
41 is(storage["http://example.com"].test, "on-quit-requested",
42 "sessionStorage data has been flushed when a quit is requested");
44 gBrowser.removeTab(tab);
45 });
47 /**
48 * This test ensures we won't lose tab data queued in the content script when
49 * duplicating a tab.
50 */
51 add_task(function flush_on_duplicate() {
52 let tab = yield createTabWithStorageData(["http://example.com"]);
53 let browser = tab.linkedBrowser;
55 yield modifySessionStorage(browser, {test: "on-duplicate"});
56 let tab2 = ss.duplicateTab(window, tab);
57 let {storage} = JSON.parse(ss.getTabState(tab2));
58 is(storage["http://example.com"].test, "on-duplicate",
59 "sessionStorage data has been flushed when duplicating tabs");
61 yield promiseTabRestored(tab2);
62 gBrowser.removeTab(tab2)
63 let [{state: {storage}}] = JSON.parse(ss.getClosedTabData(window));
64 is(storage["http://example.com"].test, "on-duplicate",
65 "sessionStorage data has been flushed when duplicating tabs");
67 gBrowser.removeTab(tab);
68 });
70 /**
71 * This test ensures we won't lose tab data queued in the content script when
72 * a window is closed.
73 */
74 add_task(function flush_on_windowclose() {
75 let win = yield promiseNewWindow();
76 let tab = yield createTabWithStorageData(["http://example.com"], win);
77 let browser = tab.linkedBrowser;
79 yield modifySessionStorage(browser, {test: "on-window-close"});
80 yield closeWindow(win);
82 let [{tabs: [_, {storage}]}] = JSON.parse(ss.getClosedWindowData());
83 is(storage["http://example.com"].test, "on-window-close",
84 "sessionStorage data has been flushed when closing a window");
85 });
87 /**
88 * This test ensures that stale tab data is ignored when reusing a tab
89 * (via e.g. setTabState) and does not overwrite the new data.
90 */
91 add_task(function flush_on_settabstate() {
92 let tab = yield createTabWithStorageData(["http://example.com"]);
93 let browser = tab.linkedBrowser;
95 // Flush to make sure our tab state is up-to-date.
96 SyncHandlers.get(browser).flush();
98 let state = ss.getTabState(tab);
99 yield modifySessionStorage(browser, {test: "on-set-tab-state"});
101 // Flush all data contained in the content script but send it using
102 // asynchronous messages.
103 SyncHandlers.get(browser).flushAsync();
105 ss.setTabState(tab, state);
106 yield promiseTabRestored(tab);
108 let {storage} = JSON.parse(ss.getTabState(tab));
109 is(storage["http://example.com"].test, INITIAL_VALUE,
110 "sessionStorage data has not been overwritten");
112 gBrowser.removeTab(tab);
113 });
115 /**
116 * This test ensures that we won't lose tab data that has been sent
117 * asynchronously just before closing a tab. Flushing must re-send all data
118 * that hasn't been received by chrome, yet.
119 */
120 add_task(function flush_on_tabclose_racy() {
121 let tab = yield createTabWithStorageData(["http://example.com"]);
122 let browser = tab.linkedBrowser;
124 // Flush to make sure we start with an empty queue.
125 SyncHandlers.get(browser).flush();
127 yield modifySessionStorage(browser, {test: "on-tab-close-racy"});
129 // Flush all data contained in the content script but send it using
130 // asynchronous messages.
131 SyncHandlers.get(browser).flushAsync();
132 gBrowser.removeTab(tab);
134 let [{state: {storage}}] = JSON.parse(ss.getClosedTabData(window));
135 is(storage["http://example.com"].test, "on-tab-close-racy",
136 "sessionStorage data has been merged correctly to prevent data loss");
137 });
139 function promiseNewWindow() {
140 let deferred = Promise.defer();
141 whenNewWindowLoaded({private: false}, deferred.resolve);
142 return deferred.promise;
143 }
145 function closeWindow(win) {
146 let deferred = Promise.defer();
147 let outerID = win.QueryInterface(Ci.nsIInterfaceRequestor)
148 .getInterface(Ci.nsIDOMWindowUtils)
149 .outerWindowID;
151 Services.obs.addObserver(function obs(subject, topic) {
152 let id = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
153 if (id == outerID) {
154 Services.obs.removeObserver(obs, topic);
155 deferred.resolve();
156 }
157 }, "outer-window-destroyed", false);
159 win.close();
160 return deferred.promise;
161 }
163 function createTabWithStorageData(urls, win = window) {
164 return Task.spawn(function task() {
165 let tab = win.gBrowser.addTab();
166 let browser = tab.linkedBrowser;
168 for (let url of urls) {
169 browser.loadURI(url);
170 yield promiseBrowserLoaded(browser);
171 yield modifySessionStorage(browser, {test: INITIAL_VALUE});
172 }
174 throw new Task.Result(tab);
175 });
176 }
178 function waitForStorageEvent(browser) {
179 return promiseContentMessage(browser, "ss-test:MozStorageChanged");
180 }
182 function sendQuitApplicationRequested() {
183 let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"]
184 .createInstance(Ci.nsISupportsPRBool);
185 Services.obs.notifyObservers(cancelQuit, "quit-application-requested", null);
186 }
188 function modifySessionStorage(browser, data) {
189 browser.messageManager.sendAsyncMessage("ss-test:modifySessionStorage", data);
190 return waitForStorageEvent(browser);
191 }