dom/system/gonk/NetworkWorker.cpp

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:41cd34df9f21
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 #include "NetworkWorker.h"
6 #include "NetworkUtils.h"
7 #include <nsThreadUtils.h>
8 #include "mozilla/ModuleUtils.h"
9 #include "mozilla/ClearOnShutdown.h"
10 #include "nsXULAppAPI.h"
11 #include "nsCxPusher.h"
12
13 #define NS_NETWORKWORKER_CID \
14 { 0x6df093e1, 0x8127, 0x4fa7, {0x90, 0x13, 0xa3, 0xaa, 0xa7, 0x79, 0xbb, 0xdd} }
15
16 using namespace mozilla;
17 using namespace mozilla::dom;
18 using namespace mozilla::ipc;
19
20 namespace mozilla {
21
22 nsCOMPtr<nsIThread> gWorkerThread;
23
24 // The singleton network worker, to be used on the main thread.
25 StaticRefPtr<NetworkWorker> gNetworkWorker;
26
27 // The singleton networkutils class, that can be used on any thread.
28 static nsAutoPtr<NetworkUtils> gNetworkUtils;
29
30 // Runnable used dispatch command result on the main thread.
31 class NetworkResultDispatcher : public nsRunnable
32 {
33 public:
34 NetworkResultDispatcher(const NetworkResultOptions& aResult)
35 {
36 MOZ_ASSERT(!NS_IsMainThread());
37
38 #define COPY_FIELD(prop) mResult.prop = aResult.prop;
39 COPY_FIELD(mId)
40 COPY_FIELD(mRet)
41 COPY_FIELD(mBroadcast)
42 COPY_FIELD(mTopic)
43 COPY_FIELD(mReason)
44 COPY_FIELD(mResultCode)
45 COPY_FIELD(mResultReason)
46 COPY_FIELD(mError)
47 COPY_FIELD(mRxBytes)
48 COPY_FIELD(mTxBytes)
49 COPY_FIELD(mDate)
50 COPY_FIELD(mEnable)
51 COPY_FIELD(mResult)
52 COPY_FIELD(mSuccess)
53 COPY_FIELD(mCurExternalIfname)
54 COPY_FIELD(mCurInternalIfname)
55 #undef COPY_FIELD
56 }
57
58 NS_IMETHOD Run()
59 {
60 MOZ_ASSERT(NS_IsMainThread());
61
62 if (gNetworkWorker) {
63 gNetworkWorker->DispatchNetworkResult(mResult);
64 }
65 return NS_OK;
66 }
67 private:
68 NetworkResultOptions mResult;
69 };
70
71 // Runnable used dispatch netd command on the worker thread.
72 class NetworkCommandDispatcher : public nsRunnable
73 {
74 public:
75 NetworkCommandDispatcher(const NetworkParams& aParams)
76 : mParams(aParams)
77 {
78 MOZ_ASSERT(NS_IsMainThread());
79 }
80
81 NS_IMETHOD Run()
82 {
83 MOZ_ASSERT(!NS_IsMainThread());
84
85 if (gNetworkUtils) {
86 gNetworkUtils->ExecuteCommand(mParams);
87 }
88 return NS_OK;
89 }
90 private:
91 NetworkParams mParams;
92 };
93
94 // Runnable used dispatch netd result on the worker thread.
95 class NetdEventRunnable : public nsRunnable
96 {
97 public:
98 NetdEventRunnable(NetdCommand* aCommand)
99 : mCommand(aCommand)
100 {
101 MOZ_ASSERT(!NS_IsMainThread());
102 }
103
104 NS_IMETHOD Run()
105 {
106 MOZ_ASSERT(!NS_IsMainThread());
107
108 if (gNetworkUtils) {
109 gNetworkUtils->onNetdMessage(mCommand);
110 }
111 return NS_OK;
112 }
113
114 private:
115 nsAutoPtr<NetdCommand> mCommand;
116 };
117
118 class NetdMessageConsumer : public NetdConsumer
119 {
120 public:
121 NetdMessageConsumer()
122 {
123 MOZ_ASSERT(NS_IsMainThread());
124 }
125
126 void MessageReceived(NetdCommand* aCommand)
127 {
128 MOZ_ASSERT(!NS_IsMainThread());
129
130 nsCOMPtr<nsIRunnable> runnable = new NetdEventRunnable(aCommand);
131 if (gWorkerThread) {
132 gWorkerThread->Dispatch(runnable, nsIEventTarget::DISPATCH_NORMAL);
133 }
134 }
135 };
136
137 NS_IMPL_ISUPPORTS(NetworkWorker, nsINetworkWorker)
138
139 NetworkWorker::NetworkWorker()
140 {
141 MOZ_ASSERT(NS_IsMainThread());
142 MOZ_ASSERT(!gNetworkWorker);
143 }
144
145 NetworkWorker::~NetworkWorker()
146 {
147 MOZ_ASSERT(!gNetworkWorker);
148 MOZ_ASSERT(!mListener);
149 }
150
151 already_AddRefed<NetworkWorker>
152 NetworkWorker::FactoryCreate()
153 {
154 if (XRE_GetProcessType() != GeckoProcessType_Default) {
155 return nullptr;
156 }
157
158 MOZ_ASSERT(NS_IsMainThread());
159
160 if (!gNetworkWorker) {
161 gNetworkWorker = new NetworkWorker();
162 ClearOnShutdown(&gNetworkWorker);
163
164 gNetworkUtils = new NetworkUtils(NetworkWorker::NotifyResult);
165 ClearOnShutdown(&gNetworkUtils);
166 }
167
168 nsRefPtr<NetworkWorker> worker = gNetworkWorker.get();
169 return worker.forget();
170 }
171
172 NS_IMETHODIMP
173 NetworkWorker::Start(nsINetworkEventListener* aListener)
174 {
175 MOZ_ASSERT(NS_IsMainThread());
176 MOZ_ASSERT(aListener);
177
178 if (mListener) {
179 return NS_OK;
180 }
181
182 nsresult rv;
183
184 rv = NS_NewNamedThread("NetworkWorker", getter_AddRefs(gWorkerThread));
185 if (NS_FAILED(rv)) {
186 NS_WARNING("Can't create network control thread");
187 return NS_ERROR_FAILURE;
188 }
189
190 StartNetd(new NetdMessageConsumer());
191 mListener = aListener;
192
193 return NS_OK;
194 }
195
196 NS_IMETHODIMP
197 NetworkWorker::Shutdown()
198 {
199 MOZ_ASSERT(NS_IsMainThread());
200
201 if (!mListener) {
202 return NS_OK;
203 }
204
205 StopNetd();
206
207 gWorkerThread->Shutdown();
208 gWorkerThread = nullptr;
209
210 mListener = nullptr;
211 return NS_OK;
212 }
213
214 // Receive command from main thread (NetworkService.js).
215 NS_IMETHODIMP
216 NetworkWorker::PostMessage(JS::Handle<JS::Value> aOptions, JSContext* aCx)
217 {
218 MOZ_ASSERT(NS_IsMainThread());
219
220 NetworkCommandOptions options;
221 if (!options.Init(aCx, aOptions)) {
222 NS_WARNING("Bad dictionary passed to NetworkWorker::SendCommand");
223 return NS_ERROR_FAILURE;
224 }
225
226 // Dispatch the command to the control thread.
227 NetworkParams NetworkParams(options);
228 nsCOMPtr<nsIRunnable> runnable = new NetworkCommandDispatcher(NetworkParams);
229 if (gWorkerThread) {
230 gWorkerThread->Dispatch(runnable, nsIEventTarget::DISPATCH_NORMAL);
231 }
232 return NS_OK;
233 }
234
235 void
236 NetworkWorker::DispatchNetworkResult(const NetworkResultOptions& aOptions)
237 {
238 MOZ_ASSERT(NS_IsMainThread());
239
240 mozilla::AutoSafeJSContext cx;
241 JS::RootedValue val(cx);
242
243 if (!aOptions.ToObject(cx, &val)) {
244 return;
245 }
246
247 // Call the listener with a JS value.
248 if (mListener) {
249 mListener->OnEvent(val);
250 }
251 }
252
253 // Callback function from network worker thread to update result on main thread.
254 void
255 NetworkWorker::NotifyResult(NetworkResultOptions& aResult)
256 {
257 MOZ_ASSERT(!NS_IsMainThread());
258
259 nsCOMPtr<nsIRunnable> runnable = new NetworkResultDispatcher(aResult);
260 NS_DispatchToMainThread(runnable);
261 }
262
263 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(NetworkWorker,
264 NetworkWorker::FactoryCreate)
265
266 NS_DEFINE_NAMED_CID(NS_NETWORKWORKER_CID);
267
268 static const mozilla::Module::CIDEntry kNetworkWorkerCIDs[] = {
269 { &kNS_NETWORKWORKER_CID, false, nullptr, NetworkWorkerConstructor },
270 { nullptr }
271 };
272
273 static const mozilla::Module::ContractIDEntry kNetworkWorkerContracts[] = {
274 { "@mozilla.org/network/worker;1", &kNS_NETWORKWORKER_CID },
275 { nullptr }
276 };
277
278 static const mozilla::Module kNetworkWorkerModule = {
279 mozilla::Module::kVersion,
280 kNetworkWorkerCIDs,
281 kNetworkWorkerContracts,
282 nullptr
283 };
284
285 } // namespace mozilla
286
287 NSMODULE_DEFN(NetworkWorkerModule) = &kNetworkWorkerModule;

mercurial