|
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/. */ |
|
4 |
|
5 "use strict" |
|
6 |
|
7 const DEBUG = false; |
|
8 function debug(s) { |
|
9 if (DEBUG) dump("-*- SettingsChangeNotifier: " + s + "\n"); |
|
10 } |
|
11 |
|
12 const Cu = Components.utils; |
|
13 const Cc = Components.classes; |
|
14 const Ci = Components.interfaces; |
|
15 |
|
16 this.EXPORTED_SYMBOLS = ["SettingsChangeNotifier"]; |
|
17 |
|
18 Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
|
19 Cu.import("resource://gre/modules/Services.jsm"); |
|
20 |
|
21 const kXpcomShutdownObserverTopic = "xpcom-shutdown"; |
|
22 const kMozSettingsChangedObserverTopic = "mozsettings-changed"; |
|
23 const kFromSettingsChangeNotifier = "fromSettingsChangeNotifier"; |
|
24 |
|
25 XPCOMUtils.defineLazyServiceGetter(this, "ppmm", |
|
26 "@mozilla.org/parentprocessmessagemanager;1", |
|
27 "nsIMessageBroadcaster"); |
|
28 |
|
29 this.SettingsChangeNotifier = { |
|
30 init: function() { |
|
31 if (DEBUG) debug("init"); |
|
32 this.children = []; |
|
33 this._messages = ["Settings:Changed", "Settings:RegisterForMessages", "child-process-shutdown"]; |
|
34 this._messages.forEach((function(msgName) { |
|
35 ppmm.addMessageListener(msgName, this); |
|
36 }).bind(this)); |
|
37 |
|
38 Services.obs.addObserver(this, kXpcomShutdownObserverTopic, false); |
|
39 Services.obs.addObserver(this, kMozSettingsChangedObserverTopic, false); |
|
40 }, |
|
41 |
|
42 observe: function(aSubject, aTopic, aData) { |
|
43 if (DEBUG) debug("observe"); |
|
44 switch (aTopic) { |
|
45 case kXpcomShutdownObserverTopic: |
|
46 this._messages.forEach((function(msgName) { |
|
47 ppmm.removeMessageListener(msgName, this); |
|
48 }).bind(this)); |
|
49 Services.obs.removeObserver(this, kXpcomShutdownObserverTopic); |
|
50 Services.obs.removeObserver(this, kMozSettingsChangedObserverTopic); |
|
51 ppmm = null; |
|
52 break; |
|
53 case kMozSettingsChangedObserverTopic: |
|
54 { |
|
55 let setting = JSON.parse(aData); |
|
56 // To avoid redundantly broadcasting settings-changed events that are |
|
57 // just requested from content processes themselves, skip the observer |
|
58 // messages that are notified from the internal SettingsChangeNotifier. |
|
59 if (setting.message && setting.message === kFromSettingsChangeNotifier) |
|
60 return; |
|
61 this.broadcastMessage("Settings:Change:Return:OK", |
|
62 { key: setting.key, value: setting.value }); |
|
63 break; |
|
64 } |
|
65 default: |
|
66 if (DEBUG) debug("Wrong observer topic: " + aTopic); |
|
67 break; |
|
68 } |
|
69 }, |
|
70 |
|
71 broadcastMessage: function broadcastMessage(aMsgName, aContent) { |
|
72 if (DEBUG) debug("Broadast"); |
|
73 this.children.forEach(function(msgMgr) { |
|
74 msgMgr.sendAsyncMessage(aMsgName, aContent); |
|
75 }); |
|
76 }, |
|
77 |
|
78 receiveMessage: function(aMessage) { |
|
79 if (DEBUG) debug("receiveMessage"); |
|
80 let msg = aMessage.data; |
|
81 let mm = aMessage.target; |
|
82 switch (aMessage.name) { |
|
83 case "Settings:Changed": |
|
84 if (!aMessage.target.assertPermission("settings-write")) { |
|
85 Cu.reportError("Settings message " + msg.name + |
|
86 " from a content process with no 'settings-write' privileges."); |
|
87 return null; |
|
88 } |
|
89 this.broadcastMessage("Settings:Change:Return:OK", |
|
90 { key: msg.key, value: msg.value }); |
|
91 Services.obs.notifyObservers(this, kMozSettingsChangedObserverTopic, |
|
92 JSON.stringify({ |
|
93 key: msg.key, |
|
94 value: msg.value, |
|
95 message: kFromSettingsChangeNotifier |
|
96 })); |
|
97 break; |
|
98 case "Settings:RegisterForMessages": |
|
99 if (!aMessage.target.assertPermission("settings-read")) { |
|
100 Cu.reportError("Settings message " + msg.name + |
|
101 " from a content process with no 'settings-read' privileges."); |
|
102 return null; |
|
103 } |
|
104 if (DEBUG) debug("Register!"); |
|
105 if (this.children.indexOf(mm) == -1) { |
|
106 this.children.push(mm); |
|
107 } |
|
108 break; |
|
109 case "child-process-shutdown": |
|
110 if (DEBUG) debug("Unregister"); |
|
111 let index; |
|
112 if ((index = this.children.indexOf(mm)) != -1) { |
|
113 if (DEBUG) debug("Unregister index: " + index); |
|
114 this.children.splice(index, 1); |
|
115 } |
|
116 break; |
|
117 default: |
|
118 if (DEBUG) debug("Wrong message: " + aMessage.name); |
|
119 } |
|
120 } |
|
121 } |
|
122 |
|
123 SettingsChangeNotifier.init(); |