Bug 678694 - (6/7) hal code for the Battery API. r=cjones
authorMounir Lamouri <mounir.lamouri@gmail.com>
Wed, 02 Nov 2011 16:14:01 +0100
changeset 80192 6450bedb1f3c42aa00999b1dcce5a3c04050b959
parent 80191 718e0171d5d2cd0f76bba9f72bac754d1327ae0e
child 80193 64f25813b37274b634eae62665df938533f54b41
push idunknown
push userunknown
push dateunknown
reviewerscjones
bugs678694
milestone10.0a1
Bug 678694 - (6/7) hal code for the Battery API. r=cjones
dom/battery/Makefile.in
dom/battery/Types.h
hal/Hal.cpp
hal/Hal.h
hal/HalSandbox.h
hal/fallback/FallbackHal.cpp
hal/sandbox/PHal.ipdl
hal/sandbox/SandboxHal.cpp
--- a/dom/battery/Makefile.in
+++ b/dom/battery/Makefile.in
@@ -47,16 +47,17 @@ LIBXUL_LIBRARY   = 1
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/dom/dom-config.mk
 
 EXPORTS_NAMESPACES = mozilla/dom/battery
 
 EXPORTS_mozilla/dom/battery = \
   Constants.h \
+  Types.h \
   $(NULL)
 
 CPPSRCS = \
   BatteryManager.cpp \
   $(NULL)
 
 LOCAL_INCLUDES = \
   -I$(topsrcdir)/content/events/src \
new file mode 100644
--- /dev/null
+++ b/dom/battery/Types.h
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Mounir Lamouri <mounir.lamouri@mozilla.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef mozilla_dom_battery_Types_h
+#define mozilla_dom_battery_Types_h
+
+namespace mozilla {
+namespace hal {
+class BatteryInformation;
+} // namespace hal
+
+template <class T>
+class Observer;
+
+typedef Observer<hal::BatteryInformation> BatteryObserver;
+
+} // namespace mozilla
+
+#endif // mozilla_dom_battery_Types_h
+
--- a/hal/Hal.cpp
+++ b/hal/Hal.cpp
@@ -36,16 +36,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "Hal.h"
 #include "mozilla/Util.h"
 #include "nsThreadUtils.h"
 #include "nsXULAppAPI.h"
+#include "mozilla/Observer.h"
 
 #define PROXY_IF_SANDBOXED(_call)                 \
   do {                                            \
     if (InSandbox()) {                            \
       hal_sandbox::_call;                         \
     } else {                                      \
       hal_impl::_call;                            \
     }                                             \
@@ -68,10 +69,104 @@ InSandbox()
 
 void
 Vibrate(const nsTArray<uint32>& pattern)
 {
   AssertMainThread();
   PROXY_IF_SANDBOXED(Vibrate(pattern));
 }
 
+class BatteryObserversManager
+{
+public:
+  void AddObserver(BatteryObserver* aObserver) {
+    if (!mObservers) {
+      mObservers = new ObserverList<BatteryInformation>();
+    }
+
+    mObservers->AddObserver(aObserver);
+
+    if (mObservers->Length() == 1) {
+      PROXY_IF_SANDBOXED(EnableBatteryNotifications());
+    }
+  }
+
+  void RemoveObserver(BatteryObserver* aObserver) {
+    mObservers->RemoveObserver(aObserver);
+
+    if (mObservers->Length() == 0) {
+      PROXY_IF_SANDBOXED(DisableBatteryNotifications());
+
+      delete mObservers;
+      mObservers = 0;
+
+      delete mBatteryInfo;
+      mBatteryInfo = 0;
+    }
+  }
+
+  void CacheBatteryInformation(const BatteryInformation& aBatteryInfo) {
+    if (mBatteryInfo) {
+      delete mBatteryInfo;
+    }
+    mBatteryInfo = new BatteryInformation(aBatteryInfo);
+  }
+
+  bool HasCachedBatteryInformation() const {
+    return mBatteryInfo;
+  }
+
+  void GetCachedBatteryInformation(BatteryInformation* aBatteryInfo) const {
+    *aBatteryInfo = *mBatteryInfo;
+  }
+
+  void Broadcast(const BatteryInformation& aBatteryInfo) {
+    MOZ_ASSERT(mObservers);
+    mObservers->Broadcast(aBatteryInfo);
+  }
+
+private:
+  ObserverList<BatteryInformation>* mObservers;
+  BatteryInformation*               mBatteryInfo;
+};
+
+static BatteryObserversManager sBatteryObservers;
+
+void
+RegisterBatteryObserver(BatteryObserver* aBatteryObserver)
+{
+  AssertMainThread();
+  sBatteryObservers.AddObserver(aBatteryObserver);
+}
+
+void
+UnregisterBatteryObserver(BatteryObserver* aBatteryObserver)
+{
+  AssertMainThread();
+  sBatteryObservers.RemoveObserver(aBatteryObserver);
+}
+
+// EnableBatteryNotifications isn't defined on purpose.
+// DisableBatteryNotifications isn't defined on purpose.
+
+void
+GetCurrentBatteryInformation(BatteryInformation* aBatteryInfo)
+{
+  AssertMainThread();
+
+  if (sBatteryObservers.HasCachedBatteryInformation()) {
+    sBatteryObservers.GetCachedBatteryInformation(aBatteryInfo);
+  } else {
+    PROXY_IF_SANDBOXED(GetCurrentBatteryInformation(aBatteryInfo));
+    sBatteryObservers.CacheBatteryInformation(*aBatteryInfo);
+  }
+}
+
+void NotifyBatteryChange(const BatteryInformation& aBatteryInfo)
+{
+  AssertMainThread();
+
+  sBatteryObservers.CacheBatteryInformation(aBatteryInfo);
+  sBatteryObservers.Broadcast(aBatteryInfo);
+}
+
 } // namespace hal
 } // namespace mozilla
--- a/hal/Hal.h
+++ b/hal/Hal.h
@@ -38,16 +38,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef mozilla_Hal_h
 #define mozilla_Hal_h 1
 
 #include "base/basictypes.h"
 #include "mozilla/Types.h"
 #include "nsTArray.h"
+#include "mozilla/dom/battery/Types.h"
 
 #ifndef MOZ_HAL_NAMESPACE
 // This goop plays some cpp tricks to ensure a uniform API across the
 // API entry point, "sandbox" implementations (for content processes),
 // and "impl" backends where the real work happens.  After this runs
 // through cpp, there will be three sets of identical APIs
 //   hal_impl:: --- the platform-specific implementation of an API.
 //   hal_sandbox:: --- forwards calls up to the parent process
@@ -58,28 +59,74 @@
 // directly.
 # include "HalImpl.h"
 # include "HalSandbox.h"
 # define MOZ_HAL_NAMESPACE hal
 # define MOZ_DEFINED_HAL_NAMESPACE 1
 #endif
 
 namespace mozilla {
+
+namespace hal {
+class BatteryInformation;
+} // namespace hal
+
 namespace MOZ_HAL_NAMESPACE /*hal*/ {
 
 /**
  * Turn the default vibrator device on/off per the pattern specified
  * by |pattern|.  Each element in the pattern is the number of
  * milliseconds to turn the vibrator on or off.  The first element in
  * |pattern| is an "on" element, the next is "off", and so on.
  *
  * If |pattern| is empty, any in-progress vibration is canceled.
  */
 void Vibrate(const nsTArray<uint32>& pattern);
 
+/**
+ * Inform the battery backend there is a new battery observer.
+ * @param aBatteryObserver The observer that should be added.
+ */
+void RegisterBatteryObserver(BatteryObserver* aBatteryObserver);
+
+/**
+ * Inform the battery backend a battery observer unregistered.
+ * @param aBatteryObserver The observer that should be removed.
+ */
+void UnregisterBatteryObserver(BatteryObserver* aBatteryObserver);
+
+/**
+ * Enables battery notifications from the backend.
+ *
+ * This method is semi-private in the sense of it is visible in the hal
+ * namespace but should not be used. Calls to this method from the hal
+ * namespace will produce a link error because it is not defined.
+ */
+void EnableBatteryNotifications();
+
+/**
+ * Disables battery notifications from the backend.
+ *
+ * This method is semi-private in the sense of it is visible in the hal
+ * namespace but should not be used. Calls to this method from the hal
+ * namespace will produce a link error because it is not defined.
+ */
+void DisableBatteryNotifications();
+
+/**
+ * Returns the current battery information.
+ */
+void GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInfo);
+
+/**
+ * Notify of a change in the battery state.
+ * @param aBatteryInfo The new battery information.
+ */
+void NotifyBatteryChange(const hal::BatteryInformation& aBatteryInfo);
+
 }
 }
 
 #ifdef MOZ_DEFINED_HAL_NAMESPACE
 # undef MOZ_DEFINED_HAL_NAMESPACE
 # undef MOZ_HAL_NAMESPACE
 #endif
 
--- a/hal/HalSandbox.h
+++ b/hal/HalSandbox.h
@@ -39,9 +39,10 @@
 
 #ifndef mozilla_Hal_h
 # error "This is an internal file, don't include it"
 #endif
 
 #undef mozilla_Hal_h
 #define MOZ_HAL_NAMESPACE hal_sandbox
 #include "Hal.h"
+#include "mozilla/hal_sandbox/PHal.h"
 #undef MOZ_HAL_NAMESPACE
--- a/hal/fallback/FallbackHal.cpp
+++ b/hal/fallback/FallbackHal.cpp
@@ -33,18 +33,34 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "Hal.h"
+#include "mozilla/dom/battery/Constants.h"
 
 namespace mozilla {
 namespace hal_impl {
 
 void
 Vibrate(const nsTArray<uint32>& pattern)
 {}
 
+void
+EnableBatteryNotifications()
+{}
+
+void
+DisableBatteryNotifications()
+{}
+
+void
+GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInfo)
+{
+  aBatteryInfo->level() = dom::battery::kDefaultLevel;
+  aBatteryInfo->charging() = dom::battery::kDefaultCharging;
+}
+
 } // hal_impl
 } // namespace mozilla
--- a/hal/sandbox/PHal.ipdl
+++ b/hal/sandbox/PHal.ipdl
@@ -35,21 +35,37 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 include protocol PContent;
 
 namespace mozilla {
+
+namespace hal {
+  struct BatteryInformation {
+    float level;
+    bool  charging;
+  };
+}
+
 namespace hal_sandbox {
 
-protocol PHal {
+sync protocol PHal {
     manager PContent;
 
+child:
+    NotifyBatteryChange(BatteryInformation aBatteryInfo);
+
 parent:
     Vibrate(uint32[] pattern);
 
+    EnableBatteryNotifications();
+    DisableBatteryNotifications();
+    sync GetCurrentBatteryInformation()
+      returns (BatteryInformation aBatteryInfo);
+
     __delete__();
 };
 
 } // namespace hal
 } // namespace mozilla
--- a/hal/sandbox/SandboxHal.cpp
+++ b/hal/sandbox/SandboxHal.cpp
@@ -36,16 +36,19 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "Hal.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/hal_sandbox/PHalChild.h"
 #include "mozilla/hal_sandbox/PHalParent.h"
+#include "mozilla/dom/battery/Types.h"
+#include "mozilla/Observer.h"
+#include "mozilla/unused.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::hal;
 
 namespace mozilla {
 namespace hal_sandbox {
 
@@ -61,30 +64,76 @@ Hal()
 
 void
 Vibrate(const nsTArray<uint32>& pattern)
 {
   AutoInfallibleTArray<uint32, 8> p(pattern);
   Hal()->SendVibrate(p);
 }
 
-class HalParent : public PHalParent {
+void
+EnableBatteryNotifications()
+{
+  Hal()->SendEnableBatteryNotifications();
+}
+
+void
+DisableBatteryNotifications()
+{
+  Hal()->SendDisableBatteryNotifications();
+}
+
+void
+GetCurrentBatteryInformation(BatteryInformation* aBatteryInfo)
+{
+  Hal()->SendGetCurrentBatteryInformation(aBatteryInfo);
+}
+
+class HalParent : public PHalParent
+                , public BatteryObserver {
 public:
   NS_OVERRIDE virtual bool
   RecvVibrate(const InfallibleTArray<unsigned int>& pattern) {
     // Forward to hal::, not hal_impl::, because we might be a
     // subprocess of another sandboxed process.  The hal:: entry point
     // will do the right thing.
     hal::Vibrate(pattern);
     return true;
   }
+
+  NS_OVERRIDE virtual bool
+  RecvEnableBatteryNotifications() {
+    hal::RegisterBatteryObserver(this);
+    return true;
+  }
+
+  NS_OVERRIDE virtual bool
+  RecvDisableBatteryNotifications() {
+    hal::UnregisterBatteryObserver(this);
+    return true;
+  }
+
+  NS_OVERRIDE virtual bool
+  RecvGetCurrentBatteryInformation(BatteryInformation* aBatteryInfo) {
+    hal::GetCurrentBatteryInformation(aBatteryInfo);
+    return true;
+  }
+
+  void Notify(const BatteryInformation& aBatteryInfo) {
+    unused << SendNotifyBatteryChange(aBatteryInfo);
+  }
 };
 
 class HalChild : public PHalChild {
 public:
+  NS_OVERRIDE virtual bool
+  RecvNotifyBatteryChange(const BatteryInformation& aBatteryInfo) {
+    hal::NotifyBatteryChange(aBatteryInfo);
+    return true;
+  }
 };
 
 PHalChild* CreateHalChild() {
   return new HalChild();
 }
 
 PHalParent* CreateHalParent() {
   return new HalParent();