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

     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/. */
     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"
    13 #define NS_NETWORKWORKER_CID \
    14   { 0x6df093e1, 0x8127, 0x4fa7, {0x90, 0x13, 0xa3, 0xaa, 0xa7, 0x79, 0xbb, 0xdd} }
    16 using namespace mozilla;
    17 using namespace mozilla::dom;
    18 using namespace mozilla::ipc;
    20 namespace mozilla {
    22 nsCOMPtr<nsIThread> gWorkerThread;
    24 // The singleton network worker, to be used on the main thread.
    25 StaticRefPtr<NetworkWorker> gNetworkWorker;
    27 // The singleton networkutils class, that can be used on any thread.
    28 static nsAutoPtr<NetworkUtils> gNetworkUtils;
    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());
    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   }
    58   NS_IMETHOD Run()
    59   {
    60     MOZ_ASSERT(NS_IsMainThread());
    62     if (gNetworkWorker) {
    63       gNetworkWorker->DispatchNetworkResult(mResult);
    64     }
    65     return NS_OK;
    66   }
    67 private:
    68   NetworkResultOptions mResult;
    69 };
    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   }
    81   NS_IMETHOD Run()
    82   {
    83     MOZ_ASSERT(!NS_IsMainThread());
    85     if (gNetworkUtils) {
    86       gNetworkUtils->ExecuteCommand(mParams);
    87     }
    88     return NS_OK;
    89   }
    90 private:
    91   NetworkParams mParams;
    92 };
    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   }
   104   NS_IMETHOD Run()
   105   {
   106     MOZ_ASSERT(!NS_IsMainThread());
   108     if (gNetworkUtils) {
   109       gNetworkUtils->onNetdMessage(mCommand);
   110     }
   111     return NS_OK;
   112   }
   114 private:
   115   nsAutoPtr<NetdCommand> mCommand;
   116 };
   118 class NetdMessageConsumer : public NetdConsumer
   119 {
   120 public:
   121   NetdMessageConsumer()
   122   {
   123     MOZ_ASSERT(NS_IsMainThread());
   124   }
   126   void MessageReceived(NetdCommand* aCommand)
   127   {
   128     MOZ_ASSERT(!NS_IsMainThread());
   130     nsCOMPtr<nsIRunnable> runnable = new NetdEventRunnable(aCommand);
   131     if (gWorkerThread) {
   132       gWorkerThread->Dispatch(runnable, nsIEventTarget::DISPATCH_NORMAL);
   133     }
   134   }
   135 };
   137 NS_IMPL_ISUPPORTS(NetworkWorker, nsINetworkWorker)
   139 NetworkWorker::NetworkWorker()
   140 {
   141   MOZ_ASSERT(NS_IsMainThread());
   142   MOZ_ASSERT(!gNetworkWorker);
   143 }
   145 NetworkWorker::~NetworkWorker()
   146 {
   147   MOZ_ASSERT(!gNetworkWorker);
   148   MOZ_ASSERT(!mListener);
   149 }
   151 already_AddRefed<NetworkWorker>
   152 NetworkWorker::FactoryCreate()
   153 {
   154   if (XRE_GetProcessType() != GeckoProcessType_Default) {
   155     return nullptr;
   156   }
   158   MOZ_ASSERT(NS_IsMainThread());
   160   if (!gNetworkWorker) {
   161     gNetworkWorker = new NetworkWorker();
   162     ClearOnShutdown(&gNetworkWorker);
   164     gNetworkUtils = new NetworkUtils(NetworkWorker::NotifyResult);
   165     ClearOnShutdown(&gNetworkUtils);
   166   }
   168   nsRefPtr<NetworkWorker> worker = gNetworkWorker.get();
   169   return worker.forget();
   170 }
   172 NS_IMETHODIMP
   173 NetworkWorker::Start(nsINetworkEventListener* aListener)
   174 {
   175   MOZ_ASSERT(NS_IsMainThread());
   176   MOZ_ASSERT(aListener);
   178   if (mListener) {
   179     return NS_OK;
   180   }
   182   nsresult rv;
   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   }
   190   StartNetd(new NetdMessageConsumer());
   191   mListener = aListener;
   193   return NS_OK;
   194 }
   196 NS_IMETHODIMP
   197 NetworkWorker::Shutdown()
   198 {
   199   MOZ_ASSERT(NS_IsMainThread());
   201   if (!mListener) {
   202     return NS_OK;
   203   }
   205   StopNetd();
   207   gWorkerThread->Shutdown();
   208   gWorkerThread = nullptr;
   210   mListener = nullptr;
   211   return NS_OK;
   212 }
   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());
   220   NetworkCommandOptions options;
   221   if (!options.Init(aCx, aOptions)) {
   222     NS_WARNING("Bad dictionary passed to NetworkWorker::SendCommand");
   223     return NS_ERROR_FAILURE;
   224   }
   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 }
   235 void
   236 NetworkWorker::DispatchNetworkResult(const NetworkResultOptions& aOptions)
   237 {
   238   MOZ_ASSERT(NS_IsMainThread());
   240   mozilla::AutoSafeJSContext cx;
   241   JS::RootedValue val(cx);
   243   if (!aOptions.ToObject(cx, &val)) {
   244     return;
   245   }
   247   // Call the listener with a JS value.
   248   if (mListener) {
   249     mListener->OnEvent(val);
   250   }
   251 }
   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());
   259   nsCOMPtr<nsIRunnable> runnable = new NetworkResultDispatcher(aResult);
   260   NS_DispatchToMainThread(runnable);
   261 }
   263 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(NetworkWorker,
   264                                          NetworkWorker::FactoryCreate)
   266 NS_DEFINE_NAMED_CID(NS_NETWORKWORKER_CID);
   268 static const mozilla::Module::CIDEntry kNetworkWorkerCIDs[] = {
   269   { &kNS_NETWORKWORKER_CID, false, nullptr, NetworkWorkerConstructor },
   270   { nullptr }
   271 };
   273 static const mozilla::Module::ContractIDEntry kNetworkWorkerContracts[] = {
   274   { "@mozilla.org/network/worker;1", &kNS_NETWORKWORKER_CID },
   275   { nullptr }
   276 };
   278 static const mozilla::Module kNetworkWorkerModule = {
   279   mozilla::Module::kVersion,
   280   kNetworkWorkerCIDs,
   281   kNetworkWorkerContracts,
   282   nullptr
   283 };
   285 } // namespace mozilla
   287 NSMODULE_DEFN(NetworkWorkerModule) = &kNetworkWorkerModule;

mercurial