1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/datastore/DataStoreChangeNotifier.jsm Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,132 @@ 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 {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; 1.11 + 1.12 +this.EXPORTED_SYMBOLS = ["DataStoreChangeNotifier"]; 1.13 + 1.14 +function debug(s) { 1.15 + //dump('DEBUG DataStoreChangeNotifier: ' + s + '\n'); 1.16 +} 1.17 + 1.18 +// DataStoreServiceInternal should not be converted into a lazy getter as it 1.19 +// runs code during initialization. 1.20 +Cu.import('resource://gre/modules/DataStoreServiceInternal.jsm'); 1.21 +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); 1.22 +Cu.import("resource://gre/modules/Services.jsm"); 1.23 + 1.24 +XPCOMUtils.defineLazyServiceGetter(this, "ppmm", 1.25 + "@mozilla.org/parentprocessmessagemanager;1", 1.26 + "nsIMessageBroadcaster"); 1.27 + 1.28 +this.DataStoreChangeNotifier = { 1.29 + children: [], 1.30 + messages: [ "DataStore:Changed", "DataStore:RegisterForMessages", 1.31 + "DataStore:UnregisterForMessages", 1.32 + "child-process-shutdown" ], 1.33 + 1.34 + init: function() { 1.35 + debug("init"); 1.36 + 1.37 + this.messages.forEach((function(msgName) { 1.38 + ppmm.addMessageListener(msgName, this); 1.39 + }).bind(this)); 1.40 + 1.41 + Services.obs.addObserver(this, 'xpcom-shutdown', false); 1.42 + }, 1.43 + 1.44 + observe: function(aSubject, aTopic, aData) { 1.45 + debug("observe"); 1.46 + 1.47 + switch (aTopic) { 1.48 + case 'xpcom-shutdown': 1.49 + this.messages.forEach((function(msgName) { 1.50 + ppmm.removeMessageListener(msgName, this); 1.51 + }).bind(this)); 1.52 + 1.53 + Services.obs.removeObserver(this, 'xpcom-shutdown'); 1.54 + ppmm = null; 1.55 + break; 1.56 + 1.57 + default: 1.58 + debug("Wrong observer topic: " + aTopic); 1.59 + break; 1.60 + } 1.61 + }, 1.62 + 1.63 + broadcastMessage: function broadcastMessage(aData) { 1.64 + debug("Broadast"); 1.65 + this.children.forEach(function(obj) { 1.66 + if (obj.store == aData.store && obj.owner == aData.owner) { 1.67 + obj.mm.sendAsyncMessage("DataStore:Changed:Return:OK", aData); 1.68 + } 1.69 + }); 1.70 + }, 1.71 + 1.72 + 1.73 + receiveMessage: function(aMessage) { 1.74 + debug("receiveMessage"); 1.75 + 1.76 + // No check has to be done when the message is 'child-process-shutdown' 1.77 + // because at this point the target is already disconnected from 1.78 + // nsFrameMessageManager, so that assertAppHasStatus will always fail. 1.79 + let prefName = 'dom.testing.datastore_enabled_for_hosted_apps'; 1.80 + if (aMessage.name != 'child-process-shutdown' && 1.81 + (Services.prefs.getPrefType(prefName) == Services.prefs.PREF_INVALID || 1.82 + !Services.prefs.getBoolPref(prefName)) && 1.83 + !aMessage.target.assertAppHasStatus(Ci.nsIPrincipal.APP_STATUS_CERTIFIED)) { 1.84 + return; 1.85 + } 1.86 + 1.87 + switch (aMessage.name) { 1.88 + case "DataStore:Changed": 1.89 + this.broadcastMessage(aMessage.data); 1.90 + break; 1.91 + 1.92 + case "DataStore:RegisterForMessages": 1.93 + debug("Register!"); 1.94 + 1.95 + for (let i = 0; i < this.children.length; ++i) { 1.96 + if (this.children[i].mm == aMessage.target && 1.97 + this.children[i].store == aMessage.data.store && 1.98 + this.children[i].owner == aMessage.data.owner) { 1.99 + debug("Register on existing index: " + i); 1.100 + ++this.children[i].count; 1.101 + return; 1.102 + } 1.103 + } 1.104 + 1.105 + this.children.push({ mm: aMessage.target, 1.106 + store: aMessage.data.store, 1.107 + owner: aMessage.data.owner, 1.108 + count: 1 }); 1.109 + break; 1.110 + 1.111 + case "child-process-shutdown": 1.112 + case "DataStore:UnregisterForMessages": 1.113 + debug("Unregister"); 1.114 + 1.115 + for (let i = 0; i < this.children.length;) { 1.116 + if (this.children[i].mm == aMessage.target) { 1.117 + debug("Unregister index: " + i); 1.118 + if (!--this.children[i].count) { 1.119 + debug("Unregister delete index: " + i); 1.120 + this.children.splice(i, 1); 1.121 + } 1.122 + break; 1.123 + } else { 1.124 + ++i; 1.125 + } 1.126 + } 1.127 + break; 1.128 + 1.129 + default: 1.130 + debug("Wrong message: " + aMessage.name); 1.131 + } 1.132 + } 1.133 +} 1.134 + 1.135 +DataStoreChangeNotifier.init();