1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/browser/components/sessionstore/test/browser_615394-SSWindowState_events.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,365 @@ 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 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +const stateBackup = JSON.parse(ss.getBrowserState()); 1.9 +const testState = { 1.10 + windows: [{ 1.11 + tabs: [ 1.12 + { entries: [{ url: "about:blank" }] }, 1.13 + { entries: [{ url: "about:rights" }] } 1.14 + ] 1.15 + }] 1.16 +}; 1.17 +const lameMultiWindowState = { windows: [ 1.18 + { 1.19 + tabs: [ 1.20 + { entries: [{ url: "http://example.org#1" }], extData: { "uniq": r() } }, 1.21 + { entries: [{ url: "http://example.org#2" }], extData: { "uniq": r() } }, 1.22 + { entries: [{ url: "http://example.org#3" }], extData: { "uniq": r() } }, 1.23 + { entries: [{ url: "http://example.org#4" }], extData: { "uniq": r() } } 1.24 + ], 1.25 + selected: 1 1.26 + }, 1.27 + { 1.28 + tabs: [ 1.29 + { entries: [{ url: "http://example.com#1" }], extData: { "uniq": r() } }, 1.30 + { entries: [{ url: "http://example.com#2" }], extData: { "uniq": r() } }, 1.31 + { entries: [{ url: "http://example.com#3" }], extData: { "uniq": r() } }, 1.32 + { entries: [{ url: "http://example.com#4" }], extData: { "uniq": r() } }, 1.33 + ], 1.34 + selected: 3 1.35 + } 1.36 + ] }; 1.37 + 1.38 + 1.39 +function getOuterWindowID(aWindow) { 1.40 + return aWindow.QueryInterface(Ci.nsIInterfaceRequestor). 1.41 + getInterface(Ci.nsIDOMWindowUtils).outerWindowID; 1.42 +} 1.43 + 1.44 +function test() { 1.45 + /** Test for Bug 615394 - Session Restore should notify when it is beginning and ending a restore **/ 1.46 + waitForExplicitFinish(); 1.47 + // Preemptively extend the timeout to prevent [orange] 1.48 + requestLongerTimeout(2); 1.49 + runNextTest(); 1.50 +} 1.51 + 1.52 + 1.53 +let tests = [ 1.54 + test_setTabState, 1.55 + test_duplicateTab, 1.56 + test_undoCloseTab, 1.57 + test_setWindowState, 1.58 + test_setBrowserState, 1.59 + test_undoCloseWindow 1.60 +]; 1.61 +function runNextTest() { 1.62 + // set an empty state & run the next test, or finish 1.63 + if (tests.length) { 1.64 + // Enumerate windows and close everything but our primary window. We can't 1.65 + // use waitForFocus() because apparently it's buggy. See bug 599253. 1.66 + var windowsEnum = Services.wm.getEnumerator("navigator:browser"); 1.67 + while (windowsEnum.hasMoreElements()) { 1.68 + var currentWindow = windowsEnum.getNext(); 1.69 + if (currentWindow != window) { 1.70 + currentWindow.close(); 1.71 + } 1.72 + } 1.73 + 1.74 + // If we closed a window, give it time to close 1.75 + executeSoon(function() { 1.76 + let currentTest = tests.shift(); 1.77 + info("prepping for " + currentTest.name); 1.78 + waitForBrowserState(testState, currentTest); 1.79 + }); 1.80 + } 1.81 + else { 1.82 + waitForBrowserState(stateBackup, finish); 1.83 + } 1.84 +} 1.85 + 1.86 +/** ACTUAL TESTS **/ 1.87 + 1.88 +function test_setTabState() { 1.89 + let tab = gBrowser.tabs[1]; 1.90 + let newTabState = JSON.stringify({ entries: [{ url: "http://example.org" }], extData: { foo: "bar" } }); 1.91 + let busyEventCount = 0; 1.92 + let readyEventCount = 0; 1.93 + 1.94 + function onSSWindowStateBusy(aEvent) { 1.95 + busyEventCount++; 1.96 + } 1.97 + 1.98 + function onSSWindowStateReady(aEvent) { 1.99 + readyEventCount++; 1.100 + is(ss.getTabValue(tab, "foo"), "bar"); 1.101 + ss.setTabValue(tab, "baz", "qux"); 1.102 + } 1.103 + 1.104 + function onSSTabRestored(aEvent) { 1.105 + is(busyEventCount, 1); 1.106 + is(readyEventCount, 1); 1.107 + is(ss.getTabValue(tab, "baz"), "qux"); 1.108 + is(tab.linkedBrowser.currentURI.spec, "http://example.org/"); 1.109 + 1.110 + window.removeEventListener("SSWindowStateBusy", onSSWindowStateBusy, false); 1.111 + window.removeEventListener("SSWindowStateReady", onSSWindowStateReady, false); 1.112 + gBrowser.tabContainer.removeEventListener("SSTabRestored", onSSTabRestored, false); 1.113 + 1.114 + runNextTest(); 1.115 + } 1.116 + 1.117 + window.addEventListener("SSWindowStateBusy", onSSWindowStateBusy, false); 1.118 + window.addEventListener("SSWindowStateReady", onSSWindowStateReady, false); 1.119 + gBrowser.tabContainer.addEventListener("SSTabRestored", onSSTabRestored, false); 1.120 + ss.setTabState(tab, newTabState); 1.121 +} 1.122 + 1.123 + 1.124 +function test_duplicateTab() { 1.125 + let tab = gBrowser.tabs[1]; 1.126 + let busyEventCount = 0; 1.127 + let readyEventCount = 0; 1.128 + let newTab; 1.129 + 1.130 + // We'll look to make sure this value is on the duplicated tab 1.131 + ss.setTabValue(tab, "foo", "bar"); 1.132 + 1.133 + function onSSWindowStateBusy(aEvent) { 1.134 + busyEventCount++; 1.135 + } 1.136 + 1.137 + function onSSWindowStateReady(aEvent) { 1.138 + newTab = gBrowser.tabs[2]; 1.139 + readyEventCount++; 1.140 + is(ss.getTabValue(newTab, "foo"), "bar"); 1.141 + ss.setTabValue(newTab, "baz", "qux"); 1.142 + } 1.143 + 1.144 + function onSSTabRestored(aEvent) { 1.145 + is(busyEventCount, 1); 1.146 + is(readyEventCount, 1); 1.147 + is(ss.getTabValue(newTab, "baz"), "qux"); 1.148 + is(newTab.linkedBrowser.currentURI.spec, "about:rights"); 1.149 + 1.150 + window.removeEventListener("SSWindowStateBusy", onSSWindowStateBusy, false); 1.151 + window.removeEventListener("SSWindowStateReady", onSSWindowStateReady, false); 1.152 + gBrowser.tabContainer.removeEventListener("SSTabRestored", onSSTabRestored, false); 1.153 + 1.154 + runNextTest(); 1.155 + } 1.156 + 1.157 + window.addEventListener("SSWindowStateBusy", onSSWindowStateBusy, false); 1.158 + window.addEventListener("SSWindowStateReady", onSSWindowStateReady, false); 1.159 + gBrowser.tabContainer.addEventListener("SSTabRestored", onSSTabRestored, false); 1.160 + 1.161 + newTab = ss.duplicateTab(window, tab); 1.162 +} 1.163 + 1.164 + 1.165 +function test_undoCloseTab() { 1.166 + let tab = gBrowser.tabs[1], 1.167 + busyEventCount = 0, 1.168 + readyEventCount = 0, 1.169 + reopenedTab; 1.170 + 1.171 + ss.setTabValue(tab, "foo", "bar"); 1.172 + 1.173 + function onSSWindowStateBusy(aEvent) { 1.174 + busyEventCount++; 1.175 + } 1.176 + 1.177 + function onSSWindowStateReady(aEvent) { 1.178 + reopenedTab = gBrowser.tabs[1]; 1.179 + readyEventCount++; 1.180 + is(ss.getTabValue(reopenedTab, "foo"), "bar"); 1.181 + ss.setTabValue(reopenedTab, "baz", "qux"); 1.182 + } 1.183 + 1.184 + function onSSTabRestored(aEvent) { 1.185 + is(busyEventCount, 1); 1.186 + is(readyEventCount, 1); 1.187 + is(ss.getTabValue(reopenedTab, "baz"), "qux"); 1.188 + is(reopenedTab.linkedBrowser.currentURI.spec, "about:rights"); 1.189 + 1.190 + window.removeEventListener("SSWindowStateBusy", onSSWindowStateBusy, false); 1.191 + window.removeEventListener("SSWindowStateReady", onSSWindowStateReady, false); 1.192 + gBrowser.tabContainer.removeEventListener("SSTabRestored", onSSTabRestored, false); 1.193 + 1.194 + runNextTest(); 1.195 + } 1.196 + 1.197 + window.addEventListener("SSWindowStateBusy", onSSWindowStateBusy, false); 1.198 + window.addEventListener("SSWindowStateReady", onSSWindowStateReady, false); 1.199 + gBrowser.tabContainer.addEventListener("SSTabRestored", onSSTabRestored, false); 1.200 + 1.201 + gBrowser.removeTab(tab); 1.202 + reopenedTab = ss.undoCloseTab(window, 0); 1.203 +} 1.204 + 1.205 + 1.206 +function test_setWindowState() { 1.207 + let testState = { 1.208 + windows: [{ 1.209 + tabs: [ 1.210 + { entries: [{ url: "about:mozilla" }], extData: { "foo": "bar" } }, 1.211 + { entries: [{ url: "http://example.org" }], extData: { "baz": "qux" } } 1.212 + ] 1.213 + }] 1.214 + }; 1.215 + 1.216 + let busyEventCount = 0, 1.217 + readyEventCount = 0, 1.218 + tabRestoredCount = 0; 1.219 + 1.220 + function onSSWindowStateBusy(aEvent) { 1.221 + busyEventCount++; 1.222 + } 1.223 + 1.224 + function onSSWindowStateReady(aEvent) { 1.225 + readyEventCount++; 1.226 + is(ss.getTabValue(gBrowser.tabs[0], "foo"), "bar"); 1.227 + is(ss.getTabValue(gBrowser.tabs[1], "baz"), "qux"); 1.228 + } 1.229 + 1.230 + function onSSTabRestored(aEvent) { 1.231 + if (++tabRestoredCount < 2) 1.232 + return; 1.233 + 1.234 + is(busyEventCount, 1); 1.235 + is(readyEventCount, 1); 1.236 + is(gBrowser.tabs[0].linkedBrowser.currentURI.spec, "about:mozilla"); 1.237 + is(gBrowser.tabs[1].linkedBrowser.currentURI.spec, "http://example.org/"); 1.238 + 1.239 + window.removeEventListener("SSWindowStateBusy", onSSWindowStateBusy, false); 1.240 + window.removeEventListener("SSWindowStateReady", onSSWindowStateReady, false); 1.241 + gBrowser.tabContainer.removeEventListener("SSTabRestored", onSSTabRestored, false); 1.242 + 1.243 + runNextTest(); 1.244 + } 1.245 + 1.246 + window.addEventListener("SSWindowStateBusy", onSSWindowStateBusy, false); 1.247 + window.addEventListener("SSWindowStateReady", onSSWindowStateReady, false); 1.248 + gBrowser.tabContainer.addEventListener("SSTabRestored", onSSTabRestored, false); 1.249 + 1.250 + ss.setWindowState(window, JSON.stringify(testState), true); 1.251 +} 1.252 + 1.253 + 1.254 +function test_setBrowserState() { 1.255 + // We'll track events per window so we are sure that they are each happening once 1.256 + // pre window. 1.257 + let windowEvents = {}; 1.258 + windowEvents[getOuterWindowID(window)] = { busyEventCount: 0, readyEventCount: 0 }; 1.259 + 1.260 + // waitForBrowserState does it's own observing for windows, but doesn't attach 1.261 + // the listeners we want here, so do it ourselves. 1.262 + let newWindow; 1.263 + function windowObserver(aSubject, aTopic, aData) { 1.264 + if (aTopic == "domwindowopened") { 1.265 + newWindow = aSubject.QueryInterface(Ci.nsIDOMWindow); 1.266 + newWindow.addEventListener("load", function() { 1.267 + newWindow.removeEventListener("load", arguments.callee, false); 1.268 + 1.269 + Services.ww.unregisterNotification(windowObserver); 1.270 + 1.271 + windowEvents[getOuterWindowID(newWindow)] = { busyEventCount: 0, readyEventCount: 0 }; 1.272 + 1.273 + newWindow.addEventListener("SSWindowStateBusy", onSSWindowStateBusy, false); 1.274 + newWindow.addEventListener("SSWindowStateReady", onSSWindowStateReady, false); 1.275 + }, false); 1.276 + } 1.277 + } 1.278 + 1.279 + function onSSWindowStateBusy(aEvent) { 1.280 + windowEvents[getOuterWindowID(aEvent.originalTarget)].busyEventCount++; 1.281 + } 1.282 + 1.283 + function onSSWindowStateReady(aEvent) { 1.284 + windowEvents[getOuterWindowID(aEvent.originalTarget)].readyEventCount++; 1.285 + } 1.286 + 1.287 + window.addEventListener("SSWindowStateBusy", onSSWindowStateBusy, false); 1.288 + window.addEventListener("SSWindowStateReady", onSSWindowStateReady, false); 1.289 + Services.ww.registerNotification(windowObserver); 1.290 + 1.291 + waitForBrowserState(lameMultiWindowState, function() { 1.292 + let checkedWindows = 0; 1.293 + for (let id of Object.keys(windowEvents)) { 1.294 + let winEvents = windowEvents[id]; 1.295 + is(winEvents.busyEventCount, 1, 1.296 + "[test_setBrowserState] window" + id + " busy event count correct"); 1.297 + is(winEvents.readyEventCount, 1, 1.298 + "[test_setBrowserState] window" + id + " ready event count correct"); 1.299 + checkedWindows++; 1.300 + } 1.301 + is(checkedWindows, 2, 1.302 + "[test_setBrowserState] checked 2 windows"); 1.303 + window.removeEventListener("SSWindowStateBusy", onSSWindowStateBusy, false); 1.304 + window.removeEventListener("SSWindowStateReady", onSSWindowStateReady, false); 1.305 + newWindow.removeEventListener("SSWindowStateBusy", onSSWindowStateBusy, false); 1.306 + newWindow.removeEventListener("SSWindowStateReady", onSSWindowStateReady, false); 1.307 + runNextTest(); 1.308 + }); 1.309 +} 1.310 + 1.311 + 1.312 +function test_undoCloseWindow() { 1.313 + let newWindow, reopenedWindow; 1.314 + 1.315 + function firstWindowObserver(aSubject, aTopic, aData) { 1.316 + if (aTopic == "domwindowopened") { 1.317 + newWindow = aSubject.QueryInterface(Ci.nsIDOMWindow); 1.318 + Services.ww.unregisterNotification(firstWindowObserver); 1.319 + } 1.320 + } 1.321 + Services.ww.registerNotification(firstWindowObserver); 1.322 + 1.323 + waitForBrowserState(lameMultiWindowState, function() { 1.324 + // Close the window which isn't window 1.325 + newWindow.close(); 1.326 + // Now give it time to close 1.327 + executeSoon(function() { 1.328 + reopenedWindow = ss.undoCloseWindow(0); 1.329 + reopenedWindow.addEventListener("SSWindowStateBusy", onSSWindowStateBusy, false); 1.330 + reopenedWindow.addEventListener("SSWindowStateReady", onSSWindowStateReady, false); 1.331 + 1.332 + reopenedWindow.addEventListener("load", function() { 1.333 + reopenedWindow.removeEventListener("load", arguments.callee, false); 1.334 + 1.335 + reopenedWindow.gBrowser.tabContainer.addEventListener("SSTabRestored", onSSTabRestored, false); 1.336 + }, false); 1.337 + }); 1.338 + }); 1.339 + 1.340 + let busyEventCount = 0, 1.341 + readyEventCount = 0, 1.342 + tabRestoredCount = 0; 1.343 + // These will listen to the reopened closed window... 1.344 + function onSSWindowStateBusy(aEvent) { 1.345 + busyEventCount++; 1.346 + } 1.347 + 1.348 + function onSSWindowStateReady(aEvent) { 1.349 + readyEventCount++; 1.350 + } 1.351 + 1.352 + function onSSTabRestored(aEvent) { 1.353 + if (++tabRestoredCount < 4) 1.354 + return; 1.355 + 1.356 + is(busyEventCount, 1); 1.357 + is(readyEventCount, 1); 1.358 + 1.359 + reopenedWindow.removeEventListener("SSWindowStateBusy", onSSWindowStateBusy, false); 1.360 + reopenedWindow.removeEventListener("SSWindowStateReady", onSSWindowStateReady, false); 1.361 + reopenedWindow.gBrowser.tabContainer.removeEventListener("SSTabRestored", onSSTabRestored, false); 1.362 + 1.363 + reopenedWindow.close(); 1.364 + 1.365 + // Give it time to close 1.366 + executeSoon(runNextTest); 1.367 + } 1.368 +}