|
1 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ |
|
2 /* vim: set ts=2 et sw=2 tw=80: */ |
|
3 /* Copyright 2012 Mozilla Foundation and Mozilla contributors |
|
4 * |
|
5 * Licensed under the Apache License, Version 2.0 (the "License"); |
|
6 * you may not use this file except in compliance with the License. |
|
7 * You may obtain a copy of the License at |
|
8 * |
|
9 * http://www.apache.org/licenses/LICENSE-2.0 |
|
10 * |
|
11 * Unless required by applicable law or agreed to in writing, software |
|
12 * distributed under the License is distributed on an "AS IS" BASIS, |
|
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
14 * See the License for the specific language governing permissions and |
|
15 * limitations under the License. |
|
16 */ |
|
17 |
|
18 #include "SystemWorkerManager.h" |
|
19 |
|
20 #include "nsINetworkService.h" |
|
21 #include "nsIWifi.h" |
|
22 #include "nsIWorkerHolder.h" |
|
23 #include "nsIXPConnect.h" |
|
24 |
|
25 #include "jsfriendapi.h" |
|
26 #include "mozilla/dom/workers/Workers.h" |
|
27 #include "AutoMounter.h" |
|
28 #include "TimeZoneSettingObserver.h" |
|
29 #include "AudioManager.h" |
|
30 #ifdef MOZ_B2G_RIL |
|
31 #include "mozilla/ipc/Ril.h" |
|
32 #endif |
|
33 #ifdef MOZ_NFC |
|
34 #include "mozilla/ipc/Nfc.h" |
|
35 #endif |
|
36 #include "mozilla/ipc/KeyStore.h" |
|
37 #include "nsIObserverService.h" |
|
38 #include "nsCxPusher.h" |
|
39 #include "nsServiceManagerUtils.h" |
|
40 #include "nsThreadUtils.h" |
|
41 #include "nsRadioInterfaceLayer.h" |
|
42 #include "WifiWorker.h" |
|
43 #include "mozilla/Services.h" |
|
44 |
|
45 USING_WORKERS_NAMESPACE |
|
46 |
|
47 using namespace mozilla::dom::gonk; |
|
48 using namespace mozilla::ipc; |
|
49 using namespace mozilla::system; |
|
50 |
|
51 namespace { |
|
52 |
|
53 NS_DEFINE_CID(kWifiWorkerCID, NS_WIFIWORKER_CID); |
|
54 |
|
55 // Doesn't carry a reference, we're owned by services. |
|
56 SystemWorkerManager *gInstance = nullptr; |
|
57 |
|
58 } // anonymous namespace |
|
59 |
|
60 SystemWorkerManager::SystemWorkerManager() |
|
61 : mShutdown(false) |
|
62 { |
|
63 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); |
|
64 NS_ASSERTION(!gInstance, "There should only be one instance!"); |
|
65 } |
|
66 |
|
67 SystemWorkerManager::~SystemWorkerManager() |
|
68 { |
|
69 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); |
|
70 NS_ASSERTION(!gInstance || gInstance == this, |
|
71 "There should only be one instance!"); |
|
72 gInstance = nullptr; |
|
73 } |
|
74 |
|
75 nsresult |
|
76 SystemWorkerManager::Init() |
|
77 { |
|
78 if (XRE_GetProcessType() != GeckoProcessType_Default) { |
|
79 return NS_ERROR_NOT_AVAILABLE; |
|
80 } |
|
81 |
|
82 NS_ASSERTION(NS_IsMainThread(), "We can only initialize on the main thread"); |
|
83 NS_ASSERTION(!mShutdown, "Already shutdown!"); |
|
84 |
|
85 mozilla::AutoSafeJSContext cx; |
|
86 |
|
87 nsresult rv = InitWifi(cx); |
|
88 if (NS_FAILED(rv)) { |
|
89 NS_WARNING("Failed to initialize WiFi Networking!"); |
|
90 return rv; |
|
91 } |
|
92 |
|
93 InitKeyStore(cx); |
|
94 |
|
95 InitAutoMounter(); |
|
96 InitializeTimeZoneSettingObserver(); |
|
97 nsCOMPtr<nsIAudioManager> audioManager = |
|
98 do_GetService(NS_AUDIOMANAGER_CONTRACTID); |
|
99 |
|
100 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); |
|
101 if (!obs) { |
|
102 NS_WARNING("Failed to get observer service!"); |
|
103 return NS_ERROR_FAILURE; |
|
104 } |
|
105 |
|
106 rv = obs->AddObserver(this, WORKERS_SHUTDOWN_TOPIC, false); |
|
107 if (NS_FAILED(rv)) { |
|
108 NS_WARNING("Failed to initialize worker shutdown event!"); |
|
109 return rv; |
|
110 } |
|
111 |
|
112 return NS_OK; |
|
113 } |
|
114 |
|
115 void |
|
116 SystemWorkerManager::Shutdown() |
|
117 { |
|
118 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); |
|
119 |
|
120 mShutdown = true; |
|
121 |
|
122 ShutdownAutoMounter(); |
|
123 |
|
124 #ifdef MOZ_B2G_RIL |
|
125 RilConsumer::Shutdown(); |
|
126 #endif |
|
127 |
|
128 #ifdef MOZ_NFC |
|
129 NfcConsumer::Shutdown(); |
|
130 #endif |
|
131 |
|
132 nsCOMPtr<nsIWifi> wifi(do_QueryInterface(mWifiWorker)); |
|
133 if (wifi) { |
|
134 wifi->Shutdown(); |
|
135 wifi = nullptr; |
|
136 } |
|
137 mWifiWorker = nullptr; |
|
138 |
|
139 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); |
|
140 if (obs) { |
|
141 obs->RemoveObserver(this, WORKERS_SHUTDOWN_TOPIC); |
|
142 } |
|
143 } |
|
144 |
|
145 // static |
|
146 already_AddRefed<SystemWorkerManager> |
|
147 SystemWorkerManager::FactoryCreate() |
|
148 { |
|
149 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); |
|
150 |
|
151 nsRefPtr<SystemWorkerManager> instance(gInstance); |
|
152 |
|
153 if (!instance) { |
|
154 instance = new SystemWorkerManager(); |
|
155 if (NS_FAILED(instance->Init())) { |
|
156 instance->Shutdown(); |
|
157 return nullptr; |
|
158 } |
|
159 |
|
160 gInstance = instance; |
|
161 } |
|
162 |
|
163 return instance.forget(); |
|
164 } |
|
165 |
|
166 // static |
|
167 nsIInterfaceRequestor* |
|
168 SystemWorkerManager::GetInterfaceRequestor() |
|
169 { |
|
170 return gInstance; |
|
171 } |
|
172 |
|
173 NS_IMETHODIMP |
|
174 SystemWorkerManager::GetInterface(const nsIID &aIID, void **aResult) |
|
175 { |
|
176 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); |
|
177 |
|
178 if (aIID.Equals(NS_GET_IID(nsIWifi))) { |
|
179 return CallQueryInterface(mWifiWorker, |
|
180 reinterpret_cast<nsIWifi**>(aResult)); |
|
181 } |
|
182 |
|
183 NS_WARNING("Got nothing for the requested IID!"); |
|
184 return NS_ERROR_NO_INTERFACE; |
|
185 } |
|
186 |
|
187 nsresult |
|
188 SystemWorkerManager::RegisterRilWorker(unsigned int aClientId, |
|
189 JS::Handle<JS::Value> aWorker, |
|
190 JSContext *aCx) |
|
191 { |
|
192 #ifndef MOZ_B2G_RIL |
|
193 return NS_ERROR_NOT_IMPLEMENTED; |
|
194 #else |
|
195 NS_ENSURE_TRUE(aWorker.isObject(), NS_ERROR_UNEXPECTED); |
|
196 |
|
197 JSAutoCompartment ac(aCx, &aWorker.toObject()); |
|
198 |
|
199 WorkerCrossThreadDispatcher *wctd = |
|
200 GetWorkerCrossThreadDispatcher(aCx, aWorker); |
|
201 if (!wctd) { |
|
202 NS_WARNING("Failed to GetWorkerCrossThreadDispatcher for ril"); |
|
203 return NS_ERROR_FAILURE; |
|
204 } |
|
205 |
|
206 return RilConsumer::Register(aClientId, wctd); |
|
207 #endif // MOZ_B2G_RIL |
|
208 } |
|
209 |
|
210 nsresult |
|
211 SystemWorkerManager::RegisterNfcWorker(JS::Handle<JS::Value> aWorker, |
|
212 JSContext* aCx) |
|
213 { |
|
214 #ifndef MOZ_NFC |
|
215 return NS_ERROR_NOT_IMPLEMENTED; |
|
216 #else |
|
217 NS_ENSURE_TRUE(aWorker.isObject(), NS_ERROR_UNEXPECTED); |
|
218 |
|
219 JSAutoCompartment ac(aCx, &aWorker.toObject()); |
|
220 |
|
221 WorkerCrossThreadDispatcher* wctd = |
|
222 GetWorkerCrossThreadDispatcher(aCx, aWorker); |
|
223 if (!wctd) { |
|
224 NS_WARNING("Failed to GetWorkerCrossThreadDispatcher for nfc"); |
|
225 return NS_ERROR_FAILURE; |
|
226 } |
|
227 |
|
228 return NfcConsumer::Register(wctd); |
|
229 #endif // MOZ_NFC |
|
230 } |
|
231 |
|
232 nsresult |
|
233 SystemWorkerManager::InitWifi(JSContext *cx) |
|
234 { |
|
235 nsCOMPtr<nsIWorkerHolder> worker = do_CreateInstance(kWifiWorkerCID); |
|
236 NS_ENSURE_TRUE(worker, NS_ERROR_FAILURE); |
|
237 |
|
238 mWifiWorker = worker; |
|
239 return NS_OK; |
|
240 } |
|
241 |
|
242 nsresult |
|
243 SystemWorkerManager::InitKeyStore(JSContext *cx) |
|
244 { |
|
245 mKeyStore = new KeyStore(); |
|
246 return NS_OK; |
|
247 } |
|
248 |
|
249 NS_IMPL_ISUPPORTS(SystemWorkerManager, |
|
250 nsIObserver, |
|
251 nsIInterfaceRequestor, |
|
252 nsISystemWorkerManager) |
|
253 |
|
254 NS_IMETHODIMP |
|
255 SystemWorkerManager::Observe(nsISupports *aSubject, const char *aTopic, |
|
256 const char16_t *aData) |
|
257 { |
|
258 if (!strcmp(aTopic, WORKERS_SHUTDOWN_TOPIC)) { |
|
259 Shutdown(); |
|
260 } |
|
261 |
|
262 return NS_OK; |
|
263 } |