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_incognito_views.js | 269 +++++++++++++++++++++ 1 file changed, 269 insertions(+) create mode 100644 browser/components/extensions/test/browser/browser_ext_incognito_views.js (limited to 'browser/components/extensions/test/browser/browser_ext_incognito_views.js') diff --git a/browser/components/extensions/test/browser/browser_ext_incognito_views.js b/browser/components/extensions/test/browser/browser_ext_incognito_views.js new file mode 100644 index 0000000000..8a7c3219b3 --- /dev/null +++ b/browser/components/extensions/test/browser/browser_ext_incognito_views.js @@ -0,0 +1,269 @@ +/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set sts=2 sw=2 et tw=80: */ +"use strict"; + +add_setup(async () => { + await SpecialPowers.pushPrefEnv({ + set: [["extensions.openPopupWithoutUserGesture.enabled", true]], + }); +}); + +add_task(async function testIncognitoViews() { + // Make sure the mouse isn't hovering over the browserAction widget. + EventUtils.synthesizeMouseAtCenter( + gURLBar.textbox, + { type: "mouseover" }, + window + ); + + let extension = ExtensionTestUtils.loadExtension({ + incognitoOverride: "spanning", + manifest: { + permissions: ["tabs"], + description: JSON.stringify({ + headless: Services.env.get("MOZ_HEADLESS"), + debug: AppConstants.DEBUG, + }), + browser_action: { + default_popup: "popup.html", + default_area: "navbar", + }, + }, + + background: async function () { + window.isBackgroundPage = true; + const { headless, debug } = JSON.parse( + browser.runtime.getManifest().description + ); + + class ConnectedPopup { + #msgPromise; + #disconnectPromise; + + static promiseNewPopup() { + return new Promise(resolvePort => { + browser.runtime.onConnect.addListener(function onConnect(port) { + browser.runtime.onConnect.removeListener(onConnect); + browser.test.assertEq("from-popup", port.name, "Port from popup"); + resolvePort(new ConnectedPopup(port)); + }); + }); + } + + constructor(port) { + this.port = port; + this.#msgPromise = new Promise(resolveMessage => { + // popup.js sends one message with the popup's metadata. + port.onMessage.addListener(resolveMessage); + }); + this.#disconnectPromise = new Promise(resolveDisconnect => { + port.onDisconnect.addListener(resolveDisconnect); + }); + } + + async getPromisedMessage() { + browser.test.log("Waiting for popup to send information"); + let msg = await this.#msgPromise; + browser.test.assertEq("popup-details", msg.message, "Got port msg"); + return msg; + } + + async promisePopupClosed(desc) { + browser.test.log(`Waiting for popup to be closed (${desc})`); + // There is currently no great way for extension to detect a closed + // popup. Extensions can observe the port.onDisconnect event for now. + await this.#disconnectPromise; + browser.test.log(`Popup was closed (${desc})`); + } + + async closePopup(desc) { + browser.test.log(`Closing popup (${desc})`); + this.port.postMessage("close_popup"); + return this.promisePopupClosed(desc); + } + } + + let testPopupForWindow = async window => { + let popupConnectionPromise = ConnectedPopup.promiseNewPopup(); + + await browser.browserAction.openPopup({ + windowId: window.id, + }); + + let connectedPopup = await popupConnectionPromise; + let msg = await connectedPopup.getPromisedMessage(); + browser.test.assertEq( + window.id, + msg.windowId, + "Got popup message from correct window" + ); + browser.test.assertEq( + window.incognito, + msg.incognito, + "Correct incognito status in browserAction popup" + ); + + return connectedPopup; + }; + + async function createPrivateWindow() { + const URL = "https://example.com/?dummy-incognito-window"; + let windowReady = new Promise(resolve => { + browser.tabs.onUpdated.addListener(function l(tabId, changed, tab) { + if (changed.status == "complete" && tab.url == URL) { + browser.tabs.onUpdated.removeListener(l); + resolve(); + } + }); + }); + let window = await browser.windows.create({ + incognito: true, + url: URL, + }); + await windowReady; + return window; + } + + function getNonPrivateViewCount() { + // The background context is in non-private browsing mode, so getViews() + // only returns the views that are not in private browsing mode. + return browser.extension.getViews({ type: "popup" }).length; + } + + try { + let nonPrivatePopup; + { + let window = await browser.windows.getCurrent(); + + nonPrivatePopup = await testPopupForWindow(window); + + browser.test.assertEq(1, getNonPrivateViewCount(), "popup is open"); + // ^ The popup will close when a new window is opened below. + if (headless) { + // ... except when --headless is used. For some reason, the popup + // does not close when another window is opened. Close manually. + await nonPrivatePopup.closePopup("Work-around for --headless bug"); + } + } + + { + let window = await createPrivateWindow(); + + let privatePopup = await testPopupForWindow(window); + + await nonPrivatePopup.promisePopupClosed("First popup closed by now"); + + browser.test.assertEq( + 0, + getNonPrivateViewCount(), + "First popup should have been closed when a new window was opened" + ); + + // TODO bug 1809000: On debug builds, a memory leak is reported when + // the popup is closed as part of closing a window. As a work-around, + // we explicitly close the popup here. + // TODO: Remove when bug 1809000 is fixed. + if (debug) { + await privatePopup.closePopup("Work-around for bug 1809000"); + } + + await browser.windows.remove(window.id); + // ^ This also closes the popup panel associated with the window. If + // it somehow does not close properly, errors may be reported, e.g. + // leakcheck failures in debug mode (like bug 1800100). + + // This check is not strictly necessary, but we're doing this to + // confirm that the private popup has indeed been closed. + await privatePopup.promisePopupClosed("Window closed = popup gone"); + } + + browser.test.notifyPass("incognito-views"); + } catch (error) { + browser.test.fail(`Error: ${error} :: ${error.stack}`); + browser.test.notifyFail("incognito-views"); + } + }, + + files: { + "popup.html": + '', + + "popup.js": async function () { + let views = browser.extension.getViews(); + + if (browser.extension.inIncognitoContext) { + let bgPage = browser.extension.getBackgroundPage(); + browser.test.assertEq( + null, + bgPage, + "Should not be able to access background page in incognito context" + ); + + bgPage = await browser.runtime.getBackgroundPage(); + browser.test.assertEq( + null, + bgPage, + "Should not be able to access background page in incognito context" + ); + + browser.test.assertEq( + 1, + views.length, + "Should only see one view in incognito popup" + ); + browser.test.assertEq( + window, + views[0], + "This window should be the only view" + ); + } else { + let bgPage = browser.extension.getBackgroundPage(); + browser.test.assertEq( + true, + bgPage.isBackgroundPage, + "Should be able to access background page in non-incognito context" + ); + + bgPage = await browser.runtime.getBackgroundPage(); + browser.test.assertEq( + true, + bgPage.isBackgroundPage, + "Should be able to access background page in non-incognito context" + ); + + browser.test.assertEq( + 2, + views.length, + "Should only two views in non-incognito popup" + ); + browser.test.assertEq( + bgPage, + views[0], + "The background page should be the first view" + ); + browser.test.assertEq( + window, + views[1], + "This window should be the second view" + ); + } + + let win = await browser.windows.getCurrent(); + let port = browser.runtime.connect({ name: "from-popup" }); + port.onMessage.addListener(msg => { + browser.test.assertEq("close_popup", msg, "Close popup msg"); + window.close(); + }); + port.postMessage({ + message: "popup-details", + windowId: win.id, + incognito: browser.extension.inIncognitoContext, + }); + }, + }, + }); + + await extension.startup(); + await extension.awaitFinish("incognito-views"); + await extension.unload(); +}); -- cgit v1.2.3