Bug 730992 - Patch 3: Hooking things up to BluetoothAdapter, r=qdot, sr=mrbkap
authorEric Chou <echou@mozilla.com>
Fri, 17 Aug 2012 18:35:59 +0800
changeset 102642 676954e4d2a7f4e99c34d218a23f515e0b3d96b7
parent 102641 6fa3009c086f8631755fe506c180f228b37393e5
child 102643 e1ebc55a599e4fda72aaab6c50de13c26a054d80
push idunknown
push userunknown
push dateunknown
reviewersqdot, mrbkap
bugs730992
milestone17.0a1
Bug 730992 - Patch 3: Hooking things up to BluetoothAdapter, r=qdot, sr=mrbkap --- dom/bluetooth/BluetoothAdapter.cpp | 204 +++++++++++++++++++++++++++++- dom/bluetooth/BluetoothAdapter.h | 8 ++ dom/bluetooth/nsIDOMBluetoothAdapter.idl | 16 +++- 3 files changed, 224 insertions(+), 4 deletions(-)
dom/bluetooth/BluetoothAdapter.cpp
dom/bluetooth/BluetoothAdapter.h
dom/bluetooth/nsIDOMBluetoothAdapter.idl
--- a/dom/bluetooth/BluetoothAdapter.cpp
+++ b/dom/bluetooth/BluetoothAdapter.cpp
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "base/basictypes.h"
 #include "BluetoothAdapter.h"
 #include "BluetoothDevice.h"
 #include "BluetoothDeviceEvent.h"
 #include "BluetoothPropertyEvent.h"
+#include "BluetoothPairingEvent.h"
 #include "BluetoothService.h"
 #include "BluetoothTypes.h"
 #include "BluetoothReplyRunnable.h"
 #include "BluetoothUtils.h"
 
 #include "nsDOMClassInfo.h"
 #include "nsDOMEvent.h"
 #include "nsThreadUtils.h"
@@ -38,25 +39,35 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INH
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mJsDeviceAddresses)
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothAdapter, 
                                                   nsDOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
   NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(devicefound)
   NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(devicedisappeared)
-  NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(propertychanged)  
+  NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(propertychanged)
+  NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(requestconfirmation)
+  NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(requestpincode)
+  NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(requestpasskey)
+  NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(authorize)
+  NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(cancel)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothAdapter, 
                                                 nsDOMEventTargetHelper)
   tmp->Unroot();
   NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(devicefound)
   NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(devicedisappeared)
   NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(propertychanged)  
+  NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(requestconfirmation)
+  NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(requestpincode)
+  NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(requestpasskey)
+  NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(authorize)
+  NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(cancel)
 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)
@@ -122,16 +133,18 @@ public:
   {
     BluetoothReplyRunnable::ReleaseMembers();
     mAdapterPtr = nullptr;
   }
 private:
   nsRefPtr<BluetoothAdapter> mAdapterPtr;
 };
 
+static int kCreatePairedDeviceTimeout = 50000; // unit: msec
+
 BluetoothAdapter::BluetoothAdapter(nsPIDOMWindow* aOwner, const BluetoothValue& aValue)
     : BluetoothPropertyContainer(BluetoothObjectType::TYPE_ADAPTER)
     , mEnabled(false)
     , mDiscoverable(false)
     , mDiscovering(false)
     , mPairable(false)
     , mPowered(false)
     , mJsUuids(nullptr)
@@ -257,38 +270,102 @@ BluetoothAdapter::Create(nsPIDOMWindow* 
     return nullptr;
   }
 
   nsRefPtr<BluetoothAdapter> adapter = new BluetoothAdapter(aOwner, aValue);
   if (NS_FAILED(bs->RegisterBluetoothSignalHandler(adapter->GetPath(), adapter))) {
     NS_WARNING("Failed to register object with observer!");
     return nullptr;
   }
+
+  if (NS_FAILED(bs->RegisterBluetoothSignalHandler(NS_LITERAL_STRING(LOCAL_AGENT_PATH), adapter))) {
+    NS_WARNING("Failed to register local agent object with observer!");
+    return nullptr;
+  }
+
+  if (NS_FAILED(bs->RegisterBluetoothSignalHandler(NS_LITERAL_STRING(REMOTE_AGENT_PATH), adapter))) {
+    NS_WARNING("Failed to register remote agent object with observer!");
+    return nullptr;
+  }
+
   return adapter.forget();
 }
 
 void
 BluetoothAdapter::Notify(const BluetoothSignal& aData)
 {
+  InfallibleTArray<BluetoothNamedValue> arr;
+
   if (aData.name().EqualsLiteral("DeviceFound")) {
     nsRefPtr<BluetoothDevice> d = BluetoothDevice::Create(GetOwner(), mPath, aData.value());
     nsRefPtr<BluetoothDeviceEvent> e = BluetoothDeviceEvent::Create(d);
     e->Dispatch(ToIDOMEventTarget(), NS_LITERAL_STRING("devicefound"));
   } else if (aData.name().EqualsLiteral("PropertyChanged")) {
     // Get BluetoothNamedValue, make sure array length is 1
-    InfallibleTArray<BluetoothNamedValue> arr = aData.value().get_ArrayOfBluetoothNamedValue();
-    if (arr.Length() != 1) {
+    arr = aData.value().get_ArrayOfBluetoothNamedValue();
+    if(arr.Length() != 1) {
       // This really should not happen
       NS_ERROR("Got more than one property in a change message!");
       return;
     }
     BluetoothNamedValue v = arr[0];
     SetPropertyByValue(v);
     nsRefPtr<BluetoothPropertyEvent> e = BluetoothPropertyEvent::Create(v.name());
     e->Dispatch(ToIDOMEventTarget(), NS_LITERAL_STRING("propertychanged"));
+  } else if (aData.name().EqualsLiteral("RequestConfirmation")) {
+    arr = aData.value().get_ArrayOfBluetoothNamedValue();
+    if(arr.Length() != 2) {
+      NS_ERROR("RequestConfirmation: Length of parameters is wrong");
+      return;
+    }
+
+    nsString deviceAddress = arr[0].value().get_nsString();
+    uint32_t passkey = arr[1].value().get_uint32_t();
+
+    nsRefPtr<BluetoothPairingEvent> e = BluetoothPairingEvent::Create(deviceAddress, passkey);
+    e->Dispatch(ToIDOMEventTarget(), NS_LITERAL_STRING("requestconfirmation"));
+  } else if (aData.name().EqualsLiteral("RequestPinCode")) {
+    arr = aData.value().get_ArrayOfBluetoothNamedValue();
+    if(arr.Length() != 1) {
+      NS_ERROR("RequestPinCode: Length of parameters is wrong");
+      return;
+    }
+
+    nsString deviceAddress = arr[0].value().get_nsString();
+
+    nsRefPtr<BluetoothPairingEvent> e = BluetoothPairingEvent::Create(deviceAddress, 0);
+    e->Dispatch(ToIDOMEventTarget(), NS_LITERAL_STRING("requestpincode"));
+  } else if (aData.name().EqualsLiteral("RequestPasskey")) {
+    arr = aData.value().get_ArrayOfBluetoothNamedValue();
+    if(arr.Length() != 1) {
+      NS_ERROR("RequestPasskey: Length of parameters is wrong");
+      return;
+    }
+
+    nsString deviceAddress = arr[0].value().get_nsString();
+
+    nsRefPtr<BluetoothPairingEvent> e = BluetoothPairingEvent::Create(deviceAddress, 0);
+    e->Dispatch(ToIDOMEventTarget(), NS_LITERAL_STRING("requestpasskey"));
+  } else if (aData.name().EqualsLiteral("Authorize")) {
+    arr = aData.value().get_ArrayOfBluetoothNamedValue();
+    if(arr.Length() != 2) {
+      NS_ERROR("Authorize: Length of parameters is wrong");
+      return;
+    }
+
+    nsString deviceAddress = arr[0].value().get_nsString();
+    nsString serviceUuid = arr[1].value().get_nsString();
+
+    nsRefPtr<BluetoothPairingEvent> e = BluetoothPairingEvent::Create(deviceAddress, serviceUuid);
+    e->Dispatch(ToIDOMEventTarget(), NS_LITERAL_STRING("authorize"));
+  } else if (aData.name().EqualsLiteral("Cancel")) {
+    // Just send a null nsString, won't be used
+    nsString deviceObjectPath = EmptyString();
+    nsRefPtr<BluetoothPairingEvent> e = BluetoothPairingEvent::Create(deviceObjectPath, 0);
+    e->Dispatch(ToIDOMEventTarget(), NS_LITERAL_STRING("cancel"));
   } else {
 #ifdef DEBUG
     nsCString warningMsg;
     warningMsg.AssignLiteral("Not handling manager signal: ");
     warningMsg.Append(NS_ConvertUTF16toUTF8(aData.name()));
     NS_WARNING(warningMsg.get());
 #endif
   }
@@ -485,11 +562,132 @@ BluetoothAdapter::GetPairedDevices(nsIDO
   nsRefPtr<BluetoothReplyRunnable> results = new GetPairedDevicesTask(this, request);
   if (NS_FAILED(bs->GetPairedDevicePropertiesInternal(mDeviceAddresses, results))) {
     return NS_ERROR_FAILURE;
   }
   request.forget(aRequest);
   return NS_OK;
 }
 
+nsresult
+BluetoothAdapter::PairUnpair(bool aPair,
+                             nsIDOMBluetoothDevice* aDevice,
+                             nsIDOMDOMRequest** aRequest)
+{
+  BluetoothService* bs = BluetoothService::Get();
+  if (!bs) {
+    NS_WARNING("BluetoothService not available!");
+    return NS_ERROR_FAILURE;
+  }
+
+  nsCOMPtr<nsIDOMRequestService> rs = do_GetService("@mozilla.org/dom/dom-request-service;1");
+  if (!rs) {
+    NS_WARNING("No DOMRequest Service!");
+    return 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);
+
+  nsString addr;
+  aDevice->GetAddress(addr);
+
+  if (aPair) {
+    rv = bs->CreatePairedDeviceInternal(mPath,
+                                        addr,
+                                        kCreatePairedDeviceTimeout,
+                                        results);
+  } else {
+    rv = bs->RemoveDeviceInternal(mPath, addr, results);
+  }
+
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Pair/Unpair failed!");
+    return NS_ERROR_FAILURE;
+  }
+
+  req.forget(aRequest);
+
+  return NS_OK;
+}
+
+nsresult
+BluetoothAdapter::Pair(nsIDOMBluetoothDevice* aDevice, nsIDOMDOMRequest** aRequest)
+{
+  return PairUnpair(true, aDevice, aRequest);
+}
+
+nsresult
+BluetoothAdapter::Unpair(nsIDOMBluetoothDevice* aDevice, nsIDOMDOMRequest** aRequest)
+{
+  return PairUnpair(false, aDevice, aRequest);
+}
+
+nsresult
+BluetoothAdapter::SetPinCode(const nsAString& aDeviceAddress, const nsAString& aPinCode)
+{
+  BluetoothService* bs = BluetoothService::Get();
+  if (!bs) {
+    NS_WARNING("BluetoothService not available!");
+    return NS_ERROR_FAILURE;
+  }
+
+  bool result = bs->SetPinCodeInternal(aDeviceAddress, aPinCode);
+
+  return result ? NS_OK : NS_ERROR_FAILURE;
+}
+
+nsresult
+BluetoothAdapter::SetPasskey(const nsAString& aDeviceAddress, PRUint32 aPasskey)
+{
+  BluetoothService* bs = BluetoothService::Get();
+  if (!bs) {
+    NS_WARNING("BluetoothService not available!");
+    return NS_ERROR_FAILURE;
+  }
+
+  bool result = bs->SetPasskeyInternal(aDeviceAddress, aPasskey);
+
+  return result ? NS_OK : NS_ERROR_FAILURE;
+}
+
+nsresult
+BluetoothAdapter::SetPairingConfirmation(const nsAString& aDeviceAddress, bool aConfirmation)
+{
+  BluetoothService* bs = BluetoothService::Get();
+  if (!bs) {
+    NS_WARNING("BluetoothService not available!");
+    return NS_ERROR_FAILURE;
+  }
+
+  bool result = bs->SetPairingConfirmationInternal(aDeviceAddress, aConfirmation);
+
+  return result ? NS_OK : NS_ERROR_FAILURE;
+}
+
+nsresult
+BluetoothAdapter::SetAuthorization(const nsAString& aDeviceAddress, bool aAllow)
+{
+  BluetoothService* bs = BluetoothService::Get();
+  if (!bs) {
+    NS_WARNING("BluetoothService not available!");
+    return NS_ERROR_FAILURE;
+  }
+
+  bool result = bs->SetAuthorizationInternal(aDeviceAddress, aAllow);
+
+  return result ? NS_OK : NS_ERROR_FAILURE;
+}
+
 NS_IMPL_EVENT_HANDLER(BluetoothAdapter, propertychanged)
 NS_IMPL_EVENT_HANDLER(BluetoothAdapter, devicefound)
 NS_IMPL_EVENT_HANDLER(BluetoothAdapter, devicedisappeared)
+NS_IMPL_EVENT_HANDLER(BluetoothAdapter, requestconfirmation)
+NS_IMPL_EVENT_HANDLER(BluetoothAdapter, requestpincode)
+NS_IMPL_EVENT_HANDLER(BluetoothAdapter, requestpasskey)
+NS_IMPL_EVENT_HANDLER(BluetoothAdapter, authorize)
+NS_IMPL_EVENT_HANDLER(BluetoothAdapter, cancel)
--- a/dom/bluetooth/BluetoothAdapter.h
+++ b/dom/bluetooth/BluetoothAdapter.h
@@ -58,16 +58,19 @@ public:
   virtual void SetPropertyByValue(const BluetoothNamedValue& aValue);  
 private:
   
   BluetoothAdapter(nsPIDOMWindow* aOwner, const BluetoothValue& aValue);
   ~BluetoothAdapter();
 
   void Root();
   nsresult StartStopDiscovery(bool aStart, nsIDOMDOMRequest** aRequest);
+  nsresult PairUnpair(bool aPair,
+                      nsIDOMBluetoothDevice* aDevice,
+                      nsIDOMDOMRequest** aRequest);
   
   nsString mAddress;
   nsString mName;
   bool mEnabled;
   bool mDiscoverable;
   bool mDiscovering;
   bool mPairable;
   bool mPowered;
@@ -78,13 +81,18 @@ private:
   nsTArray<nsString> mUuids;
   JSObject* mJsUuids;
   JSObject* mJsDeviceAddresses;
   bool mIsRooted;
   
   NS_DECL_EVENT_HANDLER(propertychanged)
   NS_DECL_EVENT_HANDLER(devicefound)
   NS_DECL_EVENT_HANDLER(devicedisappeared)
+  NS_DECL_EVENT_HANDLER(requestconfirmation)
+  NS_DECL_EVENT_HANDLER(requestpincode)
+  NS_DECL_EVENT_HANDLER(requestpasskey)
+  NS_DECL_EVENT_HANDLER(authorize)
+  NS_DECL_EVENT_HANDLER(cancel)
 };
 
 END_BLUETOOTH_NAMESPACE
 
 #endif
--- a/dom/bluetooth/nsIDOMBluetoothAdapter.idl
+++ b/dom/bluetooth/nsIDOMBluetoothAdapter.idl
@@ -4,17 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsIDOMEventTarget.idl"
 
 interface nsIDOMDOMRequest;
 interface nsIDOMBluetoothDevice;
 
-[scriptable, builtinclass, uuid(86e9fe78-ce64-476e-a357-333f7d3c8980)]
+[scriptable, builtinclass, uuid(db6b4dd6-64f1-415d-ac51-ae0fa0fe05ed)]
 interface nsIDOMBluetoothAdapter : nsIDOMEventTarget
 {
   readonly attribute DOMString address;
   [binaryname(AdapterClass)] readonly attribute unsigned long class;
   readonly attribute bool enabled;
   readonly attribute bool discovering;
 
   [implicit_jscontext]
@@ -28,16 +28,29 @@ interface nsIDOMBluetoothAdapter : nsIDO
   // Unit: sec
   readonly attribute unsigned long discoverableTimeout;
 
   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);
+
   // Fired when discoverying and any device is discovered.
   attribute nsIDOMEventListener ondevicefound;
   // Fired when any device is out of discoverable range.
   attribute nsIDOMEventListener ondevicedisappeared;
   // Fired when a property of the adapter is changed
   attribute nsIDOMEventListener onpropertychanged;
+  // Pairing related events
+  attribute nsIDOMEventListener onrequestconfirmation;
+  attribute nsIDOMEventListener onrequestpincode;
+  attribute nsIDOMEventListener onrequestpasskey;
+  attribute nsIDOMEventListener onauthorize;
+  attribute nsIDOMEventListener oncancel;
 };