dom/src/notification/NotificationStorage.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dom/src/notification/NotificationStorage.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,186 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +"use strict";
     1.9 +
    1.10 +const DEBUG = false;
    1.11 +function debug(s) { dump("-*- NotificationStorage.js: " + s + "\n"); }
    1.12 +
    1.13 +const Cc = Components.classes;
    1.14 +const Ci = Components.interfaces;
    1.15 +const Cu = Components.utils;
    1.16 +
    1.17 +Cu.import("resource://gre/modules/XPCOMUtils.jsm");
    1.18 +
    1.19 +const NOTIFICATIONSTORAGE_CID = "{37f819b0-0b5c-11e3-8ffd-0800200c9a66}";
    1.20 +const NOTIFICATIONSTORAGE_CONTRACTID = "@mozilla.org/notificationStorage;1";
    1.21 +
    1.22 +XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
    1.23 +                                   "@mozilla.org/childprocessmessagemanager;1",
    1.24 +                                   "nsIMessageSender");
    1.25 +
    1.26 +
    1.27 +function NotificationStorage() {
    1.28 +  // cache objects
    1.29 +  this._notifications = {};
    1.30 +  this._byTag = {};
    1.31 +  this._cached = false;
    1.32 +
    1.33 +  this._requests = {};
    1.34 +  this._requestCount = 0;
    1.35 +
    1.36 +  // Register for message listeners.
    1.37 +  cpmm.addMessageListener("Notification:GetAll:Return:OK", this);
    1.38 +}
    1.39 +
    1.40 +NotificationStorage.prototype = {
    1.41 +
    1.42 +  put: function(origin, id, title, dir, lang, body, tag, icon) {
    1.43 +    if (DEBUG) { debug("PUT: " + id + ": " + title); }
    1.44 +    var notification = {
    1.45 +      id: id,
    1.46 +      title: title,
    1.47 +      dir: dir,
    1.48 +      lang: lang,
    1.49 +      body: body,
    1.50 +      tag: tag,
    1.51 +      icon: icon,
    1.52 +      origin: origin
    1.53 +    };
    1.54 +
    1.55 +    this._notifications[id] = notification;
    1.56 +    if (tag) {
    1.57 +      if (!this._byTag[origin]) {
    1.58 +        this._byTag[origin] = {};
    1.59 +      }
    1.60 +
    1.61 +      // We might have existing notification with this tag,
    1.62 +      // if so we need to remove it from our cache.
    1.63 +      if (this._byTag[origin][tag]) {
    1.64 +        var oldNotification = this._byTag[origin][tag];
    1.65 +        delete this._notifications[oldNotification.id];
    1.66 +      }
    1.67 +
    1.68 +      this._byTag[origin][tag] = notification;
    1.69 +    };
    1.70 +
    1.71 +    cpmm.sendAsyncMessage("Notification:Save", {
    1.72 +      origin: origin,
    1.73 +      notification: notification
    1.74 +    });
    1.75 +  },
    1.76 +
    1.77 +  get: function(origin, tag, callback) {
    1.78 +    if (DEBUG) { debug("GET: " + origin + " " + tag); }
    1.79 +    if (this._cached) {
    1.80 +      this._fetchFromCache(origin, tag, callback);
    1.81 +    } else {
    1.82 +      this._fetchFromDB(origin, tag, callback);
    1.83 +    }
    1.84 +  },
    1.85 +
    1.86 +  delete: function(origin, id) {
    1.87 +    if (DEBUG) { debug("DELETE: " + id); }
    1.88 +    var notification = this._notifications[id];
    1.89 +    if (notification) {
    1.90 +      if (notification.tag) {
    1.91 +        delete this._byTag[origin][notification.tag];
    1.92 +      }
    1.93 +      delete this._notifications[id];
    1.94 +    }
    1.95 +
    1.96 +    cpmm.sendAsyncMessage("Notification:Delete", {
    1.97 +      origin: origin,
    1.98 +      id: id
    1.99 +    });
   1.100 +  },
   1.101 +
   1.102 +  receiveMessage: function(message) {
   1.103 +    switch (message.name) {
   1.104 +      case "Notification:GetAll:Return:OK":
   1.105 +        var request = this._requests[message.data.requestID];
   1.106 +        delete this._requests[message.data.requestID];
   1.107 +        this._populateCache(message.data.notifications);
   1.108 +        this._fetchFromCache(request.origin, request.tag, request.callback);
   1.109 +        break;
   1.110 +
   1.111 +      default:
   1.112 +        if (DEBUG) debug("Unrecognized message: " + message.name);
   1.113 +        break;
   1.114 +    }
   1.115 +  },
   1.116 +
   1.117 +  _fetchFromDB: function(origin, tag, callback) {
   1.118 +    var request = {
   1.119 +      origin: origin,
   1.120 +      tag: tag,
   1.121 +      callback: callback
   1.122 +    };
   1.123 +    var requestID = this._requestCount++;
   1.124 +    this._requests[requestID] = request;
   1.125 +    cpmm.sendAsyncMessage("Notification:GetAll", {
   1.126 +      origin: origin,
   1.127 +      requestID: requestID
   1.128 +    });
   1.129 +  },
   1.130 +
   1.131 +  _fetchFromCache: function(origin, tag, callback) {
   1.132 +    var notifications = [];
   1.133 +    // If a tag was specified and we have a notification
   1.134 +    // with this tag, return that. If no tag was specified
   1.135 +    // simple return all stored notifications.
   1.136 +    if (tag && this._byTag[origin] && this._byTag[origin][tag]) {
   1.137 +      notifications.push(this._byTag[origin][tag]);
   1.138 +    } else if (!tag) {
   1.139 +      for (var id in this._notifications) {
   1.140 +        if (this._notifications[id].origin === origin) {
   1.141 +          notifications.push(this._notifications[id]);
   1.142 +        }
   1.143 +      }
   1.144 +    }
   1.145 +
   1.146 +    // Pass each notification back separately.
   1.147 +    notifications.forEach(function(notification) {
   1.148 +      try {
   1.149 +        callback.handle(notification.id,
   1.150 +                        notification.title,
   1.151 +                        notification.dir,
   1.152 +                        notification.lang,
   1.153 +                        notification.body,
   1.154 +                        notification.tag,
   1.155 +                        notification.icon);
   1.156 +      } catch (e) {
   1.157 +        if (DEBUG) { debug("Error calling callback handle: " + e); }
   1.158 +      }
   1.159 +    });
   1.160 +    try {
   1.161 +      callback.done();
   1.162 +    } catch (e) {
   1.163 +      if (DEBUG) { debug("Error calling callback done: " + e); }
   1.164 +    }
   1.165 +  },
   1.166 +
   1.167 +  _populateCache: function(notifications) {
   1.168 +    notifications.forEach(function(notification) {
   1.169 +      this._notifications[notification.id] = notification;
   1.170 +      if (notification.tag && notification.origin) {
   1.171 +        let tag = notification.tag;
   1.172 +        let origin = notification.origin;
   1.173 +        if (!this._byTag[origin]) {
   1.174 +          this._byTag[origin] = {};
   1.175 +        }
   1.176 +        this._byTag[origin][tag] = notification;
   1.177 +      }
   1.178 +    }.bind(this));
   1.179 +    this._cached = true;
   1.180 +  },
   1.181 +
   1.182 +  classID : Components.ID(NOTIFICATIONSTORAGE_CID),
   1.183 +  contractID : NOTIFICATIONSTORAGE_CONTRACTID,
   1.184 +  QueryInterface: XPCOMUtils.generateQI([Ci.nsINotificationStorage,
   1.185 +                                         Ci.nsIMessageListener]),
   1.186 +};
   1.187 +
   1.188 +
   1.189 +this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NotificationStorage]);

mercurial