Bug 1478694 - Ensure that WebExtensions alarms set in the past are fired immediately. r=rpl
authordivyansh <sharma.divyansh.501@iitg.ernet.in>
Thu, 11 Oct 2018 19:22:21 +0000
changeset 499235 0c9456c0ba9afcb7bcd5b9ee3f6cf99e4d745fae
parent 499234 facb6f18068e502530ea84492166826d3c88d4f5
child 499236 a19bd92250b6d4c7ca6639c632bca4950d2b911d
push id1864
push userffxbld-merge
push dateMon, 03 Dec 2018 15:51:40 +0000
treeherdermozilla-release@f040763d99ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrpl
bugs1478694
milestone64.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1478694 - Ensure that WebExtensions alarms set in the past are fired immediately. r=rpl Bug 1478694 - Ensure that WebExtensions alarms set in the past are fired immediately. Differential Revision: https://phabricator.services.mozilla.com/D7287
toolkit/components/extensions/parent/ext-alarms.js
toolkit/components/extensions/test/xpcshell/test_ext_alarms.js
--- a/toolkit/components/extensions/parent/ext-alarms.js
+++ b/toolkit/components/extensions/parent/ext-alarms.js
@@ -22,16 +22,17 @@ function Alarm(api, name, alarmInfo) {
     }
     delay = this.delayInMinutes * 60 * 1000;
     scheduledTime = Date.now() + delay;
   }
 
   this.scheduledTime = scheduledTime;
 
   let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+  delay = delay > 0 ? delay : 0;
   timer.init(this, delay, Ci.nsITimer.TYPE_ONE_SHOT);
   this.timer = timer;
 }
 
 Alarm.prototype = {
   clear() {
     this.timer.cancel();
     this.api.alarms.delete(this.name);
--- a/toolkit/components/extensions/test/xpcshell/test_ext_alarms.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_alarms.js
@@ -19,93 +19,16 @@ add_task(async function test_alarm_witho
     },
   });
 
   await extension.startup();
   await extension.awaitFinish("alarms_permission");
   await extension.unload();
 });
 
-
-add_task(async function test_alarm_fires() {
-  function backgroundScript() {
-    let ALARM_NAME = "test_ext_alarms";
-    let timer;
-
-    browser.alarms.onAlarm.addListener(alarm => {
-      browser.test.assertEq(ALARM_NAME, alarm.name, "alarm has the correct name");
-      clearTimeout(timer);
-      browser.test.notifyPass("alarm-fires");
-    });
-
-    browser.alarms.create(ALARM_NAME, {delayInMinutes: 0.02});
-
-    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.notifyFail("alarm-fires");
-    }, 10000);
-  }
-
-  let extension = ExtensionTestUtils.loadExtension({
-    background: `(${backgroundScript})()`,
-    manifest: {
-      permissions: ["alarms"],
-    },
-  });
-
-  await extension.startup();
-  await extension.awaitFinish("alarm-fires");
-
-  // 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_with_when() {
-  function backgroundScript() {
-    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.notifyPass("alarm-when");
-    });
-
-    browser.alarms.create(ALARM_NAME, {when: Date.now() + 1000});
-
-    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.notifyFail("alarm-when");
-    }, 10000);
-  }
-
-  let extension = ExtensionTestUtils.loadExtension({
-    background: `(${backgroundScript})()`,
-    manifest: {
-      permissions: ["alarms"],
-    },
-  });
-
-  Services.prefs.setBoolPref("privacy.resistFingerprinting.reduceTimerPrecision.jitter", false);
-  await extension.startup();
-  await extension.awaitFinish("alarm-when");
-
-  // Defer unloading the extension so the asynchronous event listener
-  // reply finishes.
-  await new Promise(resolve => setTimeout(resolve, 0));
-  await extension.unload();
-  Services.prefs.clearUserPref("privacy.resistFingerprinting.reduceTimerPrecision.jitter");
-});
-
 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");
@@ -213,8 +136,59 @@ add_task(async function test_get_get_all
     extension.awaitMessage("get-1"),
     extension.awaitMessage("get-2"),
     extension.awaitMessage("clear"),
     extension.awaitMessage("get-invalid"),
     extension.awaitMessage("clearAll"),
   ]);
   await extension.unload();
 });
+
+async function test_alarm_fires_with_options(alarmCreateOptions) {
+  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.notifyPass("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.notifyFail("alarms-create-with-options");
+    }, 10000);
+  }
+
+  let extension = ExtensionTestUtils.loadExtension({
+    // Pass the alarms.create options to the background page.
+    background: `(${backgroundScript})(${JSON.stringify(alarmCreateOptions)})`,
+    manifest: {
+      permissions: ["alarms"],
+    },
+  });
+
+  await extension.startup();
+  await extension.awaitFinish("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");
+});