Bug 791147: Patch 1 - Make bluetooth pairing replies use DOMRequests; r=bent
authorKyle Machulis <kyle@nonpolynomial.com>
Wed, 19 Sep 2012 16:37:42 -0700
changeset 107668 3f09f3b9188952cd1a035cd735b151ba2b7f2b2a
parent 107667 a81233955b61bc423009c26015472d01abb7a08d
child 107669 1d50132603340f7c72929079034ca60a852839b6
push id82
push usershu@rfrn.org
push dateFri, 05 Oct 2012 13:20:22 +0000
reviewersbent
bugs791147
milestone18.0a1
Bug 791147: Patch 1 - Make bluetooth pairing replies use DOMRequests; r=bent
dom/bluetooth/BluetoothAdapter.cpp
dom/bluetooth/BluetoothService.h
dom/bluetooth/linux/BluetoothDBusService.cpp
dom/bluetooth/linux/BluetoothDBusService.h
dom/bluetooth/nsIDOMBluetoothAdapter.idl
--- a/dom/bluetooth/BluetoothAdapter.cpp
+++ b/dom/bluetooth/BluetoothAdapter.cpp
@@ -58,18 +58,18 @@ NS_INTERFACE_MAP_END_INHERITING(nsDOMEve
 NS_IMPL_ADDREF_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper)
 
 class GetPairedDevicesTask : public BluetoothReplyRunnable
 {
 public:
   GetPairedDevicesTask(BluetoothAdapter* aAdapterPtr,
                        nsIDOMDOMRequest* aReq) :
-    mAdapterPtr(aAdapterPtr),
-    BluetoothReplyRunnable(aReq)
+    BluetoothReplyRunnable(aReq),
+    mAdapterPtr(aAdapterPtr)
   {
     MOZ_ASSERT(aReq && aAdapterPtr);
   }
 
   virtual bool ParseSuccessfulReply(jsval* aValue)
   {
     *aValue = JSVAL_VOID;
     BluetoothValue& v = mReply->get_BluetoothReplySuccess().value();
@@ -579,69 +579,155 @@ BluetoothAdapter::Pair(nsIDOMBluetoothDe
 
 nsresult
 BluetoothAdapter::Unpair(nsIDOMBluetoothDevice* aDevice, nsIDOMDOMRequest** aRequest)
 {
   return PairUnpair(false, aDevice, aRequest);
 }
 
 nsresult
-BluetoothAdapter::SetPinCode(const nsAString& aDeviceAddress, const nsAString& aPinCode)
+BluetoothAdapter::SetPinCode(const nsAString& aDeviceAddress,
+                             const nsAString& aPinCode,
+                             nsIDOMDOMRequest** aRequest)
 {
   BluetoothService* bs = BluetoothService::Get();
   if (!bs) {
     NS_WARNING("BluetoothService not available!");
     return NS_ERROR_FAILURE;
   }
 
-  bool result = bs->SetPinCodeInternal(aDeviceAddress, aPinCode);
+  nsCOMPtr<nsIDOMRequestService> rs = do_GetService("@mozilla.org/dom/dom-request-service;1");
+  if (!rs) {
+    NS_WARNING("No DOMRequest Service!");
+    return NS_ERROR_FAILURE;
+  }
 
-  return result ? NS_OK : NS_ERROR_FAILURE;
+  nsCOMPtr<nsIDOMDOMRequest> req;
+  nsresult rv = rs->CreateRequest(GetOwner(), getter_AddRefs(req));
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Can't create DOMRequest!");
+    return NS_ERROR_FAILURE;
+  }
+
+  nsRefPtr<BluetoothVoidReplyRunnable> results = new BluetoothVoidReplyRunnable(req);
+
+  bool result = bs->SetPinCodeInternal(aDeviceAddress, aPinCode, results);
+  if(!result) {
+    NS_WARNING("SetPinCode failed!");
+    return NS_ERROR_FAILURE;
+  }
+
+  req.forget(aRequest);
+  return NS_OK;  
 }
 
 nsresult
-BluetoothAdapter::SetPasskey(const nsAString& aDeviceAddress, uint32_t aPasskey)
+BluetoothAdapter::SetPasskey(const nsAString& aDeviceAddress, uint32_t aPasskey,
+                             nsIDOMDOMRequest** aRequest)
 {
   BluetoothService* bs = BluetoothService::Get();
   if (!bs) {
     NS_WARNING("BluetoothService not available!");
     return NS_ERROR_FAILURE;
   }
 
-  bool result = bs->SetPasskeyInternal(aDeviceAddress, aPasskey);
+  nsCOMPtr<nsIDOMRequestService> rs = do_GetService("@mozilla.org/dom/dom-request-service;1");
+  if (!rs) {
+    NS_WARNING("No DOMRequest Service!");
+    return NS_ERROR_FAILURE;
+  }
 
-  return result ? NS_OK : NS_ERROR_FAILURE;
+  nsCOMPtr<nsIDOMDOMRequest> req;
+  nsresult rv = rs->CreateRequest(GetOwner(), getter_AddRefs(req));
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Can't create DOMRequest!");
+    return NS_ERROR_FAILURE;
+  }
+
+  nsRefPtr<BluetoothVoidReplyRunnable> results = new BluetoothVoidReplyRunnable(req);
+
+  bool result = bs->SetPasskeyInternal(aDeviceAddress, aPasskey, results);
+  if(!result) {
+    NS_WARNING("SetPasskeyInternal failed!");
+    return NS_ERROR_FAILURE;
+  }
+
+  req.forget(aRequest);
+  return NS_OK;  
 }
 
 nsresult
-BluetoothAdapter::SetPairingConfirmation(const nsAString& aDeviceAddress, bool aConfirmation)
+BluetoothAdapter::SetPairingConfirmation(const nsAString& aDeviceAddress,
+                                         bool aConfirmation,
+                                         nsIDOMDOMRequest** aRequest)
 {
   BluetoothService* bs = BluetoothService::Get();
   if (!bs) {
     NS_WARNING("BluetoothService not available!");
     return NS_ERROR_FAILURE;
   }
 
-  bool result = bs->SetPairingConfirmationInternal(aDeviceAddress, aConfirmation);
+  nsCOMPtr<nsIDOMRequestService> rs = do_GetService("@mozilla.org/dom/dom-request-service;1");
+  if (!rs) {
+    NS_WARNING("No DOMRequest Service!");
+    return NS_ERROR_FAILURE;
+  }
 
-  return result ? NS_OK : NS_ERROR_FAILURE;
+  nsCOMPtr<nsIDOMDOMRequest> req;
+  nsresult rv = rs->CreateRequest(GetOwner(), getter_AddRefs(req));
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Can't create DOMRequest!");
+    return NS_ERROR_FAILURE;
+  }
+
+  nsRefPtr<BluetoothVoidReplyRunnable> results = new BluetoothVoidReplyRunnable(req);
+
+  bool result = bs->SetPairingConfirmationInternal(aDeviceAddress, aConfirmation, results);
+  if(!result) {
+    NS_WARNING("SetPairingConfirmation failed!");
+    return NS_ERROR_FAILURE;
+  }
+
+  req.forget(aRequest);
+  return NS_OK;  
 }
 
 nsresult
-BluetoothAdapter::SetAuthorization(const nsAString& aDeviceAddress, bool aAllow)
+BluetoothAdapter::SetAuthorization(const nsAString& aDeviceAddress, bool aAllow,
+                                   nsIDOMDOMRequest** aRequest)
 {
   BluetoothService* bs = BluetoothService::Get();
   if (!bs) {
     NS_WARNING("BluetoothService not available!");
     return NS_ERROR_FAILURE;
   }
 
-  bool result = bs->SetAuthorizationInternal(aDeviceAddress, aAllow);
+  nsCOMPtr<nsIDOMRequestService> rs = do_GetService("@mozilla.org/dom/dom-request-service;1");
+  if (!rs) {
+    NS_WARNING("No DOMRequest Service!");
+    return NS_ERROR_FAILURE;
+  }
 
-  return result ? NS_OK : NS_ERROR_FAILURE;
+  nsCOMPtr<nsIDOMDOMRequest> req;
+  nsresult rv = rs->CreateRequest(GetOwner(), getter_AddRefs(req));
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Can't create DOMRequest!");
+    return NS_ERROR_FAILURE;
+  }
+
+  nsRefPtr<BluetoothVoidReplyRunnable> results = new BluetoothVoidReplyRunnable(req);
+
+  bool result = bs->SetAuthorizationInternal(aDeviceAddress, aAllow, results);
+  if(!result) {
+    NS_WARNING("SetAuthorization failed!");
+    return NS_ERROR_FAILURE;
+  }
+
+  req.forget(aRequest);
+  return NS_OK;  
 }
 
 NS_IMPL_EVENT_HANDLER(BluetoothAdapter, propertychanged)
 NS_IMPL_EVENT_HANDLER(BluetoothAdapter, devicefound)
 NS_IMPL_EVENT_HANDLER(BluetoothAdapter, devicedisappeared)
 NS_IMPL_EVENT_HANDLER(BluetoothAdapter, devicecreated)
 NS_IMPL_EVENT_HANDLER(BluetoothAdapter, requestconfirmation)
 NS_IMPL_EVENT_HANDLER(BluetoothAdapter, requestpincode)
--- a/dom/bluetooth/BluetoothService.h
+++ b/dom/bluetooth/BluetoothService.h
@@ -232,26 +232,30 @@ public:
                       bool aAuth,
                       bool aEncrypt,
                       BluetoothReplyRunnable* aRunnable) = 0;
 
   virtual bool
   CloseSocket(int aFd, BluetoothReplyRunnable* aRunnable) = 0;
 
   virtual bool
-  SetPinCodeInternal(const nsAString& aDeviceAddress, const nsAString& aPinCode) = 0;
+  SetPinCodeInternal(const nsAString& aDeviceAddress, const nsAString& aPinCode,
+                     BluetoothReplyRunnable* aRunnable) = 0;
 
   virtual bool
-  SetPasskeyInternal(const nsAString& aDeviceAddress, uint32_t aPasskey) = 0;
+  SetPasskeyInternal(const nsAString& aDeviceAddress, uint32_t aPasskey,
+                     BluetoothReplyRunnable* aRunnable) = 0;
 
   virtual bool
-  SetPairingConfirmationInternal(const nsAString& aDeviceAddress, bool aConfirm) = 0;
+  SetPairingConfirmationInternal(const nsAString& aDeviceAddress, bool aConfirm,
+                                 BluetoothReplyRunnable* aRunnable) = 0;
 
   virtual bool
-  SetAuthorizationInternal(const nsAString& aDeviceAddress, bool aAllow) = 0;
+  SetAuthorizationInternal(const nsAString& aDeviceAddress, bool aAllow,
+                           BluetoothReplyRunnable* aRunnable) = 0;
 
   bool
   IsEnabled() const
   {
     return mEnabled;
   }
 
 protected:
--- a/dom/bluetooth/linux/BluetoothDBusService.cpp
+++ b/dom/bluetooth/linux/BluetoothDBusService.cpp
@@ -578,17 +578,23 @@ AddReservedServices(const nsAString& aAd
   BluetoothDBusService::AddReservedServicesInternal(aAdapterPath, uuids,
                                                     sServiceHandles);
 }
 
 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!");
 
   nsString replyError;
   BluetoothValue v;
   aFunc(aMsg, nullptr, v, replyError);
@@ -891,17 +897,16 @@ GetPropertiesInternal(const nsAString& a
 
   DBusMessage* msg = dbus_func_args_timeout(gThreadConnection->GetConnection(),
                                             1000,
                                             &err,
                                             NS_ConvertUTF16toUTF8(aPath).get(),
                                             aIface,
                                             "GetProperties",
                                             DBUS_TYPE_INVALID);
-
   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!");
@@ -1785,153 +1790,195 @@ BluetoothDBusService::RemoveDeviceIntern
     return NS_ERROR_FAILURE;
   }
 
   runnable.forget();
   return NS_OK;
 }
 
 bool
-BluetoothDBusService::SetPinCodeInternal(const nsAString& aDeviceAddress, const nsAString& aPinCode)
+BluetoothDBusService::SetPinCodeInternal(const nsAString& aDeviceAddress,
+                                         const nsAString& aPinCode,
+                                         BluetoothReplyRunnable* aRunnable)
 {
+  nsString errorStr;
+  BluetoothValue v = true;
   DBusMessage *msg;
   if (!sPairingReqTable.Get(aDeviceAddress, &msg)) {
     LOG("%s: Couldn't get original request message.", __FUNCTION__);
+    errorStr.AssignLiteral("Couldn't get original request message.");
+    DispatchBluetoothReply(aRunnable, v, errorStr);
     return false;
   }
 
   DBusMessage *reply = dbus_message_new_method_return(msg);
 
   if (!reply) {
     LOG("%s: Memory can't be allocated for the message.", __FUNCTION__);
     dbus_message_unref(msg);
+    errorStr.AssignLiteral("Memory can't be allocated for the message.");
+    DispatchBluetoothReply(aRunnable, v, errorStr);
     return false;
   }
 
   bool result;
 
   nsCString tempPinCode = NS_ConvertUTF16toUTF8(aPinCode);
   const char* pinCode = tempPinCode.get();
 
   if (!dbus_message_append_args(reply,
                                 DBUS_TYPE_STRING, &pinCode,
                                 DBUS_TYPE_INVALID)) {
     LOG("%s: Couldn't append arguments to dbus message.", __FUNCTION__);
+    errorStr.AssignLiteral("Couldn't append arguments to dbus message.");
     result = false;
   } else {
     result = dbus_connection_send(mConnection, reply, NULL);
   }
 
   dbus_message_unref(msg);
   dbus_message_unref(reply);
 
   sPairingReqTable.Remove(aDeviceAddress);
-
+  DispatchBluetoothReply(aRunnable, v, errorStr);
   return result;
 }
 
 bool
-BluetoothDBusService::SetPasskeyInternal(const nsAString& aDeviceAddress, uint32_t aPasskey)
+BluetoothDBusService::SetPasskeyInternal(const nsAString& aDeviceAddress,
+                                         uint32_t aPasskey,
+                                         BluetoothReplyRunnable* aRunnable)
 {
+  nsString errorStr;
+  BluetoothValue v = true;
   DBusMessage *msg;
   if (!sPairingReqTable.Get(aDeviceAddress, &msg)) {
     LOG("%s: Couldn't get original request message.", __FUNCTION__);
+    errorStr.AssignLiteral("Couldn't get original request message.");
+    DispatchBluetoothReply(aRunnable, v, errorStr);
     return false;
   }
 
   DBusMessage *reply = dbus_message_new_method_return(msg);
 
   if (!reply) {
     LOG("%s: Memory can't be allocated for the message.", __FUNCTION__);
     dbus_message_unref(msg);
+    errorStr.AssignLiteral("Memory can't be allocated for the message.");
+    DispatchBluetoothReply(aRunnable, v, errorStr);
     return false;
   }
 
   uint32_t passkey = aPasskey;
   bool result;
 
   if (!dbus_message_append_args(reply,
                                 DBUS_TYPE_UINT32, &passkey,
                                 DBUS_TYPE_INVALID)) {
     LOG("%s: Couldn't append arguments to dbus message.", __FUNCTION__);
+    errorStr.AssignLiteral("Couldn't append arguments to dbus message.");
     result = false;
   } else {
     result = dbus_connection_send(mConnection, reply, NULL);
   }
 
   dbus_message_unref(msg);
   dbus_message_unref(reply);
 
   sPairingReqTable.Remove(aDeviceAddress);
-
+  DispatchBluetoothReply(aRunnable, v, errorStr);
   return result;
 }
 
 bool
-BluetoothDBusService::SetPairingConfirmationInternal(const nsAString& aDeviceAddress, bool aConfirm)
+BluetoothDBusService::SetPairingConfirmationInternal(const nsAString& aDeviceAddress,
+                                                     bool aConfirm,
+                                                     BluetoothReplyRunnable* aRunnable)
 {
+  nsString errorStr;
+  BluetoothValue v = true;
   DBusMessage *msg;
   if (!sPairingReqTable.Get(aDeviceAddress, &msg)) {
     LOG("%s: Couldn't get original request message.", __FUNCTION__);
+    errorStr.AssignLiteral("Couldn't get original request message.");
+    DispatchBluetoothReply(aRunnable, v, errorStr);
     return false;
   }
 
   DBusMessage *reply;
 
   if (aConfirm) {
     reply = dbus_message_new_method_return(msg);   
   } else {
-    reply = dbus_message_new_error(msg, "org.bluez.Error.Rejected", "User rejected confirmation");
+    reply = dbus_message_new_error(msg, "org.bluez.Error.Rejected",
+                                   "User rejected confirmation");
   }
 
   if (!reply) {
     LOG("%s: Memory can't be allocated for the message.", __FUNCTION__);
     dbus_message_unref(msg);
+    errorStr.AssignLiteral("Memory can't be allocated for the message.");
+    DispatchBluetoothReply(aRunnable, v, errorStr);
     return false;
   }
 
   bool result = dbus_connection_send(mConnection, reply, NULL);
+  if (!result) {
+    errorStr.AssignLiteral("Can't send message!");
+  }
   dbus_message_unref(msg);
   dbus_message_unref(reply);
 
   sPairingReqTable.Remove(aDeviceAddress);
-
+  DispatchBluetoothReply(aRunnable, v, errorStr);
   return result;
 }
 
 bool
-BluetoothDBusService::SetAuthorizationInternal(const nsAString& aDeviceAddress, bool aAllow)
+BluetoothDBusService::SetAuthorizationInternal(const nsAString& aDeviceAddress,
+                                               bool aAllow,
+                                               BluetoothReplyRunnable* aRunnable)
 {
+  nsString errorStr;
+  BluetoothValue v = true;
   DBusMessage *msg;
   
   if (!sAuthorizeReqTable.Get(aDeviceAddress, &msg)) {
     LOG("%s: Couldn't get original request message.", __FUNCTION__);
+    errorStr.AssignLiteral("Couldn't get original request message.");
+    DispatchBluetoothReply(aRunnable, v, errorStr);
     return false;
   }
 
   DBusMessage *reply;
 
   if (aAllow) {
     reply = dbus_message_new_method_return(msg);   
   } else {
-    reply = dbus_message_new_error(msg, "org.bluez.Error.Rejected", "Authorization rejected");
+    reply = dbus_message_new_error(msg, "org.bluez.Error.Rejected",
+                                   "User rejected authorization");
   }
 
   if (!reply) {
     LOG("%s: Memory can't be allocated for the message.", __FUNCTION__);
     dbus_message_unref(msg);
+    errorStr.AssignLiteral("Memory can't be allocated for the message.");
+    DispatchBluetoothReply(aRunnable, v, errorStr);
     return false;
   }
 
   bool result = dbus_connection_send(mConnection, reply, NULL);
+  if (!result) {
+    errorStr.AssignLiteral("Can't send message!");
+  }
   dbus_message_unref(msg);
   dbus_message_unref(reply);
 
   sAuthorizeReqTable.Remove(aDeviceAddress);
-
+  DispatchBluetoothReply(aRunnable, v, errorStr);
   return result;
 }
 
 class CreateBluetoothSocketRunnable : public nsRunnable
 {
 public:
   CreateBluetoothSocketRunnable(BluetoothReplyRunnable* aRunnable,
                                 const nsAString& aObjectPath,
--- a/dom/bluetooth/linux/BluetoothDBusService.h
+++ b/dom/bluetooth/linux/BluetoothDBusService.h
@@ -77,26 +77,30 @@ public:
                              BluetoothReplyRunnable* aRunnable);
 
   virtual nsresult
   RemoveDeviceInternal(const nsAString& aAdapterPath,
                        const nsAString& aDeviceObjectPath,
                        BluetoothReplyRunnable* aRunnable);
 
   virtual bool
-  SetPinCodeInternal(const nsAString& aDeviceAddress, const nsAString& aPinCode);
+  SetPinCodeInternal(const nsAString& aDeviceAddress, const nsAString& aPinCode,
+                     BluetoothReplyRunnable* aRunnable);
 
   virtual bool
-  SetPasskeyInternal(const nsAString& aDeviceAddress, uint32_t aPasskey);
+  SetPasskeyInternal(const nsAString& aDeviceAddress, uint32_t aPasskey,
+                     BluetoothReplyRunnable* aRunnable);
 
   virtual bool 
-  SetPairingConfirmationInternal(const nsAString& aDeviceAddress, bool aConfirm);
+  SetPairingConfirmationInternal(const nsAString& aDeviceAddress, bool aConfirm,
+                                 BluetoothReplyRunnable* aRunnable);
 
   virtual bool 
-  SetAuthorizationInternal(const nsAString& aDeviceAddress, bool aAllow);
+  SetAuthorizationInternal(const nsAString& aDeviceAddress, bool aAllow,
+                           BluetoothReplyRunnable* aRunnable);
 
 private:
   nsresult SendGetPropertyMessage(const nsAString& aPath,
                                   const char* aInterface,
                                   void (*aCB)(DBusMessage *, void *),
                                   BluetoothReplyRunnable* aRunnable);
   nsresult SendDiscoveryMessage(const nsAString& aAdapterPath,
                                 const char* aMessageName,
--- a/dom/bluetooth/nsIDOMBluetoothAdapter.idl
+++ b/dom/bluetooth/nsIDOMBluetoothAdapter.idl
@@ -31,20 +31,20 @@ interface nsIDOMBluetoothAdapter : nsIDO
   nsIDOMDOMRequest setName(in DOMString name);
   nsIDOMDOMRequest setDiscoverable(in bool discoverable);
   nsIDOMDOMRequest setDiscoverableTimeout(in unsigned long timeout);
   nsIDOMDOMRequest startDiscovery();
   nsIDOMDOMRequest stopDiscovery();
   nsIDOMDOMRequest pair(in nsIDOMBluetoothDevice aDevice);
   nsIDOMDOMRequest unpair(in nsIDOMBluetoothDevice aDevice);
   nsIDOMDOMRequest getPairedDevices();
-  void setPinCode(in DOMString aDeviceAddress, in DOMString aPinCode);
-  void setPasskey(in DOMString aDeviceAddress, in unsigned long aPasskey);
-  void setPairingConfirmation(in DOMString aDeviceAddress, in bool aConfirmation);
-  void setAuthorization(in DOMString aDeviceAddress, in bool aAllow);
+  nsIDOMDOMRequest setPinCode(in DOMString aDeviceAddress, in DOMString aPinCode);
+  nsIDOMDOMRequest setPasskey(in DOMString aDeviceAddress, in unsigned long aPasskey);
+  nsIDOMDOMRequest setPairingConfirmation(in DOMString aDeviceAddress, in bool aConfirmation);
+  nsIDOMDOMRequest setAuthorization(in DOMString aDeviceAddress, in bool aAllow);
 
   // Fired when discoverying and any device is discovered.
   [implicit_jscontext] attribute jsval ondevicefound;
   // Fired when any device is out of discoverable range.
   [implicit_jscontext] attribute jsval ondevicedisappeared;
   // Fired when any device is created.
   [implicit_jscontext] attribute jsval ondevicecreated;
   // Fired when a property of the adapter is changed