Bug 790133 - Final version: Fire devicecreated event with a BluetoothDevice, r=qdot, sr=mrbkap
☠☠ backed out by c97bb39c2ea6 ☠ ☠
authorGina Yeh <gyeh@mozilla.com>
Fri, 14 Sep 2012 16:54:25 +0800
changeset 107093 35c8685ee065bf19cff0b3f049b63048223476e0
parent 107092 9e68f92a96b62613704a095cebf75c77549c50f5
child 107094 c97bb39c2ea6dcfd522b6f366d0d79dd44e0e6d6
push idunknown
push userunknown
push dateunknown
reviewersqdot, mrbkap
bugs790133
milestone18.0a1
Bug 790133 - Final version: Fire devicecreated event with a BluetoothDevice, r=qdot, sr=mrbkap
content/base/src/nsGkAtomList.h
dom/bluetooth/BluetoothAdapter.cpp
dom/bluetooth/BluetoothService.h
dom/bluetooth/linux/BluetoothDBusService.cpp
dom/bluetooth/linux/BluetoothDBusService.h
dom/bluetooth/nsIDOMBluetoothAdapter.idl
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -655,16 +655,17 @@ GK_ATOM(oncompositionupdate, "oncomposit
 GK_ATOM(onconnected, "onconnected")
 GK_ATOM(onconnecting, "onconnecting")
 GK_ATOM(oncontextmenu, "oncontextmenu")
 GK_ATOM(oncopy, "oncopy")
 GK_ATOM(oncut, "oncut")
 GK_ATOM(ondatachange, "ondatachange")
 GK_ATOM(ondblclick, "ondblclick")
 GK_ATOM(ondelivered, "ondelivered")
+GK_ATOM(ondevicecreated, "ondevicecreated")
 GK_ATOM(ondevicedisappeared, "ondevicedisappeared")
 GK_ATOM(ondevicefound, "ondevicefound")
 GK_ATOM(ondialing, "ondialing")
 GK_ATOM(ondisabled, "ondisabled")
 GK_ATOM(ondischargingtimechange, "ondischargingtimechange")
 GK_ATOM(ondisconnected, "ondisconnected")
 GK_ATOM(ondisconnecting, "ondisconnecting")
 GK_ATOM(ondownloading, "ondownloading")
--- a/dom/bluetooth/BluetoothAdapter.cpp
+++ b/dom/bluetooth/BluetoothAdapter.cpp
@@ -286,16 +286,32 @@ BluetoothAdapter::Notify(const Bluetooth
     NS_NewDOMBluetoothDeviceAddressEvent(getter_AddRefs(event), nullptr, nullptr);
 
     nsCOMPtr<nsIDOMBluetoothDeviceAddressEvent> e = do_QueryInterface(event);
     e->InitBluetoothDeviceAddressEvent(NS_LITERAL_STRING("devicedisappeared"),
                                        false, false, deviceAddress);
     e->SetTrusted(true);
     bool dummy;
     DispatchEvent(event, &dummy);
+  } else if (aData.name().EqualsLiteral("DeviceCreated")) {
+    NS_ASSERTION(aData.value().type() == BluetoothValue::TArrayOfBluetoothNamedValue,
+                 "DeviceCreated: Invalid value type");
+
+    nsRefPtr<BluetoothDevice> device = BluetoothDevice::Create(GetOwner(),
+                                                               GetPath(),
+                                                               aData.value());
+    nsCOMPtr<nsIDOMEvent> event;
+    NS_NewDOMBluetoothDeviceEvent(getter_AddRefs(event), nullptr, nullptr);
+
+    nsCOMPtr<nsIDOMBluetoothDeviceEvent> e = do_QueryInterface(event);
+    e->InitBluetoothDeviceEvent(NS_LITERAL_STRING("devicecreated"),
+                                false, false, device);
+    e->SetTrusted(true);
+    bool dummy;
+    DispatchEvent(event, &dummy);
   } else if (aData.name().EqualsLiteral("PropertyChanged")) {
     // Get BluetoothNamedValue, make sure array length is 1
     arr = aData.value().get_ArrayOfBluetoothNamedValue();
 
     NS_ASSERTION(arr.Length() == 1, "Got more than one property in a change message!");
     NS_ASSERTION(arr[0].value().type() == BluetoothValue::TArrayOfBluetoothNamedValue,
                  "PropertyChanged: Invalid value type");
 
@@ -623,13 +639,14 @@ BluetoothAdapter::SetAuthorization(const
   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, devicecreated)
 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/BluetoothService.h
+++ b/dom/bluetooth/BluetoothService.h
@@ -154,28 +154,26 @@ public:
    *
    * @return NS_OK if discovery stopped correctly, false otherwise
    */
   virtual nsresult
   StartDiscoveryInternal(const nsAString& aAdapterPath,
                          BluetoothReplyRunnable* aRunnable) = 0;
 
   /** 
-   * Fetches the propertes for the specified object
+   * Fetches the propertes for the specified device
    *
-   * @param aType Type of the object (see BluetoothObjectType in BluetoothCommon.h)
-   * @param aPath Path of the object
-   * @param aRunnable Runnable to return to after receiving callback
+   * @param aDevicePath Path of the object
+   * @param aSignalPath Path to distrubute signal after receiving properties
    *
    * @return NS_OK on function run, NS_ERROR_FAILURE otherwise
    */
   virtual nsresult
-  GetProperties(BluetoothObjectType aType,
-                const nsAString& aPath,
-                BluetoothReplyRunnable* aRunnable) = 0;
+  GetDevicePropertiesInternal(const nsAString& aDevicePath,
+                              const nsAString& aSignalPath) = 0;
 
   /** 
    * Set a property for the specified object
    *
    * @param aPath Path to the object
    * @param aPropName Name of the property
    * @param aValue Boolean value
    * @param aRunnable Runnable to run on async reply
--- a/dom/bluetooth/linux/BluetoothDBusService.cpp
+++ b/dom/bluetooth/linux/BluetoothDBusService.cpp
@@ -936,16 +936,28 @@ 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);
     }
+
+    // Get device properties and then send to BluetoothAdapter
+    BluetoothService* bs = BluetoothService::Get();
+    if (!bs) {
+      NS_WARNING("BluetoothService not available!");
+    }
+
+    if (NS_FAILED(bs->GetDevicePropertiesInternal(v, signalPath))) {
+      NS_WARNING("get properties failed");
+    }
+
+    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!");
     } else {
@@ -1247,16 +1259,76 @@ BluetoothDBusService::StartDiscoveryInte
 {
   if (!mConnection) {
     NS_WARNING("Bluetooth service not started yet, cannot start discovery!");
     return NS_ERROR_FAILURE;
   }
   return SendDiscoveryMessage(aAdapterPath, "StartDiscovery", aRunnable);
 }
 
+class BluetoothDevicePropertiesRunnable : public nsRunnable
+{
+public:
+  BluetoothDevicePropertiesRunnable(const nsAString& aDevicePath,
+                                    const nsAString& aSignalPath) :
+    mDevicePath(aDevicePath),
+    mSignalPath(aSignalPath)
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+  }
+
+  ~BluetoothDevicePropertiesRunnable()
+  {
+  }
+
+  NS_IMETHOD Run()
+  {
+    MOZ_ASSERT(!NS_IsMainThread());
+
+    DBusError err;
+    dbus_error_init(&err);
+
+    BluetoothValue v = InfallibleTArray<BluetoothNamedValue>();
+    nsString replyError;
+
+    DBusMessage* msg = dbus_func_args_timeout(gThreadConnection->GetConnection(),
+                                              1000,
+                                              &err,
+                                              NS_ConvertUTF16toUTF8(mDevicePath).get(),
+                                              DBUS_DEVICE_IFACE,
+                                              "GetProperties",
+                                              DBUS_TYPE_INVALID);
+    UnpackDevicePropertiesMessage(msg, &err, v, replyError);
+
+    if (!replyError.IsEmpty()) {
+      NS_WARNING("Failed to get device properties");
+      return NS_ERROR_FAILURE;
+    }
+    if (msg) {
+      dbus_message_unref(msg);
+    }
+
+    BluetoothSignal signal(NS_LITERAL_STRING("DeviceCreated"),
+                           mSignalPath, v);
+
+    nsRefPtr<DistributeBluetoothSignalTask> t = new DistributeBluetoothSignalTask(signal);
+
+    if (NS_FAILED(NS_DispatchToMainThread(t))) {
+       NS_WARNING("Failed to dispatch to main thread!");
+       return NS_ERROR_FAILURE;
+    }
+
+    return NS_OK;
+  }
+
+private:
+  nsString mDevicePath;
+  nsString mSignalPath;
+};
+
 class BluetoothPairedDevicePropertiesRunnable : public nsRunnable
 {
 public:
   BluetoothPairedDevicePropertiesRunnable(BluetoothReplyRunnable* aRunnable,
                                           const nsTArray<nsString>& aDeviceAddresses)
     : mRunnable(dont_AddRef(aRunnable)),
       mDeviceAddresses(aDeviceAddresses)
   {
@@ -1318,42 +1390,32 @@ public:
   }
 
 private:
   nsRefPtr<BluetoothReplyRunnable> mRunnable;
   nsTArray<nsString> mDeviceAddresses;
 };
 
 nsresult
-BluetoothDBusService::GetProperties(BluetoothObjectType aType,
-                                    const nsAString& aPath,
-                                    BluetoothReplyRunnable* aRunnable)
+BluetoothDBusService::GetDevicePropertiesInternal(const nsAString& aDevicePath,
+                                                  const nsAString& aSignalPath)
 {
   NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!");
 
-  MOZ_ASSERT(aType < ArrayLength(sBluetoothDBusIfaces));
-  MOZ_ASSERT(aType < ArrayLength(sBluetoothDBusPropCallbacks));
-  
-  const char* interface = sBluetoothDBusIfaces[aType];
-  DBusCallback callback = sBluetoothDBusPropCallbacks[aType];
-  
-  nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
-
-  if (!dbus_func_args_async(mConnection,
-                            1000,
-                            callback,
-                            (void*)aRunnable,
-                            NS_ConvertUTF16toUTF8(aPath).get(),
-                            interface,
-                            "GetProperties",
-                            DBUS_TYPE_INVALID)) {
-    NS_WARNING("Could not start async function!");
+  if (!mConnection || !gThreadConnection) {
+    NS_ERROR("Bluetooth service not started yet!");
     return NS_ERROR_FAILURE;
   }
-  runnable.forget();
+
+  nsRefPtr<nsRunnable> func(new BluetoothDevicePropertiesRunnable(aDevicePath, aSignalPath));
+  if (NS_FAILED(mBluetoothCommandThread->Dispatch(func, NS_DISPATCH_NORMAL))) {
+    NS_WARNING("Cannot dispatch task!");
+    return NS_ERROR_FAILURE;
+  }
+
   return NS_OK;
 }
 
 nsresult
 BluetoothDBusService::GetPairedDevicePropertiesInternal(const nsTArray<nsString>& aDeviceAddresses,
                                                         BluetoothReplyRunnable* aRunnable)
 {
   if (!mConnection || !gThreadConnection) {
--- a/dom/bluetooth/linux/BluetoothDBusService.h
+++ b/dom/bluetooth/linux/BluetoothDBusService.h
@@ -28,25 +28,27 @@ public:
   virtual nsresult StopInternal();
   virtual nsresult GetDefaultAdapterPathInternal(BluetoothReplyRunnable* aRunnable);
   virtual nsresult GetPairedDevicePropertiesInternal(const nsTArray<nsString>& aDeviceAddresses,
                                                      BluetoothReplyRunnable* aRunnable);
   virtual nsresult StartDiscoveryInternal(const nsAString& aAdapterPath,
                                           BluetoothReplyRunnable* aRunnable);
   virtual nsresult StopDiscoveryInternal(const nsAString& aAdapterPath,
                                          BluetoothReplyRunnable* aRunnable);
+
   virtual nsresult
-  GetProperties(BluetoothObjectType aType,
-                const nsAString& aPath,
-                BluetoothReplyRunnable* aRunnable);
+  GetDevicePropertiesInternal(const nsAString& aDevicePath,
+                              const nsAString& aSignalPath);
+
   virtual nsresult
   SetProperty(BluetoothObjectType aType,
               const nsAString& aPath,
               const BluetoothNamedValue& aValue,
               BluetoothReplyRunnable* aRunnable);
+
   virtual bool
   GetDevicePath(const nsAString& aAdapterPath,
                 const nsAString& aDeviceAddress,
                 nsAString& aDevicePath);
 
   virtual bool
   AddReservedServicesInternal(const nsAString& aAdapterPath,
                               const nsTArray<uint32_t>& aServices,
--- 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(4ea7d312-f37c-4777-8114-fc7312890199)]
+[scriptable, builtinclass, uuid(df1465c6-00b7-49ab-bd20-1b63721d118f)]
 interface nsIDOMBluetoothAdapter : nsIDOMEventTarget
 {
   readonly attribute DOMString address;
   [binaryname(AdapterClass)] readonly attribute unsigned long class;
   readonly attribute bool enabled;
   readonly attribute bool discovering;
 
   [implicit_jscontext]
@@ -40,16 +40,18 @@ interface nsIDOMBluetoothAdapter : nsIDO
   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.
   [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
   [implicit_jscontext] attribute jsval onpropertychanged;
   // Pairing related events
   [implicit_jscontext] attribute jsval onrequestconfirmation;
   [implicit_jscontext] attribute jsval onrequestpincode;
   [implicit_jscontext] attribute jsval onrequestpasskey;
   [implicit_jscontext] attribute jsval onauthorize;
   [implicit_jscontext] attribute jsval oncancel;