mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-16 23:05:42 +00:00
Bug 1748524 sleep/waken functionality for background, restartable via persistent events r=rpl
Differential Revision: https://phabricator.services.mozilla.com/D135812
This commit is contained in:
parent
d860937b39
commit
9d410ec1bb
@ -4,7 +4,12 @@
|
||||
|
||||
add_task(async function testTabSwitchActionContext() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["extensions.manifestV3.enabled", true]],
|
||||
set: [
|
||||
["extensions.manifestV3.enabled", true],
|
||||
// Since we're not using AOM, and MV3 forces event pages, bypass
|
||||
// delayed-startup for MV3 test. These tests do not rely on startup events.
|
||||
["extensions.webextensions.background-delayed-startup", false],
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -19,10 +19,20 @@ async function grantOptionalPermission(extension, permissions) {
|
||||
return ExtensionPermissions.add(extension.id, permissions, ext);
|
||||
}
|
||||
|
||||
var someOtherTab, testTab;
|
||||
|
||||
add_task(async function setup() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["extensions.manifestV3.enabled", true]],
|
||||
});
|
||||
|
||||
// To help diagnose an intermittent later.
|
||||
SimpleTest.requestCompleteLog();
|
||||
|
||||
// Setup the test tab now, rather than for each test
|
||||
someOtherTab = gBrowser.selectedTab;
|
||||
testTab = await BrowserTestUtils.openNewForegroundTab(gBrowser, PAGE);
|
||||
registerCleanupFunction(() => BrowserTestUtils.removeTab(testTab));
|
||||
});
|
||||
|
||||
// Registers a context menu using menus.create(menuCreateParams) and checks
|
||||
@ -38,7 +48,7 @@ async function testShowHideEvent({
|
||||
forceTabToBackground = false,
|
||||
manifest_version = 2,
|
||||
}) {
|
||||
async function background() {
|
||||
async function background(menu_create_params) {
|
||||
function awaitMessage(expectedId) {
|
||||
return new Promise(resolve => {
|
||||
browser.test.log(`Waiting for message: ${expectedId}`);
|
||||
@ -56,7 +66,6 @@ async function testShowHideEvent({
|
||||
});
|
||||
}
|
||||
|
||||
let menuCreateParams = await awaitMessage("create-params");
|
||||
const [tab] = await browser.tabs.query({
|
||||
active: true,
|
||||
currentWindow: true,
|
||||
@ -72,7 +81,7 @@ async function testShowHideEvent({
|
||||
args[0].targetElementId = 13337; // = EXPECT_TARGET_ELEMENT
|
||||
}
|
||||
shownEvents.push(args[0]);
|
||||
if (menuCreateParams.title.includes("TEST_EXPECT_NO_TAB")) {
|
||||
if (menu_create_params.title.includes("TEST_EXPECT_NO_TAB")) {
|
||||
browser.test.assertEq(undefined, args[1], "expect no tab");
|
||||
} else {
|
||||
browser.test.assertEq(tab.id, args[1].id, "expected tab");
|
||||
@ -85,7 +94,7 @@ async function testShowHideEvent({
|
||||
|
||||
let menuId;
|
||||
await new Promise(resolve => {
|
||||
menuId = browser.menus.create(menuCreateParams, resolve);
|
||||
menuId = browser.menus.create(menu_create_params, resolve);
|
||||
});
|
||||
browser.test.assertEq(0, shownEvents.length, "no onShown before menu");
|
||||
browser.test.assertEq(0, hiddenEvents.length, "no onHidden before menu");
|
||||
@ -106,14 +115,13 @@ async function testShowHideEvent({
|
||||
browser.test.sendMessage("onShown-event-data2", shownEvents[1]);
|
||||
}
|
||||
|
||||
const someOtherTab = gBrowser.selectedTab;
|
||||
// Tab must initially open as a foreground tab, because the test extension
|
||||
// looks for the active tab.
|
||||
const tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, PAGE);
|
||||
gBrowser.selectedTab = testTab;
|
||||
|
||||
const action = manifest_version < 3 ? "browser_action" : "action";
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
background,
|
||||
background: `(${background})(${JSON.stringify(menuCreateParams)})`,
|
||||
manifest: {
|
||||
manifest_version,
|
||||
page_action: {},
|
||||
@ -128,14 +136,13 @@ async function testShowHideEvent({
|
||||
},
|
||||
});
|
||||
await extension.startup();
|
||||
extension.sendMessage("create-params", menuCreateParams);
|
||||
let menuId = await extension.awaitMessage("menu-registered");
|
||||
|
||||
if (forceTabToBackground) {
|
||||
gBrowser.selectedTab = someOtherTab;
|
||||
}
|
||||
|
||||
await doOpenMenu(extension, tab);
|
||||
await doOpenMenu(extension, testTab);
|
||||
extension.sendMessage("assert-menu-shown");
|
||||
let shownEvent = await extension.awaitMessage("onShown-event-data");
|
||||
|
||||
@ -154,7 +161,7 @@ async function testShowHideEvent({
|
||||
permissions: [],
|
||||
origins: [PAGE_HOST_PATTERN],
|
||||
});
|
||||
await doOpenMenu(extension, tab);
|
||||
await doOpenMenu(extension, testTab);
|
||||
extension.sendMessage("optional-menu-shown-with-permissions");
|
||||
let shownEvent2 = await extension.awaitMessage("onShown-event-data2");
|
||||
Assert.deepEqual(
|
||||
@ -166,7 +173,6 @@ async function testShowHideEvent({
|
||||
}
|
||||
|
||||
await extension.unload();
|
||||
BrowserTestUtils.removeTab(tab);
|
||||
}
|
||||
|
||||
// Make sure that we won't trigger onShown when extensions cannot add menus.
|
||||
|
@ -5,6 +5,12 @@
|
||||
/* globals chrome */
|
||||
|
||||
Services.prefs.setBoolPref("extensions.manifestV3.enabled", true);
|
||||
// Since we're not using AOM, and MV3 forces event pages, bypass
|
||||
// delayed-startup for MV3 test. These tests do not rely on startup events.
|
||||
Services.prefs.setBoolPref(
|
||||
"extensions.webextensions.background-delayed-startup",
|
||||
false
|
||||
);
|
||||
|
||||
async function testPermission(options) {
|
||||
function background(bgOptions) {
|
||||
|
@ -117,6 +117,13 @@ XPCOMUtils.defineLazyPreferenceGetter(
|
||||
"[]"
|
||||
);
|
||||
|
||||
// This pref modifies behavior for MV2. MV3 is enabled regardless.
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
this,
|
||||
"eventPagesEnabled",
|
||||
"extensions.eventPages.enabled"
|
||||
);
|
||||
|
||||
var {
|
||||
GlobalManager,
|
||||
ParentAPIManager,
|
||||
@ -543,6 +550,7 @@ class ExtensionData {
|
||||
|
||||
this.errors = [];
|
||||
this.warnings = [];
|
||||
this.eventPagesEnabled = eventPagesEnabled;
|
||||
}
|
||||
|
||||
get builtinMessages() {
|
||||
@ -942,6 +950,24 @@ class ExtensionData {
|
||||
return this.manifest.manifest_version;
|
||||
}
|
||||
|
||||
get persistentBackground() {
|
||||
let { manifest } = this;
|
||||
if (
|
||||
!manifest.background ||
|
||||
manifest.background.service_worker ||
|
||||
this.manifestVersion > 2
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
// V2 addons can only use event pages if the pref is also flipped and
|
||||
// persistent is explicilty set to false.
|
||||
let { persistent } = manifest.background;
|
||||
if (!this.eventPagesEnabled && !persistent) {
|
||||
this.logWarning("Event pages are not currently supported.");
|
||||
}
|
||||
return !this.eventPagesEnabled || persistent;
|
||||
}
|
||||
|
||||
async getExtensionVersionWithoutValidation() {
|
||||
return (await this.readJSON("manifest.json")).version;
|
||||
}
|
||||
|
@ -2216,7 +2216,7 @@ class EventManager {
|
||||
*/
|
||||
static _initPersistentListeners(extension) {
|
||||
if (extension.persistentListeners) {
|
||||
return false;
|
||||
return !!extension.persistentListeners.size;
|
||||
}
|
||||
|
||||
let listeners = new DefaultMap(() => new DefaultMap(() => new Map()));
|
||||
@ -2266,7 +2266,7 @@ class EventManager {
|
||||
// in an extension's startup data.
|
||||
// This function is only called during browser startup, it stores details
|
||||
// about all primed listeners in the extension's persistentListeners Map.
|
||||
static primeListeners(extension) {
|
||||
static primeListeners(extension, isInStartup = false) {
|
||||
if (!EventManager._initPersistentListeners(extension)) {
|
||||
return;
|
||||
}
|
||||
@ -2305,7 +2305,8 @@ class EventManager {
|
||||
extension,
|
||||
event,
|
||||
fire,
|
||||
listener.params
|
||||
listener.params,
|
||||
isInStartup
|
||||
);
|
||||
if (handler) {
|
||||
listener.primed = primed;
|
||||
@ -2322,6 +2323,10 @@ class EventManager {
|
||||
// `clearPersistent` is false. If false, the listeners are cleared from
|
||||
// memory, but not removed from the extension's startup data.
|
||||
static clearPrimedListeners(extension, clearPersistent = true) {
|
||||
if (!extension.persistentListeners) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let [module, moduleEntry] of extension.persistentListeners) {
|
||||
for (let [event, listeners] of moduleEntry) {
|
||||
for (let [key, listener] of listeners) {
|
||||
|
@ -325,11 +325,14 @@ ExtensionTestCommon = class ExtensionTestCommon {
|
||||
if (data.background) {
|
||||
let bgScript = Services.uuid.generateUUID().number + ".js";
|
||||
|
||||
// If persistent is set keep the flag.
|
||||
let persistent = manifest.background?.persistent;
|
||||
let scriptKey = data.useServiceWorker
|
||||
? ["background", "service_worker"]
|
||||
: ["background", "scripts"];
|
||||
let scriptVal = data.useServiceWorker ? bgScript : [bgScript];
|
||||
provide(manifest, scriptKey, scriptVal, true);
|
||||
provide(manifest, ["background", "persistent"], persistent);
|
||||
|
||||
files[bgScript] = data.background;
|
||||
}
|
||||
|
@ -258,6 +258,14 @@ class ExtensionWrapper {
|
||||
this.state = "unloaded";
|
||||
}
|
||||
|
||||
/**
|
||||
* This method sends the message to force-sleep the background scripts.
|
||||
* @returns {Promise} resolves after the background is asleep and listeners primed.
|
||||
*/
|
||||
terminateBackground() {
|
||||
return this.extension.terminateBackground();
|
||||
}
|
||||
|
||||
/*
|
||||
* This method marks the extension unloading without actually calling
|
||||
* shutdown, since shutting down a MockExtension causes it to be uninstalled.
|
||||
|
@ -266,9 +266,12 @@ this.backgroundPage = class extends ExtensionAPI {
|
||||
return this.bgInstance.build();
|
||||
}
|
||||
|
||||
onManifestEntry(entryName) {
|
||||
async primeBackground(isInStartup = true) {
|
||||
let { extension } = this;
|
||||
|
||||
if (this.bgInstance) {
|
||||
Cu.reportError(`background script exists before priming ${extension.id}`);
|
||||
}
|
||||
this.bgInstance = null;
|
||||
|
||||
// When in PPB background pages all run in a private context. This check
|
||||
@ -300,11 +303,36 @@ this.backgroundPage = class extends ExtensionAPI {
|
||||
return bgStartupPromise;
|
||||
};
|
||||
|
||||
if (extension.startupReason !== "APP_STARTUP" || !DELAYED_STARTUP) {
|
||||
extension.terminateBackground = async () => {
|
||||
await bgStartupPromise;
|
||||
this.onShutdown(false);
|
||||
EventManager.clearPrimedListeners(this.extension, false);
|
||||
// Setup background startup listeners for next primed event.
|
||||
return this.primeBackground(false);
|
||||
};
|
||||
|
||||
extension.once("terminate-background-script", async () => {
|
||||
if (!this.extension) {
|
||||
// Extension was already shut down.
|
||||
return;
|
||||
}
|
||||
this.extension.terminateBackground();
|
||||
});
|
||||
|
||||
// Persistent backgrounds are started immediately except during APP_STARTUP.
|
||||
// Non-persistent backgrounds must be started immediately for new install or enable
|
||||
// to initialize the addon and create the persisted listeners.
|
||||
if (
|
||||
isInStartup &&
|
||||
(!DELAYED_STARTUP ||
|
||||
(extension.persistentBackground &&
|
||||
extension.startupReason !== "APP_STARTUP") ||
|
||||
["ADDON_INSTALL", "ADDON_ENABLE"].includes(extension.startupReason))
|
||||
) {
|
||||
return this.build();
|
||||
}
|
||||
|
||||
EventManager.primeListeners(extension);
|
||||
EventManager.primeListeners(extension, isInStartup);
|
||||
|
||||
extension.once("start-background-script", async () => {
|
||||
if (!this.extension) {
|
||||
@ -321,23 +349,50 @@ this.backgroundPage = class extends ExtensionAPI {
|
||||
// to touch browserPaintedPromise here to initialize the listener
|
||||
// or else we can miss it if the event occurs after the first
|
||||
// window is painted but before #2
|
||||
// 2. After all windows have been restored.
|
||||
// 2. After all windows have been restored on startup (see onManifestEntry).
|
||||
extension.once("background-script-event", async () => {
|
||||
await ExtensionParent.browserPaintedPromise;
|
||||
extension.emit("start-background-script");
|
||||
});
|
||||
|
||||
ExtensionParent.browserStartupPromise.then(() => {
|
||||
extension.emit("start-background-script");
|
||||
});
|
||||
}
|
||||
|
||||
onShutdown(isAppShutdown) {
|
||||
if (this.bgInstance) {
|
||||
this.bgInstance.shutdown(isAppShutdown);
|
||||
this.bgInstance = null;
|
||||
this.extension.emit("shutdown-background-script");
|
||||
} else {
|
||||
EventManager.clearPrimedListeners(this.extension, false);
|
||||
}
|
||||
}
|
||||
|
||||
async onManifestEntry(entryName) {
|
||||
let { extension } = this;
|
||||
|
||||
await this.primeBackground();
|
||||
|
||||
ExtensionParent.browserStartupPromise.then(() => {
|
||||
// If the background has been created earlier than session restore,
|
||||
// we do not want to continue with creating it here.
|
||||
if (this.bgInstance) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If there are no listeners for the extension that were persisted, we need to
|
||||
// start the event page so they can be registered.
|
||||
if (
|
||||
extension.persistentBackground ||
|
||||
!extension.persistentListeners?.size
|
||||
) {
|
||||
extension.emit("start-background-script");
|
||||
} else {
|
||||
// During startup we only prime startup blocking listeners. At
|
||||
// this stage we need to prime all listeners for event pages.
|
||||
EventManager.clearPrimedListeners(extension, false);
|
||||
// Allow re-priming by deleting existing listeners.
|
||||
extension.persistentListeners = null;
|
||||
EventManager.primeListeners(extension, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -126,9 +126,9 @@ function makeWebRequestEvent(context, name) {
|
||||
}
|
||||
|
||||
this.webRequest = class extends ExtensionAPI {
|
||||
primeListener(extension, event, fire, params) {
|
||||
primeListener(extension, event, fire, params, isInStartup) {
|
||||
// During early startup if the listener does not use blocking we do not prime it.
|
||||
if (params[1]?.includes("blocking")) {
|
||||
if (!isInStartup || params[1]?.includes("blocking")) {
|
||||
return registerEvent(extension, event, fire, ...params);
|
||||
}
|
||||
}
|
||||
|
@ -132,7 +132,9 @@
|
||||
"page": { "$ref": "ExtensionURL" },
|
||||
"persistent": {
|
||||
"optional": true,
|
||||
"$ref": "PersistentBackgroundProperty"
|
||||
"type": "boolean",
|
||||
"max_manifest_version": 2,
|
||||
"default": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": { "$ref": "UnrecognizedProperty" }
|
||||
@ -146,7 +148,9 @@
|
||||
},
|
||||
"persistent": {
|
||||
"optional": true,
|
||||
"$ref": "PersistentBackgroundProperty"
|
||||
"type": "boolean",
|
||||
"max_manifest_version": 2,
|
||||
"default": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": { "$ref": "UnrecognizedProperty" }
|
||||
@ -722,20 +726,6 @@
|
||||
"id": "UnrecognizedProperty",
|
||||
"type": "any",
|
||||
"deprecated": "An unexpected property was found in the WebExtension manifest."
|
||||
},
|
||||
{
|
||||
"id": "PersistentBackgroundProperty",
|
||||
"choices": [
|
||||
{
|
||||
"type": "boolean",
|
||||
"enum": [true]
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"enum": [false],
|
||||
"deprecated": "Event pages are not currently supported. This will run as a persistent background page."
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -9,6 +9,12 @@ Services.scriptloader.loadSubScript(
|
||||
this
|
||||
);
|
||||
|
||||
// Bug 1748665 remove when events will start serviceworker
|
||||
Services.prefs.setBoolPref(
|
||||
"extensions.webextensions.background-delayed-startup",
|
||||
false
|
||||
);
|
||||
|
||||
add_task(assert_background_serviceworker_pref_enabled);
|
||||
|
||||
add_task(async function test_serviceWorker_register_guarded_by_pref() {
|
||||
|
@ -1,6 +1,12 @@
|
||||
"use strict";
|
||||
|
||||
Services.prefs.setBoolPref("extensions.manifestV3.enabled", true);
|
||||
// Since we're not using AOM, and MV3 forces event pages, bypass
|
||||
// delayed-startup for MV3 test. These tests do not rely on startup events.
|
||||
Services.prefs.setBoolPref(
|
||||
"extensions.webextensions.background-delayed-startup",
|
||||
false
|
||||
);
|
||||
|
||||
const server = createHttpServer({ hosts: ["example.com"] });
|
||||
|
||||
|
@ -7,6 +7,12 @@ const { TestUtils } = ChromeUtils.import(
|
||||
);
|
||||
|
||||
Services.prefs.setBoolPref("extensions.manifestV3.enabled", true);
|
||||
// Since we're not using AOM, and MV3 forces event pages, bypass
|
||||
// delayed-startup for MV3 test. These tests do not rely on startup events.
|
||||
Services.prefs.setBoolPref(
|
||||
"extensions.webextensions.background-delayed-startup",
|
||||
false
|
||||
);
|
||||
|
||||
const server = createHttpServer({
|
||||
hosts: ["example.com", "csplog.example.net"],
|
||||
|
@ -153,6 +153,15 @@ async function promiseObservable(topic, count, fn = null) {
|
||||
return results;
|
||||
}
|
||||
|
||||
function trackEvents(wrapper) {
|
||||
let events = new Map();
|
||||
for (let event of ["background-script-event", "start-background-script"]) {
|
||||
events.set(event, false);
|
||||
wrapper.extension.once(event, () => events.set(event, true));
|
||||
}
|
||||
return events;
|
||||
}
|
||||
|
||||
add_task(async function setup() {
|
||||
Services.prefs.setBoolPref(
|
||||
"extensions.webextensions.background-delayed-startup",
|
||||
@ -526,3 +535,119 @@ add_task(async function test_shutdown_before_background_loaded() {
|
||||
|
||||
await AddonTestUtils.promiseShutdownManager();
|
||||
});
|
||||
|
||||
// This test checks whether primed listeners are correctly primed to
|
||||
// restart the background once the background has been shutdown or
|
||||
// put to sleep.
|
||||
add_task(async function test_background_restarted() {
|
||||
await AddonTestUtils.promiseStartupManager();
|
||||
// ensure normal delayed startup notification had already happened at some point
|
||||
Services.obs.notifyObservers(null, "browser-delayed-startup-finished");
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
useAddonManager: "permanent",
|
||||
background() {
|
||||
let listener = arg => browser.test.sendMessage("triggered", arg);
|
||||
browser.eventtest.onEvent1.addListener(listener, "triggered");
|
||||
browser.test.sendMessage("bg_started");
|
||||
},
|
||||
});
|
||||
await Promise.all([
|
||||
promiseObservable("register-event-listener", 1),
|
||||
extension.startup(),
|
||||
]);
|
||||
await extension.awaitMessage("bg_started");
|
||||
assertPersistentListeners(extension, "eventtest", "onEvent1", {
|
||||
primed: false,
|
||||
});
|
||||
|
||||
// Shutdown the background page
|
||||
await Promise.all([
|
||||
promiseObservable("unregister-event-listener", 1),
|
||||
extension.terminateBackground(),
|
||||
]);
|
||||
// When sleeping the background, its events should become persisted
|
||||
assertPersistentListeners(extension, "eventtest", "onEvent1", {
|
||||
primed: true,
|
||||
});
|
||||
|
||||
info("Triggering persistent event to force the background page to start");
|
||||
Services.obs.notifyObservers({ listenerArgs: 123 }, "fire-onEvent1");
|
||||
await extension.awaitMessage("bg_started");
|
||||
equal(await extension.awaitMessage("triggered"), 123, "triggered event");
|
||||
|
||||
await extension.unload();
|
||||
await AddonTestUtils.promiseShutdownManager();
|
||||
});
|
||||
|
||||
// This test checks whether primed listeners are correctly primed to
|
||||
// restart the background once the background has been shutdown or
|
||||
// put to sleep.
|
||||
add_task(async function test_eventpage_startup() {
|
||||
Services.prefs.setBoolPref("extensions.eventPages.enabled", true);
|
||||
await AddonTestUtils.promiseStartupManager();
|
||||
// ensure normal delayed startup notification had already happened at some point
|
||||
Services.obs.notifyObservers(null, "browser-delayed-startup-finished");
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
useAddonManager: "permanent",
|
||||
manifest: {
|
||||
applications: { gecko: { id: "eventpage@test" } },
|
||||
background: { persistent: false },
|
||||
},
|
||||
background() {
|
||||
let listener = arg => browser.test.sendMessage("triggered", arg);
|
||||
browser.eventtest.onEvent1.addListener(listener, "triggered");
|
||||
browser.test.sendMessage("bg_started");
|
||||
},
|
||||
});
|
||||
await Promise.all([
|
||||
promiseObservable("register-event-listener", 1),
|
||||
extension.startup(),
|
||||
]);
|
||||
await extension.awaitMessage("bg_started");
|
||||
|
||||
async function testAfterRestart() {
|
||||
assertPersistentListeners(extension, "eventtest", "onEvent1", {
|
||||
primed: true,
|
||||
});
|
||||
|
||||
let events = trackEvents(extension);
|
||||
ok(
|
||||
!events.get("background-script-event"),
|
||||
"Should not have received a background script event"
|
||||
);
|
||||
ok(
|
||||
!events.get("start-background-script"),
|
||||
"Background script should not be started"
|
||||
);
|
||||
|
||||
info("Triggering persistent event to force the background page to start");
|
||||
Services.obs.notifyObservers({ listenerArgs: 123 }, "fire-onEvent1");
|
||||
await extension.awaitMessage("bg_started");
|
||||
equal(await extension.awaitMessage("triggered"), 123, "triggered event");
|
||||
ok(
|
||||
events.get("background-script-event"),
|
||||
"Should have received a background script event"
|
||||
);
|
||||
ok(
|
||||
events.get("start-background-script"),
|
||||
"Background script should be started"
|
||||
);
|
||||
}
|
||||
|
||||
// Shutdown the background page
|
||||
await AddonTestUtils.promiseRestartManager();
|
||||
await extension.awaitStartup();
|
||||
await testAfterRestart();
|
||||
|
||||
// We sleep twice to ensure startup and shutdown work correctly
|
||||
await extension.terminateBackground();
|
||||
await testAfterRestart();
|
||||
await extension.terminateBackground();
|
||||
await testAfterRestart();
|
||||
|
||||
await extension.unload();
|
||||
await AddonTestUtils.promiseShutdownManager();
|
||||
Services.prefs.setBoolPref("extensions.eventPages.enabled", false);
|
||||
});
|
||||
|
@ -52,10 +52,10 @@ function trackEvents(wrapper) {
|
||||
* expect the starting event
|
||||
* @param {boolean} expect.request wait for the request event
|
||||
*/
|
||||
async function testPersistentRequestStartup(extension, events, expect) {
|
||||
async function testPersistentRequestStartup(extension, events, expect = {}) {
|
||||
equal(
|
||||
events.get("background-script-event"),
|
||||
expect.background,
|
||||
!!expect.background,
|
||||
"Should have gotten a background script event"
|
||||
);
|
||||
equal(
|
||||
@ -70,7 +70,7 @@ async function testPersistentRequestStartup(extension, events, expect) {
|
||||
|
||||
equal(
|
||||
events.get("start-background-script"),
|
||||
expect.delayedStart,
|
||||
!!expect.delayedStart,
|
||||
"Should have gotten start-background-script event"
|
||||
);
|
||||
}
|
||||
@ -162,6 +162,80 @@ add_task(async function test_nonblocking() {
|
||||
await promiseShutdownManager();
|
||||
});
|
||||
|
||||
// Test that a non-blocking listener does not start the background on
|
||||
// startup, but that it does work after startup.
|
||||
add_task(async function test_eventpage_nonblocking() {
|
||||
Services.prefs.setBoolPref("extensions.eventPages.enabled", true);
|
||||
await promiseStartupManager();
|
||||
|
||||
let id = "event-nonblocking@test";
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
useAddonManager: "permanent",
|
||||
manifest: {
|
||||
applications: { gecko: { id } },
|
||||
permissions: ["webRequest", "http://example.com/"],
|
||||
background: { persistent: false },
|
||||
},
|
||||
|
||||
background() {
|
||||
browser.webRequest.onBeforeRequest.addListener(
|
||||
details => {
|
||||
browser.test.sendMessage("got-request");
|
||||
},
|
||||
{ urls: ["http://example.com/data/file_sample.html"] }
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
// First install runs background immediately, this sets persistent listeners
|
||||
await extension.startup();
|
||||
|
||||
// Restart to get APP_STARTUP, the background should not start
|
||||
await promiseRestartManager();
|
||||
await extension.awaitStartup();
|
||||
assertPersistentListeners(extension, "webRequest", "onBeforeRequest", {
|
||||
primed: false,
|
||||
});
|
||||
|
||||
// Test an early startup event
|
||||
let events = trackEvents(extension);
|
||||
|
||||
await ExtensionTestUtils.fetch(
|
||||
"http://example.com/",
|
||||
"http://example.com/data/file_sample.html"
|
||||
);
|
||||
|
||||
await testPersistentRequestStartup(extension, events);
|
||||
|
||||
Services.obs.notifyObservers(null, "sessionstore-windows-restored");
|
||||
await ExtensionParent.browserStartupPromise;
|
||||
// After late startup, event page listeners should be primed.
|
||||
assertPersistentListeners(extension, "webRequest", "onBeforeRequest", {
|
||||
primed: true,
|
||||
});
|
||||
|
||||
// We should not have seen any events yet.
|
||||
await testPersistentRequestStartup(extension, events);
|
||||
|
||||
// Test an event after startup
|
||||
await ExtensionTestUtils.fetch(
|
||||
"http://example.com/",
|
||||
"http://example.com/data/file_sample.html"
|
||||
);
|
||||
|
||||
// Now the event page should be started and we'll see the request.
|
||||
await testPersistentRequestStartup(extension, events, {
|
||||
background: true,
|
||||
started: true,
|
||||
request: true,
|
||||
});
|
||||
|
||||
await extension.unload();
|
||||
|
||||
await promiseShutdownManager();
|
||||
Services.prefs.setBoolPref("extensions.eventPages.enabled", false);
|
||||
});
|
||||
|
||||
// Tests that filters are handled properly: if we have a blocking listener
|
||||
// with a filter, a request that does not match the filter does not get
|
||||
// suspended and does not start the background page.
|
||||
|
@ -3,6 +3,12 @@
|
||||
const HOSTS = new Set(["example.com"]);
|
||||
|
||||
Services.prefs.setBoolPref("extensions.manifestV3.enabled", true);
|
||||
// Since we're not using AOM, and MV3 forces event pages, bypass
|
||||
// delayed-startup for MV3 test. These tests do not rely on startup events.
|
||||
Services.prefs.setBoolPref(
|
||||
"extensions.webextensions.background-delayed-startup",
|
||||
false
|
||||
);
|
||||
|
||||
const server = createHttpServer({ hosts: HOSTS });
|
||||
|
||||
|
@ -12,6 +12,7 @@ prefs =
|
||||
extensions.backgroundServiceWorker.enabled=true
|
||||
extensions.backgroundServiceWorker.forceInTestExtension=true
|
||||
extensions.webextensions.remote=true
|
||||
extensions.webextensions.background-delayed-startup=false
|
||||
|
||||
[test_ext_background_service_worker.js]
|
||||
[test_ext_alarms.js]
|
||||
|
Loading…
Reference in New Issue
Block a user