Merge b2g-inbound to m-c
authorWes Kocher <wkocher@mozilla.com>
Tue, 05 Nov 2013 17:49:16 -0800
changeset 168221 eae5235d50cb35f55dea71e85ce8235db45626d2
parent 168212 971c05007abd118c01d5aa225f43df7ae17346fb (current diff)
parent 168220 3b01163c72665e0aa5eac1bbd1c224a22f4831f1 (diff)
child 168245 ce0d975320e77361e8f82acc2b10f45e20c0a09e
push id3224
push userlsblakk@mozilla.com
push dateTue, 04 Feb 2014 01:06:49 +0000
treeherdermozilla-beta@60c04d0987f1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone28.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge b2g-inbound to m-c
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,4 +1,4 @@
 {
-    "revision": "53c6a2b0bf4c238d39ee0096b79d911aec2de0fc", 
+    "revision": "fe012cdbca542f414a72b0cba9cfb50a4aaf62ae", 
     "repo_path": "/integration/gaia-central"
 }
--- a/dom/system/gonk/SystemWorkerManager.cpp
+++ b/dom/system/gonk/SystemWorkerManager.cpp
@@ -26,16 +26,19 @@
 #include "mozilla/dom/workers/Workers.h"
 #include "mozilla/ipc/Netd.h"
 #include "AutoMounter.h"
 #include "TimeZoneSettingObserver.h"
 #include "AudioManager.h"
 #ifdef MOZ_B2G_RIL
 #include "mozilla/ipc/Ril.h"
 #endif
+#ifdef MOZ_NFC
+#include "mozilla/ipc/Nfc.h"
+#endif
 #include "mozilla/ipc/KeyStore.h"
 #include "nsIObserverService.h"
 #include "nsCxPusher.h"
 #include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
 #include "nsRadioInterfaceLayer.h"
 #include "WifiWorker.h"
 #include "mozilla/Services.h"
@@ -270,16 +273,20 @@ SystemWorkerManager::Shutdown()
   mShutdown = true;
 
   ShutdownAutoMounter();
 
 #ifdef MOZ_B2G_RIL
   RilConsumer::Shutdown();
 #endif
 
+#ifdef MOZ_NFC
+  NfcConsumer::Shutdown();
+#endif
+
   StopNetd();
   mNetdWorker = nullptr;
 
   nsCOMPtr<nsIWifi> wifi(do_QueryInterface(mWifiWorker));
   if (wifi) {
     wifi->Shutdown();
     wifi = nullptr;
   }
@@ -357,16 +364,38 @@ SystemWorkerManager::RegisterRilWorker(u
     return NS_ERROR_FAILURE;
   }
 
   return RilConsumer::Register(aClientId, wctd);
 #endif // MOZ_B2G_RIL
 }
 
 nsresult
+SystemWorkerManager::RegisterNfcWorker(const JS::Value& aWorker,
+                                       JSContext* aCx)
+{
+#ifndef MOZ_NFC
+  return NS_ERROR_NOT_IMPLEMENTED;
+#else
+  NS_ENSURE_TRUE(!JSVAL_IS_PRIMITIVE(aWorker), NS_ERROR_UNEXPECTED);
+
+  JSAutoCompartment ac(aCx, JSVAL_TO_OBJECT(aWorker));
+
+  WorkerCrossThreadDispatcher* wctd =
+    GetWorkerCrossThreadDispatcher(aCx, aWorker);
+  if (!wctd) {
+    NS_WARNING("Failed to GetWorkerCrossThreadDispatcher for nfc");
+    return NS_ERROR_FAILURE;
+  }
+
+  return NfcConsumer::Register(wctd);
+#endif // MOZ_NFC
+}
+
+nsresult
 SystemWorkerManager::InitNetd(JSContext *cx)
 {
   nsCOMPtr<nsIWorkerHolder> worker = do_GetService(kNetworkManagerCID);
   NS_ENSURE_TRUE(worker, NS_ERROR_FAILURE);
 
   JS::Value workerval;
   nsresult rv = worker->GetWorker(&workerval);
   NS_ENSURE_SUCCESS(rv, rv);
--- a/dom/system/gonk/nsISystemWorkerManager.idl
+++ b/dom/system/gonk/nsISystemWorkerManager.idl
@@ -2,15 +2,18 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 /**
  * Information about networks that is exposed to network manager API consumers.
  */
-[scriptable, builtinclass, uuid(02166330-2ff6-4ea5-895a-693c0c2b4c1f)]
+[scriptable, builtinclass, uuid(a9ea96a0-407d-11e3-aa6e-0800200c9a66)]
 interface nsISystemWorkerManager : nsISupports
 {
   [implicit_jscontext]
   void registerRilWorker(in unsigned long aClientId,
                          in jsval aWorker);
+
+  [implicit_jscontext]
+  void registerNfcWorker(in jsval aWorker);
 };
--- a/ipc/moz.build
+++ b/ipc/moz.build
@@ -12,15 +12,18 @@ DIRS += [
 ]
 
 if CONFIG['MOZ_B2G_RIL']:
     DIRS += ['ril']
 
 if CONFIG['MOZ_B2G_BT_BLUEZ']:
     DIRS += ['dbus']
 
-if CONFIG['MOZ_B2G_RIL'] or CONFIG['MOZ_B2G_BT'] or CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
+if CONFIG['MOZ_NFC']:
+    DIRS += ['nfc']
+
+if CONFIG['MOZ_B2G_RIL'] or CONFIG['MOZ_B2G_BT'] or CONFIG['MOZ_NFC'] or CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     DIRS += ['unixsocket']
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     DIRS += ['netd', 'keystore']
 
 TOOL_DIRS += ['app']
--- a/ipc/nfc/Nfc.cpp
+++ b/ipc/nfc/Nfc.cpp
@@ -1,78 +1,185 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* vim: set sw=4 ts=8 et ft=cpp: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+/* Copyright © 2013, Deutsche Telekom, Inc. */
+
+#include "mozilla/ipc/Nfc.h"
+
 #include <fcntl.h>
-#include <limits.h>
-#include <errno.h>
-
 #include <sys/socket.h>
 #include <sys/un.h>
 
 #undef LOG
 #if defined(MOZ_WIDGET_GONK)
 #include <android/log.h>
 #define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "Gonk", args)
 #else
 #define LOG(args...)  printf(args);
 #endif
 
 #include "jsfriendapi.h"
 #include "nsThreadUtils.h" // For NS_IsMainThread.
-#include "Nfc.h"
 
 USING_WORKERS_NAMESPACE
 using namespace mozilla::ipc;
 
 namespace {
 
 const char* NFC_SOCKET_NAME = "/dev/socket/nfcd";
 
 // Network port to connect to for adb forwarded sockets when doing
 // desktop development.
-const uint32_t NFCD_TEST_PORT = 6400;
+const uint32_t NFC_TEST_PORT = 6400;
+
+nsRefPtr<mozilla::ipc::NfcConsumer> sNfcConsumer;
 
-class DispatchNfcEvent : public WorkerTask
+class ConnectWorkerToNFC : public WorkerTask
+{
+public:
+    ConnectWorkerToNFC()
+    { }
+
+    virtual bool RunTask(JSContext* aCx);
+};
+
+class SendNfcSocketDataTask : public nsRunnable
 {
 public:
-    DispatchNfcEvent(UnixSocketRawData* aMessage)
-      : mMessage(aMessage)
+    SendNfcSocketDataTask(UnixSocketRawData* aRawData)
+        : mRawData(aRawData)
     { }
 
-    virtual bool RunTask(JSContext *aCx);
+    NS_IMETHOD Run()
+    {
+        MOZ_ASSERT(NS_IsMainThread());
+
+        if (!sNfcConsumer ||
+            sNfcConsumer->GetConnectionStatus() != SOCKET_CONNECTED) {
+            // Probably shuting down.
+            delete mRawData;
+            return NS_OK;
+        }
+
+        sNfcConsumer->SendSocketData(mRawData);
+        return NS_OK;
+    }
+
+private:
+    UnixSocketRawData* mRawData;
+};
+
+bool
+PostToNFC(JSContext* aCx,
+          unsigned aArgc,
+          JS::Value* aArgv)
+{
+    NS_ASSERTION(!NS_IsMainThread(), "Expecting to be on the worker thread");
+
+    if (aArgc != 1) {
+        JS_ReportError(aCx, "Expecting one argument with the NFC message");
+        return false;
+    }
+
+    JS::Value v = JS_ARGV(aCx, aArgv)[0];
+
+    JSAutoByteString abs;
+    void* data;
+    size_t size;
+    if (JSVAL_IS_STRING(v)) {
+        JSString* str = JSVAL_TO_STRING(v);
+        if (!abs.encodeUtf8(aCx, str)) {
+            return false;
+        }
+
+        data = abs.ptr();
+        size = abs.length();
+    } else if (!JSVAL_IS_PRIMITIVE(v)) {
+        JSObject* obj = JSVAL_TO_OBJECT(v);
+        if (!JS_IsTypedArrayObject(obj)) {
+            JS_ReportError(aCx, "Object passed in wasn't a typed array");
+            return false;
+        }
+
+        uint32_t type = JS_GetArrayBufferViewType(obj);
+        if (type != js::ArrayBufferView::TYPE_INT8 &&
+            type != js::ArrayBufferView::TYPE_UINT8 &&
+            type != js::ArrayBufferView::TYPE_UINT8_CLAMPED) {
+            JS_ReportError(aCx, "Typed array data is not octets");
+            return false;
+        }
+
+        size = JS_GetTypedArrayByteLength(obj);
+        data = JS_GetArrayBufferViewData(obj);
+    } else {
+        JS_ReportError(aCx,
+                       "Incorrect argument. Expecting a string or a typed array");
+        return false;
+    }
+
+    UnixSocketRawData* raw = new UnixSocketRawData(data, size);
+
+    nsRefPtr<SendNfcSocketDataTask> task =
+        new SendNfcSocketDataTask(raw);
+    NS_DispatchToMainThread(task);
+    return true;
+}
+
+bool
+ConnectWorkerToNFC::RunTask(JSContext* aCx)
+{
+    // Set up the postNFCMessage on the function for worker -> NFC thread
+    // communication.
+    NS_ASSERTION(!NS_IsMainThread(), "Expecting to be on the worker thread");
+    NS_ASSERTION(!JS_IsRunning(aCx), "Are we being called somehow?");
+    JSObject* workerGlobal = JS::CurrentGlobalOrNull(aCx);
+
+    return !!JS_DefineFunction(aCx, workerGlobal,
+                               "postNfcMessage", PostToNFC, 1, 0);
+}
+
+class DispatchNFCEvent : public WorkerTask
+{
+public:
+    DispatchNFCEvent(UnixSocketRawData* aMessage)
+        : mMessage(aMessage)
+    { }
+
+    virtual bool RunTask(JSContext* aCx);
 
 private:
     nsAutoPtr<UnixSocketRawData> mMessage;
 };
 
 bool
-DispatchNfcEvent::RunTask(JSContext *aCx)
+DispatchNFCEvent::RunTask(JSContext* aCx)
 {
-    MOZ_ASSERT(NS_IsMainThread(), "DispatchNfcEvent on main thread");
-    MOZ_ASSERT(aCx);
+    JSObject* obj = JS::CurrentGlobalOrNull(aCx);
 
-    JSObject *obj = JS::CurrentGlobalOrNull(aCx);
-    JSObject *array = JS_NewUint8Array(aCx, mMessage->mSize);
+    JSObject* array = JS_NewUint8Array(aCx, mMessage->mSize);
     if (!array) {
         return false;
     }
+
     memcpy(JS_GetArrayBufferViewData(array), mMessage->mData, mMessage->mSize);
-    jsval argv[] = { OBJECT_TO_JSVAL(array) };
+    JS::Value argv[] = { OBJECT_TO_JSVAL(array) };
     return JS_CallFunctionName(aCx, obj, "onNfcMessage", NS_ARRAY_LENGTH(argv),
                                argv, argv);
 }
 
 class NfcConnector : public mozilla::ipc::UnixSocketConnector
 {
 public:
-    NfcConnector() {}
+    NfcConnector()
+    {}
+
     virtual ~NfcConnector()
     {}
 
     virtual int Create();
     virtual bool CreateAddr(bool aIsServer,
                             socklen_t& aAddrSize,
                             sockaddr_any& aAddr,
                             const char* aAddress);
@@ -92,17 +199,17 @@ NfcConnector::Create()
 #if defined(MOZ_WIDGET_GONK)
     fd = socket(AF_LOCAL, SOCK_STREAM, 0);
 #else
     // If we can't hit a local loopback, fail later in connect.
     fd = socket(AF_INET, SOCK_STREAM, 0);
 #endif
 
     if (fd < 0) {
-        NS_WARNING("Could not open Nfc socket!");
+        NS_WARNING("Could not open nfc socket!");
         return -1;
     }
 
     if (!SetUp(fd)) {
         NS_WARNING("Could not set up socket!");
     }
     return fd;
 }
@@ -128,26 +235,25 @@ NfcConnector::CreateAddr(bool aIsServer,
             NS_WARNING("Address too long for socket struct!");
             return false;
         }
         strcpy((char*)&aAddr.un.sun_path, aAddress);
         aAddrSize = strlen(aAddress) + offsetof(struct sockaddr_un, sun_path) + 1;
         break;
     case AF_INET:
         aAddr.in.sin_family = af;
-        aAddr.in.sin_port = htons(NFCD_TEST_PORT);
+        aAddr.in.sin_port = htons(NFC_TEST_PORT);
         aAddr.in.sin_addr.s_addr = htons(INADDR_LOOPBACK);
         aAddrSize = sizeof(sockaddr_in);
         break;
     default:
         NS_WARNING("Socket type not handled by connector!");
         return false;
     }
     return true;
-
 }
 
 bool
 NfcConnector::SetUp(int aFd)
 {
     // Nothing to do here.
     return true;
 }
@@ -163,66 +269,83 @@ void
 NfcConnector::GetSocketAddr(const sockaddr_any& aAddr,
                             nsAString& aAddrStr)
 {
     MOZ_CRASH("This should never be called!");
 }
 
 } // anonymous namespace
 
-
 namespace mozilla {
 namespace ipc {
 
 NfcConsumer::NfcConsumer(WorkerCrossThreadDispatcher* aDispatcher)
     : mDispatcher(aDispatcher)
     , mShutdown(false)
 {
-    ConnectSocket(new NfcConnector(), NFC_SOCKET_NAME);
+    mAddress = NFC_SOCKET_NAME;
+
+    ConnectSocket(new NfcConnector(), mAddress.get());
+}
+
+nsresult
+NfcConsumer::Register(WorkerCrossThreadDispatcher* aDispatcher)
+{
+    MOZ_ASSERT(NS_IsMainThread());
+
+    if (sNfcConsumer) {
+        return NS_ERROR_FAILURE;
+    }
+
+    nsRefPtr<ConnectWorkerToNFC> connection = new ConnectWorkerToNFC();
+    if (!aDispatcher->PostTask(connection)) {
+        return NS_ERROR_UNEXPECTED;
+    }
+
+    // Now that we're set up, connect ourselves to the NFC thread.
+    sNfcConsumer = new NfcConsumer(aDispatcher);
+    return NS_OK;
 }
 
 void
 NfcConsumer::Shutdown()
 {
-    mShutdown = true;
-    CloseSocket();
+    MOZ_ASSERT(NS_IsMainThread());
+
+    sNfcConsumer->mShutdown = true;
+    sNfcConsumer->CloseSocket();
+    sNfcConsumer = nullptr;
 }
 
 void
 NfcConsumer::ReceiveSocketData(nsAutoPtr<UnixSocketRawData>& aMessage)
 {
     MOZ_ASSERT(NS_IsMainThread());
-#ifdef DEBUG
-    LOG("ReceiveSocketData\n");
-#endif
-    nsRefPtr<DispatchNfcEvent> dre(new DispatchNfcEvent(aMessage.forget()));
+
+    nsRefPtr<DispatchNFCEvent> dre(new DispatchNFCEvent(aMessage.forget()));
     mDispatcher->PostTask(dre);
 }
 
 void
 NfcConsumer::OnConnectSuccess()
 {
     // Nothing to do here.
-    LOG("Socket open for Nfc\n");
+    LOG("NFC: %s\n", __FUNCTION__);
 }
 
 void
 NfcConsumer::OnConnectError()
 {
-#ifdef DEBUG
-    LOG("%s\n", __FUNCTION__);
-#endif
+    LOG("NFC: %s\n", __FUNCTION__);
     CloseSocket();
 }
 
 void
 NfcConsumer::OnDisconnect()
 {
-#ifdef DEBUG
-    LOG("%s\n", __FUNCTION__);
-#endif
+    LOG("NFC: %s\n", __FUNCTION__);
     if (!mShutdown) {
-        ConnectSocket(new NfcConnector(), NFC_SOCKET_NAME, 1000);
+        ConnectSocket(new NfcConnector(), mAddress.get(), 1000);
     }
 }
 
 } // namespace ipc
 } // namespace mozilla
--- a/ipc/nfc/Nfc.h
+++ b/ipc/nfc/Nfc.h
@@ -1,37 +1,44 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set sw=2 ts=8 et ft=cpp: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+/* Copyright © 2013, Deutsche Telekom, Inc. */
+
 #ifndef mozilla_ipc_Nfc_h
 #define mozilla_ipc_Nfc_h 1
 
 #include <mozilla/dom/workers/Workers.h>
 #include <mozilla/ipc/UnixSocket.h>
 
 namespace mozilla {
 namespace ipc {
 
 class NfcConsumer : public mozilla::ipc::UnixSocketConsumer
 {
 public:
-    NfcConsumer(mozilla::dom::workers::WorkerCrossThreadDispatcher* aDispatcher);
-    virtual ~NfcConsumer() { }
-    void Shutdown();
-private:
-    virtual void ReceiveSocketData(nsAutoPtr<UnixSocketRawData>& aMessage);
+  virtual ~NfcConsumer() { }
 
-    virtual void OnConnectSuccess();
-    virtual void OnConnectError();
-    virtual void OnDisconnect();
+  static nsresult Register(mozilla::dom::workers::WorkerCrossThreadDispatcher* aDispatcher);
+  static void Shutdown();
 
 private:
-    nsRefPtr<mozilla::dom::workers::WorkerCrossThreadDispatcher> mDispatcher;
-    bool mShutdown;
+  NfcConsumer(mozilla::dom::workers::WorkerCrossThreadDispatcher* aDispatcher);
+
+  virtual void ReceiveSocketData(nsAutoPtr<UnixSocketRawData>& aMessage);
+
+  virtual void OnConnectSuccess();
+  virtual void OnConnectError();
+  virtual void OnDisconnect();
+
+private:
+  nsRefPtr<mozilla::dom::workers::WorkerCrossThreadDispatcher> mDispatcher;
+  nsCString mAddress;
+  bool mShutdown;
 };
 
 } // namespace ipc
 } // namepsace mozilla
 
 #endif // mozilla_ipc_Nfc_h
--- a/ipc/nfc/moz.build
+++ b/ipc/nfc/moz.build
@@ -1,14 +1,14 @@
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-if CONFIG['MOZ_B2G_NFC']:
+if CONFIG['MOZ_NFC']:
     MODULE = 'ipc'
     EXPORTS.mozilla.ipc += [
         'Nfc.h',
     ]
     SOURCES += [
         'Nfc.cpp',
     ]