Bug 731361 - Change bluetooth firmware loading to use a DOMRequest based API. r=bent
authorEric Chou <echou@mozilla.com>
Tue, 27 Mar 2012 19:17:35 -0400
changeset 93793 722d3bd080c2241b3bcc1ce486e39758ebfca320
parent 93792 389eee1cce65ea5c258243a67ad061b325072718
child 93794 110452fddc2aae8defb518b31b77f8ea6ccfc62c
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbent
bugs731361
milestone14.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 731361 - Change bluetooth firmware loading to use a DOMRequest based API. r=bent
dom/base/Navigator.cpp
dom/bluetooth/BluetoothAdapter.cpp
dom/bluetooth/BluetoothAdapter.h
dom/bluetooth/nsIDOMBluetoothAdapter.idl
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -1148,17 +1148,17 @@ NS_IMETHODIMP
 Navigator::GetMozBluetooth(nsIDOMBluetoothAdapter** aBluetooth)
 {
   nsCOMPtr<nsIDOMBluetoothAdapter> bluetooth = mBluetooth;
 
   if (!bluetooth) {
     nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
     NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
 
-    mBluetooth = new bluetooth::BluetoothAdapter();
+    mBluetooth = new bluetooth::BluetoothAdapter(window);
 
     bluetooth = mBluetooth;
   }
 
   bluetooth.forget(aBluetooth);
   return NS_OK;
 }
 #endif //MOZ_B2G_BT
--- a/dom/bluetooth/BluetoothAdapter.cpp
+++ b/dom/bluetooth/BluetoothAdapter.cpp
@@ -1,21 +1,41 @@
 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
 /* vim: set ts=2 et sw=2 tw=40: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * 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 "BluetoothAdapter.h"
+
 #include "nsDOMClassInfo.h"
 #include "nsDOMEvent.h"
 #include "nsThreadUtils.h"
 #include "nsXPCOMCIDInternal.h"
 #include "mozilla/LazyIdleThread.h"
+#include "mozilla/Util.h"
 #include <dlfcn.h>
-#include "BluetoothAdapter.h"
+
+static void
+FireEnabled(bool aResult, nsIDOMDOMRequest* aDomRequest)
+{
+  nsCOMPtr<nsIDOMRequestService> rs = do_GetService("@mozilla.org/dom/dom-request-service;1");
+
+  if (!rs) {
+    NS_WARNING("No DOMRequest Service!");
+    return;
+  }
+
+  mozilla::DebugOnly<nsresult> rv = aResult ?     
+                                    rs->FireSuccess(aDomRequest, JSVAL_VOID) :
+                                    rs->FireError(aDomRequest, 
+                                                  NS_LITERAL_STRING("Bluetooth firmware loading failed"));
+
+  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Bluetooth firmware loading failed");
+}
 
 USING_BLUETOOTH_NAMESPACE
 
 static struct BluedroidFunctions {
   bool initialized;
   bool tried_initialization;
 
   BluedroidFunctions() :
@@ -62,178 +82,169 @@ static bool EnsureBluetoothInit() {
   }
   sBluedroidFunctions.initialized = true;
   return true;
 }
 
 class ToggleBtResultTask : public nsRunnable
 {
   public:
-    ToggleBtResultTask(nsRefPtr<BluetoothAdapter>& adapterPtr, bool result)
-      : mResult(result)
+    ToggleBtResultTask(nsRefPtr<BluetoothAdapter>& adapterPtr, 
+                       nsCOMPtr<nsIDOMDOMRequest>& req,
+                       bool enabled,
+                       bool result)
+      : mResult(result),
+        mEnabled(enabled)
     {
       MOZ_ASSERT(!NS_IsMainThread());
 
+      mDOMRequest.swap(req);
       mAdapterPtr.swap(adapterPtr);
     }
 
     NS_IMETHOD Run() 
     {
       MOZ_ASSERT(NS_IsMainThread());
 
-      if (!mResult) {
-        //TODO:Bug-731361
-        NS_WARNING("BT firmware loading fails.\n");
+      // Update bt power status to BluetoothAdapter only if loading bluetooth 
+      // firmware succeeds.
+      if (mResult) {
+        mAdapterPtr->SetEnabledInternal(mEnabled);
       }
- 
+
+      FireEnabled(mResult, mDOMRequest);
+
       //mAdapterPtr must be null before returning to prevent the background 
       //thread from racing to release it during the destruction of this runnable.
-      mAdapterPtr->FirePowered();
       mAdapterPtr = nsnull;
+      mDOMRequest = nsnull;
 
       return NS_OK;
     }
 
   private:
     nsRefPtr<BluetoothAdapter> mAdapterPtr;
+    nsCOMPtr<nsIDOMDOMRequest> mDOMRequest;
+    bool mEnabled;
     bool mResult;
 };
 
 class ToggleBtTask : public nsRunnable
 {
   public:
-    ToggleBtTask(bool onOff, BluetoothAdapter* adapterPtr)
-      : mOnOff(onOff),
+    ToggleBtTask(bool enabled, nsIDOMDOMRequest* req, BluetoothAdapter* adapterPtr)
+      : mEnabled(enabled),
+        mDOMRequest(req),
         mAdapterPtr(adapterPtr) 
     {
       MOZ_ASSERT(NS_IsMainThread());
     }
 
     NS_IMETHOD Run() 
     {
       MOZ_ASSERT(!NS_IsMainThread());
 
+      bool result;
+
+#ifdef MOZ_WIDGET_GONK
+      // Platform specific check for gonk until object is divided in
+      // different implementations per platform. Linux doesn't require
+      // bluetooth firmware loading, but code should work otherwise.
       if(!EnsureBluetoothInit()) {
         NS_ERROR("Failed to load bluedroid library.\n");
         return NS_ERROR_FAILURE;
       }
 
-      bool result;
-
-      //Toggle BT here
+      // return 1 if it's enabled, 0 if it's disabled, and -1 on error
+      int isEnabled = sBluedroidFunctions.bt_is_enabled();
 
-      if (mOnOff) {
-        result = sBluedroidFunctions.bt_enable();
+      if ((isEnabled == 1 && mEnabled) || (isEnabled == 0 && !mEnabled)) {
+        result = true;
+      } else if (isEnabled < 0) {
+        result = false;
+      } else if (mEnabled) {
+        result = (sBluedroidFunctions.bt_enable() == 0) ? true : false;
       } else {
-        result = sBluedroidFunctions.bt_disable();
+        result = (sBluedroidFunctions.bt_disable() == 0) ? true : false;
       }
+#else
+      result = true;
+      NS_WARNING("No bluetooth support in this build configuration, faking a success event instead");
+#endif
 
       // Create a result thread and pass it to Main Thread, 
-      nsCOMPtr<nsIRunnable> resultRunnable = new ToggleBtResultTask(mAdapterPtr, result);
+      nsCOMPtr<nsIRunnable> resultRunnable = new ToggleBtResultTask(mAdapterPtr, mDOMRequest, mEnabled, result);
 
       if (NS_FAILED(NS_DispatchToMainThread(resultRunnable))) {
         NS_WARNING("Failed to dispatch to main thread!");
       }
 
       return NS_OK;
     }
 
   private:
-    bool mOnOff;
+    bool mEnabled;
     nsRefPtr<BluetoothAdapter> mAdapterPtr;
+    nsCOMPtr<nsIDOMDOMRequest> mDOMRequest;
 };
 
 DOMCI_DATA(BluetoothAdapter, BluetoothAdapter)
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothAdapter)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothAdapter, 
                                                   nsDOMEventTargetHelper)
-  NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(powered)
+  NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(enabled)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothAdapter, 
                                                 nsDOMEventTargetHelper)
-  NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(powered)
+  NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(enabled)
 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)
 
-BluetoothAdapter::BluetoothAdapter() 
-  : mPower(false)
+BluetoothAdapter::BluetoothAdapter(nsPIDOMWindow *aWindow) 
 {
+  BindToOwner(aWindow);
 }
 
 NS_IMETHODIMP
-BluetoothAdapter::GetPower(bool* aPower)
+BluetoothAdapter::SetEnabled(bool aEnabled, nsIDOMDOMRequest** aDomRequest)
 {
-#ifdef MOZ_WIDGET_GONK
-  if(!EnsureBluetoothInit()) {
-    NS_ERROR("Failed to load bluedroid library.\n");
+  nsCOMPtr<nsIDOMRequestService> rs = do_GetService("@mozilla.org/dom/dom-request-service;1");
+
+  if (!rs) {
+    NS_ERROR("No DOMRequest Service!");
     return NS_ERROR_FAILURE;
   }
-  *aPower = sBluedroidFunctions.bt_is_enabled();
-#else
-  *aPower = mPower;
-#endif
+
+  nsCOMPtr<nsIDOMDOMRequest> request;
+  nsresult rv = rs->CreateRequest(GetOwner(), getter_AddRefs(request));
+  NS_ENSURE_SUCCESS(rv, rv);
+  
+  if (!mToggleBtThread) {
+    mToggleBtThread = new LazyIdleThread(15000);
+  }
+
+  nsCOMPtr<nsIRunnable> r = new ToggleBtTask(aEnabled, request, this);
+
+  rv = mToggleBtThread->Dispatch(r, NS_DISPATCH_NORMAL);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  request.forget(aDomRequest);
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
-BluetoothAdapter::SetPower(bool aPower)
+BluetoothAdapter::GetEnabled(bool* aEnabled)
 {
-
-#ifdef MOZ_WIDGET_GONK
-  // Platform specific check for gonk until object is divided in
-  // different implementations per platform. Linux doesn't require
-  // bluetooth firmware loading, but code should work otherwise.
-  if(!EnsureBluetoothInit()) {
-    NS_ERROR("Failed to load bluedroid library.\n");
-    return NS_ERROR_FAILURE;
-  }
-#endif
-  if (mPower != aPower) {
-    mPower = aPower;
-
-#ifdef MOZ_WIDGET_GONK
-    return ToggleBluetoothAsync();
-#endif
-  }
-
-  return NS_OK;
+  *aEnabled = mEnabled;
+  return NS_OK; 
 }
 
-nsresult
-BluetoothAdapter::ToggleBluetoothAsync()
-{
-  if (!mToggleBtThread) {
-    mToggleBtThread = new LazyIdleThread(15000);
-  }
-
-  nsCOMPtr<nsIRunnable> r = new ToggleBtTask(mPower, this);
-
-  return mToggleBtThread->Dispatch(r, NS_DISPATCH_NORMAL);
-}
-
-nsresult
-BluetoothAdapter::FirePowered()
-{
-  nsRefPtr<nsDOMEvent> event = new nsDOMEvent(nsnull, nsnull);
-  nsresult rv = event->InitEvent(NS_LITERAL_STRING("powered"), false, false);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = event->SetTrusted(true);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  bool dummy;
-  rv = DispatchEvent(event, &dummy);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return NS_OK;
-}
-
-NS_IMPL_EVENT_HANDLER(BluetoothAdapter, powered)
--- a/dom/bluetooth/BluetoothAdapter.h
+++ b/dom/bluetooth/BluetoothAdapter.h
@@ -5,16 +5,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_bluetooth_bluetoothadapter_h__
 #define mozilla_dom_bluetooth_bluetoothadapter_h__
 
 #include "BluetoothCommon.h"
 #include "nsDOMEventTargetHelper.h"
 #include "nsIDOMBluetoothAdapter.h"
+#include "nsIDOMDOMRequest.h"
 
 class nsIEventTarget;
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothAdapter : public nsIDOMBluetoothAdapter
                        , public nsDOMEventTargetHelper
 {
@@ -22,24 +23,24 @@ public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMBLUETOOTHADAPTER
 
   NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper::)
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(BluetoothAdapter,
                                            nsDOMEventTargetHelper)
 
-  BluetoothAdapter();
+  BluetoothAdapter(nsPIDOMWindow*);
 
-  nsresult FirePowered();
+  inline void SetEnabledInternal(bool aEnabled) {mEnabled = aEnabled;}
 
 protected:
-  bool mPower;
+  bool mEnabled;
 
-  NS_DECL_EVENT_HANDLER(powered)
+  NS_DECL_EVENT_HANDLER(enabled)
 
 private:
   nsCOMPtr<nsIEventTarget> mToggleBtThread;
-  nsresult ToggleBluetoothAsync();
 };
 
 END_BLUETOOTH_NAMESPACE
+
 #endif
--- a/dom/bluetooth/nsIDOMBluetoothAdapter.idl
+++ b/dom/bluetooth/nsIDOMBluetoothAdapter.idl
@@ -1,17 +1,18 @@
 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
 /* vim: set ts=2 et sw=2 tw=40: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * 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 nsIDOMEventListener;
 
-[scriptable, builtinclass, uuid(3dbaa9f4-5c93-11e1-8592-ff9bfcc3ab4b)]
+[scriptable, builtinclass, uuid(ac288eab-dcdb-4f6a-b94d-6c0e286d6a73)]
 interface nsIDOMBluetoothAdapter : nsIDOMEventTarget
 {
-  attribute boolean power;
+  readonly attribute bool enabled;
 
-  attribute nsIDOMEventListener onpowered;
+  nsIDOMDOMRequest setEnabled(in boolean enabled);
 };