dom/system/gonk/NetworkWorker.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial