diff options
Diffstat (limited to 'dom/notification/old/NotificationDB.sys.mjs')
-rw-r--r-- | dom/notification/old/NotificationDB.sys.mjs | 222 |
1 files changed, 122 insertions, 100 deletions
diff --git a/dom/notification/old/NotificationDB.sys.mjs b/dom/notification/old/NotificationDB.sys.mjs index 8cd2bff8f6..7cd7e6f926 100644 --- a/dom/notification/old/NotificationDB.sys.mjs +++ b/dom/notification/old/NotificationDB.sys.mjs @@ -21,64 +21,84 @@ const NOTIFICATION_STORE_PATH = PathUtils.join( "notificationstore.json" ); -const kMessages = [ - "Notification:Save", - "Notification:Delete", - "Notification:GetAll", -]; - -var NotificationDB = { +export class NotificationDB { // Ensure we won't call init() while xpcom-shutdown is performed - _shutdownInProgress: false, + #shutdownInProgress = false; // A promise that resolves once the ongoing task queue has been drained. // The value will be reset when the queue starts again. - _queueDrainedPromise: null, - _queueDrainedPromiseResolve: null, - - init() { - if (this._shutdownInProgress) { + #queueDrainedPromise = null; + #queueDrainedPromiseResolve = null; + + #byTag = Object.create(null); + #notifications = Object.create(null); + #loaded = false; + #tasks = []; + #runningTask = null; + + storageQualifier() { + return "Notification"; + } + + prefixStorageQualifier(message) { + return `${this.storageQualifier()}:${message}`; + } + + formatMessageType(message) { + return this.prefixStorageQualifier(message); + } + + supportedMessageTypes() { + return [ + this.formatMessageType("Save"), + this.formatMessageType("Delete"), + this.formatMessageType("GetAll"), + ]; + } + + constructor() { + if (this.#shutdownInProgress) { return; } - this.notifications = Object.create(null); - this.byTag = Object.create(null); - this.loaded = false; + this.#notifications = Object.create(null); + this.#byTag = Object.create(null); + this.#loaded = false; - this.tasks = []; // read/write operation queue - this.runningTask = null; + this.#tasks = []; // read/write operation queue + this.#runningTask = null; Services.obs.addObserver(this, "xpcom-shutdown"); this.registerListeners(); // This assumes that nothing will queue a new task at profile-change-teardown phase, - // potentially replacing the _queueDrainedPromise if there was no existing task run. + // potentially replacing the #queueDrainedPromise if there was no existing task run. lazy.AsyncShutdown.profileChangeTeardown.addBlocker( "NotificationDB: Need to make sure that all notification messages are processed", - () => this._queueDrainedPromise + () => this.#queueDrainedPromise ); - }, + } registerListeners() { - for (let message of kMessages) { + for (let message of this.supportedMessageTypes()) { Services.ppmm.addMessageListener(message, this); } - }, + } unregisterListeners() { - for (let message of kMessages) { + for (let message of this.supportedMessageTypes()) { Services.ppmm.removeMessageListener(message, this); } - }, + } observe(aSubject, aTopic) { lazy.console.debug(`Topic: ${aTopic}`); if (aTopic == "xpcom-shutdown") { - this._shutdownInProgress = true; + this.#shutdownInProgress = true; Services.obs.removeObserver(this, "xpcom-shutdown"); this.unregisterListeners(); } - }, + } filterNonAppNotifications(notifications) { let result = Object.create(null); @@ -100,7 +120,7 @@ var NotificationDB = { } return result; - }, + } // Attempt to read notification file, if it's not there we will create it. load() { @@ -110,32 +130,34 @@ var NotificationDB = { if (data.length) { // Preprocessing phase intends to cleanly separate any migration-related // tasks. - this.notifications = this.filterNonAppNotifications(JSON.parse(data)); + this.#notifications = this.filterNonAppNotifications( + JSON.parse(data) + ); } // populate the list of notifications by tag - if (this.notifications) { - for (var origin in this.notifications) { - this.byTag[origin] = Object.create(null); - for (var id in this.notifications[origin]) { - var curNotification = this.notifications[origin][id]; + if (this.#notifications) { + for (var origin in this.#notifications) { + this.#byTag[origin] = Object.create(null); + for (var id in this.#notifications[origin]) { + var curNotification = this.#notifications[origin][id]; if (curNotification.tag) { - this.byTag[origin][curNotification.tag] = curNotification; + this.#byTag[origin][curNotification.tag] = curNotification; } } } } - this.loaded = true; + this.#loaded = true; }, // If read failed, we assume we have no notifications to load. () => { - this.loaded = true; + this.#loaded = true; return this.createStore(); } ); - }, + } // Creates the notification directory. createStore() { @@ -143,30 +165,30 @@ var NotificationDB = { ignoreExisting: true, }); return promise.then(this.createFile.bind(this)); - }, + } // Creates the notification file once the directory is created. createFile() { return IOUtils.writeUTF8(NOTIFICATION_STORE_PATH, "", { tmpPath: NOTIFICATION_STORE_PATH + ".tmp", }); - }, + } // Save current notifications to the file. save() { - var data = JSON.stringify(this.notifications); + var data = JSON.stringify(this.#notifications); return IOUtils.writeUTF8(NOTIFICATION_STORE_PATH, data, { tmpPath: NOTIFICATION_STORE_PATH + ".tmp", }); - }, + } // Helper function: promise will be resolved once file exists and/or is loaded. - ensureLoaded() { - if (!this.loaded) { + #ensureLoaded() { + if (!this.#loaded) { return this.load(); } return Promise.resolve(); - }, + } receiveMessage(message) { lazy.console.debug(`Received message: ${message.name}`); @@ -182,17 +204,17 @@ var NotificationDB = { } switch (message.name) { - case "Notification:GetAll": + case this.formatMessageType("GetAll"): this.queueTask("getall", message.data) - .then(function (notifications) { - returnMessage("Notification:GetAll:Return:OK", { + .then(notifications => { + returnMessage(this.formatMessageType("GetAll:Return:OK"), { requestID: message.data.requestID, origin: message.data.origin, notifications, }); }) - .catch(function (error) { - returnMessage("Notification:GetAll:Return:KO", { + .catch(error => { + returnMessage(this.formatMessageType("GetAll:Return:KO"), { requestID: message.data.requestID, origin: message.data.origin, errorMsg: error, @@ -200,30 +222,30 @@ var NotificationDB = { }); break; - case "Notification:Save": + case this.formatMessageType("Save"): this.queueTask("save", message.data) - .then(function () { - returnMessage("Notification:Save:Return:OK", { + .then(() => { + returnMessage(this.formatMessageType("Save:Return:OK"), { requestID: message.data.requestID, }); }) - .catch(function (error) { - returnMessage("Notification:Save:Return:KO", { + .catch(error => { + returnMessage(this.formatMessageType("Save:Return:KO"), { requestID: message.data.requestID, errorMsg: error, }); }); break; - case "Notification:Delete": + case this.formatMessageType("Delete"): this.queueTask("delete", message.data) - .then(function () { - returnMessage("Notification:Delete:Return:OK", { + .then(() => { + returnMessage(this.formatMessageType("Delete:Return:OK"), { requestID: message.data.requestID, }); }) - .catch(function (error) { - returnMessage("Notification:Delete:Return:KO", { + .catch(error => { + returnMessage(this.formatMessageType("Delete:Return:KO"), { requestID: message.data.requestID, errorMsg: error, }); @@ -233,7 +255,7 @@ var NotificationDB = { default: lazy.console.debug(`Invalid message name ${message.name}`); } - }, + } // We need to make sure any read/write operations are atomic, // so use a queue to run each operation sequentially. @@ -242,48 +264,48 @@ var NotificationDB = { var defer = {}; - this.tasks.push({ + this.#tasks.push({ operation, data, defer, }); - var promise = new Promise(function (resolve, reject) { + var promise = new Promise((resolve, reject) => { defer.resolve = resolve; defer.reject = reject; }); // Only run immediately if we aren't currently running another task. - if (!this.runningTask) { + if (!this.#runningTask) { lazy.console.debug("Task queue was not running, starting now..."); this.runNextTask(); - this._queueDrainedPromise = new Promise(resolve => { - this._queueDrainedPromiseResolve = resolve; + this.#queueDrainedPromise = new Promise(resolve => { + this.#queueDrainedPromiseResolve = resolve; }); } return promise; - }, + } runNextTask() { - if (this.tasks.length === 0) { + if (this.#tasks.length === 0) { lazy.console.debug("No more tasks to run, queue depleted"); - this.runningTask = null; - if (this._queueDrainedPromiseResolve) { - this._queueDrainedPromiseResolve(); + this.#runningTask = null; + if (this.#queueDrainedPromiseResolve) { + this.#queueDrainedPromiseResolve(); } else { lazy.console.debug( - "_queueDrainedPromiseResolve was null somehow, no promise to resolve" + "#queueDrainedPromiseResolve was null somehow, no promise to resolve" ); } return; } - this.runningTask = this.tasks.shift(); + this.#runningTask = this.#tasks.shift(); // Always make sure we are loaded before performing any read/write tasks. - this.ensureLoaded() + this.#ensureLoaded() .then(() => { - var task = this.runningTask; + var task = this.#runningTask; switch (task.operation) { case "getall": @@ -302,85 +324,85 @@ var NotificationDB = { } }) .then(payload => { - lazy.console.debug(`Finishing task: ${this.runningTask.operation}`); - this.runningTask.defer.resolve(payload); + lazy.console.debug(`Finishing task: ${this.#runningTask.operation}`); + this.#runningTask.defer.resolve(payload); }) .catch(err => { lazy.console.debug( - `Error while running ${this.runningTask.operation}: ${err}` + `Error while running ${this.#runningTask.operation}: ${err}` ); - this.runningTask.defer.reject(err); + this.#runningTask.defer.reject(err); }) .then(() => { this.runNextTask(); }); - }, + } taskGetAll(data) { lazy.console.debug("Task, getting all"); var origin = data.origin; var notifications = []; // Grab only the notifications for specified origin. - if (this.notifications[origin]) { + if (this.#notifications[origin]) { if (data.tag) { let n; - if ((n = this.byTag[origin][data.tag])) { + if ((n = this.#byTag[origin][data.tag])) { notifications.push(n); } } else { - for (var i in this.notifications[origin]) { - notifications.push(this.notifications[origin][i]); + for (var i in this.#notifications[origin]) { + notifications.push(this.#notifications[origin][i]); } } } return Promise.resolve(notifications); - }, + } taskSave(data) { lazy.console.debug("Task, saving"); var origin = data.origin; var notification = data.notification; - if (!this.notifications[origin]) { - this.notifications[origin] = Object.create(null); - this.byTag[origin] = Object.create(null); + if (!this.#notifications[origin]) { + this.#notifications[origin] = Object.create(null); + this.#byTag[origin] = Object.create(null); } // We might have existing notification with this tag, // if so we need to remove it before saving the new one. if (notification.tag) { - var oldNotification = this.byTag[origin][notification.tag]; + var oldNotification = this.#byTag[origin][notification.tag]; if (oldNotification) { - delete this.notifications[origin][oldNotification.id]; + delete this.#notifications[origin][oldNotification.id]; } - this.byTag[origin][notification.tag] = notification; + this.#byTag[origin][notification.tag] = notification; } - this.notifications[origin][notification.id] = notification; + this.#notifications[origin][notification.id] = notification; return this.save(); - }, + } taskDelete(data) { lazy.console.debug("Task, deleting"); var origin = data.origin; var id = data.id; - if (!this.notifications[origin]) { + if (!this.#notifications[origin]) { lazy.console.debug(`No notifications found for origin: ${origin}`); return Promise.resolve(); } // Make sure we can find the notification to delete. - var oldNotification = this.notifications[origin][id]; + var oldNotification = this.#notifications[origin][id]; if (!oldNotification) { lazy.console.debug(`No notification found with id: ${id}`); return Promise.resolve(); } if (oldNotification.tag) { - delete this.byTag[origin][oldNotification.tag]; + delete this.#byTag[origin][oldNotification.tag]; } - delete this.notifications[origin][id]; + delete this.#notifications[origin][id]; return this.save(); - }, -}; + } +} -NotificationDB.init(); +new NotificationDB(); |