|
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 // Based on: |
|
6 // https://bugzilla.mozilla.org/show_bug.cgi?id=549539 |
|
7 // https://bug549539.bugzilla.mozilla.org/attachment.cgi?id=429661 |
|
8 // https://developer.mozilla.org/en/XPCOM/XPCOM_changes_in_Gecko_1.9.3 |
|
9 // http://mxr.mozilla.org/mozilla-central/source/toolkit/components/console/hudservice/HUDService.jsm#3240 |
|
10 // https://developer.mozilla.org/en/how_to_build_an_xpcom_component_in_javascript |
|
11 |
|
12 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); |
|
13 Components.utils.import("resource://gre/modules/Services.jsm"); |
|
14 |
|
15 const Cc = Components.classes; |
|
16 const Ci = Components.interfaces; |
|
17 |
|
18 const CHILD_SCRIPT = "chrome://specialpowers/content/specialpowers.js" |
|
19 const CHILD_SCRIPT_API = "chrome://specialpowers/content/specialpowersAPI.js" |
|
20 const CHILD_LOGGER_SCRIPT = "chrome://specialpowers/content/MozillaLogger.js" |
|
21 |
|
22 |
|
23 // Glue to add in the observer API to this object. This allows us to share code with chrome tests |
|
24 var loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"] |
|
25 .getService(Components.interfaces.mozIJSSubScriptLoader); |
|
26 loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserverAPI.js"); |
|
27 |
|
28 /* XPCOM gunk */ |
|
29 this.SpecialPowersObserver = function SpecialPowersObserver() { |
|
30 this._isFrameScriptLoaded = false; |
|
31 this._mmIsGlobal = true; |
|
32 this._messageManager = Cc["@mozilla.org/globalmessagemanager;1"]. |
|
33 getService(Ci.nsIMessageBroadcaster); |
|
34 } |
|
35 |
|
36 |
|
37 SpecialPowersObserver.prototype = new SpecialPowersObserverAPI(); |
|
38 |
|
39 SpecialPowersObserver.prototype.classDescription = "Special powers Observer for use in testing."; |
|
40 SpecialPowersObserver.prototype.classID = Components.ID("{59a52458-13e0-4d93-9d85-a637344f29a1}"); |
|
41 SpecialPowersObserver.prototype.contractID = "@mozilla.org/special-powers-observer;1"; |
|
42 SpecialPowersObserver.prototype.QueryInterface = XPCOMUtils.generateQI([Components.interfaces.nsIObserver]); |
|
43 SpecialPowersObserver.prototype._xpcom_categories = [{category: "profile-after-change", service: true }]; |
|
44 |
|
45 SpecialPowersObserver.prototype.observe = function(aSubject, aTopic, aData) |
|
46 { |
|
47 switch (aTopic) { |
|
48 case "profile-after-change": |
|
49 this.init(); |
|
50 break; |
|
51 |
|
52 case "chrome-document-global-created": |
|
53 if (!this._isFrameScriptLoaded) { |
|
54 // Register for any messages our API needs us to handle |
|
55 this._messageManager.addMessageListener("SPPrefService", this); |
|
56 this._messageManager.addMessageListener("SPProcessCrashService", this); |
|
57 this._messageManager.addMessageListener("SPPingService", this); |
|
58 this._messageManager.addMessageListener("SpecialPowers.Quit", this); |
|
59 this._messageManager.addMessageListener("SpecialPowers.Focus", this); |
|
60 this._messageManager.addMessageListener("SPPermissionManager", this); |
|
61 this._messageManager.addMessageListener("SPWebAppService", this); |
|
62 this._messageManager.addMessageListener("SPObserverService", this); |
|
63 this._messageManager.addMessageListener("SPLoadChromeScript", this); |
|
64 this._messageManager.addMessageListener("SPChromeScriptMessage", this); |
|
65 |
|
66 this._messageManager.loadFrameScript(CHILD_LOGGER_SCRIPT, true); |
|
67 this._messageManager.loadFrameScript(CHILD_SCRIPT_API, true); |
|
68 this._messageManager.loadFrameScript(CHILD_SCRIPT, true); |
|
69 this._isFrameScriptLoaded = true; |
|
70 } |
|
71 break; |
|
72 |
|
73 case "http-on-modify-request": |
|
74 if (aSubject instanceof Ci.nsIChannel) { |
|
75 let uri = aSubject.URI.spec; |
|
76 this._sendAsyncMessage("specialpowers-http-notify-request", { uri: uri }); |
|
77 } |
|
78 break; |
|
79 |
|
80 case "xpcom-shutdown": |
|
81 this.uninit(); |
|
82 break; |
|
83 |
|
84 default: |
|
85 this._observe(aSubject, aTopic, aData); |
|
86 break; |
|
87 } |
|
88 }; |
|
89 |
|
90 SpecialPowersObserver.prototype._sendAsyncMessage = function(msgname, msg) |
|
91 { |
|
92 if (this._mmIsGlobal) { |
|
93 this._messageManager.broadcastAsyncMessage(msgname, msg); |
|
94 } |
|
95 else { |
|
96 this._messageManager.sendAsyncMessage(msgname, msg); |
|
97 } |
|
98 }; |
|
99 |
|
100 SpecialPowersObserver.prototype._receiveMessage = function(aMessage) { |
|
101 return this._receiveMessageAPI(aMessage); |
|
102 }; |
|
103 |
|
104 SpecialPowersObserver.prototype.init = function(messageManager) |
|
105 { |
|
106 var obs = Services.obs; |
|
107 obs.addObserver(this, "xpcom-shutdown", false); |
|
108 obs.addObserver(this, "chrome-document-global-created", false); |
|
109 obs.addObserver(this, "http-on-modify-request", false); |
|
110 |
|
111 if (messageManager) { |
|
112 this._messageManager = messageManager; |
|
113 this._mmIsGlobal = false; |
|
114 } |
|
115 }; |
|
116 |
|
117 SpecialPowersObserver.prototype.uninit = function() |
|
118 { |
|
119 var obs = Services.obs; |
|
120 obs.removeObserver(this, "chrome-document-global-created"); |
|
121 obs.removeObserver(this, "http-on-modify-request"); |
|
122 this._removeProcessCrashObservers(); |
|
123 }; |
|
124 |
|
125 SpecialPowersObserver.prototype._addProcessCrashObservers = function() { |
|
126 if (this._processCrashObserversRegistered) { |
|
127 return; |
|
128 } |
|
129 |
|
130 var obs = Components.classes["@mozilla.org/observer-service;1"] |
|
131 .getService(Components.interfaces.nsIObserverService); |
|
132 |
|
133 obs.addObserver(this, "plugin-crashed", false); |
|
134 obs.addObserver(this, "ipc:content-shutdown", false); |
|
135 this._processCrashObserversRegistered = true; |
|
136 }; |
|
137 |
|
138 SpecialPowersObserver.prototype._removeProcessCrashObservers = function() { |
|
139 if (!this._processCrashObserversRegistered) { |
|
140 return; |
|
141 } |
|
142 |
|
143 var obs = Components.classes["@mozilla.org/observer-service;1"] |
|
144 .getService(Components.interfaces.nsIObserverService); |
|
145 |
|
146 obs.removeObserver(this, "plugin-crashed"); |
|
147 obs.removeObserver(this, "ipc:content-shutdown"); |
|
148 this._processCrashObserversRegistered = false; |
|
149 }; |
|
150 |
|
151 /** |
|
152 * messageManager callback function |
|
153 * This will get requests from our API in the window and process them in chrome for it |
|
154 **/ |
|
155 SpecialPowersObserver.prototype.receiveMessage = function(aMessage) { |
|
156 switch(aMessage.name) { |
|
157 case "SPPingService": |
|
158 if (aMessage.json.op == "ping") { |
|
159 aMessage.target |
|
160 .QueryInterface(Ci.nsIFrameLoaderOwner) |
|
161 .frameLoader |
|
162 .messageManager |
|
163 .sendAsyncMessage("SPPingService", { op: "pong" }); |
|
164 } |
|
165 break; |
|
166 case "SpecialPowers.Quit": |
|
167 let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"].getService(Ci.nsIAppStartup); |
|
168 appStartup.quit(Ci.nsIAppStartup.eForceQuit); |
|
169 break; |
|
170 case "SpecialPowers.Focus": |
|
171 aMessage.target.focus(); |
|
172 break; |
|
173 default: |
|
174 return this._receiveMessage(aMessage); |
|
175 } |
|
176 }; |
|
177 |
|
178 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SpecialPowersObserver]); |