LCOV - code coverage report
Current view: directory - hal - Hal.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 235 11 4.7 %
Date: 2012-06-02 Functions: 80 14 17.5 %

       1                 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* vim: set sw=2 ts=8 et ft=cpp : */
       3                 : /* This Source Code Form is subject to the terms of the Mozilla Public
       4                 :  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
       5                 :  * You can obtain one at http://mozilla.org/MPL/2.0/. */
       6                 : 
       7                 : #include "Hal.h"
       8                 : #include "HalImpl.h"
       9                 : #include "HalSandbox.h"
      10                 : #include "mozilla/Util.h"
      11                 : #include "nsThreadUtils.h"
      12                 : #include "nsXULAppAPI.h"
      13                 : #include "mozilla/Observer.h"
      14                 : #include "nsIDOMDocument.h"
      15                 : #include "nsIDOMWindow.h"
      16                 : #include "mozilla/Services.h"
      17                 : #include "nsIWebNavigation.h"
      18                 : #include "nsITabChild.h"
      19                 : #include "nsIDocShell.h"
      20                 : #include "mozilla/ClearOnShutdown.h"
      21                 : #include "WindowIdentifier.h"
      22                 : 
      23                 : using namespace mozilla::services;
      24                 : 
      25                 : #define PROXY_IF_SANDBOXED(_call)                 \
      26                 :   do {                                            \
      27                 :     if (InSandbox()) {                            \
      28                 :       hal_sandbox::_call;                         \
      29                 :     } else {                                      \
      30                 :       hal_impl::_call;                            \
      31                 :     }                                             \
      32                 :   } while (0)
      33                 : 
      34                 : #define RETURN_PROXY_IF_SANDBOXED(_call)          \
      35                 :   do {                                            \
      36                 :     if (InSandbox()) {                            \
      37                 :       return hal_sandbox::_call;                  \
      38                 :     } else {                                      \
      39                 :       return hal_impl::_call;                     \
      40                 :     }                                             \
      41                 :   } while (0)
      42                 : 
      43                 : namespace mozilla {
      44                 : namespace hal {
      45                 : 
      46            1464 : PRLogModuleInfo *sHalLog = PR_LOG_DEFINE("hal");
      47                 : 
      48                 : namespace {
      49                 : 
      50                 : void
      51               0 : AssertMainThread()
      52                 : {
      53               0 :   MOZ_ASSERT(NS_IsMainThread());
      54               0 : }
      55                 : 
      56                 : bool
      57               0 : InSandbox()
      58                 : {
      59               0 :   return GeckoProcessType_Content == XRE_GetProcessType();
      60                 : }
      61                 : 
      62                 : bool
      63               0 : WindowIsActive(nsIDOMWindow *window)
      64                 : {
      65               0 :   NS_ENSURE_TRUE(window, false);
      66                 : 
      67               0 :   nsCOMPtr<nsIDOMDocument> doc;
      68               0 :   window->GetDocument(getter_AddRefs(doc));
      69               0 :   NS_ENSURE_TRUE(doc, false);
      70                 : 
      71               0 :   bool hidden = true;
      72               0 :   doc->GetMozHidden(&hidden);
      73               0 :   return !hidden;
      74                 : }
      75                 : 
      76            1464 : nsAutoPtr<WindowIdentifier::IDArrayType> gLastIDToVibrate;
      77                 : 
      78               0 : void InitLastIDToVibrate()
      79                 : {
      80               0 :   gLastIDToVibrate = new WindowIdentifier::IDArrayType();
      81               0 :   ClearOnShutdown(&gLastIDToVibrate);
      82               0 : }
      83                 : 
      84                 : } // anonymous namespace
      85                 : 
      86                 : void
      87               0 : Vibrate(const nsTArray<uint32>& pattern, nsIDOMWindow* window)
      88                 : {
      89               0 :   Vibrate(pattern, WindowIdentifier(window));
      90               0 : }
      91                 : 
      92                 : void
      93               0 : Vibrate(const nsTArray<uint32>& pattern, const WindowIdentifier &id)
      94                 : {
      95               0 :   AssertMainThread();
      96                 : 
      97                 :   // Only active windows may start vibrations.  If |id| hasn't gone
      98                 :   // through the IPC layer -- that is, if our caller is the outside
      99                 :   // world, not hal_proxy -- check whether the window is active.  If
     100                 :   // |id| has gone through IPC, don't check the window's visibility;
     101                 :   // only the window corresponding to the bottommost process has its
     102                 :   // visibility state set correctly.
     103               0 :   if (!id.HasTraveledThroughIPC() && !WindowIsActive(id.GetWindow())) {
     104               0 :     HAL_LOG(("Vibrate: Window is inactive, dropping vibrate."));
     105               0 :     return;
     106                 :   }
     107                 : 
     108               0 :   if (InSandbox()) {
     109               0 :     hal_sandbox::Vibrate(pattern, id);
     110                 :   }
     111                 :   else {
     112               0 :     if (!gLastIDToVibrate)
     113               0 :       InitLastIDToVibrate();
     114               0 :     *gLastIDToVibrate = id.AsArray();
     115                 : 
     116               0 :     HAL_LOG(("Vibrate: Forwarding to hal_impl."));
     117                 : 
     118                 :     // hal_impl doesn't need |id|. Send it an empty id, which will
     119                 :     // assert if it's used.
     120               0 :     hal_impl::Vibrate(pattern, WindowIdentifier());
     121                 :   }
     122                 : }
     123                 : 
     124                 : void
     125               0 : CancelVibrate(nsIDOMWindow* window)
     126                 : {
     127               0 :   CancelVibrate(WindowIdentifier(window));
     128               0 : }
     129                 : 
     130                 : void
     131               0 : CancelVibrate(const WindowIdentifier &id)
     132                 : {
     133               0 :   AssertMainThread();
     134                 : 
     135                 :   // Although only active windows may start vibrations, a window may
     136                 :   // cancel its own vibration even if it's no longer active.
     137                 :   //
     138                 :   // After a window is marked as inactive, it sends a CancelVibrate
     139                 :   // request.  We want this request to cancel a playing vibration
     140                 :   // started by that window, so we certainly don't want to reject the
     141                 :   // cancellation request because the window is now inactive.
     142                 :   //
     143                 :   // But it could be the case that, after this window became inactive,
     144                 :   // some other window came along and started a vibration.  We don't
     145                 :   // want this window's cancellation request to cancel that window's
     146                 :   // actively-playing vibration!
     147                 :   //
     148                 :   // To solve this problem, we keep track of the id of the last window
     149                 :   // to start a vibration, and only accepts cancellation requests from
     150                 :   // the same window.  All other cancellation requests are ignored.
     151                 : 
     152               0 :   if (InSandbox()) {
     153               0 :     hal_sandbox::CancelVibrate(id);
     154                 :   }
     155               0 :   else if (*gLastIDToVibrate == id.AsArray()) {
     156                 :     // Don't forward our ID to hal_impl. It doesn't need it, and we
     157                 :     // don't want it to be tempted to read it.  The empty identifier
     158                 :     // will assert if it's used.
     159               0 :     HAL_LOG(("CancelVibrate: Forwarding to hal_impl."));
     160               0 :     hal_impl::CancelVibrate(WindowIdentifier());
     161                 :   }
     162               0 : }
     163                 : 
     164                 : template <class InfoType>
     165                 : class ObserversManager
     166            4392 : {
     167                 : public:
     168               0 :   void AddObserver(Observer<InfoType>* aObserver) {
     169               0 :     if (!mObservers) {
     170               0 :       mObservers = new mozilla::ObserverList<InfoType>();
     171                 :     }
     172                 : 
     173               0 :     mObservers->AddObserver(aObserver);
     174                 : 
     175               0 :     if (mObservers->Length() == 1) {
     176               0 :       EnableNotifications();
     177                 :     }
     178               0 :   }
     179                 : 
     180               0 :   void RemoveObserver(Observer<InfoType>* aObserver) {
     181               0 :     MOZ_ASSERT(mObservers);
     182               0 :     mObservers->RemoveObserver(aObserver);
     183                 : 
     184               0 :     if (mObservers->Length() == 0) {
     185               0 :       DisableNotifications();
     186                 : 
     187               0 :       OnNotificationsDisabled();
     188                 : 
     189               0 :       delete mObservers;
     190               0 :       mObservers = 0;
     191                 :     }
     192               0 :   }
     193                 : 
     194               0 :   void BroadcastInformation(const InfoType& aInfo) {
     195               0 :     MOZ_ASSERT(mObservers);
     196               0 :     mObservers->Broadcast(aInfo);
     197               0 :   }
     198                 : 
     199                 : protected:
     200                 :   virtual void EnableNotifications() = 0;
     201                 :   virtual void DisableNotifications() = 0;
     202               0 :   virtual void OnNotificationsDisabled() {}
     203                 : 
     204                 : private:
     205                 :   mozilla::ObserverList<InfoType>* mObservers;
     206                 : };
     207                 : 
     208                 : template <class InfoType>
     209                 : class CachingObserversManager : public ObserversManager<InfoType>
     210            5902 : {
     211                 : public:
     212               0 :   InfoType GetCurrentInformation() {
     213               0 :     if (mHasValidCache) {
     214               0 :       return mInfo;
     215                 :     }
     216                 : 
     217               0 :     GetCurrentInformationInternal(&mInfo);
     218               0 :     return mInfo;
     219                 :   }
     220                 : 
     221               0 :   void CacheInformation(const InfoType& aInfo) {
     222               0 :     mHasValidCache = true;
     223               0 :     mInfo = aInfo;
     224               0 :   }
     225                 : 
     226               0 :   void BroadcastCachedInformation() {
     227               0 :     this->BroadcastInformation(mInfo);
     228               0 :   }
     229                 : 
     230                 : protected:
     231                 :   virtual void GetCurrentInformationInternal(InfoType*) = 0;
     232                 : 
     233               0 :   virtual void OnNotificationsDisabled() {
     234               0 :     mHasValidCache = false;
     235               0 :   }
     236                 : 
     237                 : private:
     238                 :   InfoType                mInfo;
     239                 :   bool                    mHasValidCache;
     240                 : };
     241                 : 
     242                 : class BatteryObserversManager : public CachingObserversManager<BatteryInformation>
     243            2951 : {
     244                 : protected:
     245               0 :   void EnableNotifications() {
     246               0 :     PROXY_IF_SANDBOXED(EnableBatteryNotifications());
     247               0 :   }
     248                 : 
     249               0 :   void DisableNotifications() {
     250               0 :     PROXY_IF_SANDBOXED(DisableBatteryNotifications());
     251               0 :   }
     252                 : 
     253               0 :   void GetCurrentInformationInternal(BatteryInformation* aInfo) {
     254               0 :     PROXY_IF_SANDBOXED(GetCurrentBatteryInformation(aInfo));
     255               0 :   }
     256                 : };
     257                 : 
     258            1464 : static BatteryObserversManager sBatteryObservers;
     259                 : 
     260                 : class NetworkObserversManager : public CachingObserversManager<NetworkInformation>
     261            2951 : {
     262                 : protected:
     263               0 :   void EnableNotifications() {
     264               0 :     PROXY_IF_SANDBOXED(EnableNetworkNotifications());
     265               0 :   }
     266                 : 
     267               0 :   void DisableNotifications() {
     268               0 :     PROXY_IF_SANDBOXED(DisableNetworkNotifications());
     269               0 :   }
     270                 : 
     271               0 :   void GetCurrentInformationInternal(NetworkInformation* aInfo) {
     272               0 :     PROXY_IF_SANDBOXED(GetCurrentNetworkInformation(aInfo));
     273               0 :   }
     274                 : };
     275                 : 
     276            1464 : static NetworkObserversManager sNetworkObservers;
     277                 : 
     278                 : class WakeLockObserversManager : public ObserversManager<WakeLockInformation>
     279            1464 : {
     280                 : protected:
     281               0 :   void EnableNotifications() {
     282               0 :     PROXY_IF_SANDBOXED(EnableWakeLockNotifications());
     283               0 :   }
     284                 : 
     285               0 :   void DisableNotifications() {
     286               0 :     PROXY_IF_SANDBOXED(DisableWakeLockNotifications());
     287               0 :   }
     288                 : };
     289                 : 
     290            1464 : static WakeLockObserversManager sWakeLockObservers;
     291                 : 
     292                 : void
     293               0 : RegisterBatteryObserver(BatteryObserver* aObserver)
     294                 : {
     295               0 :   AssertMainThread();
     296               0 :   sBatteryObservers.AddObserver(aObserver);
     297               0 : }
     298                 : 
     299                 : void
     300               0 : UnregisterBatteryObserver(BatteryObserver* aObserver)
     301                 : {
     302               0 :   AssertMainThread();
     303               0 :   sBatteryObservers.RemoveObserver(aObserver);
     304               0 : }
     305                 : 
     306                 : void
     307               0 : GetCurrentBatteryInformation(BatteryInformation* aInfo)
     308                 : {
     309               0 :   AssertMainThread();
     310               0 :   *aInfo = sBatteryObservers.GetCurrentInformation();
     311               0 : }
     312                 : 
     313                 : void
     314               0 : NotifyBatteryChange(const BatteryInformation& aInfo)
     315                 : {
     316               0 :   AssertMainThread();
     317               0 :   sBatteryObservers.CacheInformation(aInfo);
     318               0 :   sBatteryObservers.BroadcastCachedInformation();
     319               0 : }
     320                 : 
     321               0 : bool GetScreenEnabled()
     322                 : {
     323               0 :   AssertMainThread();
     324               0 :   RETURN_PROXY_IF_SANDBOXED(GetScreenEnabled());
     325                 : }
     326                 : 
     327               0 : void SetScreenEnabled(bool enabled)
     328                 : {
     329               0 :   AssertMainThread();
     330               0 :   PROXY_IF_SANDBOXED(SetScreenEnabled(enabled));
     331               0 : }
     332                 : 
     333               0 : double GetScreenBrightness()
     334                 : {
     335               0 :   AssertMainThread();
     336               0 :   RETURN_PROXY_IF_SANDBOXED(GetScreenBrightness());
     337                 : }
     338                 : 
     339               0 : void SetScreenBrightness(double brightness)
     340                 : {
     341               0 :   AssertMainThread();
     342               0 :   PROXY_IF_SANDBOXED(SetScreenBrightness(clamped(brightness, 0.0, 1.0)));
     343               0 : }
     344                 : 
     345               0 : bool SetLight(LightType light, const hal::LightConfiguration& aConfig)
     346                 : {
     347               0 :   AssertMainThread();
     348               0 :   RETURN_PROXY_IF_SANDBOXED(SetLight(light, aConfig));
     349                 : }
     350                 : 
     351               0 : bool GetLight(LightType light, hal::LightConfiguration* aConfig)
     352                 : {
     353               0 :   AssertMainThread();
     354               0 :   RETURN_PROXY_IF_SANDBOXED(GetLight(light, aConfig));
     355                 : }
     356                 : 
     357                 : 
     358                 : void 
     359               0 : AdjustSystemClock(int32_t aDeltaMilliseconds)
     360                 : {
     361               0 :   AssertMainThread();
     362               0 :   PROXY_IF_SANDBOXED(AdjustSystemClock(aDeltaMilliseconds));
     363               0 : }
     364                 : 
     365                 : void 
     366               0 : SetTimezone(const nsCString& aTimezoneSpec)
     367                 : {
     368               0 :   AssertMainThread();
     369               0 :   PROXY_IF_SANDBOXED(SetTimezone(aTimezoneSpec));
     370               0 : }
     371                 : 
     372                 : void
     373               0 : EnableSensorNotifications(SensorType aSensor) {
     374               0 :   AssertMainThread();
     375               0 :   PROXY_IF_SANDBOXED(EnableSensorNotifications(aSensor));
     376               0 : }
     377                 : 
     378                 : void
     379               0 : DisableSensorNotifications(SensorType aSensor) {
     380               0 :   AssertMainThread();
     381               0 :   PROXY_IF_SANDBOXED(DisableSensorNotifications(aSensor));
     382               0 : }
     383                 : 
     384                 : typedef mozilla::ObserverList<SensorData> SensorObserverList;
     385                 : static SensorObserverList *gSensorObservers = NULL;
     386                 : 
     387                 : static SensorObserverList &
     388               0 : GetSensorObservers(SensorType sensor_type) {
     389               0 :   MOZ_ASSERT(sensor_type < NUM_SENSOR_TYPE);
     390                 :   
     391               0 :   if(gSensorObservers == NULL)
     392               0 :     gSensorObservers = new SensorObserverList[NUM_SENSOR_TYPE];
     393               0 :   return gSensorObservers[sensor_type];
     394                 : }
     395                 : 
     396                 : void
     397               0 : RegisterSensorObserver(SensorType aSensor, ISensorObserver *aObserver) {
     398               0 :   SensorObserverList &observers = GetSensorObservers(aSensor);
     399                 : 
     400               0 :   AssertMainThread();
     401                 :   
     402               0 :   observers.AddObserver(aObserver);
     403               0 :   if(observers.Length() == 1) {
     404               0 :     EnableSensorNotifications(aSensor);
     405                 :   }
     406               0 : }
     407                 : 
     408                 : void
     409               0 : UnregisterSensorObserver(SensorType aSensor, ISensorObserver *aObserver) {
     410               0 :   SensorObserverList &observers = GetSensorObservers(aSensor);
     411                 : 
     412               0 :   AssertMainThread();
     413                 :   
     414               0 :   observers.RemoveObserver(aObserver);
     415               0 :   if(observers.Length() == 0) {
     416               0 :     DisableSensorNotifications(aSensor);
     417                 :   }
     418               0 : }
     419                 : 
     420                 : void
     421               0 : NotifySensorChange(const SensorData &aSensorData) {
     422               0 :   SensorObserverList &observers = GetSensorObservers(aSensorData.sensor());
     423                 : 
     424               0 :   AssertMainThread();
     425                 :   
     426               0 :   observers.Broadcast(aSensorData);
     427               0 : }
     428                 : 
     429                 : void
     430               0 : RegisterNetworkObserver(NetworkObserver* aObserver)
     431                 : {
     432               0 :   AssertMainThread();
     433               0 :   sNetworkObservers.AddObserver(aObserver);
     434               0 : }
     435                 : 
     436                 : void
     437               0 : UnregisterNetworkObserver(NetworkObserver* aObserver)
     438                 : {
     439               0 :   AssertMainThread();
     440               0 :   sNetworkObservers.RemoveObserver(aObserver);
     441               0 : }
     442                 : 
     443                 : void
     444               0 : GetCurrentNetworkInformation(NetworkInformation* aInfo)
     445                 : {
     446               0 :   AssertMainThread();
     447               0 :   *aInfo = sNetworkObservers.GetCurrentInformation();
     448               0 : }
     449                 : 
     450                 : void
     451               0 : NotifyNetworkChange(const NetworkInformation& aInfo)
     452                 : {
     453               0 :   sNetworkObservers.CacheInformation(aInfo);
     454               0 :   sNetworkObservers.BroadcastCachedInformation();
     455               0 : }
     456                 : 
     457               0 : void Reboot()
     458                 : {
     459               0 :   AssertMainThread();
     460               0 :   PROXY_IF_SANDBOXED(Reboot());
     461               0 : }
     462                 : 
     463               0 : void PowerOff()
     464                 : {
     465               0 :   AssertMainThread();
     466               0 :   PROXY_IF_SANDBOXED(PowerOff());
     467               0 : }
     468                 : 
     469                 : void
     470               0 : RegisterWakeLockObserver(WakeLockObserver* aObserver)
     471                 : {
     472               0 :   AssertMainThread();
     473               0 :   sWakeLockObservers.AddObserver(aObserver);
     474               0 : }
     475                 : 
     476                 : void
     477               0 : UnregisterWakeLockObserver(WakeLockObserver* aObserver)
     478                 : {
     479               0 :   AssertMainThread();
     480               0 :   sWakeLockObservers.RemoveObserver(aObserver);
     481               0 : }
     482                 : 
     483                 : void
     484               0 : ModifyWakeLock(const nsAString &aTopic,
     485                 :                hal::WakeLockControl aLockAdjust,
     486                 :                hal::WakeLockControl aHiddenAdjust)
     487                 : {
     488               0 :   AssertMainThread();
     489               0 :   PROXY_IF_SANDBOXED(ModifyWakeLock(aTopic, aLockAdjust, aHiddenAdjust));
     490               0 : }
     491                 : 
     492                 : void
     493               0 : GetWakeLockInfo(const nsAString &aTopic, WakeLockInformation *aWakeLockInfo)
     494                 : {
     495               0 :   AssertMainThread();
     496               0 :   PROXY_IF_SANDBOXED(GetWakeLockInfo(aTopic, aWakeLockInfo));
     497               0 : }
     498                 : 
     499                 : void
     500               0 : NotifyWakeLockChange(const WakeLockInformation& aInfo)
     501                 : {
     502               0 :   AssertMainThread();
     503               0 :   sWakeLockObservers.BroadcastInformation(aInfo);
     504               0 : }
     505                 : 
     506                 : } // namespace hal
     507            4392 : } // namespace mozilla

Generated by: LCOV version 1.7