diff -r 000000000000 -r 6474c204b198 dom/datastore/DataStoreChangeNotifier.jsm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dom/datastore/DataStoreChangeNotifier.jsm Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,132 @@ +/* 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" + +const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; + +this.EXPORTED_SYMBOLS = ["DataStoreChangeNotifier"]; + +function debug(s) { + //dump('DEBUG DataStoreChangeNotifier: ' + s + '\n'); +} + +// DataStoreServiceInternal should not be converted into a lazy getter as it +// runs code during initialization. +Cu.import('resource://gre/modules/DataStoreServiceInternal.jsm'); +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); + +XPCOMUtils.defineLazyServiceGetter(this, "ppmm", + "@mozilla.org/parentprocessmessagemanager;1", + "nsIMessageBroadcaster"); + +this.DataStoreChangeNotifier = { + children: [], + messages: [ "DataStore:Changed", "DataStore:RegisterForMessages", + "DataStore:UnregisterForMessages", + "child-process-shutdown" ], + + init: function() { + debug("init"); + + this.messages.forEach((function(msgName) { + ppmm.addMessageListener(msgName, this); + }).bind(this)); + + Services.obs.addObserver(this, 'xpcom-shutdown', false); + }, + + observe: function(aSubject, aTopic, aData) { + debug("observe"); + + switch (aTopic) { + case 'xpcom-shutdown': + this.messages.forEach((function(msgName) { + ppmm.removeMessageListener(msgName, this); + }).bind(this)); + + Services.obs.removeObserver(this, 'xpcom-shutdown'); + ppmm = null; + break; + + default: + debug("Wrong observer topic: " + aTopic); + break; + } + }, + + broadcastMessage: function broadcastMessage(aData) { + debug("Broadast"); + this.children.forEach(function(obj) { + if (obj.store == aData.store && obj.owner == aData.owner) { + obj.mm.sendAsyncMessage("DataStore:Changed:Return:OK", aData); + } + }); + }, + + + receiveMessage: function(aMessage) { + debug("receiveMessage"); + + // No check has to be done when the message is 'child-process-shutdown' + // because at this point the target is already disconnected from + // nsFrameMessageManager, so that assertAppHasStatus will always fail. + let prefName = 'dom.testing.datastore_enabled_for_hosted_apps'; + if (aMessage.name != 'child-process-shutdown' && + (Services.prefs.getPrefType(prefName) == Services.prefs.PREF_INVALID || + !Services.prefs.getBoolPref(prefName)) && + !aMessage.target.assertAppHasStatus(Ci.nsIPrincipal.APP_STATUS_CERTIFIED)) { + return; + } + + switch (aMessage.name) { + case "DataStore:Changed": + this.broadcastMessage(aMessage.data); + break; + + case "DataStore:RegisterForMessages": + debug("Register!"); + + for (let i = 0; i < this.children.length; ++i) { + if (this.children[i].mm == aMessage.target && + this.children[i].store == aMessage.data.store && + this.children[i].owner == aMessage.data.owner) { + debug("Register on existing index: " + i); + ++this.children[i].count; + return; + } + } + + this.children.push({ mm: aMessage.target, + store: aMessage.data.store, + owner: aMessage.data.owner, + count: 1 }); + break; + + case "child-process-shutdown": + case "DataStore:UnregisterForMessages": + debug("Unregister"); + + for (let i = 0; i < this.children.length;) { + if (this.children[i].mm == aMessage.target) { + debug("Unregister index: " + i); + if (!--this.children[i].count) { + debug("Unregister delete index: " + i); + this.children.splice(i, 1); + } + break; + } else { + ++i; + } + } + break; + + default: + debug("Wrong message: " + aMessage.name); + } + } +} + +DataStoreChangeNotifier.init();