Bug 960894 - 1/4: allow representing multiple clients in one RIL worker. r=bz
authorVicamo Yang <vyang@mozilla.com>
Mon, 17 Feb 2014 19:35:01 +0800
changeset 169518 d01667dc2bc3e399ab3cee50df9405e03085a876
parent 169517 e9055e7476f1e139fe035e6183a45c838e92df39
child 169519 5ddf528d09dff99814c7d9131db2c741d94f1ecc
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewersbz
bugs960894
milestone30.0a1
Bug 960894 - 1/4: allow representing multiple clients in one RIL worker. r=bz
dom/system/gonk/ril_worker.js
ipc/ril/Ril.cpp
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -13903,17 +13903,17 @@ let ICCContactHelper = {
 /**
  * Global stuff.
  */
 
 // Initialize buffers. This is a separate function so that unit tests can
 // re-initialize the buffers at will.
 Buf.init();
 
-function onRILMessage(data) {
+function onRILMessage(/*unused*/aClientId, data) {
   Buf.processIncoming(data);
 }
 
 onmessage = function onmessage(event) {
   RIL.handleChromeMessage(event.data);
 };
 
 onerror = function onerror(event) {
--- a/ipc/ril/Ril.cpp
+++ b/ipc/ril/Ril.cpp
@@ -139,47 +139,69 @@ bool
 ConnectWorkerToRIL::RunTask(JSContext *aCx)
 {
     // Set up the postRILMessage on the function for worker -> RIL thread
     // communication.
     NS_ASSERTION(!NS_IsMainThread(), "Expecting to be on the worker thread");
     NS_ASSERTION(!JS_IsRunning(aCx), "Are we being called somehow?");
     JS::Rooted<JSObject*> workerGlobal(aCx, JS::CurrentGlobalOrNull(aCx));
 
+    // Check whether |postRILMessage| has been defined.  No one but this class
+    // should ever define |postRILMessage| in a RIL worker, so we call to
+    // |JS_LookupProperty| instead of |JS_GetProperty| here.
+    JS::Rooted<JS::Value> val(aCx);
+    if (!JS_LookupProperty(aCx, workerGlobal, "postRILMessage", &val)) {
+        JS_ReportPendingException(aCx);
+        return false;
+    }
+
+    // |JS_LookupProperty| could still return JS_TRUE with an "undefined"
+    // |postRILMessage|, so we have to make sure that with an additional call
+    // to |JS_TypeOfValue|.
+    if (JSTYPE_FUNCTION == JS_TypeOfValue(aCx, val)) {
+        return true;
+    }
+
     return !!JS_DefineFunction(aCx, workerGlobal,
                                "postRILMessage", PostToRIL, 2, 0);
 }
 
 class DispatchRILEvent : public WorkerTask
 {
 public:
-        DispatchRILEvent(UnixSocketRawData* aMessage)
-            : mMessage(aMessage)
+        DispatchRILEvent(unsigned long aClient,
+                         UnixSocketRawData* aMessage)
+            : mClientId(aClient)
+            , mMessage(aMessage)
         { }
 
         virtual bool RunTask(JSContext *aCx);
 
 private:
+        unsigned long mClientId;
         nsAutoPtr<UnixSocketRawData> mMessage;
 };
 
 bool
 DispatchRILEvent::RunTask(JSContext *aCx)
 {
     JS::Rooted<JSObject*> obj(aCx, JS::CurrentGlobalOrNull(aCx));
 
-    JSObject *array = JS_NewUint8Array(aCx, mMessage->mSize);
+    JS::Rooted<JSObject*> array(aCx, JS_NewUint8Array(aCx, mMessage->mSize));
     if (!array) {
         return false;
     }
-    JS::Rooted<JS::Value> arrayVal(aCx, JS::ObjectValue(*array));
+    memcpy(JS_GetArrayBufferViewData(array), mMessage->mData, mMessage->mSize);
 
-    memcpy(JS_GetArrayBufferViewData(array), mMessage->mData, mMessage->mSize);
+    JS::AutoValueArray<2> args(aCx);
+    args[0].setNumber((uint32_t)mClientId);
+    args[1].setObject(*array);
+
     JS::Rooted<JS::Value> rval(aCx);
-    return JS_CallFunctionName(aCx, obj, "onRILMessage", arrayVal, &rval);
+    return JS_CallFunctionName(aCx, obj, "onRILMessage", args, &rval);
 }
 
 class RilConnector : public mozilla::ipc::UnixSocketConnector
 {
 public:
   RilConnector(unsigned long aClientId) : mClientId(aClientId)
   {}
 
@@ -349,17 +371,17 @@ RilConsumer::Shutdown()
     }
 }
 
 void
 RilConsumer::ReceiveSocketData(nsAutoPtr<UnixSocketRawData>& aMessage)
 {
     MOZ_ASSERT(NS_IsMainThread());
 
-    nsRefPtr<DispatchRILEvent> dre(new DispatchRILEvent(aMessage.forget()));
+    nsRefPtr<DispatchRILEvent> dre(new DispatchRILEvent(mClientId, aMessage.forget()));
     mDispatcher->PostTask(dre);
 }
 
 void
 RilConsumer::OnConnectSuccess()
 {
     // Nothing to do here.
     CHROMIUM_LOG("RIL[%lu]: %s\n", mClientId, __FUNCTION__);