Bug 742044 - Create BluetoothManager object for managing multiple adapters and firmware loading; r=bent
authorKyle Machulis <kyle@nonpolynomial.com>
Wed, 23 May 2012 18:06:36 -0700
changeset 94765 00238745331b8c8748e6f47673aa76d98ac2fdd8
parent 94764 d753a5f4e67346ecffe33f8ef68b2a1d1b505a0c
child 94766 89c0af47b5527dc8d9c91c9c2febc6dd616ffbb2
push idunknown
push userunknown
push dateunknown
reviewersbent
bugs742044
milestone15.0a1
Bug 742044 - Create BluetoothManager object for managing multiple adapters and firmware loading; r=bent
content/base/public/nsContentUtils.h
content/base/src/nsContentUtils.cpp
dom/base/Navigator.cpp
dom/base/Navigator.h
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfoClasses.h
dom/bluetooth/BluetoothAdapter.cpp
dom/bluetooth/BluetoothAdapter.h
dom/bluetooth/BluetoothManager.cpp
dom/bluetooth/BluetoothManager.h
dom/bluetooth/Makefile.in
dom/bluetooth/nsIDOMBluetoothAdapter.idl
dom/bluetooth/nsIDOMBluetoothManager.idl
dom/bluetooth/nsIDOMNavigatorBluetooth.idl
dom/system/gonk/SystemWorkerManager.cpp
dom/telephony/Telephony.cpp
ipc/dbus/DBusThread.cpp
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -1997,16 +1997,34 @@ public:
    * Returns true if the language name is a version of JavaScript and
    * false otherwise
    */
   static bool IsJavaScriptLanguage(const nsString& aName, PRUint32 *aVerFlags);
 
   static void SplitMimeType(const nsAString& aValue, nsString& aType,
                             nsString& aParams);
 
+  /** 
+   * Takes a window and a string to check prefs against. Assumes that
+   * the window is an app window, and that the pref is a comma
+   * seperated list of app urls that have permission to use whatever
+   * the preference refers to (for example, does the current window
+   * have access to mozTelephony). Chrome is always given permissions
+   * for the requested preference. Sets aAllowed based on preference.
+   *
+   * @param aWindow Current window asking for preference permission
+   * @param aPrefURL Preference name
+   * @param aAllowed [out] outparam on whether or not window is allowed
+   *                       to access pref
+   *
+   * @return NS_OK on successful preference lookup, error code otherwise
+   */
+  static nsresult IsOnPrefWhitelist(nsPIDOMWindow* aWindow,
+                                    const char* aPrefURL, bool *aAllowed);
+  
 private:
   static bool InitializeEventTable();
 
   static nsresult EnsureStringBundle(PropertiesFile aFile);
 
   static bool CanCallerAccess(nsIPrincipal* aSubjectPrincipal,
                                 nsIPrincipal* aPrincipal);
 
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -6660,8 +6660,82 @@ nsContentUtils::JSArrayToAtomArray(JSCon
     nsCOMPtr<nsIAtom> a = do_GetAtom(depStr);
     if (!a) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
     aRetVal.AppendObject(a);
   }
   return NS_OK;
 }
+
+// static
+nsresult
+nsContentUtils::IsOnPrefWhitelist(nsPIDOMWindow* aWindow,
+                                  const char* aPrefURL, bool* aAllowed)
+{
+  // Make sure we're dealing with an inner window.
+  nsPIDOMWindow* innerWindow = aWindow->IsInnerWindow() ?
+    aWindow :
+    aWindow->GetCurrentInnerWindow();
+  NS_ENSURE_TRUE(innerWindow, NS_ERROR_FAILURE);
+
+  // Make sure we're being called from a window that we have permission to
+  // access.
+  if (!nsContentUtils::CanCallerAccess(innerWindow)) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
+  // Need the document in order to make security decisions.
+  nsCOMPtr<nsIDocument> document =
+    do_QueryInterface(innerWindow->GetExtantDocument());
+  NS_ENSURE_TRUE(document, NS_NOINTERFACE);
+
+  // Do security checks. We assume that chrome is always allowed.
+  if (nsContentUtils::IsSystemPrincipal(document->NodePrincipal())) {
+    *aAllowed = true;
+    return NS_OK;    
+  }
+
+  // We also allow a comma seperated list of pages specified by
+  // preferences.  
+  nsCOMPtr<nsIURI> originalURI;
+  nsresult rv =
+    document->NodePrincipal()->GetURI(getter_AddRefs(originalURI));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIURI> documentURI;
+  rv = originalURI->Clone(getter_AddRefs(documentURI));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Strip the query string (if there is one) before comparing.
+  nsCOMPtr<nsIURL> documentURL = do_QueryInterface(documentURI);
+  if (documentURL) {
+    rv = documentURL->SetQuery(EmptyCString());
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  bool allowed = false;
+
+  // The pref may not exist but in that case we deny access just as we do if
+  // the url doesn't match.
+  nsCString whitelist;
+  if (NS_SUCCEEDED(Preferences::GetCString(aPrefURL,
+                                           &whitelist))) {
+    nsCOMPtr<nsIIOService> ios = do_GetIOService();
+    NS_ENSURE_TRUE(ios, NS_ERROR_FAILURE);
+
+    nsCCharSeparatedTokenizer tokenizer(whitelist, ',');
+    while (tokenizer.hasMoreTokens()) {
+      nsCOMPtr<nsIURI> uri;
+      if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), tokenizer.nextToken(),
+                                 nsnull, nsnull, ios))) {
+        rv = documentURI->EqualsExceptRef(uri, &allowed);
+        NS_ENSURE_SUCCESS(rv, rv);
+
+        if (allowed) {
+          break;
+        }
+      }
+    }
+  }
+  *aAllowed = allowed;
+  return NS_OK;
+}
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -37,18 +37,18 @@
 #include "mozilla/ClearOnShutdown.h"
 #include "Connection.h"
 #include "MobileConnection.h"
 
 #ifdef MOZ_B2G_RIL
 #include "TelephonyFactory.h"
 #endif
 #ifdef MOZ_B2G_BT
-#include "nsIDOMBluetoothAdapter.h"
-#include "BluetoothAdapter.h"
+#include "nsIDOMBluetoothManager.h"
+#include "BluetoothManager.h"
 #endif
 
 // This should not be in the namespace.
 DOMCI_DATA(Navigator, mozilla::dom::Navigator)
 
 namespace mozilla {
 namespace dom {
 
@@ -1156,25 +1156,26 @@ Navigator::GetMozMobileConnection(nsIDOM
 }
 
 #ifdef MOZ_B2G_BT
 //*****************************************************************************
 //    nsNavigator::nsIDOMNavigatorBluetooth
 //*****************************************************************************
 
 NS_IMETHODIMP
-Navigator::GetMozBluetooth(nsIDOMBluetoothAdapter** aBluetooth)
+Navigator::GetMozBluetooth(nsIDOMBluetoothManager** aBluetooth)
 {
-  nsCOMPtr<nsIDOMBluetoothAdapter> bluetooth = mBluetooth;
+  nsCOMPtr<nsIDOMBluetoothManager> bluetooth = mBluetooth;
 
   if (!bluetooth) {
     nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
     NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
 
-    mBluetooth = new bluetooth::BluetoothAdapter(window);
+    nsresult rv = NS_NewBluetoothManager(window, getter_AddRefs(mBluetooth));
+    NS_ENSURE_SUCCESS(rv, rv);
 
     bluetooth = mBluetooth;
   }
 
   bluetooth.forget(aBluetooth);
   return NS_OK;
 }
 #endif //MOZ_B2G_BT
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -29,17 +29,16 @@ class nsIDOMMozConnection;
 #include "nsIDOMNavigatorTelephony.h"
 class nsIDOMTelephony;
 #endif
 
 #ifdef MOZ_B2G_BT
 #include "nsIDOMNavigatorBluetooth.h"
 #endif
 
-class nsIDOMAdapter;
 //*****************************************************************************
 // Navigator: Script "navigator" object
 //*****************************************************************************
 
 namespace mozilla {
 namespace dom {
 
 namespace battery {
@@ -123,17 +122,17 @@ private:
   nsRefPtr<power::PowerManager> mPowerManager;
   nsRefPtr<sms::SmsManager> mSmsManager;
 #ifdef MOZ_B2G_RIL
   nsCOMPtr<nsIDOMTelephony> mTelephony;
 #endif
   nsRefPtr<network::Connection> mConnection;
   nsRefPtr<network::MobileConnection> mMobileConnection;
 #ifdef MOZ_B2G_BT
-  nsCOMPtr<nsIDOMBluetoothAdapter> mBluetooth;
+  nsCOMPtr<nsIDOMBluetoothManager> mBluetooth;
 #endif
   nsWeakPtr mWindow;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 nsresult NS_GetNavigatorUserAgent(nsAString& aUserAgent);
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -501,16 +501,17 @@ using mozilla::dom::indexedDB::IDBWrappe
 
 #ifdef MOZ_B2G_RIL
 #include "Telephony.h"
 #include "TelephonyCall.h"
 #include "CallEvent.h"
 #endif
 
 #ifdef MOZ_B2G_BT
+#include "BluetoothManager.h"
 #include "BluetoothAdapter.h"
 #endif
 
 #include "DOMError.h"
 #include "DOMRequest.h"
 
 #include "mozilla/Likely.h"
 
@@ -1619,16 +1620,18 @@ static nsDOMClassInfoData sClassInfoData
                            EVENTTARGET_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(TelephonyCall, nsEventTargetSH,
                            EVENTTARGET_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(CallEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 #endif
 
 #ifdef MOZ_B2G_BT
+  NS_DEFINE_CLASSINFO_DATA(BluetoothManager, nsEventTargetSH,
+                           EVENTTARGET_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(BluetoothAdapter, nsEventTargetSH,
                            EVENTTARGET_SCRIPTABLE_FLAGS)
 #endif
 
   NS_DEFINE_CLASSINFO_DATA(DOMError, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(DOMRequest, nsEventTargetSH,
@@ -4431,16 +4434,20 @@ nsDOMClassInfo::Init()
 
   DOM_CLASSINFO_MAP_BEGIN(CallEvent, nsIDOMCallEvent)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCallEvent)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEvent)
   DOM_CLASSINFO_MAP_END
 #endif
 
 #ifdef MOZ_B2G_BT
+  DOM_CLASSINFO_MAP_BEGIN(BluetoothManager, nsIDOMBluetoothManager)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMBluetoothManager)
+  DOM_CLASSINFO_MAP_END  
+
   DOM_CLASSINFO_MAP_BEGIN(BluetoothAdapter, nsIDOMBluetoothAdapter)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMBluetoothAdapter)
   DOM_CLASSINFO_MAP_END
 #endif
 
   DOM_CLASSINFO_MAP_BEGIN(DOMError, nsIDOMDOMError)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMError)
   DOM_CLASSINFO_MAP_END
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -515,13 +515,14 @@ DOMCI_CLASS(MozSettingsEvent)
 
 #ifdef MOZ_B2G_RIL
 DOMCI_CLASS(Telephony)
 DOMCI_CLASS(TelephonyCall)
 DOMCI_CLASS(CallEvent)
 #endif
 
 #ifdef MOZ_B2G_BT
+DOMCI_CLASS(BluetoothManager)
 DOMCI_CLASS(BluetoothAdapter)
 #endif
 
 DOMCI_CLASS(DOMError)
 DOMCI_CLASS(DOMRequest)
--- a/dom/bluetooth/BluetoothAdapter.cpp
+++ b/dom/bluetooth/BluetoothAdapter.cpp
@@ -9,192 +9,30 @@
 
 #include "nsDOMClassInfo.h"
 #include "nsDOMEvent.h"
 #include "nsThreadUtils.h"
 #include "nsXPCOMCIDInternal.h"
 #include "mozilla/LazyIdleThread.h"
 #include "mozilla/Util.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
 
-class ToggleBtResultTask : public nsRunnable
-{
-  public:
-    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());
-
-      // 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 = nsnull;
-      mDOMRequest = nsnull;
-
-      return NS_OK;
-    }
-
-  private:
-    nsRefPtr<BluetoothAdapter> mAdapterPtr;
-    nsCOMPtr<nsIDOMDOMRequest> mDOMRequest;
-    bool mEnabled;
-    bool mResult;
-};
-
-class ToggleBtTask : public nsRunnable
-{
-  public:
-    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;
-      }
-
-      // return 1 if it's enabled, 0 if it's disabled, and -1 on error
-      int isEnabled = IsBluetoothEnabled();
-
-      if ((isEnabled == 1 && mEnabled) || (isEnabled == 0 && !mEnabled)) {
-        result = true;
-      } else if (isEnabled < 0) {
-        result = false;
-      } else if (mEnabled) {
-        result = (EnableBluetooth() == 0) ? true : false;
-      } else {
-        result = (DisableBluetooth() == 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, mDOMRequest, mEnabled, result);
-
-      if (NS_FAILED(NS_DispatchToMainThread(resultRunnable))) {
-        NS_WARNING("Failed to dispatch to main thread!");
-      }
-
-      return NS_OK;
-    }
-
-  private:
-    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(enabled)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothAdapter, 
                                                 nsDOMEventTargetHelper)
-  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(nsPIDOMWindow *aWindow) 
-{
-  BindToOwner(aWindow);
-}
-
-NS_IMETHODIMP
-BluetoothAdapter::SetEnabled(bool aEnabled, nsIDOMDOMRequest** aDomRequest)
-{
-  nsCOMPtr<nsIDOMRequestService> rs = do_GetService("@mozilla.org/dom/dom-request-service;1");
-
-  if (!rs) {
-    NS_ERROR("No DOMRequest Service!");
-    return NS_ERROR_FAILURE;
-  }
-
-  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::GetEnabled(bool* aEnabled)
-{
-  *aEnabled = mEnabled;
-  return NS_OK; 
-}
-
--- a/dom/bluetooth/BluetoothAdapter.h
+++ b/dom/bluetooth/BluetoothAdapter.h
@@ -15,32 +15,21 @@
 class nsIEventTarget;
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothAdapter : public nsDOMEventTargetHelper
                        , public nsIDOMBluetoothAdapter
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMBLUETOOTHADAPTER
 
   NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper::)
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(BluetoothAdapter,
                                            nsDOMEventTargetHelper)
 
-  BluetoothAdapter(nsPIDOMWindow*);
-
-  inline void SetEnabledInternal(bool aEnabled) {mEnabled = aEnabled;}
-
-protected:
-  bool mEnabled;
-
-  NS_DECL_EVENT_HANDLER(enabled)
-
-private:
-  nsCOMPtr<nsIEventTarget> mToggleBtThread;
 };
 
 END_BLUETOOTH_NAMESPACE
 
 #endif
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth/BluetoothManager.cpp
@@ -0,0 +1,245 @@
+/* -*- 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 "BluetoothManager.h"
+#include "BluetoothCommon.h"
+#include "BluetoothFirmware.h"
+#include "BluetoothAdapter.h"
+
+#include "nsIDocument.h"
+#include "nsIURI.h"
+#include "nsIURL.h"
+#include "nsPIDOMWindow.h"
+
+#include "jsapi.h"
+#include "mozilla/Preferences.h"
+#include "nsDOMClassInfo.h"
+#include "nsDOMEvent.h"
+#include "nsThreadUtils.h"
+#include "nsXPCOMCIDInternal.h"
+#include "mozilla/LazyIdleThread.h"
+#include "mozilla/Util.h"
+#include "nsCharSeparatedTokenizer.h"
+#include "nsContentUtils.h"
+#include "nsIInterfaceRequestorUtils.h"
+#include "nsNetUtil.h"
+#include "nsServiceManagerUtils.h"
+
+#define DOM_BLUETOOTH_URL_PREF "dom.mozBluetooth.whitelist"
+
+using mozilla::Preferences;
+
+USING_BLUETOOTH_NAMESPACE
+
+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");
+}
+
+DOMCI_DATA(BluetoothManager, BluetoothManager)
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothManager)
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothManager, 
+                                                  nsDOMEventTargetHelper)
+  NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(enabled)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothManager, 
+                                                nsDOMEventTargetHelper)
+  NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(enabled)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothManager)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMBluetoothManager)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(BluetoothManager)
+NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
+
+NS_IMPL_ADDREF_INHERITED(BluetoothManager, nsDOMEventTargetHelper)
+NS_IMPL_RELEASE_INHERITED(BluetoothManager, nsDOMEventTargetHelper)
+
+class ToggleBtResultTask : public nsRunnable
+{
+  public:
+    ToggleBtResultTask(nsRefPtr<BluetoothManager>& aManager, 
+                       nsCOMPtr<nsIDOMDOMRequest>& aReq,
+                       bool aEnabled,
+                       bool aResult)
+      : mEnabled(aEnabled),
+        mResult(aResult)
+    {
+      MOZ_ASSERT(!NS_IsMainThread());
+
+      mDOMRequest.swap(aReq);
+      mManagerPtr.swap(aManager);
+    }
+
+    NS_IMETHOD Run() 
+    {
+      MOZ_ASSERT(NS_IsMainThread());
+
+      // Update bt power status to BluetoothAdapter only if loading bluetooth 
+      // firmware succeeds.
+      if (mResult) {
+        mManagerPtr->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.
+      mManagerPtr = NULL;
+      mDOMRequest = NULL;
+
+      return NS_OK;
+    }
+
+  private:
+    nsRefPtr<BluetoothManager> mManagerPtr;
+    nsCOMPtr<nsIDOMDOMRequest> mDOMRequest;
+    bool mEnabled;
+    bool mResult;
+};
+
+class ToggleBtTask : public nsRunnable
+{
+  public:
+    ToggleBtTask(bool aEnabled, nsIDOMDOMRequest* aReq, BluetoothManager* aManager)
+      : mEnabled(aEnabled),        
+        mManagerPtr(aManager),
+        mDOMRequest(aReq)
+    {
+      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;
+      }
+
+      // return 1 if it's enabled, 0 if it's disabled, and -1 on error
+      int isEnabled = sBluedroidFunctions.bt_is_enabled();
+
+      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() == 0) ? true : false;
+      }
+#else
+      result = true;
+      NS_WARNING("No bluetooth firmware loading 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(mManagerPtr, mDOMRequest, mEnabled, result);
+
+      if (NS_FAILED(NS_DispatchToMainThread(resultRunnable))) {
+        NS_WARNING("Failed to dispatch to main thread!");
+      }
+
+      return NS_OK;
+    }
+
+  private:
+    bool mEnabled;
+    nsRefPtr<BluetoothManager> mManagerPtr;
+    nsCOMPtr<nsIDOMDOMRequest> mDOMRequest;
+};
+
+BluetoothManager::BluetoothManager(nsPIDOMWindow *aWindow) :
+  mEnabled(false)
+{
+  BindToOwner(aWindow);
+}
+
+NS_IMETHODIMP
+BluetoothManager::SetEnabled(bool aEnabled, nsIDOMDOMRequest** aDomRequest)
+{
+  nsCOMPtr<nsIDOMRequestService> rs = do_GetService("@mozilla.org/dom/dom-request-service;1");
+
+  if (!rs) {
+    NS_ERROR("No DOMRequest Service!");
+    return NS_ERROR_FAILURE;
+  }
+
+  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
+BluetoothManager::GetEnabled(bool* aEnabled)
+{
+  *aEnabled = mEnabled;
+  return NS_OK; 
+}
+
+NS_IMETHODIMP
+BluetoothManager::GetDefaultAdapter(nsIDOMBluetoothAdapter** aAdapter)
+{
+  //TODO: Implement adapter fetching
+  return NS_ERROR_FAILURE;
+}
+
+nsresult
+NS_NewBluetoothManager(nsPIDOMWindow* aWindow, nsIDOMBluetoothManager** aBluetoothManager)
+{
+  NS_ASSERTION(aWindow, "Null pointer!");
+
+  bool allowed;
+  nsresult rv = nsContentUtils::IsOnPrefWhitelist(aWindow, DOM_BLUETOOTH_URL_PREF, &allowed);
+  NS_ENSURE_SUCCESS(rv, rv);
+  
+  if (!allowed) {
+    *aBluetoothManager = NULL;
+    return NS_OK;
+  }
+
+  nsRefPtr<BluetoothManager> bluetoothManager = new BluetoothManager(aWindow);
+
+  bluetoothManager.forget(aBluetoothManager);
+  return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth/BluetoothManager.h
@@ -0,0 +1,45 @@
+/* -*- 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/. */
+
+#ifndef mozilla_dom_bluetooth_bluetoothmanager_h__
+#define mozilla_dom_bluetooth_bluetoothmanager_h__
+
+#include "BluetoothCommon.h"
+#include "nsDOMEventTargetHelper.h"
+#include "nsIDOMBluetoothManager.h"
+
+BEGIN_BLUETOOTH_NAMESPACE
+
+class BluetoothAdapter;
+
+class BluetoothManager : public nsDOMEventTargetHelper
+                       , public nsIDOMBluetoothManager                         
+{
+public:
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_NSIDOMBLUETOOTHMANAGER
+
+  NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper::)
+
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(BluetoothManager,
+                                           nsDOMEventTargetHelper)
+
+  BluetoothManager(nsPIDOMWindow*);
+  inline void SetEnabledInternal(bool aEnabled) {mEnabled = aEnabled;}
+  
+private:
+  bool mEnabled;
+
+  NS_DECL_EVENT_HANDLER(enabled)
+
+  nsCOMPtr<nsIEventTarget> mToggleBtThread;
+};
+
+END_BLUETOOTH_NAMESPACE
+
+nsresult NS_NewBluetoothManager(nsPIDOMWindow* aWindow, nsIDOMBluetoothManager** aBluetoothManager);
+
+#endif
--- a/dom/bluetooth/Makefile.in
+++ b/dom/bluetooth/Makefile.in
@@ -13,22 +13,24 @@ MODULE           = dom
 LIBRARY_NAME     = dombluetooth_s
 XPIDL_MODULE     = dom_bluetooth
 LIBXUL_LIBRARY   = 1
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/dom/dom-config.mk
 
 CPPSRCS = \
+  BluetoothManager.cpp \
   BluetoothAdapter.cpp \
   BluetoothFirmware.cpp \
   $(NULL)
 
 XPIDLSRCS = \
   nsIDOMNavigatorBluetooth.idl \
+  nsIDOMBluetoothManager.idl \
   nsIDOMBluetoothAdapter.idl \
   $(NULL)
 
 ifneq (gonk,$(MOZ_WIDGET_TOOLKIT))
 CFLAGS += $(MOZ_DBUS_CFLAGS)
 CXXFLAGS += $(MOZ_DBUS_CFLAGS) -DHAVE_PTHREADS
 endif
 
--- a/dom/bluetooth/nsIDOMBluetoothAdapter.idl
+++ b/dom/bluetooth/nsIDOMBluetoothAdapter.idl
@@ -1,18 +1,12 @@
 /* -*- 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(ac288eab-dcdb-4f6a-b94d-6c0e286d6a73)]
+[scriptable, builtinclass, uuid(fe6602d2-f32f-4b95-bf66-028452bbe6d2)]
 interface nsIDOMBluetoothAdapter : nsIDOMEventTarget
 {
-  readonly attribute bool enabled;
-
-  nsIDOMDOMRequest setEnabled(in boolean enabled);
 };
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth/nsIDOMBluetoothManager.idl
@@ -0,0 +1,19 @@
+/* -*- 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 nsIDOMBluetoothAdapter;
+
+[scriptable, builtinclass, uuid(9d4bcbad-8904-4985-b366-036d32959312)]
+interface nsIDOMBluetoothManager : nsIDOMEventTarget
+{
+  readonly attribute bool enabled;
+  readonly attribute nsIDOMBluetoothAdapter defaultAdapter;
+
+  nsIDOMDOMRequest setEnabled(in boolean enabled);
+};
--- a/dom/bluetooth/nsIDOMNavigatorBluetooth.idl
+++ b/dom/bluetooth/nsIDOMNavigatorBluetooth.idl
@@ -1,15 +1,15 @@
 /* -*- 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 "nsISupports.idl"
 
-interface nsIDOMBluetoothAdapter;
+interface nsIDOMBluetoothManager;
 
-[scriptable, uuid(677f2c2d-c4d1-41ea-addc-21d30d0d3858)]
+[scriptable, uuid(3d6741c7-f0c4-4925-a606-38415f660f34)]
 interface nsIDOMNavigatorBluetooth : nsISupports
 {
-  readonly attribute nsIDOMBluetoothAdapter mozBluetooth;
+  readonly attribute nsIDOMBluetoothManager mozBluetooth;
 };
--- a/dom/system/gonk/SystemWorkerManager.cpp
+++ b/dom/system/gonk/SystemWorkerManager.cpp
@@ -206,35 +206,47 @@ SystemWorkerManager::Init()
   NS_ENSURE_TRUE(cx, NS_ERROR_FAILURE);
 
   nsCxPusher pusher;
   if (!pusher.Push(cx, false)) {
     return NS_ERROR_FAILURE;
   }
 
   nsresult rv = InitRIL(cx);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Failed to initialize RIL/Telephony!");
+    return rv;
+  }
 
   rv = InitWifi(cx);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Failed to initialize WiFi Networking!");
+    return rv;
+  }
 
 #ifdef MOZ_B2G_BT
   rv = InitBluetooth(cx);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Failed to initialize Bluetooth!");
+    return rv;
+  }
 #endif
 
   nsCOMPtr<nsIObserverService> obs =
     do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
   if (!obs) {
     NS_WARNING("Failed to get observer service!");
     return NS_ERROR_FAILURE;
   }
 
   rv = obs->AddObserver(this, WORKERS_SHUTDOWN_TOPIC, false);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Failed to initialize worker shutdown event!");
+    return rv;
+  }
 
   return NS_OK;
 }
 
 void
 SystemWorkerManager::Shutdown()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
--- a/dom/telephony/Telephony.cpp
+++ b/dom/telephony/Telephony.cpp
@@ -492,81 +492,31 @@ Telephony::NotifyError(PRInt32 aCallInde
   return NS_OK;
 }
 
 nsresult
 NS_NewTelephony(nsPIDOMWindow* aWindow, nsIDOMTelephony** aTelephony)
 {
   NS_ASSERTION(aWindow, "Null pointer!");
 
-  // Make sure we're dealing with an inner window.
   nsPIDOMWindow* innerWindow = aWindow->IsInnerWindow() ?
-                               aWindow :
-                               aWindow->GetCurrentInnerWindow();
-  NS_ENSURE_TRUE(innerWindow, NS_ERROR_FAILURE);
-
-  // Make sure we're being called from a window that we have permission to
-  // access.
-  if (!nsContentUtils::CanCallerAccess(innerWindow)) {
-    return NS_ERROR_DOM_SECURITY_ERR;
-  }
+    aWindow :
+    aWindow->GetCurrentInnerWindow();
 
-  // Need the document in order to make security decisions.
-  nsCOMPtr<nsIDocument> document =
-    do_QueryInterface(innerWindow->GetExtantDocument());
-  NS_ENSURE_TRUE(document, NS_NOINTERFACE);
-
-  // Do security checks. We assume that chrome is always allowed and we also
-  // allow a single page specified by preferences.
-  if (!nsContentUtils::IsSystemPrincipal(document->NodePrincipal())) {
-    nsCOMPtr<nsIURI> originalURI;
-    nsresult rv =
-      document->NodePrincipal()->GetURI(getter_AddRefs(originalURI));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    nsCOMPtr<nsIURI> documentURI;
-    rv = originalURI->Clone(getter_AddRefs(documentURI));
-    NS_ENSURE_SUCCESS(rv, rv);
 
-    // Strip the query string (if there is one) before comparing.
-    nsCOMPtr<nsIURL> documentURL = do_QueryInterface(documentURI);
-    if (documentURL) {
-      rv = documentURL->SetQuery(EmptyCString());
-      NS_ENSURE_SUCCESS(rv, rv);
-    }
-
-    bool allowed = false;
-
-    // The pref may not exist but in that case we deny access just as we do if
-    // the url doesn't match.
-    nsCString whitelist;
-    if (NS_SUCCEEDED(Preferences::GetCString(DOM_TELEPHONY_APP_PHONE_URL_PREF,
-                                             &whitelist))) {
-      nsCOMPtr<nsIIOService> ios = do_GetIOService();
-      NS_ENSURE_TRUE(ios, NS_ERROR_FAILURE);
-
-      nsCCharSeparatedTokenizer tokenizer(whitelist, ',');
-      while (tokenizer.hasMoreTokens()) {
-        nsCOMPtr<nsIURI> uri;
-        if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), tokenizer.nextToken(),
-                                   nsnull, nsnull, ios))) {
-          rv = documentURI->EqualsExceptRef(uri, &allowed);
-          NS_ENSURE_SUCCESS(rv, rv);
-
-          if (allowed) {
-            break;
-          }
-        }
-      }
-    }
-
-    if (!allowed) {
-      *aTelephony = nsnull;
-      return NS_OK;
-    }
+  bool allowed;
+  nsresult rv =
+    nsContentUtils::IsOnPrefWhitelist(innerWindow,
+                                      DOM_TELEPHONY_APP_PHONE_URL_PREF,
+                                      &allowed);
+  NS_ENSURE_SUCCESS(rv, rv);
+  
+  if (!allowed) {
+    *aTelephony = nsnull;
+    return NS_OK;
   }
 
   nsCOMPtr<nsIRILContentHelper> ril =
     do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
   NS_ENSURE_TRUE(ril, NS_ERROR_UNEXPECTED);
 
   nsRefPtr<Telephony> telephony = Telephony::Create(innerWindow, ril);
   NS_ENSURE_TRUE(telephony, NS_ERROR_UNEXPECTED);
--- a/ipc/dbus/DBusThread.cpp
+++ b/ipc/dbus/DBusThread.cpp
@@ -526,35 +526,39 @@ DBusThread::IsEventLoopRunning()
   return mIsRunning;
 }
 
 // Startup/Shutdown utility functions
 
 static void
 ConnectDBus(Monitor* aMonitor, bool* aSuccess)
 {
-  MOZ_ASSERT(!sDBusThread);
-
+  if(sDBusThread) {
+    NS_WARNING("Trying to start DBus Thread that is already currently running, skipping.");
+    return;
+  }
   sDBusThread = new DBusThread();
   *aSuccess = true;
   if(!sDBusThread->StartEventLoop())
   {
     *aSuccess = false;
   }
   {
     MonitorAutoLock lock(*aMonitor);
     lock.Notify();
   }
 }
 
 static void
 DisconnectDBus(Monitor* aMonitor, bool* aSuccess)
 {
-  MOZ_ASSERT(sDBusThread);
-
+  if(!sDBusThread) {
+    NS_WARNING("Trying to shutdown DBus Thread that is not currently running, skipping.");
+    return;
+  }
   *aSuccess = true;
   sDBusThread->StopEventLoop();
   sDBusThread = NULL;
   {
     MonitorAutoLock lock(*aMonitor);
     lock.Notify();
   }
 }