|
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 {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; |
|
8 |
|
9 this.EXPORTED_SYMBOLS = ["DataStoreChangeNotifier"]; |
|
10 |
|
11 function debug(s) { |
|
12 //dump('DEBUG DataStoreChangeNotifier: ' + s + '\n'); |
|
13 } |
|
14 |
|
15 // DataStoreServiceInternal should not be converted into a lazy getter as it |
|
16 // runs code during initialization. |
|
17 Cu.import('resource://gre/modules/DataStoreServiceInternal.jsm'); |
|
18 Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
|
19 Cu.import("resource://gre/modules/Services.jsm"); |
|
20 |
|
21 XPCOMUtils.defineLazyServiceGetter(this, "ppmm", |
|
22 "@mozilla.org/parentprocessmessagemanager;1", |
|
23 "nsIMessageBroadcaster"); |
|
24 |
|
25 this.DataStoreChangeNotifier = { |
|
26 children: [], |
|
27 messages: [ "DataStore:Changed", "DataStore:RegisterForMessages", |
|
28 "DataStore:UnregisterForMessages", |
|
29 "child-process-shutdown" ], |
|
30 |
|
31 init: function() { |
|
32 debug("init"); |
|
33 |
|
34 this.messages.forEach((function(msgName) { |
|
35 ppmm.addMessageListener(msgName, this); |
|
36 }).bind(this)); |
|
37 |
|
38 Services.obs.addObserver(this, 'xpcom-shutdown', false); |
|
39 }, |
|
40 |
|
41 observe: function(aSubject, aTopic, aData) { |
|
42 debug("observe"); |
|
43 |
|
44 switch (aTopic) { |
|
45 case 'xpcom-shutdown': |
|
46 this.messages.forEach((function(msgName) { |
|
47 ppmm.removeMessageListener(msgName, this); |
|
48 }).bind(this)); |
|
49 |
|
50 Services.obs.removeObserver(this, 'xpcom-shutdown'); |
|
51 ppmm = null; |
|
52 break; |
|
53 |
|
54 default: |
|
55 debug("Wrong observer topic: " + aTopic); |
|
56 break; |
|
57 } |
|
58 }, |
|
59 |
|
60 broadcastMessage: function broadcastMessage(aData) { |
|
61 debug("Broadast"); |
|
62 this.children.forEach(function(obj) { |
|
63 if (obj.store == aData.store && obj.owner == aData.owner) { |
|
64 obj.mm.sendAsyncMessage("DataStore:Changed:Return:OK", aData); |
|
65 } |
|
66 }); |
|
67 }, |
|
68 |
|
69 |
|
70 receiveMessage: function(aMessage) { |
|
71 debug("receiveMessage"); |
|
72 |
|
73 // No check has to be done when the message is 'child-process-shutdown' |
|
74 // because at this point the target is already disconnected from |
|
75 // nsFrameMessageManager, so that assertAppHasStatus will always fail. |
|
76 let prefName = 'dom.testing.datastore_enabled_for_hosted_apps'; |
|
77 if (aMessage.name != 'child-process-shutdown' && |
|
78 (Services.prefs.getPrefType(prefName) == Services.prefs.PREF_INVALID || |
|
79 !Services.prefs.getBoolPref(prefName)) && |
|
80 !aMessage.target.assertAppHasStatus(Ci.nsIPrincipal.APP_STATUS_CERTIFIED)) { |
|
81 return; |
|
82 } |
|
83 |
|
84 switch (aMessage.name) { |
|
85 case "DataStore:Changed": |
|
86 this.broadcastMessage(aMessage.data); |
|
87 break; |
|
88 |
|
89 case "DataStore:RegisterForMessages": |
|
90 debug("Register!"); |
|
91 |
|
92 for (let i = 0; i < this.children.length; ++i) { |
|
93 if (this.children[i].mm == aMessage.target && |
|
94 this.children[i].store == aMessage.data.store && |
|
95 this.children[i].owner == aMessage.data.owner) { |
|
96 debug("Register on existing index: " + i); |
|
97 ++this.children[i].count; |
|
98 return; |
|
99 } |
|
100 } |
|
101 |
|
102 this.children.push({ mm: aMessage.target, |
|
103 store: aMessage.data.store, |
|
104 owner: aMessage.data.owner, |
|
105 count: 1 }); |
|
106 break; |
|
107 |
|
108 case "child-process-shutdown": |
|
109 case "DataStore:UnregisterForMessages": |
|
110 debug("Unregister"); |
|
111 |
|
112 for (let i = 0; i < this.children.length;) { |
|
113 if (this.children[i].mm == aMessage.target) { |
|
114 debug("Unregister index: " + i); |
|
115 if (!--this.children[i].count) { |
|
116 debug("Unregister delete index: " + i); |
|
117 this.children.splice(i, 1); |
|
118 } |
|
119 break; |
|
120 } else { |
|
121 ++i; |
|
122 } |
|
123 } |
|
124 break; |
|
125 |
|
126 default: |
|
127 debug("Wrong message: " + aMessage.name); |
|
128 } |
|
129 } |
|
130 } |
|
131 |
|
132 DataStoreChangeNotifier.init(); |