Bug 838146 part 6. Implement gamepad, bluetooth, time, audiochannel WebIDL APIs on Navigator. r=smaug, sr=sicking
☠☠ backed out by 33fb417caccf ☠ ☠
authorBoris Zbarsky <bzbarsky@mit.edu>
Fri, 12 Jul 2013 10:36:32 -0400
changeset 151527 fd3a62dd39104255c2130d7b5a493afb43e42cd0
parent 151526 f06b420e0dfa610a1a2e95ecfdbab0fef586d652
child 151528 7cddfebc261c604ca1f83cbd6a972392cca00705
push id382
push userakeybl@mozilla.com
push dateMon, 21 Oct 2013 21:47:13 +0000
treeherdermozilla-release@5f1868ee45cb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, sicking
bugs838146
milestone25.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 838146 part 6. Implement gamepad, bluetooth, time, audiochannel WebIDL APIs on Navigator. r=smaug, sr=sicking
dom/base/Navigator.cpp
dom/base/Navigator.h
dom/bindings/Bindings.conf
dom/bluetooth/BluetoothManager.cpp
dom/bluetooth/BluetoothManager.h
dom/webidl/Navigator.webidl
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -1598,25 +1598,22 @@ Navigator::GetMozIccManager(ErrorResult&
 #ifdef MOZ_GAMEPAD
 //*****************************************************************************
 //    Navigator::nsINavigatorGamepads
 //*****************************************************************************
 
 NS_IMETHODIMP
 Navigator::GetGamepads(nsIVariant** aRetVal)
 {
-  NS_ENSURE_ARG_POINTER(aRetVal);
-  *aRetVal = nullptr;
-
-  NS_ENSURE_STATE(mWindow);
-  NS_ENSURE_TRUE(mWindow->GetDocShell(), NS_OK);
-  nsGlobalWindow* win = static_cast<nsGlobalWindow*>(mWindow.get());
-
+  ErrorResult rv;
   nsAutoTArray<nsRefPtr<Gamepad>, 2> gamepads;
-  win->GetGamepads(gamepads);
+  GetGamepads(gamepads, rv);
+  if (rv.Failed()) {
+    return rv.ErrorCode();
+  }
 
   nsRefPtr<nsVariant> out = new nsVariant();
   NS_ENSURE_STATE(out);
 
   if (gamepads.Length() == 0) {
     nsresult rv = out->SetAsEmptyArray();
     NS_ENSURE_SUCCESS(rv, rv);
   } else {
@@ -1624,16 +1621,29 @@ Navigator::GetGamepads(nsIVariant** aRet
                     &NS_GET_IID(nsISupports),
                     gamepads.Length(),
                     const_cast<void*>(static_cast<const void*>(gamepads.Elements())));
   }
   out.forget(aRetVal);
 
   return NS_OK;
 }
+
+void
+Navigator::GetGamepads(nsTArray<nsRefPtr<Gamepad> >& aGamepads,
+                       ErrorResult& aRv)
+{
+  if (!mWindow) {
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return;
+  }
+  NS_ENSURE_TRUE_VOID(mWindow->GetDocShell());
+  nsGlobalWindow* win = static_cast<nsGlobalWindow*>(mWindow.get());
+  win->GetGamepads(aGamepads);
+}
 #endif
 
 //*****************************************************************************
 //    Navigator::nsIDOMNavigatorNetwork
 //*****************************************************************************
 
 NS_IMETHODIMP
 Navigator::GetMozConnection(nsIDOMMozConnection** aConnection)
@@ -1695,28 +1705,43 @@ Navigator::GetMozMobileConnection(ErrorR
 #ifdef MOZ_B2G_BT
 //*****************************************************************************
 //    nsNavigator::nsIDOMNavigatorBluetooth
 //*****************************************************************************
 
 NS_IMETHODIMP
 Navigator::GetMozBluetooth(nsIDOMBluetoothManager** aBluetooth)
 {
-  nsCOMPtr<nsIDOMBluetoothManager> bluetooth = mBluetooth;
-
-  if (!bluetooth) {
+  if (!mBluetooth) {
     NS_ENSURE_STATE(mWindow);
-    nsresult rv = NS_NewBluetoothManager(mWindow, getter_AddRefs(mBluetooth));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    bluetooth = mBluetooth;
+    if (!bluetooth::BluetoothManager::CheckPermission(mWindow)) {
+      *aBluetooth = nullptr;
+      return NS_OK;
+    }
   }
 
-  bluetooth.forget(aBluetooth);
-  return NS_OK;
+  ErrorResult rv;
+  NS_IF_ADDREF(*aBluetooth = GetMozBluetooth(rv));
+  return rv.ErrorCode();
+}
+
+nsIDOMBluetoothManager*
+Navigator::GetMozBluetooth(ErrorResult& aRv)
+{
+  // Callers (either the XPCOM method or the WebIDL binding) are responsible for
+  // the permission check here.
+  if (!mBluetooth) {
+    if (!mWindow) {
+      aRv.Throw(NS_ERROR_UNEXPECTED);
+      return nullptr;
+    }
+    mBluetooth = bluetooth::BluetoothManager::Create(mWindow);
+  }
+
+  return mBluetooth;
 }
 #endif //MOZ_B2G_BT
 
 //*****************************************************************************
 //    nsNavigator::nsIDOMNavigatorSystemMessages
 //*****************************************************************************
 nsresult
 Navigator::EnsureMessagesManager()
@@ -1815,29 +1840,40 @@ Navigator::MozSetMessageHandler(const ns
 
 //*****************************************************************************
 //    Navigator::nsIDOMNavigatorTime
 //*****************************************************************************
 #ifdef MOZ_TIME_MANAGER
 NS_IMETHODIMP
 Navigator::GetMozTime(nsISupports** aTime)
 {
-  *aTime = nullptr;
-
-  NS_ENSURE_STATE(mWindow);
   if (!CheckPermission("time")) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
+  ErrorResult rv;
+  NS_IF_ADDREF(*aTime = GetMozTime(rv));
+  return rv.ErrorCode();
+}
+
+time::TimeManager*
+Navigator::GetMozTime(ErrorResult& aRv)
+{
+  // Callers (either the XPCOM method or the WebIDL binding) are responsible for
+  // the permission check here.
+  if (!mWindow) {
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return nullptr;
+  }
+
   if (!mTimeManager) {
     mTimeManager = new time::TimeManager(mWindow);
   }
 
-  NS_ADDREF(*aTime = mTimeManager);
-  return NS_OK;
+  return mTimeManager;
 }
 #endif
 
 //*****************************************************************************
 //    nsNavigator::nsIDOMNavigatorCamera
 //*****************************************************************************
 
 NS_IMETHODIMP
@@ -1940,26 +1976,34 @@ Navigator::CheckPermission(nsPIDOMWindow
 
 //*****************************************************************************
 //    Navigator::nsINavigatorAudioChannelManager
 //*****************************************************************************
 #ifdef MOZ_AUDIO_CHANNEL_MANAGER
 NS_IMETHODIMP
 Navigator::GetMozAudioChannelManager(nsISupports** aAudioChannelManager)
 {
-  *aAudioChannelManager = nullptr;
+  ErrorResult rv;
+  NS_IF_ADDREF(*aAudioChannelManager = GetMozAudioChannelManager(rv));
+  return rv.ErrorCode();
+}
 
+system::AudioChannelManager*
+Navigator::GetMozAudioChannelManager(ErrorResult& aRv)
+{
   if (!mAudioChannelManager) {
-    NS_ENSURE_STATE(mWindow);
+    if (!mWindow) {
+      aRv.Throw(NS_ERROR_UNEXPECTED);
+      return nullptr;
+    }
     mAudioChannelManager = new system::AudioChannelManager();
     mAudioChannelManager->Init(mWindow);
   }
 
-  NS_ADDREF(*aAudioChannelManager = mAudioChannelManager);
-  return NS_OK;
+  return mAudioChannelManager;
 }
 #endif
 
 /* static */
 bool
 Navigator::HasBatterySupport(JSContext* /* unused*/, JSObject* /*unused */)
 {
   return battery::BatteryManager::HasSupport();
@@ -2084,16 +2128,36 @@ bool
 Navigator::HasIccManagerSupport(JSContext* /* unused */,
                                 JSObject* aGlobal)
 {
   nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
   return win && CheckPermission(win, "mobileconnection");
 }
 #endif // MOZ_B2G_RIL
 
+#ifdef MOZ_B2G_BT
+/* static */
+bool
+Navigator::HasBluetoothSupport(JSContext* /* unused */, JSObject* aGlobal)
+{
+  nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
+  return win && bluetooth::BluetoothManager::CheckPermission(win);
+}
+#endif // MOZ_B2G_BT
+
+#ifdef MOZ_TIME_MANAGER
+/* static */
+bool
+Navigator::HasTimeSupport(JSContext* /* unused */, JSObject* aGlobal)
+{
+  nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
+  return win && CheckPermission(win, "time");
+}
+#endif // MOZ_TIME_MANAGER
+
 /* static */
 already_AddRefed<nsPIDOMWindow>
 Navigator::GetWindowFromGlobal(JSObject* aGlobal)
 {
   nsCOMPtr<nsPIDOMWindow> win =
     do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(aGlobal));
   MOZ_ASSERT(!win || win->IsInnerWindow());
   return win.forget();
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -78,16 +78,19 @@ namespace dom {
 namespace battery {
 class BatteryManager;
 } // namespace battery
 
 class DesktopNotificationCenter;
 class SmsManager;
 class MobileMessageManager;
 class MozIdleObserver;
+#ifdef MOZ_GAMEPAD
+class Gamepad;
+#endif // MOZ_GAMEPAD
 
 namespace icc {
 #ifdef MOZ_B2G_RIL
 class IccManager;
 #endif
 }
 
 namespace network {
@@ -308,16 +311,28 @@ public:
   bool MozHasPendingMessage(const nsAString& aType, ErrorResult& aRv);
 #ifdef MOZ_B2G_RIL
   nsIDOMTelephony* GetMozTelephony(ErrorResult& aRv);
   nsIDOMMozMobileConnection* GetMozMobileConnection(ErrorResult& aRv);
   nsIDOMMozCellBroadcast* GetMozCellBroadcast(ErrorResult& aRv);
   nsIDOMMozVoicemail* GetMozVoicemail(ErrorResult& aRv);
   nsIDOMMozIccManager* GetMozIccManager(ErrorResult& aRv);
 #endif // MOZ_B2G_RIL
+#ifdef MOZ_GAMEPAD
+  void GetGamepads(nsTArray<nsRefPtr<Gamepad> >& aGamepads, ErrorResult& aRv);
+#endif // MOZ_GAMEPAD
+#ifdef MOZ_B2G_BT
+  nsIDOMBluetoothManager* GetMozBluetooth(ErrorResult& aRv);
+#endif // MOZ_B2G_BT
+#ifdef MOZ_TIME_MANAGER
+  time::TimeManager* GetMozTime(ErrorResult& aRv);
+#endif // MOZ_TIME_MANAGER
+#ifdef MOZ_AUDIO_CHANNEL_MANAGER
+  system::AudioChannelManager* GetMozAudioChannelManager(ErrorResult& aRv);
+#endif // MOZ_AUDIO_CHANNEL_MANAGER
 
 
   // WebIDL helper methods
   static bool HasBatterySupport(JSContext* /* unused*/, JSObject* /*unused */);
   static bool HasPowerSupport(JSContext* /* unused */, JSObject* aGlobal);
   static bool HasIdleSupport(JSContext* /* unused */, JSObject* aGlobal);
   static bool HasWakeLockSupport(JSContext* /* unused*/, JSObject* /*unused */);
   static bool HasDesktopNotificationSupport(JSContext* /* unused*/,
@@ -337,16 +352,23 @@ public:
                                          JSObject* aGlobal);
   static bool HasCellBroadcastSupport(JSContext* /* unused */,
                                       JSObject* aGlobal);
   static bool HasVoicemailSupport(JSContext* /* unused */,
                                   JSObject* aGlobal);
   static bool HasIccManagerSupport(JSContext* /* unused */,
                                    JSObject* aGlobal);
 #endif // MOZ_B2G_RIL
+#ifdef MOZ_B2G_BT
+  static bool HasBluetoothSupport(JSContext* /* unused */, JSObject* aGlobal);
+#endif // MOZ_B2G_BT
+#ifdef MOZ_TIME_MANAGER
+  static bool HasTimeSupport(JSContext* /* unused */, JSObject* aGlobal);
+#endif // MOZ_TIME_MANAGER
+
   nsPIDOMWindow* GetParentObject() const
   {
     return GetWindow();
   }
 
 private:
   bool CheckPermission(const char* type);
   static bool CheckPermission(nsPIDOMWindow* aWindow, const char* aType);
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -1701,16 +1701,17 @@ addExternalIface('FileCallback', nativeT
 addExternalIface('HitRegionOptions', nativeType='nsISupports')
 addExternalIface('IDBDatabase', nativeType='nsIIDBDatabase')
 addExternalIface('IDBOpenDBRequest', nativeType='nsIIDBOpenDBRequest')
 addExternalIface('imgINotificationObserver', nativeType='imgINotificationObserver')
 addExternalIface('imgIRequest', nativeType='imgIRequest', notflattened=True)
 addExternalIface('LockedFile')
 addExternalIface('MediaList')
 addExternalIface('MenuBuilder', nativeType='nsIMenuBuilder', notflattened=True)
+addExternalIface('MozBluetoothManager', nativeType='nsIDOMBluetoothManager')
 addExternalIface('MozBoxObject', nativeType='nsIBoxObject')
 addExternalIface('MozCellBroadcast')
 addExternalIface('MozConnection', headerFile='nsIDOMConnection.h')
 addExternalIface('MozControllers', nativeType='nsIControllers')
 addExternalIface('MozFrameLoader', nativeType='nsIFrameLoader', notflattened=True)
 addExternalIface('MozIccManager', headerFile='nsIDOMIccManager.h')
 addExternalIface('MozMobileConnection', headerFile='nsIDOMMobileConnection.h')
 addExternalIface('MozMobileMessageManager', headerFile='nsIDOMMobileMessageManager.h')
--- a/dom/bluetooth/BluetoothManager.cpp
+++ b/dom/bluetooth/BluetoothManager.cpp
@@ -163,40 +163,33 @@ BluetoothManager::Create(nsPIDOMWindow* 
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aWindow);
 
   nsRefPtr<BluetoothManager> manager = new BluetoothManager(aWindow);
   return manager.forget();
 }
 
-nsresult
-NS_NewBluetoothManager(nsPIDOMWindow* aWindow,
-                       nsIDOMBluetoothManager** aBluetoothManager)
+// static
+bool
+BluetoothManager::CheckPermission(nsPIDOMWindow* aWindow)
 {
   NS_ASSERTION(aWindow, "Null pointer!");
 
   nsCOMPtr<nsIPermissionManager> permMgr =
     do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
-  NS_ENSURE_TRUE(permMgr, NS_ERROR_UNEXPECTED);
+  NS_ENSURE_TRUE(permMgr, false);
 
   uint32_t permission;
   nsresult rv =
     permMgr->TestPermissionFromWindow(aWindow, "bluetooth",
                                       &permission);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsRefPtr<BluetoothManager> bluetoothManager;
+  NS_ENSURE_SUCCESS(rv, false);
 
-  if (permission == nsIPermissionManager::ALLOW_ACTION) {
-    bluetoothManager = BluetoothManager::Create(aWindow);
-  }
-
-  bluetoothManager.forget(aBluetoothManager);
-  return NS_OK;
+  return permission == nsIPermissionManager::ALLOW_ACTION;
 }
 
 void
 BluetoothManager::Notify(const BluetoothSignal& aData)
 {
   BT_LOG("[M] %s: %s", __FUNCTION__, NS_ConvertUTF16toUTF8(aData.name()).get());
 
   if (aData.name().EqualsLiteral("AdapterAdded")) {
--- a/dom/bluetooth/BluetoothManager.h
+++ b/dom/bluetooth/BluetoothManager.h
@@ -24,23 +24,22 @@ class BluetoothManager : public nsDOMEve
                        , public BluetoothPropertyContainer
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMBLUETOOTHMANAGER
 
   NS_REALLY_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper)
 
+  // Never returns null
   static already_AddRefed<BluetoothManager>
-  Create(nsPIDOMWindow* aWindow);
+    Create(nsPIDOMWindow* aWindow);
+  static bool CheckPermission(nsPIDOMWindow* aWindow);
   void Notify(const BluetoothSignal& aData);
   virtual void SetPropertyByValue(const BluetoothNamedValue& aValue) MOZ_OVERRIDE;
 private:
   BluetoothManager(nsPIDOMWindow* aWindow);
   ~BluetoothManager();
 };
 
 END_BLUETOOTH_NAMESPACE
 
-nsresult NS_NewBluetoothManager(nsPIDOMWindow* aWindow,
-                                nsIDOMBluetoothManager** aBluetoothManager);
-
 #endif
--- a/dom/webidl/Navigator.webidl
+++ b/dom/webidl/Navigator.webidl
@@ -5,16 +5,17 @@
  *
  * The origin of this IDL file is
  * http://www.whatwg.org/specs/web-apps/current-work/#the-navigator-object
  * http://www.w3.org/TR/tracking-dnt/
  * http://www.w3.org/TR/geolocation-API/#geolocation_interface
  * http://www.w3.org/TR/battery-status/#navigatorbattery-interface
  * http://www.w3.org/TR/vibration/#vibration-interface
  * http://www.w3.org/2012/sysapps/runtime/#extension-to-the-navigator-interface-1
+ * https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html#navigator-interface-extension
  *
  * © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and
  * Opera Software ASA. You are granted a license to use, reproduce
  * and create derivative works of this document.
  */
 
 interface MozPowerManager;
 interface MozWakeLock;
@@ -291,8 +292,41 @@ partial interface Navigator {
 
 // nsIMozNavigatorIccManager
 interface MozIccManager;
 partial interface Navigator {
   [Throws, Func="Navigator::HasIccManagerSupport"]
   readonly attribute MozIccManager? mozIccManager;
 };
 #endif // MOZ_B2G_RIL
+
+#ifdef MOZ_GAMEPAD
+// https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html#navigator-interface-extension
+partial interface Navigator {
+  [Throws, Pref="dom.gamepad.enabled"]
+  sequence<Gamepad?> getGamepads();
+};
+#endif // MOZ_GAMEPAD
+
+#ifdef MOZ_B2G_BT
+// nsIDOMNavigatorBluetooth
+interface MozBluetoothManager;
+partial interface Navigator {
+  [Throws, Func="Navigator::HasBluetoothSupport"]
+  readonly attribute MozBluetoothManager mozBluetooth;
+};
+#endif // MOZ_B2G_BT
+
+#ifdef MOZ_TIME_MANAGER
+// nsIDOMMozNavigatorTime
+partial interface Navigator {
+  [Throws, Func="Navigator::HasTimeSupport"]
+  readonly attribute MozTimeManager mozTime;
+};
+#endif // MOZ_TIME_MANAGER
+
+#ifdef MOZ_AUDIO_CHANNEL_MANAGER
+// nsIMozNavigatorAudioChannelManager
+partial interface Navigator {
+  [Throws]
+  readonly attribute AudioChannelManager mozAudioChannelManager;
+};
+#endif // MOZ_AUDIO_CHANNEL_MANAGER