1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/settings/SettingsChangeNotifier.jsm Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,123 @@ 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) { 1.12 + if (DEBUG) dump("-*- SettingsChangeNotifier: " + s + "\n"); 1.13 +} 1.14 + 1.15 +const Cu = Components.utils; 1.16 +const Cc = Components.classes; 1.17 +const Ci = Components.interfaces; 1.18 + 1.19 +this.EXPORTED_SYMBOLS = ["SettingsChangeNotifier"]; 1.20 + 1.21 +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); 1.22 +Cu.import("resource://gre/modules/Services.jsm"); 1.23 + 1.24 +const kXpcomShutdownObserverTopic = "xpcom-shutdown"; 1.25 +const kMozSettingsChangedObserverTopic = "mozsettings-changed"; 1.26 +const kFromSettingsChangeNotifier = "fromSettingsChangeNotifier"; 1.27 + 1.28 +XPCOMUtils.defineLazyServiceGetter(this, "ppmm", 1.29 + "@mozilla.org/parentprocessmessagemanager;1", 1.30 + "nsIMessageBroadcaster"); 1.31 + 1.32 +this.SettingsChangeNotifier = { 1.33 + init: function() { 1.34 + if (DEBUG) debug("init"); 1.35 + this.children = []; 1.36 + this._messages = ["Settings:Changed", "Settings:RegisterForMessages", "child-process-shutdown"]; 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, kXpcomShutdownObserverTopic, false); 1.42 + Services.obs.addObserver(this, kMozSettingsChangedObserverTopic, false); 1.43 + }, 1.44 + 1.45 + observe: function(aSubject, aTopic, aData) { 1.46 + if (DEBUG) debug("observe"); 1.47 + switch (aTopic) { 1.48 + case kXpcomShutdownObserverTopic: 1.49 + this._messages.forEach((function(msgName) { 1.50 + ppmm.removeMessageListener(msgName, this); 1.51 + }).bind(this)); 1.52 + Services.obs.removeObserver(this, kXpcomShutdownObserverTopic); 1.53 + Services.obs.removeObserver(this, kMozSettingsChangedObserverTopic); 1.54 + ppmm = null; 1.55 + break; 1.56 + case kMozSettingsChangedObserverTopic: 1.57 + { 1.58 + let setting = JSON.parse(aData); 1.59 + // To avoid redundantly broadcasting settings-changed events that are 1.60 + // just requested from content processes themselves, skip the observer 1.61 + // messages that are notified from the internal SettingsChangeNotifier. 1.62 + if (setting.message && setting.message === kFromSettingsChangeNotifier) 1.63 + return; 1.64 + this.broadcastMessage("Settings:Change:Return:OK", 1.65 + { key: setting.key, value: setting.value }); 1.66 + break; 1.67 + } 1.68 + default: 1.69 + if (DEBUG) debug("Wrong observer topic: " + aTopic); 1.70 + break; 1.71 + } 1.72 + }, 1.73 + 1.74 + broadcastMessage: function broadcastMessage(aMsgName, aContent) { 1.75 + if (DEBUG) debug("Broadast"); 1.76 + this.children.forEach(function(msgMgr) { 1.77 + msgMgr.sendAsyncMessage(aMsgName, aContent); 1.78 + }); 1.79 + }, 1.80 + 1.81 + receiveMessage: function(aMessage) { 1.82 + if (DEBUG) debug("receiveMessage"); 1.83 + let msg = aMessage.data; 1.84 + let mm = aMessage.target; 1.85 + switch (aMessage.name) { 1.86 + case "Settings:Changed": 1.87 + if (!aMessage.target.assertPermission("settings-write")) { 1.88 + Cu.reportError("Settings message " + msg.name + 1.89 + " from a content process with no 'settings-write' privileges."); 1.90 + return null; 1.91 + } 1.92 + this.broadcastMessage("Settings:Change:Return:OK", 1.93 + { key: msg.key, value: msg.value }); 1.94 + Services.obs.notifyObservers(this, kMozSettingsChangedObserverTopic, 1.95 + JSON.stringify({ 1.96 + key: msg.key, 1.97 + value: msg.value, 1.98 + message: kFromSettingsChangeNotifier 1.99 + })); 1.100 + break; 1.101 + case "Settings:RegisterForMessages": 1.102 + if (!aMessage.target.assertPermission("settings-read")) { 1.103 + Cu.reportError("Settings message " + msg.name + 1.104 + " from a content process with no 'settings-read' privileges."); 1.105 + return null; 1.106 + } 1.107 + if (DEBUG) debug("Register!"); 1.108 + if (this.children.indexOf(mm) == -1) { 1.109 + this.children.push(mm); 1.110 + } 1.111 + break; 1.112 + case "child-process-shutdown": 1.113 + if (DEBUG) debug("Unregister"); 1.114 + let index; 1.115 + if ((index = this.children.indexOf(mm)) != -1) { 1.116 + if (DEBUG) debug("Unregister index: " + index); 1.117 + this.children.splice(index, 1); 1.118 + } 1.119 + break; 1.120 + default: 1.121 + if (DEBUG) debug("Wrong message: " + aMessage.name); 1.122 + } 1.123 + } 1.124 +} 1.125 + 1.126 +SettingsChangeNotifier.init();