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 --- .../test/browser/browser_ext_tabs_discarded.js | 386 +++++++++++++++++++++ 1 file changed, 386 insertions(+) create mode 100644 browser/components/extensions/test/browser/browser_ext_tabs_discarded.js (limited to 'browser/components/extensions/test/browser/browser_ext_tabs_discarded.js') diff --git a/browser/components/extensions/test/browser/browser_ext_tabs_discarded.js b/browser/components/extensions/test/browser/browser_ext_tabs_discarded.js new file mode 100644 index 0000000000..48c57b5a05 --- /dev/null +++ b/browser/components/extensions/test/browser/browser_ext_tabs_discarded.js @@ -0,0 +1,386 @@ +/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set sts=2 sw=2 et tw=80: */ +/* global gBrowser SessionStore */ +"use strict"; + +const triggeringPrincipal_base64 = E10SUtils.SERIALIZED_SYSTEMPRINCIPAL; + +let lazyTabState = { + entries: [ + { + url: "http://example.com/", + triggeringPrincipal_base64, + title: "Example Domain", + }, + ], +}; + +add_task(async function test_discarded() { + let extension = ExtensionTestUtils.loadExtension({ + manifest: { + permissions: ["tabs", "webNavigation"], + }, + + background() { + browser.webNavigation.onCompleted.addListener( + async details => { + browser.test.log(`webNav onCompleted received for ${details.tabId}`); + let updatedTab = await browser.tabs.get(details.tabId); + browser.test.assertEq( + false, + updatedTab.discarded, + "lazy to non-lazy update discard property" + ); + browser.test.notifyPass("test-finished"); + }, + { url: [{ hostContains: "example.com" }] } + ); + + browser.tabs.onCreated.addListener(function (tab) { + browser.test.assertEq( + true, + tab.discarded, + "non-lazy tab onCreated discard property" + ); + browser.tabs.update(tab.id, { active: true }); + }); + }, + }); + + await extension.startup(); + + let testTab = BrowserTestUtils.addTab(gBrowser, "about:blank", { + createLazyBrowser: true, + }); + SessionStore.setTabState(testTab, lazyTabState); + + await extension.awaitFinish("test-finished"); + await extension.unload(); + + BrowserTestUtils.removeTab(testTab); +}); + +// Regression test for Bug 1819794. +add_task(async function test_create_discarded_with_cookieStoreId() { + let extension = ExtensionTestUtils.loadExtension({ + manifest: { + permissions: ["contextualIdentities", "cookies"], + }, + async background() { + const [{ cookieStoreId }] = await browser.contextualIdentities.query({}); + browser.test.assertEq( + "firefox-container-1", + cookieStoreId, + "Got expected cookieStoreId" + ); + await browser.tabs.create({ + url: `http://example.com/#${cookieStoreId}`, + cookieStoreId, + discarded: true, + }); + await browser.tabs.create({ + url: `http://example.com/#no-container`, + discarded: true, + }); + }, + // Needed by ExtensionSettingsStore (as a side-effect of contextualIdentities permission). + useAddonManager: "temporary", + }); + + const tabContainerPromise = BrowserTestUtils.waitForEvent( + window, + "TabOpen", + false, + evt => { + return evt.target.getAttribute("usercontextid", "1"); + } + ).then(evt => evt.target); + const tabDefaultPromise = BrowserTestUtils.waitForEvent( + window, + "TabOpen", + false, + evt => { + return !evt.target.hasAttribute("usercontextid"); + } + ).then(evt => evt.target); + + await extension.startup(); + + const tabContainer = await tabContainerPromise; + ok( + tabContainer.hasAttribute("pending"), + "new container tab should be discarded" + ); + const tabContainerState = SessionStore.getTabState(tabContainer); + is( + JSON.parse(tabContainerState).userContextId, + 1, + `Expect a userContextId associated to the new discarded container tab: ${tabContainerState}` + ); + + const tabDefault = await tabDefaultPromise; + ok( + tabDefault.hasAttribute("pending"), + "new non-container tab should be discarded" + ); + const tabDefaultState = SessionStore.getTabState(tabDefault); + is( + JSON.parse(tabDefaultState).userContextId, + 0, + `Expect userContextId 0 associated to the new discarded non-container tab: ${tabDefaultState}` + ); + + BrowserTestUtils.removeTab(tabContainer); + BrowserTestUtils.removeTab(tabDefault); + await extension.unload(); +}); + +// If discard is called immediately after creating a new tab, the new tab may not have loaded, +// and the sessionstore for that tab is not ready for discarding. The result was a corrupted +// sessionstore for the tab, which when the tab was activated, resulted in a tab with partial +// state. +add_task(async function test_create_then_discard() { + let extension = ExtensionTestUtils.loadExtension({ + manifest: { + permissions: ["tabs", "webNavigation"], + }, + + background: async function () { + let createdTab; + + browser.tabs.onUpdated.addListener((tabId, updatedInfo) => { + if (!updatedInfo.discarded) { + return; + } + + browser.webNavigation.onCompleted.addListener( + async details => { + browser.test.assertEq( + createdTab.id, + details.tabId, + "created tab navigation is completed" + ); + let activeTab = await browser.tabs.get(details.tabId); + browser.test.assertEq( + "http://example.com/", + details.url, + "created tab url is correct" + ); + browser.test.assertEq( + "http://example.com/", + activeTab.url, + "created tab url is correct" + ); + browser.tabs.remove(details.tabId); + browser.test.notifyPass("test-finished"); + }, + { url: [{ hostContains: "example.com" }] } + ); + + browser.tabs.update(tabId, { active: true }); + }); + + createdTab = await browser.tabs.create({ + url: "http://example.com/", + active: false, + }); + browser.tabs.discard(createdTab.id); + }, + }); + await extension.startup(); + await extension.awaitFinish("test-finished"); + await extension.unload(); +}); + +add_task(async function test_create_discarded() { + let extension = ExtensionTestUtils.loadExtension({ + manifest: { + permissions: ["tabs", "webNavigation"], + }, + + background() { + let tabOpts = { + url: "http://example.com/", + active: false, + discarded: true, + title: "discarded tab", + }; + + browser.webNavigation.onCompleted.addListener( + async details => { + let activeTab = await browser.tabs.get(details.tabId); + browser.test.assertEq( + tabOpts.url, + activeTab.url, + "restored tab url matches active tab url" + ); + browser.test.assertEq( + "mochitest index /", + activeTab.title, + "restored tab title is correct" + ); + browser.tabs.remove(details.tabId); + browser.test.notifyPass("test-finished"); + }, + { url: [{ hostContains: "example.com" }] } + ); + + browser.tabs.onCreated.addListener(tab => { + browser.test.assertEq( + tabOpts.active, + tab.active, + "lazy tab is not active" + ); + browser.test.assertEq( + tabOpts.discarded, + tab.discarded, + "lazy tab is discarded" + ); + browser.test.assertEq(tabOpts.url, tab.url, "lazy tab url is correct"); + browser.test.assertEq( + tabOpts.title, + tab.title, + "lazy tab title is correct" + ); + browser.tabs.update(tab.id, { active: true }); + }); + + browser.tabs.create(tabOpts); + }, + }); + await extension.startup(); + await extension.awaitFinish("test-finished"); + await extension.unload(); +}); + +add_task(async function test_discarded_private_tab_restored() { + let extension = ExtensionTestUtils.loadExtension({ + incognitoOverride: "spanning", + + background() { + let isDiscarding = false; + browser.tabs.onUpdated.addListener( + async function listener(tabId, changeInfo, tab) { + const { active, discarded, incognito } = tab; + if (!incognito || active || discarded || isDiscarding) { + return; + } + // Remove the onUpdated listener to prevent intermittent failure + // to be hit if the listener gets called again for unrelated + // tabs.onUpdated events that may get fired after the test case got + // the tab-discarded test message that was expecting. + isDiscarding = true; + browser.tabs.onUpdated.removeListener(listener); + browser.test.log( + `Test extension discarding ${tabId}: ${JSON.stringify(changeInfo)}` + ); + await browser.tabs.discard(tabId); + browser.test.sendMessage("tab-discarded"); + }, + { properties: ["status"] } + ); + }, + }); + + // Open a private browsing window. + const privateWin = await BrowserTestUtils.openNewBrowserWindow({ + private: true, + }); + + await extension.startup(); + + const newTab = await BrowserTestUtils.addTab( + privateWin.gBrowser, + "https://example.com/" + ); + await extension.awaitMessage("tab-discarded"); + is(newTab.getAttribute("pending"), "true", "private tab should be discarded"); + + const promiseTabLoaded = BrowserTestUtils.browserLoaded(newTab.linkedBrowser); + + info("Switching to the discarded background tab"); + await BrowserTestUtils.switchTab(privateWin.gBrowser, newTab); + + info("Wait for the restored tab to complete loading"); + await promiseTabLoaded; + is( + newTab.hasAttribute("pending"), + false, + "discarded private tab should have been restored" + ); + + is( + newTab.linkedBrowser.currentURI.spec, + "https://example.com/", + "Got the expected url on the restored tab" + ); + + await extension.unload(); + await BrowserTestUtils.closeWindow(privateWin); +}); + +add_task(async function test_update_discarded() { + let extension = ExtensionTestUtils.loadExtension({ + manifest: { + permissions: ["tabs", ""], + }, + + background() { + browser.test.onMessage.addListener(async msg => { + let [tab] = await browser.tabs.query({ url: "http://example.com/" }); + if (msg == "update") { + await browser.tabs.update(tab.id, { url: "https://example.com/" }); + } else { + browser.test.fail(`Unexpected message received: ${msg}`); + } + }); + browser.test.sendMessage("ready"); + }, + }); + + await extension.startup(); + await extension.awaitMessage("ready"); + + let lazyTab = BrowserTestUtils.addTab(gBrowser, "http://example.com/", { + createLazyBrowser: true, + lazyTabTitle: "Example Domain", + }); + + let tabBrowserInsertedPromise = BrowserTestUtils.waitForEvent( + lazyTab, + "TabBrowserInserted" + ); + + SimpleTest.waitForExplicitFinish(); + let waitForConsole = new Promise(resolve => { + SimpleTest.monitorConsole(resolve, [ + { + message: + /Lazy browser prematurely inserted via 'loadURI' property access:/, + forbid: true, + }, + ]); + }); + + extension.sendMessage("update"); + await tabBrowserInsertedPromise; + + await BrowserTestUtils.waitForBrowserStateChange( + lazyTab.linkedBrowser, + "https://example.com/", + stateFlags => { + return ( + stateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW && + stateFlags & Ci.nsIWebProgressListener.STATE_STOP + ); + } + ); + + await TestUtils.waitForTick(); + BrowserTestUtils.removeTab(lazyTab); + + await extension.unload(); + + SimpleTest.endMonitorConsole(); + await waitForConsole; +}); -- cgit v1.2.3