browser_history_recently_closed_tabs.js (11071B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 /** 4 * This test verifies behavior from bug 1819675: 5 * https://bugzilla.mozilla.org/show_bug.cgi?id=1819675 6 * 7 * The recently closed tabs menu item should be enabled when there are tabs 8 * closed from any window that is in the same private/non-private bucket as 9 * the current window. 10 */ 11 12 const { SessionStoreTestUtils } = ChromeUtils.importESModule( 13 "resource://testing-common/SessionStoreTestUtils.sys.mjs" 14 ); 15 const triggeringPrincipal_base64 = E10SUtils.SERIALIZED_SYSTEMPRINCIPAL; 16 SessionStoreTestUtils.init(this, window); 17 18 async function checkMenu(window, expected) { 19 await SimpleTest.promiseFocus(window); 20 const historyMenubarItem = window.document.getElementById("history-menu"); 21 const historyMenu = window.document.getElementById("historyMenuPopup"); 22 const recentlyClosedTabsItem = historyMenu.querySelector("#historyUndoMenu"); 23 24 const menuShown = BrowserTestUtils.waitForEvent(historyMenu, "popupshown"); 25 historyMenubarItem.openMenu(true); 26 info("checkMenu:, waiting for menuShown"); 27 await menuShown; 28 29 Assert.equal( 30 recentlyClosedTabsItem.disabled, 31 expected.menuItemDisabled, 32 `Recently closed tabs menu item is ${ 33 expected.menuItemDisabled ? "disabled" : "not disabled" 34 }` 35 ); 36 const menuHidden = BrowserTestUtils.waitForEvent(historyMenu, "popuphidden"); 37 historyMenu.hidePopup(); 38 info("checkMenu:, waiting for menuHidden"); 39 await menuHidden; 40 info("checkMenu:, menuHidden, returning"); 41 } 42 43 function resetClosedTabsAndWindows() { 44 // Clear the lists of closed windows and tabs. 45 Services.obs.notifyObservers(null, "browser:purge-session-history"); 46 is(SessionStore.getClosedWindowCount(), 0, "Expect 0 closed windows"); 47 for (const win of BrowserWindowTracker.orderedWindows) { 48 is( 49 SessionStore.getClosedTabCountForWindow(win), 50 0, 51 "Expect 0 closed tabs for this window" 52 ); 53 } 54 } 55 56 add_setup(async function () { 57 await SpecialPowers.pushPrefEnv({ 58 set: [["test.wait300msAfterTabSwitch", true]], 59 }); 60 }); 61 62 add_task(async function test_recently_closed_tabs_nonprivate() { 63 await resetClosedTabsAndWindows(); 64 65 const win1 = window; 66 const win2 = await BrowserTestUtils.openNewBrowserWindow(); 67 await BrowserTestUtils.openNewForegroundTab( 68 win1.gBrowser, 69 "https://example.com" 70 ); 71 // we're going to close a tab and don't want to accidentally close the window when it has 0 tabs 72 await BrowserTestUtils.openNewForegroundTab(win2.gBrowser, "about:about"); 73 await BrowserTestUtils.openNewForegroundTab( 74 win2.gBrowser, 75 "https://example.org" 76 ); 77 78 info("Checking the menuitem is initially disabled in both windows"); 79 for (let win of [win1, win2]) { 80 await checkMenu(win, { 81 menuItemDisabled: true, 82 }); 83 } 84 85 await SessionStoreTestUtils.closeTab(win2.gBrowser.selectedTab); 86 is( 87 SessionStore.getClosedTabCount(), 88 1, 89 "Expect closed tab count of 1 after closing a tab" 90 ); 91 92 for (let win of [win1, win2]) { 93 await checkMenu(win, { 94 menuItemDisabled: false, 95 }); 96 } 97 98 // clean up 99 info("clean up opened window"); 100 const sessionStoreChanged = TestUtils.topicObserved( 101 "sessionstore-closed-objects-changed" 102 ); 103 await BrowserTestUtils.closeWindow(win2); 104 await sessionStoreChanged; 105 106 info("starting tab cleanup"); 107 while (gBrowser.tabs.length > 1) { 108 await SessionStoreTestUtils.closeTab( 109 gBrowser.tabs[gBrowser.tabs.length - 1] 110 ); 111 } 112 info("finished tab cleanup"); 113 }); 114 115 add_task(async function test_recently_closed_tabs_nonprivate_pref_off() { 116 await SpecialPowers.pushPrefEnv({ 117 set: [["browser.sessionstore.closedTabsFromAllWindows", false]], 118 }); 119 await resetClosedTabsAndWindows(); 120 121 const win1 = window; 122 const win2 = await BrowserTestUtils.openNewBrowserWindow(); 123 await BrowserTestUtils.openNewForegroundTab( 124 win1.gBrowser, 125 "https://example.com" 126 ); 127 // we're going to close a tab and don't want to accidentally close the window when it has 0 tabs 128 await BrowserTestUtils.openNewForegroundTab(win2.gBrowser, "about:about"); 129 await BrowserTestUtils.openNewForegroundTab( 130 win2.gBrowser, 131 "https://example.org" 132 ); 133 134 info("Checking the menuitem is initially disabled in both windows"); 135 for (let win of [win1, win2]) { 136 await checkMenu(win, { 137 menuItemDisabled: true, 138 }); 139 } 140 await SimpleTest.promiseFocus(win2); 141 await SessionStoreTestUtils.closeTab(win2.gBrowser.selectedTab); 142 is( 143 SessionStore.getClosedTabCount(), 144 1, 145 "Expect closed tab count of 1 after closing a tab" 146 ); 147 148 await checkMenu(win1, { 149 menuItemDisabled: true, 150 }); 151 await checkMenu(win2, { 152 menuItemDisabled: false, 153 }); 154 155 // clean up 156 info("clean up opened window"); 157 const sessionStoreChanged = TestUtils.topicObserved( 158 "sessionstore-closed-objects-changed" 159 ); 160 await BrowserTestUtils.closeWindow(win2); 161 await sessionStoreChanged; 162 163 info("starting tab cleanup"); 164 while (gBrowser.tabs.length > 1) { 165 await SessionStoreTestUtils.closeTab( 166 gBrowser.tabs[gBrowser.tabs.length - 1] 167 ); 168 } 169 info("finished tab cleanup"); 170 SpecialPowers.popPrefEnv(); 171 }); 172 173 add_task(async function test_recently_closed_tabs_mixed_private() { 174 await resetClosedTabsAndWindows(); 175 is( 176 SessionStore.getClosedTabCount(), 177 0, 178 "Expect closed tab count of 0 after reset" 179 ); 180 181 await BrowserTestUtils.openNewForegroundTab(window.gBrowser, "about:robots"); 182 await BrowserTestUtils.openNewForegroundTab( 183 window.gBrowser, 184 "https://example.com" 185 ); 186 187 const privateWin = await BrowserTestUtils.openNewBrowserWindow({ 188 private: true, 189 }); 190 await BrowserTestUtils.openNewForegroundTab( 191 privateWin.gBrowser, 192 "about:about" 193 ); 194 await BrowserTestUtils.openNewForegroundTab( 195 privateWin.gBrowser, 196 "https://example.org" 197 ); 198 199 for (let win of [window, privateWin]) { 200 await checkMenu(win, { 201 menuItemDisabled: true, 202 }); 203 } 204 205 await SessionStoreTestUtils.closeTab(privateWin.gBrowser.selectedTab); 206 is( 207 SessionStore.getClosedTabCount(privateWin), 208 1, 209 "Expect closed tab count of 1 for private windows" 210 ); 211 is( 212 SessionStore.getClosedTabCount(window), 213 0, 214 "Expect closed tab count of 0 for non-private windows" 215 ); 216 217 // the menu should be enabled only for the private window 218 await checkMenu(window, { 219 menuItemDisabled: true, 220 }); 221 await checkMenu(privateWin, { 222 menuItemDisabled: false, 223 }); 224 225 await resetClosedTabsAndWindows(); 226 await SimpleTest.promiseFocus(window); 227 228 info("closing tab in non-private window"); 229 await SessionStoreTestUtils.closeTab(window.gBrowser.selectedTab); 230 is( 231 SessionStore.getClosedTabCount(window), 232 1, 233 "Expect 1 closed tab count after closing the a tab in the non-private window" 234 ); 235 236 // the menu should be enabled only for the non-private window 237 await checkMenu(window, { 238 menuItemDisabled: false, 239 }); 240 await checkMenu(privateWin, { 241 menuItemDisabled: true, 242 }); 243 244 // clean up 245 info("closing private window"); 246 await BrowserTestUtils.closeWindow(privateWin); 247 await TestUtils.waitForTick(); 248 249 info("starting tab cleanup"); 250 while (gBrowser.tabs.length > 1) { 251 await SessionStoreTestUtils.closeTab( 252 gBrowser.tabs[gBrowser.tabs.length - 1] 253 ); 254 } 255 info("finished tab cleanup"); 256 }); 257 258 add_task(async function test_recently_closed_tabs_mixed_private_pref_off() { 259 await SpecialPowers.pushPrefEnv({ 260 set: [["browser.sessionstore.closedTabsFromAllWindows", false]], 261 }); 262 await resetClosedTabsAndWindows(); 263 264 await BrowserTestUtils.openNewForegroundTab(window.gBrowser, "about:robots"); 265 await BrowserTestUtils.openNewForegroundTab( 266 window.gBrowser, 267 "https://example.com" 268 ); 269 270 const privateWin = await BrowserTestUtils.openNewBrowserWindow({ 271 private: true, 272 }); 273 await BrowserTestUtils.openNewForegroundTab( 274 privateWin.gBrowser, 275 "about:about" 276 ); 277 await BrowserTestUtils.openNewForegroundTab( 278 privateWin.gBrowser, 279 "https://example.org" 280 ); 281 282 for (let win of [window, privateWin]) { 283 await checkMenu(win, { 284 menuItemDisabled: true, 285 }); 286 } 287 288 await SimpleTest.promiseFocus(privateWin); 289 await SessionStoreTestUtils.closeTab(privateWin.gBrowser.selectedTab); 290 is( 291 SessionStore.getClosedTabCount(privateWin), 292 1, 293 "Expect closed tab count of 1 for private windows" 294 ); 295 is( 296 SessionStore.getClosedTabCount(window), 297 0, 298 "Expect closed tab count of 0 for non-private windows" 299 ); 300 301 // the menu should be enabled only for the private window 302 await checkMenu(window, { 303 menuItemDisabled: true, 304 }); 305 await checkMenu(privateWin, { 306 menuItemDisabled: false, 307 }); 308 309 await resetClosedTabsAndWindows(); 310 is( 311 SessionStore.getClosedTabCount(privateWin), 312 0, 313 "Expect 0 closed tab count after reset" 314 ); 315 is( 316 SessionStore.getClosedTabCount(window), 317 0, 318 "Expect 0 closed tab count after reset" 319 ); 320 321 info("closing tab in non-private window"); 322 await SimpleTest.promiseFocus(window); 323 await SessionStoreTestUtils.closeTab(window.gBrowser.selectedTab); 324 325 // the menu should be enabled only for the non-private window 326 await checkMenu(window, { 327 menuItemDisabled: false, 328 }); 329 await checkMenu(privateWin, { 330 menuItemDisabled: true, 331 }); 332 333 // clean up 334 info("closing private window"); 335 await BrowserTestUtils.closeWindow(privateWin); 336 await TestUtils.waitForTick(); 337 338 info("starting tab cleanup"); 339 while (gBrowser.tabs.length > 1) { 340 await SessionStoreTestUtils.closeTab( 341 gBrowser.tabs[gBrowser.tabs.length - 1] 342 ); 343 } 344 info("finished tab cleanup"); 345 SpecialPowers.popPrefEnv(); 346 }); 347 348 add_task(async function test_recently_closed_tabs_closed_windows() { 349 // prepare window state with closed tabs from closed windows 350 await SpecialPowers.pushPrefEnv({ 351 set: [["sessionstore.closedTabsFromClosedWindows", true]], 352 }); 353 const closedTabUrls = ["about:robots"]; 354 const closedWindowState = { 355 tabs: [ 356 { 357 entries: [{ url: "about:mozilla", triggeringPrincipal_base64 }], 358 }, 359 ], 360 _closedTabs: closedTabUrls.map(url => { 361 return { 362 state: { 363 entries: [ 364 { 365 url, 366 triggeringPrincipal_base64, 367 }, 368 ], 369 }, 370 }; 371 }), 372 }; 373 await SessionStoreTestUtils.promiseBrowserState({ 374 windows: [ 375 { 376 tabs: [ 377 { 378 entries: [{ url: "about:mozilla", triggeringPrincipal_base64 }], 379 }, 380 ], 381 }, 382 ], 383 _closedWindows: [closedWindowState], 384 }); 385 386 // verify the recently-closed-tabs menu item is enabled 387 await checkMenu(window, { 388 menuItemDisabled: false, 389 }); 390 391 // flip the pref 392 await SpecialPowers.popPrefEnv(); 393 await SpecialPowers.pushPrefEnv({ 394 set: [["browser.sessionstore.closedTabsFromClosedWindows", false]], 395 }); 396 397 // verify the recently-closed-tabs menu item is disabled 398 await checkMenu(window, { 399 menuItemDisabled: true, 400 }); 401 402 SpecialPowers.popPrefEnv(); 403 });