379 lines
11 KiB
JavaScript
379 lines
11 KiB
JavaScript
/* -*- 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";
|
|
|
|
AddonTestUtils.init(this);
|
|
AddonTestUtils.overrideCertDB();
|
|
AddonTestUtils.createAppInfo(
|
|
"xpcshell@tests.mozilla.org",
|
|
"XPCShell",
|
|
"1",
|
|
"43"
|
|
);
|
|
|
|
add_task(
|
|
{
|
|
// TODO(Bug 1725478): remove the skip if once webidl API bindings will be hidden based on permissions.
|
|
skip_if: () => ExtensionTestUtils.isInBackgroundServiceWorkerTests(),
|
|
},
|
|
async function test_alarm_without_permissions() {
|
|
function backgroundScript() {
|
|
browser.test.assertTrue(
|
|
!browser.alarms,
|
|
"alarm API is not available when the alarm permission is not required"
|
|
);
|
|
browser.test.notifyPass("alarms_permission");
|
|
}
|
|
|
|
let extension = ExtensionTestUtils.loadExtension({
|
|
background: `(${backgroundScript})()`,
|
|
manifest: {
|
|
permissions: [],
|
|
},
|
|
});
|
|
|
|
await extension.startup();
|
|
await extension.awaitFinish("alarms_permission");
|
|
await extension.unload();
|
|
}
|
|
);
|
|
|
|
add_task(async function test_alarm_clear_non_matching_name() {
|
|
async function backgroundScript() {
|
|
let ALARM_NAME = "test_ext_alarms";
|
|
|
|
browser.alarms.create(ALARM_NAME, { when: Date.now() + 2000000 });
|
|
|
|
let wasCleared = await browser.alarms.clear(ALARM_NAME + "1");
|
|
browser.test.assertFalse(wasCleared, "alarm was not cleared");
|
|
|
|
let alarms = await browser.alarms.getAll();
|
|
browser.test.assertEq(1, alarms.length, "alarm was not removed");
|
|
browser.test.notifyPass("alarm-clear");
|
|
}
|
|
|
|
let extension = ExtensionTestUtils.loadExtension({
|
|
background: `(${backgroundScript})()`,
|
|
manifest: {
|
|
permissions: ["alarms"],
|
|
},
|
|
});
|
|
|
|
await extension.startup();
|
|
await extension.awaitFinish("alarm-clear");
|
|
await extension.unload();
|
|
});
|
|
|
|
add_task(async function test_alarm_get_and_clear_single_argument() {
|
|
async function backgroundScript() {
|
|
browser.alarms.create({ when: Date.now() + 2000000 });
|
|
|
|
let alarm = await browser.alarms.get();
|
|
browser.test.assertEq("", alarm.name, "expected alarm returned");
|
|
|
|
let wasCleared = await browser.alarms.clear();
|
|
browser.test.assertTrue(wasCleared, "alarm was cleared");
|
|
|
|
let alarms = await browser.alarms.getAll();
|
|
browser.test.assertEq(0, alarms.length, "alarm was removed");
|
|
|
|
browser.test.notifyPass("alarm-single-arg");
|
|
}
|
|
|
|
let extension = ExtensionTestUtils.loadExtension({
|
|
background: `(${backgroundScript})()`,
|
|
manifest: {
|
|
permissions: ["alarms"],
|
|
},
|
|
});
|
|
|
|
await extension.startup();
|
|
await extension.awaitFinish("alarm-single-arg");
|
|
await extension.unload();
|
|
});
|
|
|
|
// This test case covers the behavior of browser.alarms.create when the
|
|
// first optional argument (the alarm name) is passed explicitly as null
|
|
// or undefined instead of being omitted.
|
|
add_task(async function test_alarm_name_arg_null_or_undefined() {
|
|
async function backgroundScript(alarmName) {
|
|
browser.alarms.create(alarmName, { when: Date.now() + 2000000 });
|
|
|
|
let alarm = await browser.alarms.get();
|
|
browser.test.assertTrue(alarm, "got an alarm");
|
|
browser.test.assertEq("", alarm.name, "expected alarm returned");
|
|
|
|
let wasCleared = await browser.alarms.clear();
|
|
browser.test.assertTrue(wasCleared, "alarm was cleared");
|
|
|
|
let alarms = await browser.alarms.getAll();
|
|
browser.test.assertEq(0, alarms.length, "alarm was removed");
|
|
|
|
browser.test.notifyPass("alarm-test-done");
|
|
}
|
|
|
|
for (const alarmName of [null, undefined]) {
|
|
info(`Test alarm.create with alarm name ${alarmName}`);
|
|
let extension = ExtensionTestUtils.loadExtension({
|
|
background: `(${backgroundScript})(${alarmName})`,
|
|
manifest: {
|
|
permissions: ["alarms"],
|
|
},
|
|
});
|
|
await extension.startup();
|
|
await extension.awaitFinish("alarm-test-done");
|
|
await extension.unload();
|
|
}
|
|
});
|
|
|
|
add_task(async function test_get_get_all_clear_all_alarms() {
|
|
async function backgroundScript() {
|
|
const ALARM_NAME = "test_alarm";
|
|
|
|
let suffixes = [0, 1, 2];
|
|
|
|
for (let suffix of suffixes) {
|
|
browser.alarms.create(ALARM_NAME + suffix, {
|
|
when: Date.now() + (suffix + 1) * 10000,
|
|
});
|
|
}
|
|
|
|
let alarms = await browser.alarms.getAll();
|
|
browser.test.assertEq(
|
|
suffixes.length,
|
|
alarms.length,
|
|
"expected number of alarms were found"
|
|
);
|
|
alarms.forEach((alarm, index) => {
|
|
browser.test.assertEq(
|
|
ALARM_NAME + index,
|
|
alarm.name,
|
|
"alarm has the expected name"
|
|
);
|
|
});
|
|
|
|
for (let suffix of suffixes) {
|
|
let alarm = await browser.alarms.get(ALARM_NAME + suffix);
|
|
browser.test.assertEq(
|
|
ALARM_NAME + suffix,
|
|
alarm.name,
|
|
"alarm has the expected name"
|
|
);
|
|
browser.test.sendMessage(`get-${suffix}`);
|
|
}
|
|
|
|
let wasCleared = await browser.alarms.clear(ALARM_NAME + suffixes[0]);
|
|
browser.test.assertTrue(wasCleared, "alarm was cleared");
|
|
|
|
alarms = await browser.alarms.getAll();
|
|
browser.test.assertEq(2, alarms.length, "alarm was removed");
|
|
|
|
let alarm = await browser.alarms.get(ALARM_NAME + suffixes[0]);
|
|
browser.test.assertEq(undefined, alarm, "non-existent alarm is undefined");
|
|
browser.test.sendMessage(`get-invalid`);
|
|
|
|
wasCleared = await browser.alarms.clearAll();
|
|
browser.test.assertTrue(wasCleared, "alarms were cleared");
|
|
|
|
alarms = await browser.alarms.getAll();
|
|
browser.test.assertEq(0, alarms.length, "no alarms exist");
|
|
browser.test.sendMessage("clearAll");
|
|
browser.test.sendMessage("clear");
|
|
browser.test.sendMessage("getAll");
|
|
}
|
|
|
|
let extension = ExtensionTestUtils.loadExtension({
|
|
background: `(${backgroundScript})()`,
|
|
manifest: {
|
|
permissions: ["alarms"],
|
|
},
|
|
});
|
|
|
|
await Promise.all([
|
|
extension.startup(),
|
|
extension.awaitMessage("getAll"),
|
|
extension.awaitMessage("get-0"),
|
|
extension.awaitMessage("get-1"),
|
|
extension.awaitMessage("get-2"),
|
|
extension.awaitMessage("clear"),
|
|
extension.awaitMessage("get-invalid"),
|
|
extension.awaitMessage("clearAll"),
|
|
]);
|
|
await extension.unload();
|
|
});
|
|
|
|
function getAlarmExtension(alarmCreateOptions, extOpts = {}) {
|
|
info(
|
|
`Test alarms.create fires with options: ${JSON.stringify(
|
|
alarmCreateOptions
|
|
)}`
|
|
);
|
|
|
|
function backgroundScript(createOptions) {
|
|
let ALARM_NAME = "test_ext_alarms";
|
|
let timer;
|
|
|
|
browser.alarms.onAlarm.addListener(alarm => {
|
|
browser.test.assertEq(
|
|
ALARM_NAME,
|
|
alarm.name,
|
|
"alarm has the expected name"
|
|
);
|
|
clearTimeout(timer);
|
|
browser.test.sendMessage("alarms-create-with-options");
|
|
});
|
|
|
|
browser.alarms.create(ALARM_NAME, createOptions);
|
|
|
|
timer = setTimeout(async () => {
|
|
browser.test.fail("alarm fired within expected time");
|
|
let wasCleared = await browser.alarms.clear(ALARM_NAME);
|
|
browser.test.assertTrue(wasCleared, "alarm was cleared");
|
|
browser.test.sendMessage("alarms-create-with-options");
|
|
}, 10000);
|
|
}
|
|
|
|
let { persistent, useAddonManager } = extOpts;
|
|
return ExtensionTestUtils.loadExtension({
|
|
useAddonManager,
|
|
// Pass the alarms.create options to the background page.
|
|
background: `(${backgroundScript})(${JSON.stringify(alarmCreateOptions)})`,
|
|
manifest: {
|
|
permissions: ["alarms"],
|
|
background: { persistent },
|
|
},
|
|
});
|
|
}
|
|
|
|
async function test_alarm_fires_with_options(alarmCreateOptions) {
|
|
let extension = getAlarmExtension(alarmCreateOptions);
|
|
|
|
await extension.startup();
|
|
await extension.awaitMessage("alarms-create-with-options");
|
|
|
|
// Defer unloading the extension so the asynchronous event listener
|
|
// reply finishes.
|
|
await new Promise(resolve => setTimeout(resolve, 0));
|
|
await extension.unload();
|
|
}
|
|
|
|
add_task(async function test_alarm_fires() {
|
|
Services.prefs.setBoolPref(
|
|
"privacy.resistFingerprinting.reduceTimerPrecision.jitter",
|
|
false
|
|
);
|
|
|
|
await test_alarm_fires_with_options({ delayInMinutes: 0.01 });
|
|
await test_alarm_fires_with_options({ when: Date.now() + 1000 });
|
|
await test_alarm_fires_with_options({ delayInMinutes: -10 });
|
|
await test_alarm_fires_with_options({ when: Date.now() - 1000 });
|
|
|
|
Services.prefs.clearUserPref(
|
|
"privacy.resistFingerprinting.reduceTimerPrecision.jitter"
|
|
);
|
|
});
|
|
|
|
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(
|
|
{
|
|
// TODO(Bug 1748665): remove the skip once background service worker is also
|
|
// woken up by persistent listeners.
|
|
skip_if: () => ExtensionTestUtils.isInBackgroundServiceWorkerTests(),
|
|
pref_set: [
|
|
["privacy.resistFingerprinting.reduceTimerPrecision.jitter", false],
|
|
["extensions.eventPages.enabled", true],
|
|
],
|
|
},
|
|
async function test_alarm_persists() {
|
|
await AddonTestUtils.promiseStartupManager();
|
|
|
|
let extension = getAlarmExtension(
|
|
{ periodInMinutes: 0.01 },
|
|
{ useAddonManager: "permanent", persistent: false }
|
|
);
|
|
info(`wait startup`);
|
|
await extension.startup();
|
|
assertPersistentListeners(extension, "alarms", "onAlarm", {
|
|
primed: false,
|
|
});
|
|
info(`wait first alarm`);
|
|
await extension.awaitMessage("alarms-create-with-options");
|
|
|
|
await extension.terminateBackground({ disableResetIdleForTest: true });
|
|
ok(
|
|
!extension.extension.backgroundContext,
|
|
"Background Extension context should have been destroyed"
|
|
);
|
|
|
|
assertPersistentListeners(extension, "alarms", "onAlarm", {
|
|
primed: true,
|
|
});
|
|
|
|
// Test an early startup event
|
|
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("waiting for alarm to wake background");
|
|
await extension.awaitMessage("alarms-create-with-options");
|
|
ok(
|
|
events.get("background-script-event"),
|
|
"Should have received a background script event"
|
|
);
|
|
ok(
|
|
events.get("start-background-script"),
|
|
"Background script should be started"
|
|
);
|
|
|
|
await extension.unload();
|
|
await AddonTestUtils.promiseShutdownManager();
|
|
}
|
|
);
|
|
|
|
add_task(async function test_alarms_create_return() {
|
|
function background() {
|
|
const ALARM_NAME = "test_ext_alarms";
|
|
const when = Date.now() + 2000000;
|
|
|
|
// test callback return
|
|
browser.alarms.create(ALARM_NAME, { when }, result => {
|
|
browser.test.assertEq(undefined, result, "no callback params");
|
|
browser.test.sendMessage("callback done");
|
|
});
|
|
|
|
// test promise return
|
|
browser.alarms.create(ALARM_NAME + 1, { when }).then(result => {
|
|
browser.test.assertEq(undefined, result, "no promise params");
|
|
browser.test.sendMessage("promise done");
|
|
});
|
|
}
|
|
|
|
const extension = ExtensionTestUtils.loadExtension({
|
|
manifest: {
|
|
permissions: ["alarms"],
|
|
},
|
|
background,
|
|
});
|
|
|
|
await extension.startup();
|
|
await Promise.all([
|
|
extension.awaitMessage("callback done"),
|
|
extension.awaitMessage("promise done"),
|
|
]);
|
|
await extension.unload();
|
|
});
|