|
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 |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); |
|
6 |
|
7 const Cc = Components.classes; |
|
8 const Ci = Components.interfaces; |
|
9 |
|
10 const CATEGORY_WAKEUP_REQUEST = "wakeup-request"; |
|
11 |
|
12 function MessageWakeupService() { }; |
|
13 |
|
14 MessageWakeupService.prototype = |
|
15 { |
|
16 classID: Components.ID("{f9798742-4f7b-4188-86ba-48b116412b29}"), |
|
17 QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]), |
|
18 |
|
19 messagesData: [], |
|
20 |
|
21 get messageManager() { |
|
22 if (!this._messageManager) |
|
23 this._messageManager = Cc["@mozilla.org/parentprocessmessagemanager;1"]. |
|
24 getService(Ci.nsIMessageListenerManager); |
|
25 return this._messageManager; |
|
26 }, |
|
27 |
|
28 requestWakeup: function(aMessageName, aCid, aIid, aMethod) { |
|
29 this.messagesData[aMessageName] = { |
|
30 cid: aCid, |
|
31 iid: aIid, |
|
32 method: aMethod, |
|
33 }; |
|
34 |
|
35 this.messageManager.addMessageListener(aMessageName, this); |
|
36 }, |
|
37 |
|
38 receiveMessage: function(aMessage) { |
|
39 let data = this.messagesData[aMessage.name]; |
|
40 // TODO: When bug 593407 is ready, stop doing the wrappedJSObject hack |
|
41 // and use this line instead: |
|
42 // QueryInterface(Ci.nsIMessageListener); |
|
43 let service = Cc[data.cid][data.method](Ci[data.iid]). |
|
44 wrappedJSObject; |
|
45 |
|
46 // The receiveMessage() call itself may spin an event loop, and we |
|
47 // do not want to swap listeners in that - it would cause the current |
|
48 // message to be answered by two listeners. So, we call that first, |
|
49 // then queue the swap for the next event loop |
|
50 let ret = service.receiveMessage(aMessage); |
|
51 |
|
52 if (data.timer) { |
|
53 // Handle the case of two such messages happening in quick succession |
|
54 data.timer.cancel(); |
|
55 data.timer = null; |
|
56 } |
|
57 |
|
58 data.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); |
|
59 let self = this; |
|
60 data.timer.initWithCallback(function() { |
|
61 self.messageManager.addMessageListener(aMessage.name, service); |
|
62 self.messageManager.removeMessageListener(aMessage.name, self); |
|
63 delete self.messagesData[aMessage.name]; |
|
64 }, 0, Ci.nsITimer.TYPE_ONE_SHOT); |
|
65 |
|
66 return ret; |
|
67 }, |
|
68 |
|
69 observe: function TM_observe(aSubject, aTopic, aData) { |
|
70 switch (aTopic) { |
|
71 case "profile-after-change": |
|
72 { |
|
73 var catMan = Cc["@mozilla.org/categorymanager;1"]. |
|
74 getService(Ci.nsICategoryManager); |
|
75 var entries = catMan.enumerateCategory(CATEGORY_WAKEUP_REQUEST); |
|
76 while (entries.hasMoreElements()) { |
|
77 var entry = entries.getNext().QueryInterface(Ci.nsISupportsCString).data; |
|
78 var value = catMan.getCategoryEntry(CATEGORY_WAKEUP_REQUEST, entry); |
|
79 var parts = value.split(","); |
|
80 var cid = parts[0]; |
|
81 var iid = parts[1]; |
|
82 var method = parts[2]; |
|
83 var messages = parts.slice(3); |
|
84 messages.forEach(function(messageName) { |
|
85 this.requestWakeup(messageName, cid, iid, method); |
|
86 }, this); |
|
87 } |
|
88 } |
|
89 break; |
|
90 } |
|
91 }, |
|
92 }; |
|
93 |
|
94 var components = [MessageWakeupService]; |
|
95 this.NSGetFactory = XPCOMUtils.generateNSGetFactory(components); |
|
96 |