LCOV - code coverage report
Current view: top level - dom/power - PowerManagerService.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 18 93 19.4 %
Date: 2017-07-14 16:53:18 Functions: 6 19 31.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       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
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "mozilla/dom/ContentParent.h"
       8             : #include "mozilla/Hal.h"
       9             : #include "mozilla/HalWakeLock.h"
      10             : #include "mozilla/ClearOnShutdown.h"
      11             : #include "mozilla/Preferences.h"
      12             : #include "mozilla/Services.h"
      13             : #include "jsprf.h"
      14             : #include "nsIDOMWakeLockListener.h"
      15             : #include "nsIDOMWindow.h"
      16             : #include "nsIObserverService.h"
      17             : #include "PowerManagerService.h"
      18             : #include "WakeLock.h"
      19             : 
      20             : // For _exit().
      21             : #ifdef XP_WIN
      22             : #include <process.h>
      23             : #else
      24             : #include <unistd.h>
      25             : #endif
      26             : 
      27             : #ifdef ANDROID
      28             : #include <android/log.h>
      29             : extern "C" char* PrintJSStack();
      30             : static void LogFunctionAndJSStack(const char* funcname) {
      31             :   char *jsstack = PrintJSStack();
      32             :   __android_log_print(ANDROID_LOG_INFO, "PowerManagerService", \
      33             :                       "Call to %s. The JS stack is:\n%s\n",
      34             :                       funcname,
      35             :                       jsstack ? jsstack : "<no JS stack>");
      36             :   JS_smprintf_free(jsstack);
      37             : }
      38             : // bug 839452
      39             : #define LOG_FUNCTION_AND_JS_STACK() \
      40             :   LogFunctionAndJSStack(__PRETTY_FUNCTION__);
      41             : #else
      42             : #define LOG_FUNCTION_AND_JS_STACK()
      43             : #endif
      44             : 
      45             : namespace mozilla {
      46             : namespace dom {
      47             : namespace power {
      48             : 
      49             : using namespace hal;
      50             : 
      51          16 : NS_IMPL_ISUPPORTS(PowerManagerService, nsIPowerManagerService)
      52             : 
      53           3 : /* static */ StaticRefPtr<PowerManagerService> PowerManagerService::sSingleton;
      54             : 
      55             : /* static */ already_AddRefed<PowerManagerService>
      56           1 : PowerManagerService::GetInstance()
      57             : {
      58           1 :   if (!sSingleton) {
      59           1 :     sSingleton = new PowerManagerService();
      60           1 :     sSingleton->Init();
      61           1 :     ClearOnShutdown(&sSingleton);
      62             :   }
      63             : 
      64           2 :   RefPtr<PowerManagerService> service = sSingleton.get();
      65           2 :   return service.forget();
      66             : }
      67             : 
      68             : void
      69           1 : PowerManagerService::Init()
      70             : {
      71           1 :   RegisterWakeLockObserver(this);
      72             : 
      73             :   // NB: default to *enabling* the watchdog even when the pref is
      74             :   // absent, in case the profile might be damaged and we need to
      75             :   // restart to repair it.
      76           1 :   mWatchdogTimeoutSecs =
      77           1 :     Preferences::GetInt("shutdown.watchdog.timeoutSecs", 10);
      78           1 : }
      79             : 
      80           0 : PowerManagerService::~PowerManagerService()
      81             : {
      82           0 :   UnregisterWakeLockObserver(this);
      83           0 : }
      84             : 
      85             : void
      86           0 : PowerManagerService::ComputeWakeLockState(const WakeLockInformation& aWakeLockInfo,
      87             :                                           nsAString &aState)
      88             : {
      89           0 :   WakeLockState state = hal::ComputeWakeLockState(aWakeLockInfo.numLocks(),
      90           0 :                                                   aWakeLockInfo.numHidden());
      91           0 :   switch (state) {
      92             :   case WAKE_LOCK_STATE_UNLOCKED:
      93           0 :     aState.AssignLiteral("unlocked");
      94           0 :     break;
      95             :   case WAKE_LOCK_STATE_HIDDEN:
      96           0 :     aState.AssignLiteral("locked-background");
      97           0 :     break;
      98             :   case WAKE_LOCK_STATE_VISIBLE:
      99           0 :     aState.AssignLiteral("locked-foreground");
     100           0 :     break;
     101             :   }
     102           0 : }
     103             : 
     104             : void
     105           0 : PowerManagerService::Notify(const WakeLockInformation& aWakeLockInfo)
     106             : {
     107           0 :   nsAutoString state;
     108           0 :   ComputeWakeLockState(aWakeLockInfo, state);
     109             : 
     110             :   /**
     111             :    * Copy the listeners list before we walk through the callbacks
     112             :    * because the callbacks may install new listeners. We expect no
     113             :    * more than one listener per window, so it shouldn't be too long.
     114             :    */
     115           0 :   AutoTArray<nsCOMPtr<nsIDOMMozWakeLockListener>, 2> listeners(mWakeLockListeners);
     116             : 
     117           0 :   for (uint32_t i = 0; i < listeners.Length(); ++i) {
     118           0 :     listeners[i]->Callback(aWakeLockInfo.topic(), state);
     119             :   }
     120           0 : }
     121             : 
     122             : void
     123           0 : PowerManagerService::SyncProfile()
     124             : {
     125           0 :   nsCOMPtr<nsIObserverService> obsServ = services::GetObserverService();
     126           0 :   if (obsServ) {
     127           0 :     const char16_t* context = u"shutdown-persist";
     128           0 :     obsServ->NotifyObservers(nullptr, "profile-change-net-teardown", context);
     129           0 :     obsServ->NotifyObservers(nullptr, "profile-change-teardown", context);
     130           0 :     obsServ->NotifyObservers(nullptr, "profile-before-change", context);
     131           0 :     obsServ->NotifyObservers(nullptr, "profile-before-change-qm", context);
     132           0 :     obsServ->NotifyObservers(nullptr, "profile-before-change-telemetry", context);
     133             :   }
     134           0 : }
     135             : 
     136             : NS_IMETHODIMP
     137           0 : PowerManagerService::Reboot()
     138             : {
     139             :   LOG_FUNCTION_AND_JS_STACK() // bug 839452
     140             : 
     141           0 :   StartForceQuitWatchdog(eHalShutdownMode_Reboot, mWatchdogTimeoutSecs);
     142             :   // To synchronize any unsaved user data before rebooting.
     143           0 :   SyncProfile();
     144           0 :   hal::Reboot();
     145           0 :   MOZ_CRASH("hal::Reboot() shouldn't return");
     146             : }
     147             : 
     148             : NS_IMETHODIMP
     149           0 : PowerManagerService::PowerOff()
     150             : {
     151             :   LOG_FUNCTION_AND_JS_STACK() // bug 839452
     152             : 
     153           0 :   StartForceQuitWatchdog(eHalShutdownMode_PowerOff, mWatchdogTimeoutSecs);
     154             :   // To synchronize any unsaved user data before powering off.
     155           0 :   SyncProfile();
     156           0 :   hal::PowerOff();
     157           0 :   MOZ_CRASH("hal::PowerOff() shouldn't return");
     158             : }
     159             : 
     160             : NS_IMETHODIMP
     161           0 : PowerManagerService::Restart()
     162             : {
     163             :   LOG_FUNCTION_AND_JS_STACK() // bug 839452
     164             : 
     165             :   // FIXME/bug 796826 this implementation is currently gonk-specific,
     166             :   // because it relies on the Gonk to initialize the Gecko processes to
     167             :   // restart B2G. It's better to do it here to have a real "restart".
     168           0 :   StartForceQuitWatchdog(eHalShutdownMode_Restart, mWatchdogTimeoutSecs);
     169             :   // Ensure all content processes are dead before we continue
     170             :   // restarting.  This code is used to restart to apply updates, and
     171             :   // if we don't join all the subprocesses, race conditions can cause
     172             :   // them to see an inconsistent view of the application directory.
     173           0 :   ContentParent::JoinAllSubprocesses();
     174             : 
     175             :   // To synchronize any unsaved user data before restarting.
     176           0 :   SyncProfile();
     177             : #ifdef XP_UNIX
     178           0 :   sync();
     179             : #endif
     180           0 :   _exit(0);
     181             :   MOZ_CRASH("_exit() shouldn't return");
     182             : }
     183             : 
     184             : NS_IMETHODIMP
     185           1 : PowerManagerService::AddWakeLockListener(nsIDOMMozWakeLockListener *aListener)
     186             : {
     187           1 :   if (mWakeLockListeners.Contains(aListener))
     188           0 :     return NS_OK;
     189             : 
     190           1 :   mWakeLockListeners.AppendElement(aListener);
     191           1 :   return NS_OK;
     192             : }
     193             : 
     194             : NS_IMETHODIMP
     195           0 : PowerManagerService::RemoveWakeLockListener(nsIDOMMozWakeLockListener *aListener)
     196             : {
     197           0 :   mWakeLockListeners.RemoveElement(aListener);
     198           0 :   return NS_OK;
     199             : }
     200             : 
     201             : NS_IMETHODIMP
     202           0 : PowerManagerService::GetWakeLockState(const nsAString &aTopic, nsAString &aState)
     203             : {
     204           0 :   WakeLockInformation info;
     205           0 :   GetWakeLockInfo(aTopic, &info);
     206             : 
     207           0 :   ComputeWakeLockState(info, aState);
     208             : 
     209           0 :   return NS_OK;
     210             : }
     211             : 
     212             : already_AddRefed<WakeLock>
     213           0 : PowerManagerService::NewWakeLock(const nsAString& aTopic,
     214             :                                  nsPIDOMWindowInner* aWindow,
     215             :                                  mozilla::ErrorResult& aRv)
     216             : {
     217           0 :   RefPtr<WakeLock> wakelock = new WakeLock();
     218           0 :   aRv = wakelock->Init(aTopic, aWindow);
     219           0 :   if (aRv.Failed()) {
     220           0 :     return nullptr;
     221             :   }
     222             : 
     223           0 :   return wakelock.forget();
     224             : }
     225             : 
     226             : NS_IMETHODIMP
     227           0 : PowerManagerService::NewWakeLock(const nsAString &aTopic,
     228             :                                  mozIDOMWindow *aWindow,
     229             :                                  nsISupports **aWakeLock)
     230             : {
     231           0 :   mozilla::ErrorResult rv;
     232             :   RefPtr<WakeLock> wakelock =
     233           0 :     NewWakeLock(aTopic, nsPIDOMWindowInner::From(aWindow), rv);
     234           0 :   if (rv.Failed()) {
     235           0 :     return rv.StealNSResult();
     236             :   }
     237             : 
     238           0 :   nsCOMPtr<nsIDOMEventListener> eventListener = wakelock.get();
     239           0 :   eventListener.forget(aWakeLock);
     240           0 :   return NS_OK;
     241             : }
     242             : 
     243             : already_AddRefed<WakeLock>
     244           0 : PowerManagerService::NewWakeLockOnBehalfOfProcess(const nsAString& aTopic,
     245             :                                                   ContentParent* aContentParent)
     246             : {
     247           0 :   RefPtr<WakeLock> wakelock = new WakeLock();
     248           0 :   nsresult rv = wakelock->Init(aTopic, aContentParent);
     249           0 :   NS_ENSURE_SUCCESS(rv, nullptr);
     250           0 :   return wakelock.forget();
     251             : }
     252             : 
     253             : } // namespace power
     254             : } // namespace dom
     255             : } // namespace mozilla

Generated by: LCOV version 1.13