Bug 878745 - BluetoothService cleanup, r=echou
authorGina Yeh <gyeh@mozilla.com>
Mon, 10 Jun 2013 12:18:00 +0800
changeset 134487 1b54057a41ccb383aa23b0cba8978c63fb4702f5
parent 134486 86a801e6e76357903ff9a8805f740aee3d7480e2
child 134488 252b1ac4d537267abe953b79957b308b00e6f032
push id29232
push useremorley@mozilla.com
push dateMon, 10 Jun 2013 09:07:08 +0000
treeherdermozilla-inbound@deb589f7e2dc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersechou
bugs878745
milestone24.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
Bug 878745 - BluetoothService cleanup, r=echou
dom/bluetooth/BluetoothService.cpp
dom/bluetooth/BluetoothService.h
dom/bluetooth/ipc/BluetoothServiceChildProcess.cpp
dom/bluetooth/ipc/BluetoothServiceChildProcess.h
dom/bluetooth/linux/BluetoothDBusService.cpp
dom/bluetooth/linux/BluetoothDBusService.h
--- a/dom/bluetooth/BluetoothService.cpp
+++ b/dom/bluetooth/BluetoothService.cpp
@@ -815,8 +815,18 @@ BluetoothService::Notify(const Bluetooth
   NS_ENSURE_TRUE_VOID(systemMessenger);
 
   systemMessenger->BroadcastMessage(type, OBJECT_TO_JSVAL(obj));
 
   if (!oldType.IsEmpty()) {
     systemMessenger->BroadcastMessage(oldType, OBJECT_TO_JSVAL(obj));
   }
 }
+
+void
+BluetoothService::DispatchToCommandThread(nsRunnable* aRunnable)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(aRunnable);
+  MOZ_ASSERT(mBluetoothCommandThread);
+
+  mBluetoothCommandThread->Dispatch(aRunnable, NS_DISPATCH_NORMAL);
+}
--- a/dom/bluetooth/BluetoothService.h
+++ b/dom/bluetooth/BluetoothService.h
@@ -154,26 +154,16 @@ public:
    * Start device discovery (platform specific implementation)
    *
    * @return NS_OK if discovery stopped correctly, false otherwise
    */
   virtual nsresult
   StartDiscoveryInternal(BluetoothReplyRunnable* aRunnable) = 0;
 
   /**
-   * Fetches the propertes for the specified device
-   *
-   * @param aSignal BluetoothSignal to be distrubuted after retrieving device properties
-   *
-   * @return NS_OK on function run, NS_ERROR_FAILURE otherwise
-   */
-  virtual nsresult
-  GetDevicePropertiesInternal(const BluetoothSignal& aSignal) = 0;
-
-  /**
    * Set a property for the specified object
    *
    * @param aPropName Name of the property
    * @param aValue Boolean value
    * @param aRunnable Runnable to run on async reply
    *
    * @return NS_OK if property is set correctly, NS_ERROR_FAILURE otherwise
    */
@@ -241,19 +231,16 @@ public:
   virtual bool
   SetPairingConfirmationInternal(const nsAString& aDeviceAddress, bool aConfirm,
                                  BluetoothReplyRunnable* aRunnable) = 0;
 
   virtual bool
   SetAuthorizationInternal(const nsAString& aDeviceAddress, bool aAllow,
                            BluetoothReplyRunnable* aRunnable) = 0;
 
-  virtual nsresult
-  PrepareAdapterInternal() = 0;
-
   virtual void
   Connect(const nsAString& aDeviceAddress,
           uint16_t aProfileId,
           BluetoothReplyRunnable* aRunnable) = 0;
 
   virtual void
   Disconnect(uint16_t aProfileId, BluetoothReplyRunnable* aRunnable) = 0;
 
@@ -294,16 +281,19 @@ public:
   }
 
   bool
   IsToggling() const;
 
   void
   RemoveObserverFromTable(const nsAString& key);
 
+  void
+  DispatchToCommandThread(nsRunnable* aRunnable);
+
 protected:
   BluetoothService()
   : mEnabled(false)
   {
     mBluetoothSignalObserverTable.Init();
   }
 
   virtual ~BluetoothService();
--- a/dom/bluetooth/ipc/BluetoothServiceChildProcess.cpp
+++ b/dom/bluetooth/ipc/BluetoothServiceChildProcess.cpp
@@ -98,24 +98,16 @@ nsresult
 BluetoothServiceChildProcess::GetDefaultAdapterPathInternal(
                                               BluetoothReplyRunnable* aRunnable)
 {
   SendRequest(aRunnable, DefaultAdapterPathRequest());
   return NS_OK;
 }
 
 nsresult
-BluetoothServiceChildProcess::GetDevicePropertiesInternal(
-                                                 const BluetoothSignal& aSignal)
-{
-  MOZ_NOT_REACHED("Should never be called from child");
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-nsresult
 BluetoothServiceChildProcess::GetConnectedDevicePropertiesInternal(
                                               uint16_t aProfileId,
                                               BluetoothReplyRunnable* aRunnable)
 {
   SendRequest(aRunnable, ConnectedDevicePropertiesRequest(aProfileId));
   return NS_OK;
 }
 nsresult
@@ -272,23 +264,16 @@ BluetoothServiceChildProcess::SetAuthori
                 ConfirmAuthorizationRequest(nsString(aDeviceAddress)));
   } else {
     SendRequest(aRunnable,
                 DenyAuthorizationRequest(nsString(aDeviceAddress)));
   }
   return true;
 }
 
-nsresult
-BluetoothServiceChildProcess::PrepareAdapterInternal()
-{
-  MOZ_NOT_REACHED("Should never be called from child");
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
 void
 BluetoothServiceChildProcess::Connect(
   const nsAString& aDeviceAddress,
   const uint16_t aProfileId,
   BluetoothReplyRunnable* aRunnable)
 {
   SendRequest(aRunnable,
               ConnectRequest(nsString(aDeviceAddress),
--- a/dom/bluetooth/ipc/BluetoothServiceChildProcess.h
+++ b/dom/bluetooth/ipc/BluetoothServiceChildProcess.h
@@ -180,24 +180,16 @@ private:
   // This method should never be called.
   virtual nsresult
   StopInternal() MOZ_OVERRIDE;
 
   // This method should never be called.
   virtual bool
   IsEnabledInternal() MOZ_OVERRIDE;
 
-  // Should never be called from the child
-  virtual nsresult
-  GetDevicePropertiesInternal(const BluetoothSignal& aSignal) MOZ_OVERRIDE;
-
-  // This method should never be called from the child.
-  virtual nsresult
-  PrepareAdapterInternal() MOZ_OVERRIDE;
-
   bool
   IsSignalRegistered(const nsAString& aNodeName) {
     return !!mBluetoothSignalObserverTable.Get(aNodeName);
   }
 };
 
 END_BLUETOOTH_NAMESPACE
 
--- a/dom/bluetooth/linux/BluetoothDBusService.cpp
+++ b/dom/bluetooth/linux/BluetoothDBusService.cpp
@@ -168,35 +168,33 @@ public:
     MOZ_ASSERT(!aDeviceObjectPath.IsEmpty());
     MOZ_ASSERT(aRunnable);
   }
 
   nsresult Run()
   {
     MOZ_ASSERT(!NS_IsMainThread());
 
-    BluetoothValue v = true;
-    nsAutoString errorStr;
-
     const char* tempDeviceObjectPath = mDeviceObjectPath.get();
 
     DBusMessage *reply =
       dbus_func_args(gThreadConnection->GetConnection(),
                      NS_ConvertUTF16toUTF8(sAdapterPath).get(),
                      DBUS_ADAPTER_IFACE, "RemoveDevice",
                      DBUS_TYPE_OBJECT_PATH, &tempDeviceObjectPath,
                      DBUS_TYPE_INVALID);
 
+    nsAutoString errorStr;
     if (reply) {
       dbus_message_unref(reply);
     } else {
       errorStr.AssignLiteral("RemoveDevice failed");
     }
 
-    DispatchBluetoothReply(mRunnable, v, errorStr);
+    DispatchBluetoothReply(mRunnable, BluetoothValue(true), errorStr);
 
     return NS_OK;
   }
 
 private:
   nsCString mDeviceObjectPath;
   nsRefPtr<BluetoothReplyRunnable> mRunnable;
 };
@@ -250,110 +248,42 @@ public:
                      NS_ConvertUTF16toUTF8(sAdapterPath).get(),
                      DBUS_ADAPTER_IFACE, mMessageName,
                      DBUS_TYPE_INVALID);
 
     if (reply) {
       dbus_message_unref(reply);
     }
 
-    BluetoothValue v = true;
-    nsAutoString errorStr;
-    DispatchBluetoothReply(mRunnable, v, errorStr);
+    DispatchBluetoothReply(mRunnable, BluetoothValue(true), EmptyString());
 
     return NS_OK;
   }
 
 private:
   const char* mMessageName;
   nsRefPtr<BluetoothReplyRunnable> mRunnable;
 };
 
 class DistributeBluetoothSignalTask : public nsRunnable
 {
 public:
-  DistributeBluetoothSignalTask(const BluetoothSignal& aSignal) :
-    mSignal(aSignal)
+  DistributeBluetoothSignalTask(const BluetoothSignal& aSignal)
+    : mSignal(aSignal)
   {
   }
 
-  NS_IMETHOD
-  Run()
-  {
-    MOZ_ASSERT(NS_IsMainThread());
-    BluetoothService* bs = BluetoothService::Get();
-    if (!bs) {
-      NS_WARNING("BluetoothService not available!");
-      return NS_ERROR_FAILURE;
-    }
-    bs->DistributeSignal(mSignal);
-    return NS_OK;
-  }
-
-private:
-  BluetoothSignal mSignal;
-};
-
-class PrepareAdapterTask : public nsRunnable
-{
-public:
-  PrepareAdapterTask(const nsAString& aPath) :
-    mPath(aPath)
-  {
-  }
-
-  NS_IMETHOD
-  Run()
+  nsresult Run()
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     BluetoothService* bs = BluetoothService::Get();
     NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE);
-    sAdapterPath = mPath;
-
-    // Due to the fact that we need to queue the dbus call to the command
-    // thread inside the bluetoothservice, we have to route the call down
-    // to the main thread and then back out to the command thread. There has
-    // to be a better way to do this.
-    if (NS_FAILED(bs->PrepareAdapterInternal())) {
-      NS_WARNING("Prepare adapter failed");
-      return NS_ERROR_FAILURE;
-    }
-    return NS_OK;
-  }
-
-private:
-  nsString mPath;
-};
-
-class DevicePropertiesSignalHandler : public nsRunnable
-{
-public:
-  DevicePropertiesSignalHandler(const BluetoothSignal& aSignal) :
-    mSignal(aSignal)
-  {
-  }
-
-  NS_IMETHODIMP
-  Run()
-  {
-    MOZ_ASSERT(NS_IsMainThread());
-
-    // Get device properties and then send to BluetoothAdapter
-    BluetoothService* bs = BluetoothService::Get();
-    NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE);
-
-    // Due to the fact that we need to queue the dbus call to the command thread
-    // inside the bluetoothservice, we have to route the call down to the main
-    // thread and then back out to the command thread. There has to be a better
-    // way to do this.
-    if (NS_FAILED(bs->GetDevicePropertiesInternal(mSignal))) {
-      NS_WARNING("Get device properties failed");
-      return NS_ERROR_FAILURE;
-    }
+    bs->DistributeSignal(mSignal);
+
     return NS_OK;
   }
 
 private:
   BluetoothSignal mSignal;
 };
 
 class SinkPropertyChangedHandler : public nsRunnable
@@ -421,18 +351,18 @@ static void
 UnpackIntMessage(DBusMessage* aMsg, DBusError* aErr,
                  BluetoothValue& aValue, nsAString& aErrorStr)
 {
   MOZ_ASSERT(aMsg);
 
   DBusError err;
   dbus_error_init(&err);
   if (!IsDBusMessageError(aMsg, aErr, aErrorStr)) {
-    NS_ASSERTION(dbus_message_get_type(aMsg) == DBUS_MESSAGE_TYPE_METHOD_RETURN,
-                 "Got dbus callback that's not a METHOD_RETURN!");
+    MOZ_ASSERT(dbus_message_get_type(aMsg) == DBUS_MESSAGE_TYPE_METHOD_RETURN,
+               "Got dbus callback that's not a METHOD_RETURN!");
     int i;
     if (!dbus_message_get_args(aMsg, &err, DBUS_TYPE_INT32,
                                &i, DBUS_TYPE_INVALID)) {
       if (dbus_error_is_set(&err)) {
         aErrorStr = NS_ConvertUTF8toUTF16(err.message);
         LOG_AND_FREE_DBUS_ERROR(&err);
       }
     } else {
@@ -443,395 +373,74 @@ UnpackIntMessage(DBusMessage* aMsg, DBus
 
 static void
 UnpackObjectPathMessage(DBusMessage* aMsg, DBusError* aErr,
                         BluetoothValue& aValue, nsAString& aErrorStr)
 {
   DBusError err;
   dbus_error_init(&err);
   if (!IsDBusMessageError(aMsg, aErr, aErrorStr)) {
-    NS_ASSERTION(dbus_message_get_type(aMsg) == DBUS_MESSAGE_TYPE_METHOD_RETURN,
-                 "Got dbus callback that's not a METHOD_RETURN!");
+    MOZ_ASSERT(dbus_message_get_type(aMsg) == DBUS_MESSAGE_TYPE_METHOD_RETURN,
+               "Got dbus callback that's not a METHOD_RETURN!");
     const char* object_path;
     if (!dbus_message_get_args(aMsg, &err, DBUS_TYPE_OBJECT_PATH,
                                &object_path, DBUS_TYPE_INVALID) ||
         !object_path) {
       if (dbus_error_is_set(&err)) {
         aErrorStr = NS_ConvertUTF8toUTF16(err.message);
         LOG_AND_FREE_DBUS_ERROR(&err);
       }
     } else {
       aValue = NS_ConvertUTF8toUTF16(object_path);
     }
   }
 }
 
 static void
-KeepDBusPairingMessage(const nsString& aDeviceAddress, DBusMessage* aMsg)
-{
-  sPairingReqTable.Put(aDeviceAddress, aMsg);
-
-  // Increase ref count here because we need this message later.
-  // It'll be unrefed when set*Internal() is called.
-  dbus_message_ref(aMsg);
-}
-
-static DBusHandlerResult
-AgentEventFilter(DBusConnection *conn, DBusMessage *msg, void *data)
-{
-  if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_METHOD_CALL) {
-    BT_WARNING("%s: agent handler not interested (not a method call).\n",
-               __FUNCTION__);
-    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-  }
-
-  DBusError err;
-  dbus_error_init(&err);
-
-  BT_LOG("%s: %s, %s", __FUNCTION__,
-                       dbus_message_get_path(msg),
-                       dbus_message_get_member(msg));
-
-  nsString signalPath = NS_ConvertUTF8toUTF16(dbus_message_get_path(msg));
-  nsString signalName = NS_ConvertUTF8toUTF16(dbus_message_get_member(msg));
-  nsString errorStr;
-  BluetoothValue v;
-  InfallibleTArray<BluetoothNamedValue> parameters;
-
-  // The following descriptions of each signal are retrieved from:
-  //
-  // http://maemo.org/api_refs/5.0/beta/bluez/agent.html
-  //
-  if (dbus_message_is_method_call(msg, DBUS_AGENT_IFACE, "Cancel")) {
-    // This method gets called to indicate that the agent request failed before
-    // a reply was returned.
-
-    // Return directly
-    DBusMessage *reply = dbus_message_new_method_return(msg);
-
-    if (!reply) {
-      errorStr.AssignLiteral("Memory can't be allocated for the message.");
-    } else {
-      dbus_func_send(conn, nullptr, reply);
-      dbus_message_unref(reply);
-      v = parameters;
-    }
-  } else if (dbus_message_is_method_call(msg, DBUS_AGENT_IFACE, "Authorize")) {
-    // This method gets called when the service daemon needs to authorize a
-    // connection/service request.
-    char *objectPath;
-    const char *uuid;
-    if (!dbus_message_get_args(msg, NULL,
-                               DBUS_TYPE_OBJECT_PATH, &objectPath,
-                               DBUS_TYPE_STRING, &uuid,
-                               DBUS_TYPE_INVALID)) {
-      BT_WARNING("%s: Invalid arguments for Authorize() method", __FUNCTION__);
-      errorStr.AssignLiteral("Invalid arguments for Authorize() method");
-    } else {
-      nsString deviceAddress =
-        GetAddressFromObjectPath(NS_ConvertUTF8toUTF16(objectPath));
-
-      parameters.AppendElement(BluetoothNamedValue(
-                                 NS_LITERAL_STRING("deviceAddress"),
-                                 deviceAddress));
-      parameters.AppendElement(BluetoothNamedValue(
-                                 NS_LITERAL_STRING("uuid"),
-                                 NS_ConvertUTF8toUTF16(uuid)));
-
-      // Because we may have authorization request and pairing request from the
-      // same remote device at the same time, we need two tables to keep these
-      // messages.
-      sAuthorizeReqTable.Put(deviceAddress, msg);
-
-      // Increase ref count here because we need this message later.
-      // It'll be unrefed when setAuthorizationInternal() is called.
-      dbus_message_ref(msg);
-
-      v = parameters;
-    }
-  } else if (dbus_message_is_method_call(msg, DBUS_AGENT_IFACE,
-                                         "RequestConfirmation")) {
-    // This method gets called when the service daemon needs to confirm a
-    // passkey for an authentication.
-    char *objectPath;
-    uint32_t passkey;
-    if (!dbus_message_get_args(msg, NULL,
-                               DBUS_TYPE_OBJECT_PATH, &objectPath,
-                               DBUS_TYPE_UINT32, &passkey,
-                               DBUS_TYPE_INVALID)) {
-      BT_WARNING("%s: Invalid arguments: RequestConfirmation()", __FUNCTION__);
-      errorStr.AssignLiteral("Invalid arguments: RequestConfirmation()");
-    } else {
-      parameters.AppendElement(BluetoothNamedValue(
-                                 NS_LITERAL_STRING("path"),
-                                 NS_ConvertUTF8toUTF16(objectPath)));
-      parameters.AppendElement(BluetoothNamedValue(
-                                 NS_LITERAL_STRING("method"),
-                                 NS_LITERAL_STRING("confirmation")));
-      parameters.AppendElement(BluetoothNamedValue(
-                                 NS_LITERAL_STRING("passkey"),
-                                 passkey));
-
-      KeepDBusPairingMessage(GetAddressFromObjectPath(
-                               NS_ConvertUTF8toUTF16(objectPath)), msg);
-
-      BluetoothSignal signal(signalName, signalPath, parameters);
-
-      // Fire a Device properties fetcher at the main thread
-      nsRefPtr<DevicePropertiesSignalHandler> b =
-        new DevicePropertiesSignalHandler(signal);
-      if (NS_FAILED(NS_DispatchToMainThread(b))) {
-        NS_WARNING("Failed to dispatch to main thread!");
-      }
-      // Since we're handling this in other threads, just fall out here
-      return DBUS_HANDLER_RESULT_HANDLED;
-    }
-  } else if (dbus_message_is_method_call(msg, DBUS_AGENT_IFACE,
-                                         "RequestPinCode")) {
-    // This method gets called when the service daemon needs to get the passkey
-    // for an authentication. The return value should be a string of 1-16
-    // characters length. The string can be alphanumeric.
-    char *objectPath;
-    if (!dbus_message_get_args(msg, NULL,
-                               DBUS_TYPE_OBJECT_PATH, &objectPath,
-                               DBUS_TYPE_INVALID)) {
-      BT_WARNING("%s: Invalid arguments for RequestPinCode() method",
-                 __FUNCTION__);
-      errorStr.AssignLiteral("Invalid arguments for RequestPinCode() method");
-    } else {
-      parameters.AppendElement(BluetoothNamedValue(
-                                 NS_LITERAL_STRING("path"),
-                                 NS_ConvertUTF8toUTF16(objectPath)));
-      parameters.AppendElement(BluetoothNamedValue(
-                                 NS_LITERAL_STRING("method"),
-                                 NS_LITERAL_STRING("pincode")));
-
-      KeepDBusPairingMessage(GetAddressFromObjectPath(
-                               NS_ConvertUTF8toUTF16(objectPath)), msg);
-
-      BluetoothSignal signal(signalName, signalPath, parameters);
-
-      // Fire a Device properties fetcher at the main thread
-      nsRefPtr<DevicePropertiesSignalHandler> b =
-        new DevicePropertiesSignalHandler(signal);
-      if (NS_FAILED(NS_DispatchToMainThread(b))) {
-        NS_WARNING("Failed to dispatch to main thread!");
-      }
-      // Since we're handling this in other threads, just fall out here
-      return DBUS_HANDLER_RESULT_HANDLED;
-    }
-  } else if (dbus_message_is_method_call(msg, DBUS_AGENT_IFACE,
-                                         "RequestPasskey")) {
-    // This method gets called when the service daemon needs to get the passkey
-    // for an authentication. The return value should be a numeric value
-    // between 0-999999.
-    char *objectPath;
-    if (!dbus_message_get_args(msg, NULL,
-                               DBUS_TYPE_OBJECT_PATH, &objectPath,
-                               DBUS_TYPE_INVALID)) {
-      BT_WARNING("%s: Invalid arguments for RequestPasskey() method",
-                 __FUNCTION__);
-      errorStr.AssignLiteral("Invalid arguments for RequestPasskey() method");
-    } else {
-      parameters.AppendElement(BluetoothNamedValue(
-                                 NS_LITERAL_STRING("path"),
-                                 NS_ConvertUTF8toUTF16(objectPath)));
-      parameters.AppendElement(BluetoothNamedValue(
-                                 NS_LITERAL_STRING("method"),
-                                 NS_LITERAL_STRING("passkey")));
-
-      KeepDBusPairingMessage(GetAddressFromObjectPath(
-                               NS_ConvertUTF8toUTF16(objectPath)), msg);
-
-      BluetoothSignal signal(signalName, signalPath, parameters);
-
-      // Fire a Device properties fetcher at the main thread
-      nsRefPtr<DevicePropertiesSignalHandler> b =
-        new DevicePropertiesSignalHandler(signal);
-      if (NS_FAILED(NS_DispatchToMainThread(b))) {
-        NS_WARNING("Failed to dispatch to main thread!");
-      }
-      // Since we're handling this in other threads, just fall out here
-      return DBUS_HANDLER_RESULT_HANDLED;
-    }
-  } else if (dbus_message_is_method_call(msg, DBUS_AGENT_IFACE, "Release")) {
-    // This method gets called when the service daemon unregisters the agent.
-    // An agent can use it to do cleanup tasks. There is no need to unregister
-    // the agent, because when this method gets called it has already been
-    // unregistered.
-    DBusMessage *reply = dbus_message_new_method_return(msg);
-
-    if (!reply) {
-      errorStr.AssignLiteral("Memory can't be allocated for the message.");
-    } else {
-      dbus_func_send(conn, nullptr, reply);
-      dbus_message_unref(reply);
-
-      // Do not send an notification to upper layer, too annoying.
-      return DBUS_HANDLER_RESULT_HANDLED;
-    }
-  } else {
-#ifdef DEBUG
-    BT_WARNING("agent handler %s: Unhandled event. Ignore.", __FUNCTION__);
-#endif
-    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-  }
-
-  if (!errorStr.IsEmpty()) {
-    NS_WARNING(NS_ConvertUTF16toUTF8(errorStr).get());
-    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-  }
-
-  BluetoothSignal signal(signalName, signalPath, v);
-  nsRefPtr<DistributeBluetoothSignalTask> t =
-    new DistributeBluetoothSignalTask(signal);
-  if (NS_FAILED(NS_DispatchToMainThread(t))) {
-     NS_WARNING("Failed to dispatch to main thread!");
-  }
-
-  return DBUS_HANDLER_RESULT_HANDLED;
-}
-
-static const DBusObjectPathVTable agentVtable = {
-  NULL, AgentEventFilter, NULL, NULL, NULL, NULL
-};
-
-// Local agent means agent for Adapter, not agent for Device. Some signals
-// will be passed to local agent, some will be passed to device agent.
-// For example, if a remote device would like to pair with us, then the
-// signal will be passed to local agent. If we start pairing process with
-// calling CreatePairedDevice, we'll get signal which should be passed to
-// device agent.
-static bool
-RegisterLocalAgent(const char* adapterPath,
-                   const char* agentPath,
-                   const char* capabilities)
-{
-  MOZ_ASSERT(!NS_IsMainThread());
-
-  if (!dbus_connection_register_object_path(gThreadConnection->GetConnection(),
-                                            agentPath,
-                                            &agentVtable,
-                                            NULL)) {
-    BT_WARNING("%s: Can't register object path %s for agent!",
-                __FUNCTION__, agentPath);
-    return false;
-  }
-
-  DBusMessage* msg =
-    dbus_message_new_method_call("org.bluez", adapterPath,
-                                 DBUS_ADAPTER_IFACE, "RegisterAgent");
-  if (!msg) {
-    BT_WARNING("%s: Can't allocate new method call for agent!", __FUNCTION__);
-    return false;
-  }
-
-  if (!dbus_message_append_args(msg,
-                                DBUS_TYPE_OBJECT_PATH, &agentPath,
-                                DBUS_TYPE_STRING, &capabilities,
-                                DBUS_TYPE_INVALID)) {
-    BT_WARNING("%s: Couldn't append arguments to dbus message.", __FUNCTION__);
-    return false;
-  }
-
-  DBusError err = DBUS_ERROR_INIT;
-  DBusMessage* reply;
-
-  dbus_bool_t success = dbus_func_send_and_block(gThreadConnection->GetConnection(),
-                                                 -1, &reply, &err, msg);
-  if (!success) {
-    if (dbus_error_is_set(&err)) {
-      if (!strcmp(err.name, "org.bluez.Error.AlreadyExists")) {
-        LOG_AND_FREE_DBUS_ERROR(&err);
-#ifdef DEBUG
-        BT_WARNING("Agent already registered, still returning true");
-#endif
-      } else {
-        LOG_AND_FREE_DBUS_ERROR(&err);
-        BT_WARNING("%s: Can't register agent!", __FUNCTION__);
-        return false;
-      }
-    }
-  } else if (reply) {
-    dbus_message_unref(reply);
-  }
-
-  dbus_connection_flush(gThreadConnection->GetConnection());
-  return true;
-}
-
-static bool
-RegisterAgent()
-{
-  MOZ_ASSERT(!NS_IsMainThread());
-
-  if (!RegisterLocalAgent(NS_ConvertUTF16toUTF8(sAdapterPath).get(),
-                          KEY_LOCAL_AGENT,
-                          B2G_AGENT_CAPABILITIES)) {
-    return false;
-  }
-
-  // There is no "RegisterAgent" function defined in device interface.
-  // When we call "CreatePairedDevice", it will do device agent registration
-  // for us. (See maemo.org/api_refs/5.0/beta/bluez/adapter.html)
-  if (!dbus_connection_register_object_path(gThreadConnection->GetConnection(),
-                                            KEY_REMOTE_AGENT,
-                                            &agentVtable,
-                                            NULL)) {
-    BT_WARNING("%s: Can't register object path %s for remote device agent!",
-               __FUNCTION__, KEY_REMOTE_AGENT);
-
-    return false;
-  }
-
-  return true;
-}
-
-static void
 ExtractHandles(DBusMessage *aReply, nsTArray<uint32_t>& aOutHandles)
 {
-  uint32_t* handles = NULL;
+  uint32_t* handles = nullptr;
   int len;
 
   DBusError err;
   dbus_error_init(&err);
 
   if (dbus_message_get_args(aReply, &err,
                             DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &handles, &len,
                             DBUS_TYPE_INVALID)) {
-     if (!handles) {
-       BT_WARNING("Null array in extract_handles");
-     } else {
-        for (int i = 0; i < len; ++i) {
+    if (!handles) {
+      BT_WARNING("Null array in extract_handles");
+    } else {
+      for (int i = 0; i < len; ++i) {
         aOutHandles.AppendElement(handles[i]);
       }
     }
   } else {
     LOG_AND_FREE_DBUS_ERROR(&err);
   }
 }
 
-// static
+// static 
 bool
 BluetoothDBusService::AddServiceRecords(const char* serviceName,
                                         unsigned long long uuidMsb,
                                         unsigned long long uuidLsb,
                                         int channel)
 {
   MOZ_ASSERT(!NS_IsMainThread());
 
-  DBusMessage *reply;
-  reply = dbus_func_args(gThreadConnection->GetConnection(),
-                         NS_ConvertUTF16toUTF8(sAdapterPath).get(),
-                         DBUS_ADAPTER_IFACE, "AddRfcommServiceRecord",
-                         DBUS_TYPE_STRING, &serviceName,
-                         DBUS_TYPE_UINT64, &uuidMsb,
-                         DBUS_TYPE_UINT64, &uuidLsb,
-                         DBUS_TYPE_UINT16, &channel,
-                         DBUS_TYPE_INVALID);
+  DBusMessage* reply =
+    dbus_func_args(gThreadConnection->GetConnection(),
+                   NS_ConvertUTF16toUTF8(sAdapterPath).get(),
+                   DBUS_ADAPTER_IFACE, "AddRfcommServiceRecord",
+                   DBUS_TYPE_STRING, &serviceName,
+                   DBUS_TYPE_UINT64, &uuidMsb,
+                   DBUS_TYPE_UINT64, &uuidLsb,
+                   DBUS_TYPE_UINT16, &channel,
+                   DBUS_TYPE_INVALID);
 
   return reply ? dbus_returns_uint32(reply) : -1;
 }
 
 // static
 bool
 BluetoothDBusService::AddReservedServicesInternal(
                                    const nsTArray<uint32_t>& aServices,
@@ -873,18 +482,17 @@ BluetoothDBusService::DisconnectAllAcls(
   if (reply) {
     dbus_message_unref(reply);
   }
 }
 
 class PrepareProfileManagersRunnable : public nsRunnable
 {
 public:
-  NS_IMETHOD
-  Run()
+  nsresult Run()
   {
     BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
     if (!hfp || !hfp->Listen()) {
       NS_WARNING("Failed to start listening for BluetoothHfpManager!");
       return NS_ERROR_FAILURE;
     }
 
     BluetoothOppManager* opp = BluetoothOppManager::Get();
@@ -892,71 +500,31 @@ public:
       NS_WARNING("Failed to start listening for BluetoothOppManager!");
       return NS_ERROR_FAILURE;
     }
 
     return NS_OK;
   }
 };
 
-class PrepareAdapterRunnable : public nsRunnable
-{
-public:
-  PrepareAdapterRunnable()
-  {
-    MOZ_ASSERT(NS_IsMainThread());
-  }
-
-  NS_IMETHOD
-  Run()
-  {
-    MOZ_ASSERT(!NS_IsMainThread());
-
-    nsTArray<uint32_t> uuids;
-
-    uuids.AppendElement(BluetoothServiceClass::HANDSFREE_AG);
-    uuids.AppendElement(BluetoothServiceClass::HEADSET_AG);
-    uuids.AppendElement(BluetoothServiceClass::OBJECT_PUSH);
-
-    // TODO/qdot: This needs to be held for the life of the bluetooth connection
-    // so we could clean it up. For right now though, we can throw it away.
-    nsTArray<uint32_t> handles;
-
-    if (!BluetoothDBusService::AddReservedServicesInternal(uuids, handles)) {
-      NS_WARNING("Failed to add reserved services");
-#ifdef MOZ_WIDGET_GONK
-      return NS_ERROR_FAILURE;
-#endif
-    }
-
-    if(!RegisterAgent()) {
-      NS_WARNING("Failed to register agent");
-      return NS_ERROR_FAILURE;
-    }
-
-    NS_DispatchToMainThread(new PrepareProfileManagersRunnable());
-    return NS_OK;
-  }
-};
-
 static void
 RunDBusCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable,
                 UnpackFunc aFunc)
 {
 #ifdef MOZ_WIDGET_GONK
   // Due to the fact that we're running two dbus loops on desktop implicitly by
   // being gtk based, sometimes we'll get signals/reply coming in on the main
   // thread. There's not a lot we can do about that for the time being and it
   // (technically) shouldn't hurt anything. However, on gonk, die.
   MOZ_ASSERT(!NS_IsMainThread());
 #endif
   nsRefPtr<BluetoothReplyRunnable> replyRunnable =
     dont_AddRef(static_cast< BluetoothReplyRunnable* >(aBluetoothReplyRunnable));
 
-  NS_ASSERTION(replyRunnable, "Callback reply runnable is null!");
+  MOZ_ASSERT(replyRunnable, "Callback reply runnable is null!");
 
   nsAutoString replyError;
   BluetoothValue v;
   aFunc(aMsg, nullptr, v, replyError);
   DispatchBluetoothReply(replyRunnable, v, replyError);
 }
 
 static void
@@ -1029,33 +597,16 @@ static void
 SinkDisconnectCallback(DBusMessage* aMsg, void* aParam)
 {
 #ifdef DEBUG
   CheckForSinkError(false, aMsg, aParam);
 #endif
 }
 
 static bool
-IsDeviceConnectedTypeBoolean()
-{
-#if defined(MOZ_WIDGET_GONK)
-  char connProp[PROPERTY_VALUE_MAX];
-
-  property_get(PROP_DEVICE_CONNECTED_TYPE, connProp, "boolean");
-  if (strcmp(connProp, "boolean") == 0) {
-    return true;
-  }
-  return false;
-#else
-  // Assume it's always a boolean on desktop. Fixing someday in Bug 806457.
-  return true;
-#endif
-}
-
-static bool
 HasAudioService(uint32_t aCodValue)
 {
   return ((aCodValue & 0x200000) == 0x200000);
 }
 
 static bool
 ContainsIcon(const InfallibleTArray<BluetoothNamedValue>& aProperties)
 {
@@ -1170,17 +721,16 @@ GetProperty(DBusMessageIter aIter, Prope
           dbus_message_iter_get_basic(&array_val_iter, &tmp);
           arr.AppendElement(tmp);
         } while (dbus_message_iter_next(&array_val_iter));
         propertyValue = arr;
       } else {
         // This happens when the array is 0-length. Apparently we get a
         // DBUS_TYPE_INVALID type.
         propertyValue = InfallibleTArray<nsString>();
-        NS_WARNING("Received array type that's not a string array!");
       }
       break;
     default:
       NS_NOTREACHED("Cannot find dbus message type!");
   }
 
   if (convert) {
     MOZ_ASSERT(propertyValue.type() == BluetoothValue::TArrayOfuint8_t);
@@ -1198,24 +748,24 @@ ParseProperties(DBusMessageIter* aIter,
                 BluetoothValue& aValue,
                 nsAString& aErrorStr,
                 Properties* aPropertyTypes,
                 const int aPropertyTypeLen)
 {
   DBusMessageIter dict_entry, dict;
   int prop_index = -1;
 
-  NS_ASSERTION(dbus_message_iter_get_arg_type(aIter) == DBUS_TYPE_ARRAY,
-               "Trying to parse a property from sth. that's not an array");
+  MOZ_ASSERT(dbus_message_iter_get_arg_type(aIter) == DBUS_TYPE_ARRAY,
+             "Trying to parse a property from sth. that's not an array");
 
   dbus_message_iter_recurse(aIter, &dict);
   InfallibleTArray<BluetoothNamedValue> props;
   do {
-    NS_ASSERTION(dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY,
-                 "Trying to parse a property from sth. that's not an dict!");
+    MOZ_ASSERT(dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY,
+               "Trying to parse a property from sth. that's not an dict!");
     dbus_message_iter_recurse(&dict, &dict_entry);
 
     if (!GetProperty(dict_entry, aPropertyTypes, aPropertyTypeLen, &prop_index,
                      props)) {
       aErrorStr.AssignLiteral("Can't Create Property!");
       NS_WARNING("Can't create property!");
       return;
     }
@@ -1331,65 +881,516 @@ ParsePropertyChange(DBusMessage* aMsg, B
 
 static bool
 GetPropertiesInternal(const nsAString& aPath,
                       const char* aIface,
                       BluetoothValue& aValue)
 {
   MOZ_ASSERT(!NS_IsMainThread());
 
-  nsAutoString replyError;
   DBusError err;
-
   dbus_error_init(&err);
 
   DBusMessage* msg = dbus_func_args_timeout(gThreadConnection->GetConnection(),
                                             1000,
                                             &err,
                                             NS_ConvertUTF16toUTF8(aPath).get(),
                                             aIface,
                                             "GetProperties",
                                             DBUS_TYPE_INVALID);
+
+  nsAutoString replyError;
   if (!strcmp(aIface, DBUS_DEVICE_IFACE)) {
     UnpackDevicePropertiesMessage(msg, &err, aValue, replyError);
   } else if (!strcmp(aIface, DBUS_ADAPTER_IFACE)) {
     UnpackAdapterPropertiesMessage(msg, &err, aValue, replyError);
   } else if (!strcmp(aIface, DBUS_MANAGER_IFACE)) {
     UnpackManagerPropertiesMessage(msg, &err, aValue, replyError);
   } else {
     NS_WARNING("Unknown interface for GetProperties!");
     return false;
   }
 
   if (!replyError.IsEmpty()) {
     NS_WARNING("Failed to get device properties");
     return false;
   }
+
   if (msg) {
     dbus_message_unref(msg);
   }
+
   return true;
 }
 
+class AppendDeviceNameRunnable : public nsRunnable
+{
+public:
+  AppendDeviceNameRunnable(const BluetoothSignal& aSignal)
+    : mSignal(aSignal)
+  {
+  }
+
+  nsresult Run()
+  {
+    MOZ_ASSERT(!NS_IsMainThread());
+
+    InfallibleTArray<BluetoothNamedValue>& arr =
+      mSignal.value().get_ArrayOfBluetoothNamedValue();
+    nsString devicePath = arr[0].value().get_nsString();
+
+    // Replace object path with device address
+    InfallibleTArray<BluetoothNamedValue>& parameters =
+      mSignal.value().get_ArrayOfBluetoothNamedValue();
+    nsString address = GetAddressFromObjectPath(devicePath);
+    parameters[0].name().AssignLiteral("address");
+    parameters[0].value() = address;
+
+    BluetoothValue prop;
+    if(!GetPropertiesInternal(devicePath, DBUS_DEVICE_IFACE, prop)) {
+      return NS_ERROR_FAILURE;
+    }
+
+    // Get device name from result of GetPropertiesInternal and append to
+    // original signal
+    InfallibleTArray<BluetoothNamedValue>& properties =
+      prop.get_ArrayOfBluetoothNamedValue();
+   uint8_t i;
+    for (i = 0; i < properties.Length(); i++) {
+      if (properties[i].name().EqualsLiteral("Name")) {
+        properties[i].name().AssignLiteral("name");
+        parameters.AppendElement(properties[i]);
+        break;
+      }
+    }
+    MOZ_ASSERT_IF(i == properties.Length(), "failed to get device name");
+
+    nsRefPtr<DistributeBluetoothSignalTask> task =
+      new DistributeBluetoothSignalTask(mSignal);
+    NS_DispatchToMainThread(task);
+
+    return NS_OK;
+  }
+
+private:
+  BluetoothSignal mSignal;
+};
+
+class AppendDeviceNameHandler : public nsRunnable
+{
+public:
+  AppendDeviceNameHandler(const BluetoothSignal& aSignal)
+    : mSignal(aSignal)
+  {
+  }
+
+  nsresult Run()
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+    BluetoothService* bs = BluetoothService::Get();
+    NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE);
+
+    BluetoothValue v = mSignal.value();
+    if (v.type() != BluetoothValue::TArrayOfBluetoothNamedValue ||
+        v.get_ArrayOfBluetoothNamedValue().Length() == 0) {
+      NS_WARNING("Invalid argument type for AppendDeviceNameHandler");
+      return NS_ERROR_FAILURE;
+    }
+    const InfallibleTArray<BluetoothNamedValue>& arr =
+      v.get_ArrayOfBluetoothNamedValue();
+
+    // Device object path should be put in the first element
+    if (!arr[0].name().EqualsLiteral("path") ||
+        arr[0].value().type() != BluetoothValue::TnsString) {
+      NS_WARNING("Invalid object path for AppendDeviceNameHandler");
+      return NS_ERROR_FAILURE;
+    }
+
+    nsRefPtr<nsRunnable> func(new AppendDeviceNameRunnable(mSignal));
+    bs->DispatchToCommandThread(func);
+
+    return NS_OK;
+  }
+
+private:
+  BluetoothSignal mSignal;
+};
+
+static DBusHandlerResult
+AgentEventFilter(DBusConnection *conn, DBusMessage *msg, void *data)
+{
+  if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_METHOD_CALL) {
+    BT_WARNING("%s: agent handler not interested (not a method call).\n",
+               __FUNCTION__);
+    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+  }
+
+  DBusError err;
+  dbus_error_init(&err);
+
+  BT_LOG("%s: %s, %s", __FUNCTION__,
+                       dbus_message_get_path(msg),
+                       dbus_message_get_member(msg));
+
+  nsString signalPath = NS_ConvertUTF8toUTF16(dbus_message_get_path(msg));
+  nsString signalName = NS_ConvertUTF8toUTF16(dbus_message_get_member(msg));
+  nsString errorStr;
+  BluetoothValue v;
+  InfallibleTArray<BluetoothNamedValue> parameters;
+  nsRefPtr<nsRunnable> handler;
+  bool isPairingReq = false;
+  BluetoothSignal signal(signalName, signalPath, v);
+  char *objectPath;
+
+  // The following descriptions of each signal are retrieved from:
+  //
+  // http://maemo.org/api_refs/5.0/beta/bluez/agent.html
+  //
+  if (dbus_message_is_method_call(msg, DBUS_AGENT_IFACE, "Cancel")) {
+    // This method gets called to indicate that the agent request failed before
+    // a reply was returned.
+
+    // Return directly
+    DBusMessage *reply = dbus_message_new_method_return(msg);
+
+    if (!reply) {
+      errorStr.AssignLiteral("Memory can't be allocated for the message.");
+      goto handle_error;
+    }
+
+    dbus_connection_send(conn, reply, NULL);
+    dbus_message_unref(reply);
+    v = parameters;
+  } else if (dbus_message_is_method_call(msg, DBUS_AGENT_IFACE, "Authorize")) {
+    // This method gets called when the service daemon needs to authorize a
+    // connection/service request.
+    const char *uuid;
+    if (!dbus_message_get_args(msg, NULL,
+                               DBUS_TYPE_OBJECT_PATH, &objectPath,
+                               DBUS_TYPE_STRING, &uuid,
+                               DBUS_TYPE_INVALID)) {
+      BT_WARNING("%s: Invalid arguments for Authorize() method", __FUNCTION__);
+      errorStr.AssignLiteral("Invalid arguments for Authorize() method");
+      goto handle_error;
+    }
+
+    nsString deviceAddress =
+      GetAddressFromObjectPath(NS_ConvertUTF8toUTF16(objectPath));
+
+    parameters.AppendElement(
+      BluetoothNamedValue(NS_LITERAL_STRING("deviceAddress"), deviceAddress));
+    parameters.AppendElement(
+      BluetoothNamedValue(NS_LITERAL_STRING("uuid"),
+                          NS_ConvertUTF8toUTF16(uuid)));
+
+    // Because we may have authorization request and pairing request from the
+    // same remote device at the same time, we need two tables to keep these
+    // messages.
+    sAuthorizeReqTable.Put(deviceAddress, msg);
+
+    // Increase ref count here because we need this message later.
+    // It'll be unrefed when setAuthorizationInternal() is called.
+    dbus_message_ref(msg);
+
+    v = parameters;
+  } else if (dbus_message_is_method_call(msg, DBUS_AGENT_IFACE,
+                                         "RequestConfirmation")) {
+    // This method gets called when the service daemon needs to confirm a
+    // passkey for an authentication.
+    uint32_t passkey;
+    if (!dbus_message_get_args(msg, NULL,
+                               DBUS_TYPE_OBJECT_PATH, &objectPath,
+                               DBUS_TYPE_UINT32, &passkey,
+                               DBUS_TYPE_INVALID)) {
+      BT_WARNING("%s: Invalid arguments: RequestConfirmation()", __FUNCTION__);
+      errorStr.AssignLiteral("Invalid arguments: RequestConfirmation()");
+      goto handle_error;
+    }
+
+    parameters.AppendElement(
+      BluetoothNamedValue(NS_LITERAL_STRING("path"),
+                          NS_ConvertUTF8toUTF16(objectPath)));
+    parameters.AppendElement(
+      BluetoothNamedValue(NS_LITERAL_STRING("method"),
+                          NS_LITERAL_STRING("confirmation")));
+    parameters.AppendElement(
+      BluetoothNamedValue(NS_LITERAL_STRING("passkey"), passkey));
+
+    v = parameters;
+    isPairingReq = true;
+  } else if (dbus_message_is_method_call(msg, DBUS_AGENT_IFACE,
+                                         "RequestPinCode")) {
+    // This method gets called when the service daemon needs to get the passkey
+    // for an authentication. The return value should be a string of 1-16
+    // characters length. The string can be alphanumeric.
+    if (!dbus_message_get_args(msg, NULL,
+                               DBUS_TYPE_OBJECT_PATH, &objectPath,
+                               DBUS_TYPE_INVALID)) {
+      BT_WARNING("%s: Invalid arguments for RequestPinCode() method",
+                 __FUNCTION__);
+      errorStr.AssignLiteral("Invalid arguments for RequestPinCode() method");
+      goto handle_error;
+    }
+
+    parameters.AppendElement(
+      BluetoothNamedValue(NS_LITERAL_STRING("path"),
+                          NS_ConvertUTF8toUTF16(objectPath)));
+    parameters.AppendElement(
+      BluetoothNamedValue(NS_LITERAL_STRING("method"),
+                          NS_LITERAL_STRING("pincode")));
+
+    v = parameters;
+    isPairingReq = true;
+  } else if (dbus_message_is_method_call(msg, DBUS_AGENT_IFACE,
+                                         "RequestPasskey")) {
+    // This method gets called when the service daemon needs to get the passkey
+    // for an authentication. The return value should be a numeric value
+    // between 0-999999.
+    if (!dbus_message_get_args(msg, NULL,
+                               DBUS_TYPE_OBJECT_PATH, &objectPath,
+                               DBUS_TYPE_INVALID)) {
+      BT_WARNING("%s: Invalid arguments for RequestPasskey() method",
+                 __FUNCTION__);
+      errorStr.AssignLiteral("Invalid arguments for RequestPasskey() method");
+      goto handle_error;
+    }
+
+    parameters.AppendElement(BluetoothNamedValue(
+                               NS_LITERAL_STRING("path"),
+                               NS_ConvertUTF8toUTF16(objectPath)));
+    parameters.AppendElement(BluetoothNamedValue(
+                               NS_LITERAL_STRING("method"),
+                               NS_LITERAL_STRING("passkey")));
+
+    v = parameters;
+    isPairingReq = true;
+  } else if (dbus_message_is_method_call(msg, DBUS_AGENT_IFACE, "Release")) {
+    // This method gets called when the service daemon unregisters the agent.
+    // An agent can use it to do cleanup tasks. There is no need to unregister
+    // the agent, because when this method gets called it has already been
+    // unregistered.
+    DBusMessage *reply = dbus_message_new_method_return(msg);
+
+    if (!reply) {
+      errorStr.AssignLiteral("Memory can't be allocated for the message.");
+      goto handle_error;
+    }
+
+    dbus_connection_send(conn, reply, NULL);
+    dbus_message_unref(reply);
+
+    // Do not send an notification to upper layer, too annoying.
+    return DBUS_HANDLER_RESULT_HANDLED;
+  } else {
+#ifdef DEBUG
+    BT_WARNING("agent handler %s: Unhandled event. Ignore.", __FUNCTION__);
+#endif
+    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+  }
+
+  if (!errorStr.IsEmpty()) {
+    NS_WARNING(NS_ConvertUTF16toUTF8(errorStr).get());
+    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+  }
+
+  // Update value after parsing DBus message
+  signal.value() = v;
+
+  if (isPairingReq) {
+    sPairingReqTable.Put(
+      GetAddressFromObjectPath(NS_ConvertUTF8toUTF16(objectPath)), msg);
+
+    // Increase ref count here because we need this message later.
+    // It'll be unrefed when set*Internal() is called.
+    dbus_message_ref(msg);
+
+    handler = new AppendDeviceNameHandler(signal);
+  } else {
+    handler = new DistributeBluetoothSignalTask(signal);
+  }
+  NS_DispatchToMainThread(handler);
+
+  return DBUS_HANDLER_RESULT_HANDLED;
+
+handle_error:
+  NS_WARNING(NS_ConvertUTF16toUTF8(errorStr).get());
+  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static const DBusObjectPathVTable agentVtable = {
+  NULL, AgentEventFilter, NULL, NULL, NULL, NULL
+};
+
+// Local agent means agent for Adapter, not agent for Device. Some signals
+// will be passed to local agent, some will be passed to device agent.
+// For example, if a remote device would like to pair with us, then the
+// signal will be passed to local agent. If we start pairing process with
+// calling CreatePairedDevice, we'll get signal which should be passed to
+// device agent.
+static bool
+RegisterLocalAgent(const char* adapterPath,
+                   const char* agentPath,
+                   const char* capabilities)
+{
+  MOZ_ASSERT(!NS_IsMainThread());
+
+  if (!dbus_connection_register_object_path(gThreadConnection->GetConnection(),
+                                            agentPath,
+                                            &agentVtable,
+                                            NULL)) {
+    BT_WARNING("%s: Can't register object path %s for agent!",
+                __FUNCTION__, agentPath);
+    return false;
+  }
+
+  DBusMessage* msg =
+    dbus_message_new_method_call("org.bluez", adapterPath,
+                                 DBUS_ADAPTER_IFACE, "RegisterAgent");
+  if (!msg) {
+    BT_WARNING("%s: Can't allocate new method call for agent!", __FUNCTION__);
+    return false;
+  }
+
+  if (!dbus_message_append_args(msg,
+                                DBUS_TYPE_OBJECT_PATH, &agentPath,
+                                DBUS_TYPE_STRING, &capabilities,
+                                DBUS_TYPE_INVALID)) {
+    BT_WARNING("%s: Couldn't append arguments to dbus message.", __FUNCTION__);
+    return false;
+  }
+
+  DBusError err;
+  dbus_error_init(&err);
+
+  DBusMessage* reply =
+    dbus_connection_send_with_reply_and_block(gThreadConnection->GetConnection(),
+                                              msg, -1, &err);
+  dbus_message_unref(msg);
+
+  if (!reply) {
+    if (dbus_error_is_set(&err)) {
+      if (!strcmp(err.name, "org.bluez.Error.AlreadyExists")) {
+        LOG_AND_FREE_DBUS_ERROR(&err);
+#ifdef DEBUG
+        BT_WARNING("Agent already registered, still returning true");
+#endif
+      } else {
+        LOG_AND_FREE_DBUS_ERROR(&err);
+        BT_WARNING("%s: Can't register agent!", __FUNCTION__);
+        return false;
+      }
+    }
+  } else {
+    dbus_message_unref(reply);
+  }
+
+  dbus_connection_flush(gThreadConnection->GetConnection());
+  return true;
+}
+
+static bool
+RegisterAgent()
+{
+  MOZ_ASSERT(!NS_IsMainThread());
+
+  if (!RegisterLocalAgent(NS_ConvertUTF16toUTF8(sAdapterPath).get(),
+                          KEY_LOCAL_AGENT,
+                          B2G_AGENT_CAPABILITIES)) {
+    return false;
+  }
+
+  // There is no "RegisterAgent" function defined in device interface.
+  // When we call "CreatePairedDevice", it will do device agent registration
+  // for us. (See maemo.org/api_refs/5.0/beta/bluez/adapter.html)
+  if (!dbus_connection_register_object_path(gThreadConnection->GetConnection(),
+                                            KEY_REMOTE_AGENT,
+                                            &agentVtable,
+                                            NULL)) {
+    BT_WARNING("%s: Can't register object path %s for remote device agent!",
+               __FUNCTION__, KEY_REMOTE_AGENT);
+
+    return false;
+  }
+
+  return true;
+}
+
+class PrepareAdapterRunnable : public nsRunnable
+{
+public:
+  nsresult Run()
+  {
+    MOZ_ASSERT(!NS_IsMainThread());
+    nsTArray<uint32_t> uuids;
+
+    uuids.AppendElement(BluetoothServiceClass::HANDSFREE_AG);
+    uuids.AppendElement(BluetoothServiceClass::HEADSET_AG);
+    uuids.AppendElement(BluetoothServiceClass::OBJECT_PUSH);
+
+    // TODO/qdot: This needs to be held for the life of the bluetooth connection
+    // so we could clean it up. For right now though, we can throw it away.
+    nsTArray<uint32_t> handles;
+
+    if (!BluetoothDBusService::AddReservedServicesInternal(uuids, handles)) {
+      NS_WARNING("Failed to add reserved services");
+#ifdef MOZ_WIDGET_GONK
+      return NS_ERROR_FAILURE;
+#endif
+    }
+
+    if(!RegisterAgent()) {
+      NS_WARNING("Failed to register agent");
+      return NS_ERROR_FAILURE;
+    }
+
+    NS_DispatchToMainThread(new PrepareProfileManagersRunnable());
+    return NS_OK;
+  }
+};
+
+class PrepareAdapterTask : public nsRunnable
+{
+public:
+  PrepareAdapterTask(const nsAString& aPath)
+    : mPath(aPath)
+  {
+  }
+
+  nsresult Run()
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    BluetoothService* bs = BluetoothService::Get();
+    NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE);
+    sAdapterPath = mPath;
+    nsRefPtr<nsRunnable> func(new PrepareAdapterRunnable());
+    bs->DispatchToCommandThread(func);
+    return NS_OK;
+  }
+
+private:
+  nsString mPath;
+};
+
 // Called by dbus during WaitForAndDispatchEventNative()
 // This function is called on the IOThread
 static DBusHandlerResult
 EventFilter(DBusConnection* aConn, DBusMessage* aMsg, void* aData)
 {
-  NS_ASSERTION(!NS_IsMainThread(), "Shouldn't be called from Main Thread!");
+  MOZ_ASSERT(!NS_IsMainThread(), "Shouldn't be called from Main Thread!");
 
   if (dbus_message_get_type(aMsg) != DBUS_MESSAGE_TYPE_SIGNAL) {
     BT_WARNING("%s: event handler not interested in %s (not a signal).\n",
         __FUNCTION__, dbus_message_get_member(aMsg));
     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
   }
 
   if (dbus_message_get_path(aMsg) == NULL) {
     BT_WARNING("DBusMessage %s has no bluetooth destination, ignoring\n",
-        dbus_message_get_member(aMsg));
+               dbus_message_get_member(aMsg));
     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
   }
 
   DBusError err;
   dbus_error_init(&err);
 
   nsAutoString signalPath;
   nsAutoString signalName;
@@ -1423,65 +1424,57 @@ EventFilter(DBusConnection* aConn, DBusM
     if (!dbus_message_iter_init(aMsg, &iter)) {
       NS_WARNING("Can't create iterator!");
       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
     }
 
     const char* addr;
     dbus_message_iter_get_basic(&iter, &addr);
 
-    if (dbus_message_iter_next(&iter)) {
-      Properties* props = sDeviceProperties;
+    if (!dbus_message_iter_next(&iter)) {
+      errorStr.AssignLiteral("Unexpected message struct in msg DeviceFound");
+    } else {
       ParseProperties(&iter,
                       v,
                       errorStr,
-                      props,
+                      sDeviceProperties,
                       ArrayLength(sDeviceProperties));
-      if (v.type() == BluetoothValue::TArrayOfBluetoothNamedValue)
-      {
-        // The DBus DeviceFound message actually passes back a key value object
-        // with the address as the key and the rest of the device properties as
-        // a dict value. After we parse out the properties, we need to go back
-        // and add the address to the ipdl dict we've created to make sure we
-        // have all of the information to correctly build the device.
-        nsAutoString addrstr = NS_ConvertUTF8toUTF16(addr);
-        nsString path = GetObjectPathFromAddress(signalPath, addrstr);
-
-        v.get_ArrayOfBluetoothNamedValue()
-          .AppendElement(BluetoothNamedValue(NS_LITERAL_STRING("Address"),
-                                             addrstr));
-
-        // We also need to create a path for the device, to make sure we know
-        // where to access it later.
-        v.get_ArrayOfBluetoothNamedValue()
-          .AppendElement(BluetoothNamedValue(NS_LITERAL_STRING("Path"),
-                                             path));
-        const InfallibleTArray<BluetoothNamedValue>& properties =
-          v.get_ArrayOfBluetoothNamedValue();
-        if (!ContainsIcon(properties)) {
-          for (uint8_t i = 0; i < properties.Length(); i++) {
-            // It is possible that property Icon missed due to CoD of major
-            // class is TOY but service class is "Audio", we need to assign
-            // Icon as audio-card. This is for PTS test TC_AG_COD_BV_02_I.
-            // As HFP specification defined that
-            // service class is "Audio" can be considered as HFP AG.
-            if (properties[i].name().EqualsLiteral("Class")) {
-              if (HasAudioService(properties[i].value().get_uint32_t())) {
-                v.get_ArrayOfBluetoothNamedValue()
-                  .AppendElement(
-                    BluetoothNamedValue(NS_LITERAL_STRING("Icon"),
-                                        NS_LITERAL_STRING("audio-card")));
-              }
-              break;
+
+      InfallibleTArray<BluetoothNamedValue>& properties =
+        v.get_ArrayOfBluetoothNamedValue();
+
+      // The DBus DeviceFound message actually passes back a key value object
+      // with the address as the key and the rest of the device properties as
+      // a dict value. After we parse out the properties, we need to go back
+      // and add the address to the ipdl dict we've created to make sure we
+      // have all of the information to correctly build the device.
+      nsAutoString address = NS_ConvertUTF8toUTF16(addr);
+      properties.AppendElement(
+        BluetoothNamedValue(NS_LITERAL_STRING("Address"), address));
+      properties.AppendElement(
+        BluetoothNamedValue(NS_LITERAL_STRING("Path"),
+                            GetObjectPathFromAddress(signalPath, address)));
+
+      if (!ContainsIcon(properties)) {
+        for (uint8_t i = 0; i < properties.Length(); i++) {
+          // It is possible that property Icon missed due to CoD of major
+          // class is TOY but service class is "Audio", we need to assign
+          // Icon as audio-card. This is for PTS test TC_AG_COD_BV_02_I.
+          // As HFP specification defined that
+          // service class is "Audio" can be considered as HFP AG.
+          if (properties[i].name().EqualsLiteral("Class")) {
+            if (HasAudioService(properties[i].value().get_uint32_t())) {
+              v.get_ArrayOfBluetoothNamedValue().AppendElement(
+                BluetoothNamedValue(NS_LITERAL_STRING("Icon"),
+                                    NS_LITERAL_STRING("audio-card")));
             }
+            break;
           }
         }
       }
-    } else {
-      errorStr.AssignLiteral("Unexpected message struct in msg DeviceFound");
     }
   } else if (dbus_message_is_signal(aMsg, DBUS_ADAPTER_IFACE,
                                     "DeviceDisappeared")) {
     const char* str;
     if (!dbus_message_get_args(aMsg, &err,
                                DBUS_TYPE_STRING, &str,
                                DBUS_TYPE_INVALID)) {
       LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, aMsg);
@@ -1495,27 +1488,16 @@ EventFilter(DBusConnection* aConn, DBusM
     if (!dbus_message_get_args(aMsg, &err,
                                DBUS_TYPE_OBJECT_PATH, &str,
                                DBUS_TYPE_INVALID)) {
       LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, aMsg);
       errorStr.AssignLiteral("Cannot parse device path!");
     } else {
       v = NS_ConvertUTF8toUTF16(str);
     }
-
-    BluetoothSignal signal(signalName, signalPath, v);
-
-    // Fire a Device properties fetcher at the main thread
-    nsRefPtr<DevicePropertiesSignalHandler> b =
-      new DevicePropertiesSignalHandler(signal);
-    if (NS_FAILED(NS_DispatchToMainThread(b))) {
-      NS_WARNING("Failed to dispatch to main thread!");
-    }
-    // Since we're handling this in other threads, just fall out here
-    return DBUS_HANDLER_RESULT_HANDLED;
   } else if (dbus_message_is_signal(aMsg, DBUS_ADAPTER_IFACE,
                                     "DeviceRemoved")) {
     const char* str;
     if (!dbus_message_get_args(aMsg, &err,
                                DBUS_TYPE_OBJECT_PATH, &str,
                                DBUS_TYPE_INVALID)) {
       LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, aMsg);
       errorStr.AssignLiteral("Cannot parse device path!");
@@ -1526,88 +1508,77 @@ EventFilter(DBusConnection* aConn, DBusM
                                     "PropertyChanged")) {
     ParsePropertyChange(aMsg,
                         v,
                         errorStr,
                         sAdapterProperties,
                         ArrayLength(sAdapterProperties));
   } else if (dbus_message_is_signal(aMsg, DBUS_DEVICE_IFACE,
                                     "PropertyChanged")) {
-    Properties* props = sDeviceProperties;
     ParsePropertyChange(aMsg,
                         v,
                         errorStr,
-                        props,
+                        sDeviceProperties,
                         ArrayLength(sDeviceProperties));
 
+    // Fire another task for sending system message of
+    // "bluetooth-pairedstatuschanged"
     BluetoothNamedValue& property = v.get_ArrayOfBluetoothNamedValue()[0];
     if (property.name().EqualsLiteral("Paired")) {
-      // transfer signal to BluetoothService and
-      // broadcast system message of bluetooth-pairingstatuschanged
-      signalName = NS_LITERAL_STRING("PairedStatusChanged");
-      signalPath = NS_LITERAL_STRING(KEY_LOCAL_AGENT);
-      property.name() = NS_LITERAL_STRING("paired");
+      BluetoothValue newValue(v);
+      ToLowerCase(newValue.get_ArrayOfBluetoothNamedValue()[0].name());
+      BluetoothSignal signal(NS_LITERAL_STRING("PairedStatusChanged"),
+                             NS_LITERAL_STRING(KEY_LOCAL_AGENT),
+                             newValue);
+      NS_DispatchToMainThread(new DistributeBluetoothSignalTask(signal));
     }
   } else if (dbus_message_is_signal(aMsg, DBUS_MANAGER_IFACE, "AdapterAdded")) {
     const char* str;
     if (!dbus_message_get_args(aMsg, &err,
                                DBUS_TYPE_OBJECT_PATH, &str,
                                DBUS_TYPE_INVALID)) {
       LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, aMsg);
       errorStr.AssignLiteral("Cannot parse manager path!");
     } else {
       v = NS_ConvertUTF8toUTF16(str);
-      nsRefPtr<PrepareAdapterTask> b = new PrepareAdapterTask(v.get_nsString());
-      if (NS_FAILED(NS_DispatchToMainThread(b))) {
-        NS_WARNING("Failed to dispatch to main thread!");
-      }
+      NS_DispatchToMainThread(new PrepareAdapterTask(v.get_nsString()));
     }
   } else if (dbus_message_is_signal(aMsg, DBUS_MANAGER_IFACE,
                                     "PropertyChanged")) {
     ParsePropertyChange(aMsg,
                         v,
                         errorStr,
                         sManagerProperties,
                         ArrayLength(sManagerProperties));
   } else if (dbus_message_is_signal(aMsg, DBUS_SINK_IFACE,
                                     "PropertyChanged")) {
     ParsePropertyChange(aMsg,
                         v,
                         errorStr,
                         sSinkProperties,
                         ArrayLength(sSinkProperties));
   } else {
-    nsAutoCString signalStr;
-    signalStr += dbus_message_get_member(aMsg);
-    signalStr += " Signal not handled!";
-    NS_WARNING(signalStr.get());
-    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+    errorStr = NS_ConvertUTF8toUTF16(dbus_message_get_member(aMsg));
+    errorStr.AppendLiteral(" Signal not handled!");
   }
 
   if (!errorStr.IsEmpty()) {
     NS_WARNING(NS_ConvertUTF16toUTF8(errorStr).get());
     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
   }
 
   BluetoothSignal signal(signalName, signalPath, v);
-  nsRefPtr<nsRunnable> task;
-  if (signalInterface.EqualsLiteral(DBUS_SINK_IFACE)) {
-    task = new SinkPropertyChangedHandler(signal);
-  } else {
-    task = new DistributeBluetoothSignalTask(signal);
-  }
-
-  if (NS_FAILED(NS_DispatchToMainThread(task))) {
-    NS_WARNING("Failed to dispatch to main thread!");
-  }
+  nsRefPtr<DistributeBluetoothSignalTask> task
+    = new DistributeBluetoothSignalTask(signal);
+  NS_DispatchToMainThread(task);
 
   return DBUS_HANDLER_RESULT_HANDLED;
 }
 
-nsresult
+static bool
 GetDefaultAdapterPath(BluetoothValue& aValue, nsString& aError)
 {
   // This could block. It should never be run on the main thread.
   MOZ_ASSERT(!NS_IsMainThread());
 
   DBusError err;
   dbus_error_init(&err);
 
@@ -1696,17 +1667,17 @@ BluetoothDBusService::StartInternal()
   }
 
   if (!sAuthorizeReqTable.IsInitialized()) {
     sAuthorizeReqTable.Init();
   }
 
   BluetoothValue v;
   nsAutoString replyError;
-  if (NS_FAILED(GetDefaultAdapterPath(v, replyError))) {
+  if (!GetDefaultAdapterPath(v, replyError)) {
     // Adapter path is not ready yet
     // Let's do PrepareAdapterTask when we receive signal 'AdapterAdded'
   } else {
     // Adapter path has been ready. let's do PrepareAdapterTask now
     nsRefPtr<PrepareAdapterTask> b = new PrepareAdapterTask(v.get_nsString());
     if (NS_FAILED(NS_DispatchToMainThread(b))) {
       NS_WARNING("Failed to dispatch to main thread!");
     }
@@ -1791,25 +1762,23 @@ BluetoothDBusService::IsEnabledInternal(
 class DefaultAdapterPropertiesRunnable : public nsRunnable
 {
 public:
   DefaultAdapterPropertiesRunnable(BluetoothReplyRunnable* aRunnable)
     : mRunnable(dont_AddRef(aRunnable))
   {
   }
 
-  nsresult
-  Run()
+  nsresult Run()
   {
     MOZ_ASSERT(!NS_IsMainThread());
 
     BluetoothValue v;
     nsAutoString replyError;
-
-    if (NS_FAILED(GetDefaultAdapterPath(v, replyError))) {
+    if (GetDefaultAdapterPath(v, replyError)) {
       DispatchBluetoothReply(mRunnable, v, replyError);
       return NS_ERROR_FAILURE;
     }
 
     DBusError err;
     dbus_error_init(&err);
 
     nsString objectPath = v.get_nsString();
@@ -1831,23 +1800,21 @@ public:
 private:
   nsRefPtr<BluetoothReplyRunnable> mRunnable;
 };
 
 nsresult
 BluetoothDBusService::GetDefaultAdapterPathInternal(
                                               BluetoothReplyRunnable* aRunnable)
 {
-  NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!");
+  MOZ_ASSERT(NS_IsMainThread());
 
   if (!IsReady()) {
-    BluetoothValue v;
-    nsAutoString errorStr;
-    errorStr.AssignLiteral("Bluetooth service is not ready yet!");
-    DispatchBluetoothReply(aRunnable, v, errorStr);
+    NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
+    DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
     return NS_OK;
   }
 
   nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
   nsRefPtr<nsRunnable> func(new DefaultAdapterPropertiesRunnable(runnable));
   if (NS_FAILED(mBluetoothCommandThread->Dispatch(func, NS_DISPATCH_NORMAL))) {
     NS_WARNING("Cannot dispatch firmware loading task!");
     return NS_ERROR_FAILURE;
@@ -1856,29 +1823,25 @@ BluetoothDBusService::GetDefaultAdapterP
   runnable.forget();
   return NS_OK;
 }
 
 nsresult
 BluetoothDBusService::SendDiscoveryMessage(const char* aMessageName,
                                            BluetoothReplyRunnable* aRunnable)
 {
-  NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!");
-  NS_ASSERTION(mConnection, "Must have a connection here!");
+  MOZ_ASSERT(NS_IsMainThread());
 
   if (!IsReady()) {
-    BluetoothValue v;
-    nsAutoString errorStr;
-    errorStr.AssignLiteral("Bluetooth service is not ready yet!");
-    DispatchBluetoothReply(aRunnable, v, errorStr);
+    NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
+    DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
     return NS_OK;
   }
 
-  nsRefPtr<nsRunnable> task(new SendDiscoveryTask(aMessageName,
-                                                  aRunnable));
+  nsRefPtr<nsRunnable> task(new SendDiscoveryTask(aMessageName, aRunnable));
   if (NS_FAILED(mBluetoothCommandThread->Dispatch(task, NS_DISPATCH_NORMAL))) {
     NS_WARNING("Cannot dispatch firmware loading task!");
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
@@ -1922,90 +1885,30 @@ BluetoothDBusService::StopDiscoveryInter
 }
 
 nsresult
 BluetoothDBusService::StartDiscoveryInternal(BluetoothReplyRunnable* aRunnable)
 {
   return SendDiscoveryMessage("StartDiscovery", aRunnable);
 }
 
-class BluetoothDevicePropertiesRunnable : public nsRunnable
-{
-public:
-  BluetoothDevicePropertiesRunnable(const BluetoothSignal& aSignal) :
-    mSignal(aSignal)
-  {
-    MOZ_ASSERT(NS_IsMainThread());
-  }
-
-  NS_IMETHOD Run()
-  {
-    MOZ_ASSERT(!NS_IsMainThread());
-
-    const InfallibleTArray<BluetoothNamedValue>& arr =
-      mSignal.value().get_ArrayOfBluetoothNamedValue();
-    nsString devicePath = arr[0].value().get_nsString();
-
-    BluetoothValue prop;
-    bool rv = GetPropertiesInternal(devicePath, DBUS_DEVICE_IFACE, prop);
-    NS_ENSURE_TRUE(rv, NS_ERROR_FAILURE);
-
-    // Return original dbus message parameters and also device name
-    // for agent events "RequestConfirmation", "RequestPinCode",
-    // and "RequestPasskey"
-    InfallibleTArray<BluetoothNamedValue>& parameters =
-      mSignal.value().get_ArrayOfBluetoothNamedValue();
-
-    // Replace object path with device address
-    nsString address = GetAddressFromObjectPath(devicePath);
-    parameters[0].name().AssignLiteral("address");
-    parameters[0].value() = address;
-
-    InfallibleTArray<BluetoothNamedValue>& properties =
-      prop.get_ArrayOfBluetoothNamedValue();
-    uint8_t i;
-    for (i = 0; i < properties.Length(); i++) {
-      // Append device name
-      if (properties[i].name().EqualsLiteral("Name")) {
-        properties[i].name().AssignLiteral("name");
-        parameters.AppendElement(properties[i]);
-        break;
-      }
-    }
-    MOZ_ASSERT(i != properties.Length(), "failed to get device name");
-
-    nsRefPtr<DistributeBluetoothSignalTask> t =
-      new DistributeBluetoothSignalTask(mSignal);
-    if (NS_FAILED(NS_DispatchToMainThread(t))) {
-      NS_WARNING("Failed to dispatch to main thread!");
-      return NS_ERROR_FAILURE;
-    }
-
-    return NS_OK;
-  }
-
-private:
-  BluetoothSignal mSignal;
-};
-
 class BluetoothArrayOfDevicePropertiesRunnable : public nsRunnable
 {
 public:
   BluetoothArrayOfDevicePropertiesRunnable(
                                      const nsTArray<nsString>& aDeviceAddresses,
                                      BluetoothReplyRunnable* aRunnable,
                                      FilterFunc aFilterFunc)
     : mDeviceAddresses(aDeviceAddresses)
     , mRunnable(dont_AddRef(aRunnable))
     , mFilterFunc(aFilterFunc)
   {
   }
 
-  nsresult
-  Run()
+  nsresult Run()
   {
     MOZ_ASSERT(!NS_IsMainThread());
     DBusError err;
     dbus_error_init(&err);
 
     BluetoothValue values = InfallibleTArray<BluetoothNamedValue>();
     nsAutoString errorStr;
 
@@ -2060,60 +1963,26 @@ public:
 
 private:
   nsTArray<nsString> mDeviceAddresses;
   nsRefPtr<BluetoothReplyRunnable> mRunnable;
   FilterFunc mFilterFunc;
 };
 
 nsresult
-BluetoothDBusService::GetDevicePropertiesInternal(const BluetoothSignal& aSignal)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  if (!mConnection || !gThreadConnection) {
-    NS_ERROR("Bluetooth service not started yet!");
-    return NS_ERROR_FAILURE;
-  }
-
-  BluetoothValue v = aSignal.value();
-  if (v.type() != BluetoothValue::TArrayOfBluetoothNamedValue ||
-      v.get_ArrayOfBluetoothNamedValue().Length() == 0) {
-    NS_WARNING("Invalid value type for GetDevicePropertiesInternal() method");
-    return NS_ERROR_FAILURE;
-  }
-
-  const InfallibleTArray<BluetoothNamedValue>& arr =
-    v.get_ArrayOfBluetoothNamedValue();
-
-  // Device object path should be put in the first element
-  if (!arr[0].name().EqualsLiteral("path") ||
-      arr[0].value().type() != BluetoothValue::TnsString) {
-    NS_WARNING("Invalid object path for GetDevicePropertiesInternal() method");
-    return NS_ERROR_FAILURE;
-  }
-
-  nsRefPtr<nsRunnable> func(new BluetoothDevicePropertiesRunnable(aSignal));
-  if (NS_FAILED(mBluetoothCommandThread->Dispatch(func, NS_DISPATCH_NORMAL))) {
-    NS_WARNING("Cannot dispatch task!");
-    return NS_ERROR_FAILURE;
-  }
-
-  return NS_OK;
-}
-
-nsresult
 BluetoothDBusService::GetConnectedDevicePropertiesInternal(uint16_t aProfileId,
                                               BluetoothReplyRunnable* aRunnable)
 {
+  MOZ_ASSERT(NS_IsMainThread());
+
   nsAutoString errorStr;
   BluetoothValue values = InfallibleTArray<BluetoothNamedValue>();
   if (!IsReady()) {
-    errorStr.AssignLiteral("Bluetooth service is not ready yet!");
-    DispatchBluetoothReply(aRunnable, values, errorStr);
+    NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
+    DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
     return NS_OK;
   }
 
   nsTArray<nsString> deviceAddresses;
   if (aProfileId == BluetoothServiceClass::HANDSFREE ||
       aProfileId == BluetoothServiceClass::HEADSET) {
     BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
     if (hfp->IsConnected()) {
@@ -2149,21 +2018,21 @@ BluetoothDBusService::GetConnectedDevice
   return NS_OK;
 }
 
 nsresult
 BluetoothDBusService::GetPairedDevicePropertiesInternal(
                                      const nsTArray<nsString>& aDeviceAddresses,
                                      BluetoothReplyRunnable* aRunnable)
 {
+  MOZ_ASSERT(NS_IsMainThread());
+
   if (!IsReady()) {
-    BluetoothValue v;
-    nsAutoString errorStr;
-    errorStr.AssignLiteral("Bluetooth service is not ready yet!");
-    DispatchBluetoothReply(aRunnable, v, errorStr);
+    NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
+    DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
     return NS_OK;
   }
 
   nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
   nsRefPtr<nsRunnable> func(
     new BluetoothArrayOfDevicePropertiesRunnable(aDeviceAddresses,
                                                  runnable,
                                                  GetPairedDevicesFilter));
@@ -2176,23 +2045,21 @@ BluetoothDBusService::GetPairedDevicePro
   return NS_OK;
 }
 
 nsresult
 BluetoothDBusService::SetProperty(BluetoothObjectType aType,
                                   const BluetoothNamedValue& aValue,
                                   BluetoothReplyRunnable* aRunnable)
 {
-  NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!");
+  MOZ_ASSERT(NS_IsMainThread());
 
   if (!IsReady()) {
-    BluetoothValue v;
-    nsAutoString errorStr;
-    errorStr.AssignLiteral("Bluetooth service is not ready yet!");
-    DispatchBluetoothReply(aRunnable, v, errorStr);
+    NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
+    DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
     return NS_OK;
   }
 
   MOZ_ASSERT(aType < ArrayLength(sBluetoothDBusIfaces));
   const char* interface = sBluetoothDBusIfaces[aType];
 
   /* Compose the command */
   DBusMessage* msg = dbus_message_new_method_call(
@@ -2377,20 +2244,18 @@ BluetoothDBusService::CreatePairedDevice
   return NS_OK;
 }
 
 nsresult
 BluetoothDBusService::RemoveDeviceInternal(const nsAString& aDeviceAddress,
                                            BluetoothReplyRunnable* aRunnable)
 {
   if (!IsReady()) {
-    BluetoothValue v;
-    nsAutoString errorStr;
-    errorStr.AssignLiteral("Bluetooth service is not ready yet!");
-    DispatchBluetoothReply(aRunnable, v, errorStr);
+    NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
+    DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
     return NS_OK;
   }
 
   nsCString tempDeviceObjectPath =
     NS_ConvertUTF16toUTF8(GetObjectPathFromAddress(sAdapterPath,
                                                    aDeviceAddress));
 
   nsRefPtr<nsRunnable> task(new RemoveDeviceTask(tempDeviceObjectPath,
@@ -2584,35 +2449,16 @@ BluetoothDBusService::SetAuthorizationIn
   dbus_message_unref(msg);
   dbus_message_unref(reply);
 
   sAuthorizeReqTable.Remove(aDeviceAddress);
   DispatchBluetoothReply(aRunnable, v, errorStr);
   return result;
 }
 
-nsresult
-BluetoothDBusService::PrepareAdapterInternal()
-{
-  NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!");
-
-  if (!mConnection || !gThreadConnection) {
-    NS_ERROR("Bluetooth service not started yet!");
-    return NS_ERROR_FAILURE;
-  }
-
-  nsRefPtr<nsRunnable> func(new PrepareAdapterRunnable());
-  if (NS_FAILED(mBluetoothCommandThread->Dispatch(func, NS_DISPATCH_NORMAL))) {
-    NS_WARNING("Cannot dispatch task!");
-    return NS_ERROR_FAILURE;
-  }
-
-  return NS_OK;
-}
-
 void
 BluetoothDBusService::Connect(const nsAString& aDeviceAddress,
                               const uint16_t aProfileId,
                               BluetoothReplyRunnable* aRunnable)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (aProfileId == BluetoothServiceClass::HANDSFREE) {
@@ -2629,40 +2475,40 @@ BluetoothDBusService::Connect(const nsAS
                            NS_LITERAL_STRING("UnknownProfileError"));
   }
 }
 
 void
 BluetoothDBusService::Disconnect(const uint16_t aProfileId,
                                  BluetoothReplyRunnable* aRunnable)
 {
+  MOZ_ASSERT(NS_IsMainThread());
+
   if (aProfileId == BluetoothServiceClass::HANDSFREE ||
       aProfileId == BluetoothServiceClass::HEADSET) {
     BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
     hfp->Disconnect();
   } else if (aProfileId == BluetoothServiceClass::OBJECT_PUSH) {
     BluetoothOppManager* opp = BluetoothOppManager::Get();
     opp->Disconnect();
   } else {
     NS_WARNING("Unknown profile");
     return;
   }
 
   // Currently, just fire success because Disconnect() doesn't fail,
   // but we still make aRunnable pass into this function for future
   // once Disconnect will fail.
-  nsAutoString replyError;
-  BluetoothValue v = true;
-  DispatchBluetoothReply(aRunnable, v, replyError);
+  DispatchBluetoothReply(aRunnable, BluetoothValue(true), EmptyString());
 }
 
 bool
 BluetoothDBusService::IsConnected(const uint16_t aProfileId)
 {
-  NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!");
+  MOZ_ASSERT(NS_IsMainThread());
 
   if (aProfileId == BluetoothServiceClass::HANDSFREE ||
       aProfileId == BluetoothServiceClass::HEADSET) {
     BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
     return (hfp->IsConnected());
   } else if (aProfileId == BluetoothServiceClass::OBJECT_PUSH) {
     BluetoothOppManager* opp = BluetoothOppManager::Get();
     return opp->IsTransferring();
@@ -2694,23 +2540,21 @@ public:
   }
 
   nsresult
   Run()
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     nsString address = GetAddressFromObjectPath(mObjectPath);
-    BluetoothValue v;
-    nsAutoString replyError;
     BluetoothUnixSocketConnector* c =
       new BluetoothUnixSocketConnector(mType, mChannel, mAuth, mEncrypt);
     if (!mConsumer->ConnectSocket(c, NS_ConvertUTF16toUTF8(address).get())) {
-      replyError.AssignLiteral("SocketConnectionError");
-      DispatchBluetoothReply(mRunnable, v, replyError);
+      NS_NAMED_LITERAL_STRING(errorStr, "SocketConnectionError");
+      DispatchBluetoothReply(mRunnable, BluetoothValue(), errorStr);
       return NS_ERROR_FAILURE;
     }
     return NS_OK;
   }
 
 private:
   nsRefPtr<BluetoothReplyRunnable> mRunnable;
   nsRefPtr<UnixSocketConsumer> mConsumer;
@@ -2805,20 +2649,17 @@ public:
   {
     MOZ_ASSERT(!NS_IsMainThread());
 
     int channel = GetDeviceServiceChannel(mObjectPath, mServiceUuid, 0x0004);
     nsRefPtr<nsRunnable> r(new OnGetServiceChannelRunnable(mObjectPath,
                                                            mServiceUuid,
                                                            channel,
                                                            mManager));
-    if (NS_FAILED(NS_DispatchToMainThread(r))) {
-      return NS_ERROR_FAILURE;
-    }
-
+    NS_DispatchToMainThread(r);    
     return NS_OK;
   }
 
 private:
   nsString mObjectPath;
   nsString mServiceUuid;
   BluetoothProfileManagerBase* mManager;
 };
@@ -2831,20 +2672,17 @@ BluetoothDBusService::GetServiceChannel(
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mBluetoothCommandThread);
 
   nsString objectPath(GetObjectPathFromAddress(sAdapterPath, aDeviceAddress));
 
   nsRefPtr<nsRunnable> r(new GetServiceChannelRunnable(objectPath,
                                                        aServiceUuid,
                                                        aManager));
-
-  if (NS_FAILED(mBluetoothCommandThread->Dispatch(r, NS_DISPATCH_NORMAL))) {
-    return NS_ERROR_FAILURE;
-  }
+  mBluetoothCommandThread->Dispatch(r, NS_DISPATCH_NORMAL);
 
   return NS_OK;
 }
 
 static void
 DiscoverServicesCallback(DBusMessage* aMsg, void* aData)
 {
   MOZ_ASSERT(!NS_IsMainThread());
@@ -2882,17 +2720,17 @@ BluetoothDBusService::UpdateSdpRecords(c
 }
 
 nsresult
 BluetoothDBusService::GetScoSocket(const nsAString& aAddress,
                                    bool aAuth,
                                    bool aEncrypt,
                                    mozilla::ipc::UnixSocketConsumer* aConsumer)
 {
-  NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!");
+  MOZ_ASSERT(NS_IsMainThread());
 
   if (!mConnection || !gThreadConnection) {
     NS_ERROR("Bluetooth service not started yet!");
     return NS_ERROR_FAILURE;
   }
 
   BluetoothUnixSocketConnector* c =
     new BluetoothUnixSocketConnector(BluetoothSocketType::SCO, -1,
@@ -2908,74 +2746,74 @@ BluetoothDBusService::GetScoSocket(const
 }
 
 void
 BluetoothDBusService::SendFile(const nsAString& aDeviceAddress,
                                BlobParent* aBlobParent,
                                BlobChild* aBlobChild,
                                BluetoothReplyRunnable* aRunnable)
 {
-  NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!");
+  MOZ_ASSERT(NS_IsMainThread());
 
   // Currently we only support one device sending one file at a time,
   // so we don't need aDeviceAddress here because the target device
   // has been determined when calling 'Connect()'. Nevertheless, keep
   // it for future use.
   BluetoothOppManager* opp = BluetoothOppManager::Get();
-  BluetoothValue v = true;
+  NS_ENSURE_TRUE_VOID(opp);
+
   nsAutoString errorStr;
-
   if (!opp->SendFile(aDeviceAddress, aBlobParent)) {
     errorStr.AssignLiteral("Calling SendFile() failed");
   }
 
-  DispatchBluetoothReply(aRunnable, v, errorStr);
+  DispatchBluetoothReply(aRunnable, BluetoothValue(true), errorStr);
 }
 
 void
 BluetoothDBusService::StopSendingFile(const nsAString& aDeviceAddress,
                                       BluetoothReplyRunnable* aRunnable)
 {
-  NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!");
+  MOZ_ASSERT(NS_IsMainThread());
 
   // Currently we only support one device sending one file at a time,
   // so we don't need aDeviceAddress here because the target device
   // has been determined when calling 'Connect()'. Nevertheless, keep
   // it for future use.
   BluetoothOppManager* opp = BluetoothOppManager::Get();
-  BluetoothValue v = true;
+  NS_ENSURE_TRUE_VOID(opp);
+
   nsAutoString errorStr;
-
   if (!opp->StopSendingFile()) {
     errorStr.AssignLiteral("Calling StopSendingFile() failed");
   }
 
-  DispatchBluetoothReply(aRunnable, v, errorStr);
+  DispatchBluetoothReply(aRunnable, BluetoothValue(true), errorStr);
 }
 
 void
 BluetoothDBusService::ConfirmReceivingFile(const nsAString& aDeviceAddress,
                                            bool aConfirm,
                                            BluetoothReplyRunnable* aRunnable)
 {
   NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!");
 
   // Currently we only support one device sending one file at a time,
   // so we don't need aDeviceAddress here because the target device
   // has been determined when calling 'Connect()'. Nevertheless, keep
   // it for future use.
   BluetoothOppManager* opp = BluetoothOppManager::Get();
-  BluetoothValue v = true;
+  NS_ENSURE_TRUE_VOID(opp);
+
   nsAutoString errorStr;
-
   if (!opp->ConfirmReceivingFile(aConfirm)) {
     errorStr.AssignLiteral("Calling ConfirmReceivingFile() failed");
   }
 
-  DispatchBluetoothReply(aRunnable, v, errorStr);
+  DispatchBluetoothReply(aRunnable, BluetoothValue(true), errorStr);
 }
 
 void
 BluetoothDBusService::ConnectSco(BluetoothReplyRunnable* aRunnable)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
--- a/dom/bluetooth/linux/BluetoothDBusService.h
+++ b/dom/bluetooth/linux/BluetoothDBusService.h
@@ -43,19 +43,16 @@ public:
                                      const nsTArray<nsString>& aDeviceAddresses,
                                      BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
   virtual nsresult StartDiscoveryInternal(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
   virtual nsresult StopDiscoveryInternal(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
   virtual nsresult
-  GetDevicePropertiesInternal(const BluetoothSignal& aSignal) MOZ_OVERRIDE;
-
-  virtual nsresult
   SetProperty(BluetoothObjectType aType,
               const BluetoothNamedValue& aValue,
               BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
   virtual bool
   GetDevicePath(const nsAString& aAdapterPath,
                 const nsAString& aDeviceAddress,
                 nsAString& aDevicePath) MOZ_OVERRIDE;
@@ -114,19 +111,16 @@ public:
   virtual bool
   SetPairingConfirmationInternal(const nsAString& aDeviceAddress, bool aConfirm,
                                  BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
   virtual bool
   SetAuthorizationInternal(const nsAString& aDeviceAddress, bool aAllow,
                            BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
-  virtual nsresult
-  PrepareAdapterInternal() MOZ_OVERRIDE;
-
   virtual void
   Connect(const nsAString& aDeviceAddress,
           const uint16_t aProfileId,
           BluetoothReplyRunnable* aRunnable);
 
   virtual bool
   IsConnected(uint16_t aProfileId) MOZ_OVERRIDE;