/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ "use strict"; // The ext-* files are imported into the same scopes. /* import-globals-from ext-toolkit.js */ // Manages an alarm created by the extension (alarms API). class Alarm { constructor(api, name, alarmInfo) { this.api = api; this.name = name; this.when = alarmInfo.when; this.delayInMinutes = alarmInfo.delayInMinutes; this.periodInMinutes = alarmInfo.periodInMinutes; this.canceled = false; let delay, scheduledTime; if (this.when) { scheduledTime = this.when; delay = this.when - Date.now(); } else { if (!this.delayInMinutes) { this.delayInMinutes = this.periodInMinutes; } 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; } clear() { this.timer.cancel(); this.api.alarms.delete(this.name); this.canceled = true; } observe() { if (this.canceled) { return; } for (let callback of this.api.callbacks) { callback(this); } if (!this.periodInMinutes) { this.clear(); return; } let delay = this.periodInMinutes * 60 * 1000; this.scheduledTime = Date.now() + delay; this.timer.init(this, delay, Ci.nsITimer.TYPE_ONE_SHOT); } get data() { return { name: this.name, scheduledTime: this.scheduledTime, periodInMinutes: this.periodInMinutes, }; } } this.alarms = class extends ExtensionAPIPersistent { constructor(extension) { super(extension); this.alarms = new Map(); this.callbacks = new Set(); } onShutdown() { for (let alarm of this.alarms.values()) { alarm.clear(); } } PERSISTENT_EVENTS = { onAlarm({ fire }) { let callback = alarm => { fire.sync(alarm.data); }; this.callbacks.add(callback); return { unregister: () => { this.callbacks.delete(callback); }, convert(_fire) { fire = _fire; }, }; }, }; getAPI(context) { const self = this; return { alarms: { create: function (name, alarmInfo) { name = name || ""; if (self.alarms.has(name)) { self.alarms.get(name).clear(); } let alarm = new Alarm(self, name, alarmInfo); self.alarms.set(alarm.name, alarm); }, get: function (name) { name = name || ""; if (self.alarms.has(name)) { return Promise.resolve(self.alarms.get(name).data); } return Promise.resolve(); }, getAll: function () { let result = Array.from(self.alarms.values(), alarm => alarm.data); return Promise.resolve(result); }, clear: function (name) { name = name || ""; if (self.alarms.has(name)) { self.alarms.get(name).clear(); return Promise.resolve(true); } return Promise.resolve(false); }, clearAll: function () { let cleared = false; for (let alarm of self.alarms.values()) { alarm.clear(); cleared = true; } return Promise.resolve(cleared); }, onAlarm: new EventManager({ context, module: "alarms", event: "onAlarm", extensionApi: self, }).api(), }, }; } };