From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../browser_ext_sessions_getRecentlyClosed_tabs.js | 287 +++++++++++++++++++++ 1 file changed, 287 insertions(+) create mode 100644 browser/components/extensions/test/browser/browser_ext_sessions_getRecentlyClosed_tabs.js (limited to 'browser/components/extensions/test/browser/browser_ext_sessions_getRecentlyClosed_tabs.js') diff --git a/browser/components/extensions/test/browser/browser_ext_sessions_getRecentlyClosed_tabs.js b/browser/components/extensions/test/browser/browser_ext_sessions_getRecentlyClosed_tabs.js new file mode 100644 index 0000000000..6c386aaf97 --- /dev/null +++ b/browser/components/extensions/test/browser/browser_ext_sessions_getRecentlyClosed_tabs.js @@ -0,0 +1,287 @@ +/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set sts=2 sw=2 et tw=80: */ +"use strict"; + +function expectedTabInfo(tab, window) { + let browser = tab.linkedBrowser; + return { + url: browser.currentURI.spec, + title: browser.contentTitle, + favIconUrl: window.gBrowser.getIcon(tab) || undefined, + // 'selected' is marked as unsupported in schema, so we've removed it. + // For more details, see bug 1337509 + selected: undefined, + }; +} + +function checkTabInfo(expected, actual) { + for (let prop in expected) { + is( + actual[prop], + expected[prop], + `Expected value found for ${prop} of tab object.` + ); + } +} + +add_task(async function test_sessions_get_recently_closed_tabs() { + // Below, the test makes assumptions about the last accessed time of tabs that are + // not true is we execute fast and reduce the timer precision enough + await SpecialPowers.pushPrefEnv({ + set: [ + ["privacy.reduceTimerPrecision", false], + ["browser.navigation.requireUserInteraction", false], + ], + }); + + async function background() { + browser.test.onMessage.addListener(async msg => { + if (msg == "check-sessions") { + let recentlyClosed = await browser.sessions.getRecentlyClosed(); + browser.test.sendMessage("recentlyClosed", recentlyClosed); + } + }); + } + + let extension = ExtensionTestUtils.loadExtension({ + manifest: { + permissions: ["sessions", "tabs"], + }, + background, + }); + + let win = await BrowserTestUtils.openNewBrowserWindow(); + let tabBrowser = win.gBrowser.selectedBrowser; + for (let url of ["about:robots", "about:mozilla", "about:config"]) { + BrowserTestUtils.loadURIString(tabBrowser, url); + await BrowserTestUtils.browserLoaded(tabBrowser, false, url); + } + + // Ensure that getRecentlyClosed returns correct results after the back + // button has been used. + let goBackPromise = BrowserTestUtils.waitForLocationChange( + win.gBrowser, + "about:mozilla" + ); + tabBrowser.goBack(); + await goBackPromise; + + let expectedTabs = []; + let tab = win.gBrowser.selectedTab; + // Because there is debounce logic in ContentLinkHandler.jsm to reduce the + // favicon loads, we have to wait some time before checking that icon was + // stored properly. If that page doesn't have favicon links, let it timeout. + try { + await BrowserTestUtils.waitForCondition( + () => { + return gBrowser.getIcon(tab) != null; + }, + "wait for favicon load to finish", + 100, + 5 + ); + } catch (e) { + // This page doesn't have any favicon link, just continue. + } + expectedTabs.push(expectedTabInfo(tab, win)); + let lastAccessedTimes = new Map(); + lastAccessedTimes.set("about:mozilla", tab.lastAccessed); + + for (let url of ["about:robots", "about:buildconfig"]) { + tab = await BrowserTestUtils.openNewForegroundTab(win.gBrowser, url); + try { + await BrowserTestUtils.waitForCondition( + () => { + return gBrowser.getIcon(tab) != null; + }, + "wait for favicon load to finish", + 100, + 5 + ); + } catch (e) { + // This page doesn't have any favicon link, just continue. + } + expectedTabs.push(expectedTabInfo(tab, win)); + lastAccessedTimes.set(url, tab.lastAccessed); + } + + await extension.startup(); + + let sessionUpdatePromise = BrowserTestUtils.waitForSessionStoreUpdate(tab); + // Test with a closed tab. + BrowserTestUtils.removeTab(tab); + await sessionUpdatePromise; + + extension.sendMessage("check-sessions"); + let recentlyClosed = await extension.awaitMessage("recentlyClosed"); + let tabInfo = recentlyClosed[0].tab; + let expectedTab = expectedTabs.pop(); + checkTabInfo(expectedTab, tabInfo); + ok( + tabInfo.lastAccessed > lastAccessedTimes.get(tabInfo.url), + "lastAccessed has been updated" + ); + + // Test with a closed window containing tabs. + await BrowserTestUtils.closeWindow(win); + + extension.sendMessage("check-sessions"); + recentlyClosed = await extension.awaitMessage("recentlyClosed"); + let tabInfos = recentlyClosed[0].window.tabs; + is(tabInfos.length, 2, "Expected number of tabs in closed window."); + for (let x = 0; x < tabInfos.length; x++) { + checkTabInfo(expectedTabs[x], tabInfos[x]); + ok( + tabInfos[x].lastAccessed > lastAccessedTimes.get(tabInfos[x].url), + "lastAccessed has been updated" + ); + } + + await extension.unload(); + + // Test without tabs and host permissions. + extension = ExtensionTestUtils.loadExtension({ + manifest: { + permissions: ["sessions"], + }, + background, + }); + + await extension.startup(); + + extension.sendMessage("check-sessions"); + recentlyClosed = await extension.awaitMessage("recentlyClosed"); + tabInfos = recentlyClosed[0].window.tabs; + is(tabInfos.length, 2, "Expected number of tabs in closed window."); + for (let tabInfo of tabInfos) { + for (let prop in expectedTabs[0]) { + is( + undefined, + tabInfo[prop], + `${prop} of tab object is undefined without tabs permission.` + ); + } + } + + await extension.unload(); + + // Test with host permission. + win = await BrowserTestUtils.openNewBrowserWindow(); + tabBrowser = win.gBrowser.selectedBrowser; + BrowserTestUtils.loadURIString(tabBrowser, "http://example.com/testpage"); + await BrowserTestUtils.browserLoaded( + tabBrowser, + false, + "http://example.com/testpage" + ); + tab = win.gBrowser.getTabForBrowser(tabBrowser); + try { + await BrowserTestUtils.waitForCondition( + () => { + return gBrowser.getIcon(tab) != null; + }, + "wait for favicon load to finish", + 100, + 5 + ); + } catch (e) { + // This page doesn't have any favicon link, just continue. + } + expectedTab = expectedTabInfo(tab, win); + await BrowserTestUtils.closeWindow(win); + + extension = ExtensionTestUtils.loadExtension({ + manifest: { + permissions: ["sessions", "http://example.com/*"], + }, + background, + }); + await extension.startup(); + + extension.sendMessage("check-sessions"); + recentlyClosed = await extension.awaitMessage("recentlyClosed"); + tabInfo = recentlyClosed[0].window.tabs[0]; + checkTabInfo(expectedTab, tabInfo); + + await extension.unload(); +}); + +add_task( + async function test_sessions_get_recently_closed_for_loading_non_web_controlled_blank_page() { + info("Prepare extension that calls browser.sessions.getRecentlyClosed()"); + let extension = ExtensionTestUtils.loadExtension({ + manifest: { + permissions: ["sessions", "tabs"], + }, + background: async () => { + browser.test.onMessage.addListener(async msg => { + if (msg == "check-sessions") { + let recentlyClosed = await browser.sessions.getRecentlyClosed(); + browser.test.sendMessage("recentlyClosed", recentlyClosed); + } + }); + }, + }); + + info( + "Open a page having a link for non web controlled page in _blank target" + ); + const testRoot = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "https://example.com" + ); + let url = `${testRoot}file_has_non_web_controlled_blank_page_link.html`; + let win = await BrowserTestUtils.openNewBrowserWindow(); + BrowserTestUtils.loadURIString(win.gBrowser.selectedBrowser, url); + await BrowserTestUtils.browserLoaded( + win.gBrowser.selectedBrowser, + false, + url + ); + + info("Open the non web controlled page in _blank target"); + let onNewTabOpened = new Promise(resolve => + win.gBrowser.addTabsProgressListener({ + onStateChange(browser, webProgress, request, stateFlags, status) { + if (stateFlags & Ci.nsIWebProgressListener.STATE_START) { + win.gBrowser.removeTabsProgressListener(this); + resolve(win.gBrowser.getTabForBrowser(browser)); + } + }, + }) + ); + let targetUrl = await SpecialPowers.spawn( + win.gBrowser.selectedBrowser, + [], + () => { + const target = content.document.querySelector("a"); + EventUtils.synthesizeMouseAtCenter(target, {}, content); + return target.href; + } + ); + let tab = await onNewTabOpened; + + info("Remove tab while loading to get getRecentlyClosed()"); + await extension.startup(); + let sessionUpdatePromise = BrowserTestUtils.waitForSessionStoreUpdate(tab); + BrowserTestUtils.removeTab(tab); + await sessionUpdatePromise; + + info("Check the result of getRecentlyClosed()"); + extension.sendMessage("check-sessions"); + let recentlyClosed = await extension.awaitMessage("recentlyClosed"); + checkTabInfo( + { + index: 1, + url: targetUrl, + title: targetUrl, + favIconUrl: undefined, + selected: undefined, + }, + recentlyClosed[0].tab + ); + + await extension.unload(); + await BrowserTestUtils.closeWindow(win); + } +); -- cgit v1.2.3