Bug 850157 - Add GetConnectedDevices() in nsIDOMBluetoothAdapter.idl, r=echou, sr= mrbkap
authorGina Yeh <gyeh@mozilla.com>
Fri, 26 Apr 2013 18:48:21 +0800
changeset 140886 4db652bb932f7acbf6760df5833a9e8e78512bf9
parent 140885 23e508b1d49645ce849828aba86471bdb4fad628
child 140887 cbbd94e6ab326be36f8a524bfebb6cd8351ae9cd
push id2579
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 18:52:47 +0000
treeherdermozilla-beta@b69b7de8a05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersechou
bugs850157
milestone23.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 850157 - Add GetConnectedDevices() in nsIDOMBluetoothAdapter.idl, r=echou, sr= mrbkap
dom/bluetooth/BluetoothAdapter.cpp
dom/bluetooth/BluetoothHfpManager.cpp
dom/bluetooth/BluetoothHfpManager.h
dom/bluetooth/BluetoothOppManager.cpp
dom/bluetooth/BluetoothOppManager.h
dom/bluetooth/BluetoothService.h
dom/bluetooth/ipc/BluetoothParent.cpp
dom/bluetooth/ipc/BluetoothParent.h
dom/bluetooth/ipc/BluetoothServiceChildProcess.cpp
dom/bluetooth/ipc/BluetoothServiceChildProcess.h
dom/bluetooth/ipc/PBluetooth.ipdl
dom/bluetooth/linux/BluetoothDBusService.cpp
dom/bluetooth/linux/BluetoothDBusService.h
dom/bluetooth/nsIDOMBluetoothAdapter.idl
--- a/dom/bluetooth/BluetoothAdapter.cpp
+++ b/dom/bluetooth/BluetoothAdapter.cpp
@@ -49,20 +49,20 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothAdapter)
   NS_INTERFACE_MAP_ENTRY(nsIDOMBluetoothAdapter)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(BluetoothAdapter)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper)
 
-class GetPairedDevicesTask : public BluetoothReplyRunnable
+class GetDevicesTask : public BluetoothReplyRunnable
 {
 public:
-  GetPairedDevicesTask(BluetoothAdapter* aAdapterPtr,
+  GetDevicesTask(BluetoothAdapter* aAdapterPtr,
                        nsIDOMDOMRequest* aReq) :
     BluetoothReplyRunnable(aReq),
     mAdapterPtr(aAdapterPtr)
   {
     MOZ_ASSERT(aReq && aAdapterPtr);
   }
 
   virtual bool ParseSuccessfulReply(JS::Value* aValue)
@@ -232,16 +232,22 @@ BluetoothAdapter::SetPropertyByValue(con
                                     mUuids,
                                     &mJsUuids))) {
       NS_WARNING("Cannot set JS UUIDs object!");
       return;
     }
     Root();
   } else if (name.EqualsLiteral("Devices")) {
     mDeviceAddresses = value.get_ArrayOfnsString();
+
+    uint32_t length = mDeviceAddresses.Length();
+    for (int i = 0; i < length; i++) {
+      mDeviceAddresses[i] = GetAddressFromObjectPath(mDeviceAddresses[i]);
+    }
+
     nsresult rv;
     nsIScriptContext* sc = GetContextForEventHandlers(&rv);
     NS_ENSURE_SUCCESS_VOID(rv);
 
     if (NS_FAILED(nsTArrayToJSArray(sc->GetNativeContext(),
                                     mDeviceAddresses,
                                     &mJsDeviceAddresses))) {
       NS_WARNING("Cannot set JS Devices object!");
@@ -448,46 +454,62 @@ BluetoothAdapter::SetDiscoverableTimeout
     return FirePropertyAlreadySet(GetOwner(), aRequest);
   }
   BluetoothValue value(aDiscoverableTimeout);
   BluetoothNamedValue property(NS_LITERAL_STRING("DiscoverableTimeout"), value);
   return SetProperty(GetOwner(), property, aRequest);
 }
 
 NS_IMETHODIMP
-BluetoothAdapter::GetPairedDevices(nsIDOMDOMRequest** aRequest)
+BluetoothAdapter::GetConnectedDevices(uint16_t aProfileId,
+                                      nsIDOMDOMRequest** aRequest)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   nsCOMPtr<nsIDOMDOMRequest> req;
-  nsresult rv;
-  rv = PrepareDOMRequest(GetOwner(), getter_AddRefs(req));
+  nsresult rv = PrepareDOMRequest(GetOwner(), getter_AddRefs(req));
   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
 
   nsRefPtr<BluetoothReplyRunnable> results =
-    new GetPairedDevicesTask(this, req);
+    new GetDevicesTask(this, req);
 
   BluetoothService* bs = BluetoothService::Get();
   NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE);
-  if (NS_FAILED(bs->GetPairedDevicePropertiesInternal(mDeviceAddresses,
-                                                      results))) {
-    NS_WARNING("GetPairedDevices failed!");
-    return NS_ERROR_FAILURE;
-  }
+  rv = bs->GetConnectedDevicePropertiesInternal(aProfileId, results);
+  NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
+
+  req.forget(aRequest);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+BluetoothAdapter::GetPairedDevices(nsIDOMDOMRequest** aRequest)
+{
+  nsCOMPtr<nsIDOMDOMRequest> req;
+  nsresult rv = PrepareDOMRequest(GetOwner(), getter_AddRefs(req));
+  NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
+
+  nsRefPtr<BluetoothReplyRunnable> results =
+    new GetDevicesTask(this, req);
+
+  BluetoothService* bs = BluetoothService::Get();
+  NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE);
+  rv = bs->GetPairedDevicePropertiesInternal(mDeviceAddresses, results);
+  NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
 
   req.forget(aRequest);
   return NS_OK;
 }
 
 nsresult
 BluetoothAdapter::PairUnpair(bool aPair,
                              nsIDOMBluetoothDevice* aDevice,
                              nsIDOMDOMRequest** aRequest)
 {
   nsCOMPtr<nsIDOMDOMRequest> req;
-  nsresult rv;
-  rv = PrepareDOMRequest(GetOwner(), getter_AddRefs(req));
+  nsresult rv = PrepareDOMRequest(GetOwner(), getter_AddRefs(req));
   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
 
   nsRefPtr<BluetoothVoidReplyRunnable> results =
     new BluetoothVoidReplyRunnable(req);
 
   nsAutoString addr;
   aDevice->GetAddress(addr);
 
@@ -525,18 +547,17 @@ BluetoothAdapter::Unpair(nsIDOMBluetooth
 }
 
 nsresult
 BluetoothAdapter::SetPinCode(const nsAString& aDeviceAddress,
                              const nsAString& aPinCode,
                              nsIDOMDOMRequest** aRequest)
 {
   nsCOMPtr<nsIDOMDOMRequest> req;
-  nsresult rv;
-  rv = PrepareDOMRequest(GetOwner(), getter_AddRefs(req));
+  nsresult rv = PrepareDOMRequest(GetOwner(), getter_AddRefs(req));
   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
 
   nsRefPtr<BluetoothVoidReplyRunnable> results =
     new BluetoothVoidReplyRunnable(req);
 
   BluetoothService* bs = BluetoothService::Get();
   NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE);
   if(!bs->SetPinCodeInternal(aDeviceAddress, aPinCode, results)) {
@@ -548,18 +569,17 @@ BluetoothAdapter::SetPinCode(const nsASt
   return NS_OK;
 }
 
 nsresult
 BluetoothAdapter::SetPasskey(const nsAString& aDeviceAddress, uint32_t aPasskey,
                              nsIDOMDOMRequest** aRequest)
 {
   nsCOMPtr<nsIDOMDOMRequest> req;
-  nsresult rv;
-  rv = PrepareDOMRequest(GetOwner(), getter_AddRefs(req));
+  nsresult rv = PrepareDOMRequest(GetOwner(), getter_AddRefs(req));
   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
 
   nsRefPtr<BluetoothVoidReplyRunnable> results =
     new BluetoothVoidReplyRunnable(req);
 
   BluetoothService* bs = BluetoothService::Get();
   NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE);
   if(bs->SetPasskeyInternal(aDeviceAddress, aPasskey, results)) {
@@ -572,18 +592,17 @@ BluetoothAdapter::SetPasskey(const nsASt
 }
 
 nsresult
 BluetoothAdapter::SetPairingConfirmation(const nsAString& aDeviceAddress,
                                          bool aConfirmation,
                                          nsIDOMDOMRequest** aRequest)
 {
   nsCOMPtr<nsIDOMDOMRequest> req;
-  nsresult rv;
-  rv = PrepareDOMRequest(GetOwner(), getter_AddRefs(req));
+  nsresult rv = PrepareDOMRequest(GetOwner(), getter_AddRefs(req));
   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
 
   nsRefPtr<BluetoothVoidReplyRunnable> results =
     new BluetoothVoidReplyRunnable(req);
 
   BluetoothService* bs = BluetoothService::Get();
   NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE);
   if(!bs->SetPairingConfirmationInternal(aDeviceAddress,
@@ -597,18 +616,17 @@ BluetoothAdapter::SetPairingConfirmation
   return NS_OK;
 }
 
 nsresult
 BluetoothAdapter::SetAuthorization(const nsAString& aDeviceAddress, bool aAllow,
                                    nsIDOMDOMRequest** aRequest)
 {
   nsCOMPtr<nsIDOMDOMRequest> req;
-  nsresult rv;
-  rv = PrepareDOMRequest(GetOwner(), getter_AddRefs(req));
+  nsresult rv = PrepareDOMRequest(GetOwner(), getter_AddRefs(req));
   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
 
   nsRefPtr<BluetoothVoidReplyRunnable> results =
     new BluetoothVoidReplyRunnable(req);
 
   BluetoothService* bs = BluetoothService::Get();
   NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE);
   if(!bs->SetAuthorizationInternal(aDeviceAddress, aAllow, results)) {
@@ -621,18 +639,17 @@ BluetoothAdapter::SetAuthorization(const
 }
 
 NS_IMETHODIMP
 BluetoothAdapter::Connect(const nsAString& aDeviceAddress,
                           uint16_t aProfileId,
                           nsIDOMDOMRequest** aRequest)
 {
   nsCOMPtr<nsIDOMDOMRequest> req;
-  nsresult rv;
-  rv = PrepareDOMRequest(GetOwner(), getter_AddRefs(req));
+  nsresult rv = PrepareDOMRequest(GetOwner(), getter_AddRefs(req));
   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
 
   BluetoothService* bs = BluetoothService::Get();
   NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE);
 
   nsRefPtr<BluetoothVoidReplyRunnable> results =
     new BluetoothVoidReplyRunnable(req);
   bs->Connect(aDeviceAddress, aProfileId, results);
@@ -641,18 +658,17 @@ BluetoothAdapter::Connect(const nsAStrin
   return NS_OK;
 }
 
 NS_IMETHODIMP
 BluetoothAdapter::Disconnect(uint16_t aProfileId,
                              nsIDOMDOMRequest** aRequest)
 {
   nsCOMPtr<nsIDOMDOMRequest> req;
-  nsresult rv;
-  rv = PrepareDOMRequest(GetOwner(), getter_AddRefs(req));
+  nsresult rv = PrepareDOMRequest(GetOwner(), getter_AddRefs(req));
   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
 
   nsRefPtr<BluetoothVoidReplyRunnable> results =
     new BluetoothVoidReplyRunnable(req);
 
   BluetoothService* bs = BluetoothService::Get();
   NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE);
   bs->Disconnect(aProfileId, results);
@@ -662,18 +678,17 @@ BluetoothAdapter::Disconnect(uint16_t aP
 }
 
 NS_IMETHODIMP
 BluetoothAdapter::SendFile(const nsAString& aDeviceAddress,
                            nsIDOMBlob* aBlob,
                            nsIDOMDOMRequest** aRequest)
 {
   nsCOMPtr<nsIDOMDOMRequest> req;
-  nsresult rv;
-  rv = PrepareDOMRequest(GetOwner(), getter_AddRefs(req));
+  nsresult rv = PrepareDOMRequest(GetOwner(), getter_AddRefs(req));
   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
 
   nsRefPtr<BluetoothVoidReplyRunnable> results =
     new BluetoothVoidReplyRunnable(req);
 
   BlobChild* actor =
     mozilla::dom::ContentChild::GetSingleton()->GetOrCreateActorForBlob(aBlob);
   if (!actor) {
@@ -689,18 +704,17 @@ BluetoothAdapter::SendFile(const nsAStri
   return NS_OK;
 }
 
 NS_IMETHODIMP
 BluetoothAdapter::StopSendingFile(const nsAString& aDeviceAddress,
                                   nsIDOMDOMRequest** aRequest)
 {
   nsCOMPtr<nsIDOMDOMRequest> req;
-  nsresult rv;
-  rv = PrepareDOMRequest(GetOwner(), getter_AddRefs(req));
+  nsresult rv = PrepareDOMRequest(GetOwner(), getter_AddRefs(req));
   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
 
   nsRefPtr<BluetoothVoidReplyRunnable> results =
     new BluetoothVoidReplyRunnable(req);
 
   BluetoothService* bs = BluetoothService::Get();
   NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE);
   bs->StopSendingFile(aDeviceAddress, results);
@@ -710,18 +724,17 @@ BluetoothAdapter::StopSendingFile(const 
 }
 
 nsresult
 BluetoothAdapter::ConfirmReceivingFile(const nsAString& aDeviceAddress,
                                        bool aConfirmation,
                                        nsIDOMDOMRequest** aRequest)
 {
   nsCOMPtr<nsIDOMDOMRequest> req;
-  nsresult rv;
-  rv = PrepareDOMRequest(GetOwner(), getter_AddRefs(req));
+  nsresult rv = PrepareDOMRequest(GetOwner(), getter_AddRefs(req));
   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
 
   nsRefPtr<BluetoothVoidReplyRunnable> results =
     new BluetoothVoidReplyRunnable(req);
 
   BluetoothService* bs = BluetoothService::Get();
   NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE);
   bs->ConfirmReceivingFile(aDeviceAddress, aConfirmation, results);
--- a/dom/bluetooth/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/BluetoothHfpManager.cpp
@@ -1450,8 +1450,14 @@ BluetoothHfpManager::IsConnected()
 {
   if (mSocket) {
     return mSocket->GetConnectionStatus() ==
            SocketConnectionStatus::SOCKET_CONNECTED;
   }
 
   return false;
 }
+
+void
+BluetoothHfpManager::GetAddress(nsAString& aDeviceAddress)
+{
+  return mSocket->GetAddress(aDeviceAddress);
+}
--- a/dom/bluetooth/BluetoothHfpManager.h
+++ b/dom/bluetooth/BluetoothHfpManager.h
@@ -70,16 +70,17 @@ public:
   bool Listen();
 
   /**
    * @param aSend A boolean indicates whether we need to notify headset or not
    */
   void HandleCallStateChanged(uint32_t aCallIndex, uint16_t aCallState,
                               const nsAString& aNumber, bool aSend);
   bool IsConnected();
+  void GetAddress(nsAString& aDeviceAddress);
 
 private:
   class GetVolumeTask;
   class SendRingIndicatorTask;
 
   friend class GetVolumeTask;
   friend class SendRingIndicatorTask;
   friend class BluetoothHfpManagerObserver;
--- a/dom/bluetooth/BluetoothOppManager.cpp
+++ b/dom/bluetooth/BluetoothOppManager.cpp
@@ -1161,16 +1161,22 @@ BluetoothOppManager::SendAbortRequest()
 
 bool
 BluetoothOppManager::IsTransferring()
 {
   return (mConnected && !mSendTransferCompleteFlag);
 }
 
 void
+BluetoothOppManager::GetAddress(nsAString& aDeviceAddress)
+{
+  return mSocket->GetAddress(aDeviceAddress);
+}
+
+void
 BluetoothOppManager::ReplyToConnect()
 {
   if (mConnected) return;
 
   // Section 3.3.1 "Connect", IrOBEX 1.2
   // [opcode:1][length:2][version:1][flags:1][MaxPktSizeWeCanReceive:2]
   // [Headers:var]
   uint8_t req[255];
--- a/dom/bluetooth/BluetoothOppManager.h
+++ b/dom/bluetooth/BluetoothOppManager.h
@@ -68,16 +68,17 @@ public:
 
   void ExtractPacketHeaders(const ObexHeaderSet& aHeader);
   bool ExtractBlobHeaders();
   nsresult HandleShutdown();
 
   // Return true if there is an ongoing file-transfer session, please see
   // Bug 827267 for more information.
   bool IsTransferring();
+  void GetAddress(nsAString& aDeviceAddress);
 
   // Implement interface BluetoothSocketObserver
   void ReceiveSocketData(
     BluetoothSocket* aSocket,
     nsAutoPtr<mozilla::ipc::UnixSocketRawData>& aMessage) MOZ_OVERRIDE;
 
   virtual void OnConnectSuccess(BluetoothSocket* aSocket) MOZ_OVERRIDE;
   virtual void OnConnectError(BluetoothSocket* aSocket) MOZ_OVERRIDE;
--- a/dom/bluetooth/BluetoothService.h
+++ b/dom/bluetooth/BluetoothService.h
@@ -126,17 +126,27 @@ public:
    * specific method.
    *
    * @return NS_OK on success, NS_ERROR_FAILURE otherwise
    */
   virtual nsresult
   GetPairedDevicePropertiesInternal(const nsTArray<nsString>& aDeviceAddresses,
                                     BluetoothReplyRunnable* aRunnable) = 0;
 
-  /** 
+  /**
+   * Returns the properties of connected devices regarding to specific profile,
+   * implemented via a platform specific methood.
+   *
+   * @return NS_OK on success, NS_ERROR_FAILURE otherwise
+   */
+  virtual nsresult
+  GetConnectedDevicePropertiesInternal(uint16_t aProfileId,
+                                       BluetoothReplyRunnable* aRunnable) = 0;
+
+  /**
    * Stop device discovery (platform specific implementation)
    *
    * @return NS_OK if discovery stopped correctly, false otherwise
    */
   virtual nsresult
   StopDiscoveryInternal(BluetoothReplyRunnable* aRunnable) = 0;
 
   /** 
--- a/dom/bluetooth/ipc/BluetoothParent.cpp
+++ b/dom/bluetooth/ipc/BluetoothParent.cpp
@@ -192,18 +192,20 @@ BluetoothParent::RecvPBluetoothRequestCo
     case Request::TStartDiscoveryRequest:
       return actor->DoRequest(aRequest.get_StartDiscoveryRequest());
     case Request::TStopDiscoveryRequest:
       return actor->DoRequest(aRequest.get_StopDiscoveryRequest());
     case Request::TPairRequest:
       return actor->DoRequest(aRequest.get_PairRequest());
     case Request::TUnpairRequest:
       return actor->DoRequest(aRequest.get_UnpairRequest());
-    case Request::TDevicePropertiesRequest:
-      return actor->DoRequest(aRequest.get_DevicePropertiesRequest());
+    case Request::TPairedDevicePropertiesRequest:
+      return actor->DoRequest(aRequest.get_PairedDevicePropertiesRequest());
+    case Request::TConnectedDevicePropertiesRequest:
+      return actor->DoRequest(aRequest.get_ConnectedDevicePropertiesRequest());
     case Request::TSetPinCodeRequest:
       return actor->DoRequest(aRequest.get_SetPinCodeRequest());
     case Request::TSetPasskeyRequest:
       return actor->DoRequest(aRequest.get_SetPasskeyRequest());
     case Request::TConfirmPairingConfirmationRequest:
       return actor->DoRequest(aRequest.get_ConfirmPairingConfirmationRequest());
     case Request::TConfirmAuthorizationRequest:
       return actor->DoRequest(aRequest.get_ConfirmAuthorizationRequest());
@@ -367,25 +369,36 @@ BluetoothRequestParent::DoRequest(const 
     mService->RemoveDeviceInternal(aRequest.address(),
                                    mReplyRunnable.get());
   NS_ENSURE_SUCCESS(rv, false);
 
   return true;
 }
 
 bool
-BluetoothRequestParent::DoRequest(const DevicePropertiesRequest& aRequest)
+BluetoothRequestParent::DoRequest(const PairedDevicePropertiesRequest& aRequest)
 {
   MOZ_ASSERT(mService);
-  MOZ_ASSERT(mRequestType == Request::TDevicePropertiesRequest);
+  MOZ_ASSERT(mRequestType == Request::TPairedDevicePropertiesRequest);
 
   nsresult rv =
     mService->GetPairedDevicePropertiesInternal(aRequest.addresses(),
                                                 mReplyRunnable.get());
   NS_ENSURE_SUCCESS(rv, false);
+  return true;
+}
+bool
+BluetoothRequestParent::DoRequest(const ConnectedDevicePropertiesRequest& aRequest)
+{
+  MOZ_ASSERT(mService);
+  MOZ_ASSERT(mRequestType == Request::TConnectedDevicePropertiesRequest);
+  nsresult rv =
+    mService->GetConnectedDevicePropertiesInternal(aRequest.profileId(),
+                                                mReplyRunnable.get());
+  NS_ENSURE_SUCCESS(rv, false);
 
   return true;
 }
 
 bool
 BluetoothRequestParent::DoRequest(const SetPinCodeRequest& aRequest)
 {
   MOZ_ASSERT(mService);
--- a/dom/bluetooth/ipc/BluetoothParent.h
+++ b/dom/bluetooth/ipc/BluetoothParent.h
@@ -141,17 +141,19 @@ protected:
 
   bool
   DoRequest(const PairRequest& aRequest);
 
   bool
   DoRequest(const UnpairRequest& aRequest);
 
   bool
-  DoRequest(const DevicePropertiesRequest& aRequest);
+  DoRequest(const PairedDevicePropertiesRequest& aRequest);
+  bool
+  DoRequest(const ConnectedDevicePropertiesRequest& aRequest);
 
   bool
   DoRequest(const SetPinCodeRequest& aRequest);
 
   bool
   DoRequest(const SetPasskeyRequest& aRequest);
 
   bool
--- a/dom/bluetooth/ipc/BluetoothServiceChildProcess.cpp
+++ b/dom/bluetooth/ipc/BluetoothServiceChildProcess.cpp
@@ -106,21 +106,29 @@ 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
 BluetoothServiceChildProcess::GetPairedDevicePropertiesInternal(
                                      const nsTArray<nsString>& aDeviceAddresses,
                                      BluetoothReplyRunnable* aRunnable)
 {
-  DevicePropertiesRequest request;
+  PairedDevicePropertiesRequest request;
   request.addresses().AppendElements(aDeviceAddresses);
 
   SendRequest(aRunnable, request);
   return NS_OK;
 }
 
 nsresult
 BluetoothServiceChildProcess::StopDiscoveryInternal(
--- a/dom/bluetooth/ipc/BluetoothServiceChildProcess.h
+++ b/dom/bluetooth/ipc/BluetoothServiceChildProcess.h
@@ -47,16 +47,20 @@ public:
   GetDefaultAdapterPathInternal(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
   virtual nsresult
   GetPairedDevicePropertiesInternal(const nsTArray<nsString>& aDeviceAddresses,
                                     BluetoothReplyRunnable* aRunnable)
                                     MOZ_OVERRIDE;
 
   virtual nsresult
+  GetConnectedDevicePropertiesInternal(uint16_t aProfileId,
+                                       BluetoothReplyRunnable* aRunnable)
+                                       MOZ_OVERRIDE;
+  virtual nsresult
   StopDiscoveryInternal(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
   virtual nsresult
   StartDiscoveryInternal(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
   virtual nsresult
   SetProperty(BluetoothObjectType aType,
               const BluetoothNamedValue& aValue,
--- a/dom/bluetooth/ipc/PBluetooth.ipdl
+++ b/dom/bluetooth/ipc/PBluetooth.ipdl
@@ -83,20 +83,24 @@ struct ConfirmAuthorizationRequest
   nsString path;
 };
 
 struct DenyAuthorizationRequest
 {
   nsString path;
 };
 
-struct DevicePropertiesRequest
+struct PairedDevicePropertiesRequest
 {
   nsString[] addresses;
 };
+struct ConnectedDevicePropertiesRequest
+{
+  uint16_t profileId;
+};
 
 struct ConnectRequest
 {
   nsString address;
   uint16_t profileId;
 };
 
 struct DisconnectRequest
@@ -135,17 +139,18 @@ union Request
   PairRequest;
   UnpairRequest;
   SetPinCodeRequest;
   SetPasskeyRequest;
   ConfirmPairingConfirmationRequest;
   DenyPairingConfirmationRequest;
   ConfirmAuthorizationRequest;
   DenyAuthorizationRequest;
-  DevicePropertiesRequest;
+  ConnectedDevicePropertiesRequest;
+  PairedDevicePropertiesRequest;
   ConnectRequest;
   DisconnectRequest;
   SendFileRequest;
   StopSendingFileRequest;
   ConfirmReceivingFileRequest;
   DenyReceivingFileRequest;
 };
 
--- a/dom/bluetooth/linux/BluetoothDBusService.cpp
+++ b/dom/bluetooth/linux/BluetoothDBusService.cpp
@@ -142,16 +142,17 @@ static const char* sBluetoothDBusSignals
  */
 static nsAutoPtr<RawDBusConnection> gThreadConnection;
 static nsDataHashtable<nsStringHashKey, DBusMessage* > sPairingReqTable;
 static nsDataHashtable<nsStringHashKey, DBusMessage* > sAuthorizeReqTable;
 static int32_t sIsPairing = 0;
 static nsString sAdapterPath;
 
 typedef void (*UnpackFunc)(DBusMessage*, DBusError*, BluetoothValue&, nsAString&);
+typedef bool (*FilterFunc)(const BluetoothValue&);
 
 class RemoveDeviceTask : public nsRunnable {
 public:
   RemoveDeviceTask(const nsACString& aDeviceObjectPath,
                    BluetoothReplyRunnable* aRunnable)
     : mDeviceObjectPath(aDeviceObjectPath)
     , mRunnable(aRunnable)
   {
@@ -186,16 +187,44 @@ public:
     return NS_OK;
   }
 
 private:
   nsCString mDeviceObjectPath;
   nsRefPtr<BluetoothReplyRunnable> mRunnable;
 };
 
+static bool
+GetConnectedDevicesFilter(const BluetoothValue& aValue)
+{
+  // We don't have to filter device here
+  return true;
+}
+
+static bool
+GetPairedDevicesFilter(const BluetoothValue& aValue)
+{
+  // Check property 'Paired' and only paired device will be returned
+  if (aValue.type() != BluetoothValue::TArrayOfBluetoothNamedValue) {
+    NS_WARNING("Not a BluetoothNamedValue array!");
+    return false;
+  }
+
+  const InfallibleTArray<BluetoothNamedValue>& deviceProperties =
+    aValue.get_ArrayOfBluetoothNamedValue();
+  uint32_t length = deviceProperties.Length();
+  for (uint32_t p = 0; p < length; ++p) {
+    if (deviceProperties[p].name().EqualsLiteral("Paired")) {
+      return deviceProperties[p].value().get_bool();
+    }
+  }
+
+  return false;
+}
+
 class SendDiscoveryTask : public nsRunnable {
 public:
   SendDiscoveryTask(const char* aMessageName,
                     BluetoothReplyRunnable* aRunnable)
     : mMessageName(aMessageName)
     , mRunnable(aRunnable)
   {
     MOZ_ASSERT(aMessageName);
@@ -1906,80 +1935,70 @@ public:
 
     return NS_OK;
   }
 
 private:
   BluetoothSignal mSignal;
 };
 
-class BluetoothPairedDevicePropertiesRunnable : public nsRunnable
+class BluetoothArrayOfDevicePropertiesRunnable : public nsRunnable
 {
 public:
-  BluetoothPairedDevicePropertiesRunnable(
+  BluetoothArrayOfDevicePropertiesRunnable(
+                                     const nsTArray<nsString>& aDeviceAddresses,
                                      BluetoothReplyRunnable* aRunnable,
-                                     const nsTArray<nsString>& aDeviceAddresses)
-    : mRunnable(dont_AddRef(aRunnable)),
-      mDeviceAddresses(aDeviceAddresses)
+                                     FilterFunc aFilterFunc)
+    : mDeviceAddresses(aDeviceAddresses)
+    , mRunnable(dont_AddRef(aRunnable))
+    , mFilterFunc(aFilterFunc)
   {
   }
 
   nsresult
   Run()
   {
     MOZ_ASSERT(!NS_IsMainThread());
     DBusError err;
     dbus_error_init(&err);
 
     BluetoothValue values = InfallibleTArray<BluetoothNamedValue>();
+    nsAutoString errorStr;
 
     for (uint32_t i = 0; i < mDeviceAddresses.Length(); i++) {
       BluetoothValue v;
-      if (!GetPropertiesInternal(mDeviceAddresses[i], DBUS_DEVICE_IFACE, v)) {
-        nsAutoString errorStr;
+      nsString objectPath = GetObjectPathFromAddress(sAdapterPath, mDeviceAddresses[i]);
+
+      if (!GetPropertiesInternal(objectPath, DBUS_DEVICE_IFACE, v)) {
         errorStr.AssignLiteral("Getting properties failed!");
-        NS_WARNING(NS_ConvertUTF16toUTF8(errorStr).get());
-        mRunnable->SetReply(new BluetoothReply(BluetoothReplyError(errorStr)));
-        if (NS_FAILED(NS_DispatchToMainThread(mRunnable))) {
-          NS_WARNING("Failed to dispatch to main thread!");
-        }
+        DispatchBluetoothReply(mRunnable, values, errorStr);
         return NS_OK;
       }
+
+      // We have to manually attach the path to the rest of the elements
       v.get_ArrayOfBluetoothNamedValue().AppendElement(
-        BluetoothNamedValue(NS_LITERAL_STRING("Path"), mDeviceAddresses[i])
+        BluetoothNamedValue(NS_LITERAL_STRING("Path"), objectPath)
       );
 
-      InfallibleTArray<BluetoothNamedValue>& deviceProperties =
-        v.get_ArrayOfBluetoothNamedValue();
-      for (uint32_t p = 0;
-           p < v.get_ArrayOfBluetoothNamedValue().Length(); ++p) {
-        BluetoothNamedValue& property = v.get_ArrayOfBluetoothNamedValue()[p];
-        // Only paired devices will be return back to main thread
-        if (property.name().EqualsLiteral("Paired")) {
-          bool paired = property.value();
-          if (paired) {
-            values.get_ArrayOfBluetoothNamedValue().AppendElement(
-              BluetoothNamedValue(mDeviceAddresses[i], deviceProperties)
-            );
-          }
-          break;
-        }
+      if (mFilterFunc(v)) {
+        values.get_ArrayOfBluetoothNamedValue().AppendElement(
+          BluetoothNamedValue(mDeviceAddresses[i],
+                              v.get_ArrayOfBluetoothNamedValue())
+        );
       }
     }
 
-    mRunnable->SetReply(new BluetoothReply(BluetoothReplySuccess(values)));
-    if (NS_FAILED(NS_DispatchToMainThread(mRunnable))) {
-      NS_WARNING("Failed to dispatch to main thread!");
-    }
+    DispatchBluetoothReply(mRunnable, values, errorStr);
     return NS_OK;
   }
 
 private:
+  nsTArray<nsString> mDeviceAddresses;
   nsRefPtr<BluetoothReplyRunnable> mRunnable;
-  nsTArray<nsString> mDeviceAddresses;
+  FilterFunc mFilterFunc;
 };
 
 nsresult
 BluetoothDBusService::GetDevicePropertiesInternal(const BluetoothSignal& aSignal)
 {
   NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!");
 
   if (!mConnection || !gThreadConnection) {
@@ -1992,31 +2011,82 @@ BluetoothDBusService::GetDevicePropertie
     NS_WARNING("Cannot dispatch task!");
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 nsresult
+BluetoothDBusService::GetConnectedDevicePropertiesInternal(uint16_t aProfileId,
+                                              BluetoothReplyRunnable* aRunnable)
+{
+  nsAutoString errorStr;
+  BluetoothValue values = InfallibleTArray<BluetoothNamedValue>();
+  if (!IsReady()) {
+    errorStr.AssignLiteral("Bluetooth service is not ready yet!");
+    DispatchBluetoothReply(aRunnable, values, errorStr);
+    return NS_OK;
+  }
+
+  nsTArray<nsString> deviceAddresses;
+  if (aProfileId == BluetoothServiceClass::HANDSFREE ||
+      aProfileId == BluetoothServiceClass::HEADSET) {
+    BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
+    if (hfp->IsConnected()) {
+      nsString address;
+      hfp->GetAddress(address);
+      deviceAddresses.AppendElement(address);
+    }
+  } else if (aProfileId == BluetoothServiceClass::OBJECT_PUSH) {
+    BluetoothOppManager* opp = BluetoothOppManager::Get();
+    if (opp->IsTransferring()) {
+      nsString address;
+      opp->GetAddress(address);
+      deviceAddresses.AppendElement(address);
+    }
+  } else {
+    errorStr.AssignLiteral("Unknown profile");
+    DispatchBluetoothReply(aRunnable, values, errorStr);
+    return NS_OK;
+  }
+
+  nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
+  nsRefPtr<nsRunnable> func(
+    new BluetoothArrayOfDevicePropertiesRunnable(deviceAddresses,
+                                                 runnable,
+                                                 GetConnectedDevicesFilter));
+
+  if (NS_FAILED(mBluetoothCommandThread->Dispatch(func, NS_DISPATCH_NORMAL))) {
+    NS_WARNING("Cannot dispatch task!");
+    return NS_ERROR_FAILURE;
+  }
+
+  runnable.forget();
+  return NS_OK;
+}
+
+nsresult
 BluetoothDBusService::GetPairedDevicePropertiesInternal(
                                      const nsTArray<nsString>& aDeviceAddresses,
                                      BluetoothReplyRunnable* aRunnable)
 {
   if (!IsReady()) {
     BluetoothValue v;
     nsAutoString errorStr;
     errorStr.AssignLiteral("Bluetooth service is not ready yet!");
     DispatchBluetoothReply(aRunnable, v, errorStr);
     return NS_OK;
   }
 
   nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
   nsRefPtr<nsRunnable> func(
-    new BluetoothPairedDevicePropertiesRunnable(runnable, aDeviceAddresses));
+    new BluetoothArrayOfDevicePropertiesRunnable(aDeviceAddresses,
+                                                 runnable,
+                                                 GetPairedDevicesFilter));
   if (NS_FAILED(mBluetoothCommandThread->Dispatch(func, NS_DISPATCH_NORMAL))) {
     NS_WARNING("Cannot dispatch task!");
     return NS_ERROR_FAILURE;
   }
 
   runnable.forget();
   return NS_OK;
 }
@@ -2482,17 +2552,18 @@ BluetoothDBusService::Connect(const nsAS
     BluetoothOppManager* opp = BluetoothOppManager::Get();
     if (!opp->Connect(GetObjectPathFromAddress(sAdapterPath, aDeviceAddress),
                       aRunnable)) {
       errorStr.AssignLiteral("BluetoothOppManager has been connected/is \
                               connecting!");
       DispatchBluetoothReply(aRunnable, v, errorStr);
     }
   } else {
-    NS_WARNING("Unknown Profile");
+    errorStr.AssignLiteral("Unknown profile");
+    DispatchBluetoothReply(aRunnable, v, errorStr);
   }
 }
 
 void
 BluetoothDBusService::Disconnect(const uint16_t aProfileId,
                                  BluetoothReplyRunnable* aRunnable)
 {
   if (aProfileId == BluetoothServiceClass::HANDSFREE ||
--- a/dom/bluetooth/linux/BluetoothDBusService.h
+++ b/dom/bluetooth/linux/BluetoothDBusService.h
@@ -27,20 +27,25 @@ public:
   bool IsReady();
 
   virtual nsresult StartInternal();
 
   virtual nsresult StopInternal();
 
   virtual bool IsEnabledInternal();
 
-  virtual nsresult GetDefaultAdapterPathInternal(BluetoothReplyRunnable* aRunnable);
+  virtual nsresult GetDefaultAdapterPathInternal(
+                                             BluetoothReplyRunnable* aRunnable);
 
-  virtual nsresult GetPairedDevicePropertiesInternal(const nsTArray<nsString>& aDeviceAddresses,
-                                                     BluetoothReplyRunnable* aRunnable);
+  virtual nsresult GetConnectedDevicePropertiesInternal(uint16_t aProfileId,
+                                             BluetoothReplyRunnable* aRunnable);
+
+  virtual nsresult GetPairedDevicePropertiesInternal(
+                                     const nsTArray<nsString>& aDeviceAddresses,
+                                     BluetoothReplyRunnable* aRunnable);
 
   virtual nsresult StartDiscoveryInternal(BluetoothReplyRunnable* aRunnable);
 
   virtual nsresult StopDiscoveryInternal(BluetoothReplyRunnable* aRunnable);
 
   virtual nsresult
   GetDevicePropertiesInternal(const BluetoothSignal& aSignal);
 
--- a/dom/bluetooth/nsIDOMBluetoothAdapter.idl
+++ b/dom/bluetooth/nsIDOMBluetoothAdapter.idl
@@ -5,17 +5,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsIDOMEventTarget.idl"
 
 interface nsIDOMDOMRequest;
 interface nsIDOMBlob;
 interface nsIDOMBluetoothDevice;
 
-[scriptable, builtinclass, uuid(4321647b-0d45-4231-920b-8d238b6d1700)]
+[scriptable, builtinclass, uuid(88a5638f-f55a-4d67-8437-392d0a9a87c7)]
 interface nsIDOMBluetoothAdapter : nsIDOMEventTarget
 {
   readonly attribute DOMString address;
   [binaryname(AdapterClass)] readonly attribute unsigned long class;
   readonly attribute bool discovering;
 
   [implicit_jscontext]
   readonly attribute jsval devices;
@@ -31,16 +31,17 @@ 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();
+  nsIDOMDOMRequest getConnectedDevices(in unsigned short aProfile);
   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);
 
   /** 
    * Connect/Disconnect to a specific service of a target remote device. 
    * To check the value of service UUIDs, please check "Bluetooth Assigned