nsresult
SystemWorkerManager::InitNetd(JSContext *cx)
{
  nsCOMPtr<nsIWorkerHolder> worker = do_GetService(kNetworkManagerCID);
  NS_ENSURE_TRUE(worker, NS_ERROR_FAILURE);

  jsval workerval;
  nsresult rv = worker->GetWorker(&workerval);
  NS_ENSURE_SUCCESS(rv, rv);
  NS_ENSURE_TRUE(!JSVAL_IS_PRIMITIVE(workerval), NS_ERROR_UNEXPECTED);

  JSAutoRequest ar(cx);
  JSAutoCompartment ac(cx, JSVAL_TO_OBJECT(workerval));

  WorkerCrossThreadDispatcher *wctd =
    GetWorkerCrossThreadDispatcher(cx, workerval);
  if (!wctd) {
    NS_WARNING("Failed to GetWorkerCrossThreadDispatcher");
    return NS_ERROR_FAILURE;
  }

  nsRefPtr<ConnectWorkerToNetd> connection = new ConnectWorkerToNetd();
  if (!wctd->PostTask(connection)) {
    NS_WARNING("Failed to connect worker to netd");
    return NS_ERROR_UNEXPECTED;
  }

  // Now that we're set up, connect ourselves to the Netd process.
  mozilla::RefPtr<NetdReceiver> receiver = new NetdReceiver(wctd);
  StartNetd(receiver);
  mNetdWorker = worker;
  return NS_OK;
}
nsresult
RadioManager::Init()
{
  NS_ASSERTION(NS_IsMainThread(), "We can only initialize on the main thread");

  nsCOMPtr<nsIObserverService> obs =
    do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
  if (!obs) {
    NS_WARNING("Failed to get observer service!");
    return NS_ERROR_FAILURE;
  }

  nsresult rv = obs->AddObserver(this, PROFILE_BEFORE_CHANGE_TOPIC, false);
  NS_ENSURE_SUCCESS(rv, rv);

  // The telephony worker component is a hack that gives us a global object for
  // our own functions and makes creating the worker possible.
  nsCOMPtr<nsIRadioWorker> worker(do_CreateInstance(kTelephonyWorkerCID));
  NS_ENSURE_TRUE(worker, NS_ERROR_FAILURE);

  jsval workerval;
  rv = worker->GetWorker(&workerval);
  NS_ENSURE_SUCCESS(rv, rv);
  NS_ASSERTION(!JSVAL_IS_PRIMITIVE(workerval), "bad worker value");

  JSContext *cx;
  rv = nsContentUtils::ThreadJSContextStack()->GetSafeJSContext(&cx);
  NS_ENSURE_SUCCESS(rv, rv);
  nsCxPusher pusher;
  if (!cx || !pusher.Push(cx, false)) {
    return NS_ERROR_FAILURE;
  }

  JSObject *workerobj = JSVAL_TO_OBJECT(workerval);

  JSAutoRequest ar(cx);
  JSAutoEnterCompartment ac;
  if (!ac.enter(cx, workerobj)) {
    return NS_ERROR_OUT_OF_MEMORY;
  }

  WorkerCrossThreadDispatcher *wctd = GetWorkerCrossThreadDispatcher(cx, workerval);
  if (!wctd) {
    return NS_ERROR_FAILURE;
  }

  nsRefPtr<ConnectWorkerToRIL> connection = new ConnectWorkerToRIL();
  if (!wctd->PostTask(connection)) {
    return NS_ERROR_UNEXPECTED;
  }

  // Now that we're set up, connect ourselves to the RIL thread.
  mozilla::RefPtr<RILReceiver> receiver = new RILReceiver(wctd);
  StartRil(receiver);

  mTelephone = do_QueryInterface(worker);
  NS_ENSURE_TRUE(mTelephone, NS_ERROR_FAILURE);

  return NS_OK;
}
nsresult
SystemWorkerManager::RegisterRilWorker(unsigned int aClientId,
                                       const JS::Value& aWorker,
                                       JSContext *aCx)
{
  NS_ENSURE_TRUE(!JSVAL_IS_PRIMITIVE(aWorker), NS_ERROR_UNEXPECTED);

  mRilConsumers.EnsureLengthAtLeast(aClientId + 1);

  if (mRilConsumers[aClientId]) {
    NS_WARNING("RilConsumer already registered");
    return NS_ERROR_FAILURE;
  }

  JSAutoRequest ar(aCx);
  JSAutoCompartment ac(aCx, JSVAL_TO_OBJECT(aWorker));

  WorkerCrossThreadDispatcher *wctd =
    GetWorkerCrossThreadDispatcher(aCx, aWorker);
  if (!wctd) {
    NS_WARNING("Failed to GetWorkerCrossThreadDispatcher for ril");
    return NS_ERROR_FAILURE;
  }

  nsRefPtr<ConnectWorkerToRIL> connection = new ConnectWorkerToRIL(aClientId);
  if (!wctd->PostTask(connection)) {
    NS_WARNING("Failed to connect worker to ril");
    return NS_ERROR_UNEXPECTED;
  }

  // Now that we're set up, connect ourselves to the RIL thread.
  mRilConsumers[aClientId] = new RilConsumer(aClientId, wctd);
  return NS_OK;
}
nsresult
SystemWorkerManager::RegisterRilWorker(const JS::Value& aWorker,
                                       JSContext *aCx)
{
  NS_ENSURE_TRUE(!JSVAL_IS_PRIMITIVE(aWorker), NS_ERROR_UNEXPECTED);

  JSAutoRequest ar(aCx);
  JSAutoCompartment ac(aCx, JSVAL_TO_OBJECT(aWorker));

  WorkerCrossThreadDispatcher *wctd =
    GetWorkerCrossThreadDispatcher(aCx, aWorker);
  if (!wctd) {
    return NS_ERROR_FAILURE;
  }

  nsRefPtr<ConnectWorkerToRIL> connection = new ConnectWorkerToRIL();
  if (!wctd->PostTask(connection)) {
    return NS_ERROR_UNEXPECTED;
  }

  // Now that we're set up, connect ourselves to the RIL thread.
  mozilla::RefPtr<RILReceiver> receiver = new RILReceiver(wctd);
  StartRil(receiver);
  return NS_OK;
}
nsresult
SystemWorkerManager::InitRIL(JSContext *cx)
{
  // We're keeping as much of this implementation as possible in JS, so the real
  // worker lives in RadioInterfaceLayer.js. All we do here is hold it alive and
  // hook it up to the RIL thread.
  nsCOMPtr<nsIRadioInterfaceLayer> ril = do_CreateInstance("@mozilla.org/ril;1");
  NS_ENSURE_TRUE(ril, NS_ERROR_FAILURE);

  nsCOMPtr<nsIWorkerHolder> worker = do_QueryInterface(ril);
  if (worker) {
    jsval workerval;
    nsresult rv = worker->GetWorker(&workerval);
    NS_ENSURE_SUCCESS(rv, rv);

    NS_ENSURE_TRUE(!JSVAL_IS_PRIMITIVE(workerval), NS_ERROR_UNEXPECTED);

    JSAutoRequest ar(cx);
    JSAutoCompartment ac(cx, JSVAL_TO_OBJECT(workerval));

    WorkerCrossThreadDispatcher *wctd =
      GetWorkerCrossThreadDispatcher(cx, workerval);
    if (!wctd) {
      return NS_ERROR_FAILURE;
    }

    nsRefPtr<ConnectWorkerToRIL> connection = new ConnectWorkerToRIL();
    if (!wctd->PostTask(connection)) {
      return NS_ERROR_UNEXPECTED;
    }

    // Now that we're set up, connect ourselves to the RIL thread.
    mozilla::RefPtr<RILReceiver> receiver = new RILReceiver(wctd);
    StartRil(receiver);
  }

  mRIL = ril;
  return NS_OK;
}