1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
8 function debug(s) { dump("-*- NotificationStorage.js: " + s + "\n"); }
10 const Cc = Components.classes;
11 const Ci = Components.interfaces;
12 const Cu = Components.utils;
14 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
16 const NOTIFICATIONSTORAGE_CID = "{37f819b0-0b5c-11e3-8ffd-0800200c9a66}";
17 const NOTIFICATIONSTORAGE_CONTRACTID = "@mozilla.org/notificationStorage;1";
19 XPCOMUtils.defineLazyModuleGetter(this, "Services",
20 "resource://gre/modules/Services.jsm");
22 XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
23 "@mozilla.org/childprocessmessagemanager;1",
26 const kMessageNotificationGetAllOk = "Notification:GetAll:Return:OK";
27 const kMessageNotificationGetAllKo = "Notification:GetAll:Return:KO";
28 const kMessageNotificationSaveKo = "Notification:Save:Return:KO";
29 const kMessageNotificationDeleteKo = "Notification:Delete:Return:KO";
32 kMessageNotificationGetAllOk,
33 kMessageNotificationGetAllKo,
34 kMessageNotificationSaveKo,
35 kMessageNotificationDeleteKo
38 function NotificationStorage() {
40 this._notifications = {};
45 this._requestCount = 0;
47 Services.obs.addObserver(this, "xpcom-shutdown", false);
48 // Register for message listeners.
49 this.registerListeners();
52 NotificationStorage.prototype = {
54 registerListeners: function() {
55 for (let message of kMessages) {
56 cpmm.addMessageListener(message, this);
60 unregisterListeners: function() {
61 for (let message of kMessages) {
62 cpmm.removeMessageListener(message, this);
66 observe: function(aSubject, aTopic, aData) {
67 if (DEBUG) debug("Topic: " + aTopic);
68 if (aTopic == "xpcom-shutdown") {
69 Services.obs.removeObserver(this, "xpcom-shutdown");
70 this.unregisterListeners();
74 put: function(origin, id, title, dir, lang, body, tag, icon, alertName,
76 if (DEBUG) { debug("PUT: " + id + ": " + title); }
86 timestamp: new Date().getTime(),
91 this._notifications[id] = notification;
93 if (!this._byTag[origin]) {
94 this._byTag[origin] = {};
97 // We might have existing notification with this tag,
98 // if so we need to remove it from our cache.
99 if (this._byTag[origin][tag]) {
100 var oldNotification = this._byTag[origin][tag];
101 delete this._notifications[oldNotification.id];
104 this._byTag[origin][tag] = notification;
107 cpmm.sendAsyncMessage("Notification:Save", {
109 notification: notification
113 get: function(origin, tag, callback) {
114 if (DEBUG) { debug("GET: " + origin + " " + tag); }
116 this._fetchFromCache(origin, tag, callback);
118 this._fetchFromDB(origin, tag, callback);
122 delete: function(origin, id) {
123 if (DEBUG) { debug("DELETE: " + id); }
124 var notification = this._notifications[id];
126 if (notification.tag) {
127 delete this._byTag[origin][notification.tag];
129 delete this._notifications[id];
132 cpmm.sendAsyncMessage("Notification:Delete", {
138 receiveMessage: function(message) {
139 var request = this._requests[message.data.requestID];
141 switch (message.name) {
142 case kMessageNotificationGetAllOk:
143 delete this._requests[message.data.requestID];
144 this._populateCache(message.data.notifications);
145 this._fetchFromCache(request.origin, request.tag, request.callback);
148 case kMessageNotificationGetAllKo:
149 delete this._requests[message.data.requestID];
151 request.callback.done();
153 debug("Error calling callback done: " + e);
155 case kMessageNotificationSaveKo:
156 case kMessageNotificationDeleteKo:
158 debug("Error received when treating: '" + message.name +
159 "': " + message.data.errorMsg);
164 if (DEBUG) debug("Unrecognized message: " + message.name);
169 _fetchFromDB: function(origin, tag, callback) {
175 var requestID = this._requestCount++;
176 this._requests[requestID] = request;
177 cpmm.sendAsyncMessage("Notification:GetAll", {
183 _fetchFromCache: function(origin, tag, callback) {
184 var notifications = [];
185 // If a tag was specified and we have a notification
186 // with this tag, return that. If no tag was specified
187 // simple return all stored notifications.
188 if (tag && this._byTag[origin] && this._byTag[origin][tag]) {
189 notifications.push(this._byTag[origin][tag]);
191 for (var id in this._notifications) {
192 if (this._notifications[id].origin === origin) {
193 notifications.push(this._notifications[id]);
198 // Pass each notification back separately.
199 notifications.forEach(function(notification) {
201 callback.handle(notification.id,
210 if (DEBUG) { debug("Error calling callback handle: " + e); }
216 if (DEBUG) { debug("Error calling callback done: " + e); }
220 _populateCache: function(notifications) {
221 notifications.forEach(function(notification) {
222 this._notifications[notification.id] = notification;
223 if (notification.tag && notification.origin) {
224 let tag = notification.tag;
225 let origin = notification.origin;
226 if (!this._byTag[origin]) {
227 this._byTag[origin] = {};
229 this._byTag[origin][tag] = notification;
235 classID : Components.ID(NOTIFICATIONSTORAGE_CID),
236 contractID : NOTIFICATIONSTORAGE_CONTRACTID,
237 QueryInterface: XPCOMUtils.generateQI([Ci.nsINotificationStorage,
238 Ci.nsIMessageListener]),
242 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NotificationStorage]);