This is an automated email from the git hooks/post-receive script.
richard pushed a commit to branch tor-browser-91.8.0esr-11.0-1 in repository tor-browser.
commit 0f2b9259d75d088357f46d2f2f41516f0967cc85 Author: Luca Greco lgreco@mozilla.com AuthorDate: Tue Dec 14 19:15:15 2021 +0000
Bug 1735899 - Cover the browserAction popup preload with a smoketest. r=mixedpuppy, a=RyanVM
This patch includes a new test file to cover a scenario similar to the one fixed in Bug 1735899, and possibly some other similar ones that may slip through unnoticed.
This test triggers the issue consistently on a build where the fix is not included and pass consistently in build including the fix, but even if it doesn't include any arbitrary timeouts to trigger the issue there is still a chance that the test may start to fail intermittently for some other reasons.
Keeping it as a separate test file will make it easier to disable it as a temporary measure if turns out to be necessary.
Differential Revision: https://phabricator.services.mozilla.com/D132267 --- .../components/extensions/test/browser/browser.ini | 2 + ...er_ext_browserAction_popup_preload_smoketest.js | 198 +++++++++++++++++++++ 2 files changed, 200 insertions(+)
diff --git a/browser/components/extensions/test/browser/browser.ini b/browser/components/extensions/test/browser/browser.ini index 9ff104a32a022..1ad1e3ef6c05d 100644 --- a/browser/components/extensions/test/browser/browser.ini +++ b/browser/components/extensions/test/browser/browser.ini @@ -69,6 +69,8 @@ skip-if = debug && os == 'linux' && bits == 32# Bug 1313372 [browser_ext_browserAction_popup_port.js] [browser_ext_browserAction_popup_preload.js] skip-if = (os == 'win' && !debug) || (verify && debug && (os == 'mac')) # bug 1352668 +[browser_ext_browserAction_popup_preload_smoketest.js] +skip-if = debug # Bug 1746047 [browser_ext_browserAction_popup_resize.js] [browser_ext_browserAction_popup_resize_bottom.js] skip-if = debug # Bug 1522164 diff --git a/browser/components/extensions/test/browser/browser_ext_browserAction_popup_preload_smoketest.js b/browser/components/extensions/test/browser/browser_ext_browserAction_popup_preload_smoketest.js new file mode 100644 index 0000000000000..22d5c1a047e21 --- /dev/null +++ b/browser/components/extensions/test/browser/browser_ext_browserAction_popup_preload_smoketest.js @@ -0,0 +1,198 @@ +/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set sts=2 sw=2 et tw=80: */ +/* eslint-disable mozilla/no-arbitrary-setTimeout */ +"use strict"; + +// This test does create and cancel the preloaded popup +// multiple times and in some cases it takes longer than +// the default timeouts allows. +requestLongerTimeout(4); + +const { AddonTestUtils } = ChromeUtils.import( + "resource://testing-common/AddonTestUtils.jsm" +); + +async function installTestAddon(addonId, unpacked = false) { + let xpi = AddonTestUtils.createTempWebExtensionFile({ + manifest: { + browser_specific_settings: { gecko: { id: addonId } }, + browser_action: { + default_popup: "popup.html", + }, + }, + files: { + "popup.html": `<!DOCTYPE html> + <html> + <head> + <meta charset="utf-8"> + <link rel="stylesheet" href="popup.css"> + </head> + <body> + </body> + </html> + `, + "popup.css": `@import "imported.css";`, + "imported.css": ` + /* Increasing the imported.css file size to increase the + * chances to trigger the stylesheet preload issue that + * has been fixed by Bug 1735899 consistently and with + * a smaller number of preloaded popup cancelled. + * + * ${new Array(600000).fill("x").join("\n")} + */ + body { width: 300px; height: 300px; background: red; } + `, + }, + }); + + if (unpacked) { + // This temporary directory is going to be removed from the + // cleanup function, but also make it unique as we do for the + // other temporary files (e.g. like getTemporaryFile as defined + // in XPInstall.jsm). + const random = Math.round(Math.random() * 36 ** 3).toString(36); + const tmpDirName = `mochitest_unpacked_addons_${random}`; + let tmpExtPath = FileUtils.getDir("TmpD", [tmpDirName], true); + registerCleanupFunction(() => { + tmpExtPath.remove(true); + }); + + // Unpacking the xpi file into the tempoary directory. + const extDir = await AddonTestUtils.manuallyInstall( + xpi, + tmpExtPath, + null, + /* unpacked */ true + ); + + // Install temporarily as unpacked. + return AddonManager.installTemporaryAddon(extDir); + } + + // Install temporarily as packed. + return AddonManager.installTemporaryAddon(xpi); +} + +async function waitForExtensionAndBrowserAction(addonId) { + const { + Management: { + global: { browserActionFor }, + }, + } = ChromeUtils.import("resource://gre/modules/Extension.jsm"); + + // trigger a number of preloads + let extension; + let browserAction; + await TestUtils.waitForCondition(() => { + extension = WebExtensionPolicy.getByID(addonId)?.extension; + browserAction = extension && browserActionFor(extension); + return browserAction; + }, "got the extension and browserAction"); + + let widget = getBrowserActionWidget(extension).forWindow(window); + + return { extension, browserAction, widget }; +} + +async function testCancelPreloadedPopup({ browserAction, widget }) { + // Trigger the preloaded popup. + EventUtils.synthesizeMouseAtCenter( + widget.node, + { type: "mouseover", button: 0 }, + window + ); + await TestUtils.waitForCondition( + () => browserAction.pendingPopup, + "Wait for the preloaded popup" + ); + // Cancel the preloaded popup. + EventUtils.synthesizeMouseAtCenter( + widget.node, + { type: "mouseout", button: 0 }, + window + ); + EventUtils.synthesizeMouseAtCenter( + window.gURLBar.textbox, + { type: "mouseover" }, + window + ); + await TestUtils.waitForCondition( + () => !browserAction.pendingPopup, + "Wait for the preloaded popup to be cancelled" + ); +} + +async function testPopupLoadCompleted({ extension, browserAction, widget }) { + const promiseViewShowing = BrowserTestUtils.waitForEvent( + document, + "ViewShowing", + false, + ev => ev.target.id === browserAction.viewId + ); + EventUtils.synthesizeMouseAtCenter( + widget.node, + { type: "mousedown", button: 0 }, + window + ); + EventUtils.synthesizeMouseAtCenter( + widget.node, + { type: "mouseup", button: 0 }, + window + ); + + info("Await the browserAction popup to be shown"); + await promiseViewShowing; + + info("Await the browserAction popup to be fully loaded"); + const browser = await awaitExtensionPanel( + extension, + window, + /* awaitLoad */ true + ); + + await TestUtils.waitForCondition(async () => { + const docReadyState = await SpecialPowers.spawn(browser, [], () => { + return this.content.document.readyState; + }); + + return docReadyState === "complete"; + }, "Wait the popup document to get to readyState complete"); + + ok(true, "Popup document was fully loaded"); +} + +// This test is covering a scenario similar to the one fixed in Bug 1735899, +// and possibly some other similar ones that may slip through unnoticed. +add_task(async function testCancelPopupPreloadRaceOnUnpackedAddon() { + const ID = "preloaded-popup@test"; + const addon = await installTestAddon(ID, /* unpacked */ true); + const { + extension, + browserAction, + widget, + } = await waitForExtensionAndBrowserAction(ID); + info("Preload popup and cancel it multiple times"); + for (let i = 0; i < 200; i++) { + await testCancelPreloadedPopup({ browserAction, widget }); + } + await testPopupLoadCompleted({ extension, browserAction, widget }); + await addon.uninstall(); +}); + +// This test is covering a scenario similar to the one fixed in Bug 1735899, +// and possibly some other similar ones that may slip through unnoticed. +add_task(async function testCancelPopupPreloadRaceOnPackedAddon() { + const ID = "preloaded-popup@test"; + const addon = await installTestAddon(ID, /* unpacked */ false); + const { + extension, + browserAction, + widget, + } = await waitForExtensionAndBrowserAction(ID); + info("Preload popup and cancel it multiple times"); + for (let i = 0; i < 200; i++) { + await testCancelPreloadedPopup({ browserAction, widget }); + } + await testPopupLoadCompleted({ extension, browserAction, widget }); + await addon.uninstall(); +});