hal/windows/WindowsBattery.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "Hal.h"
     7 #include "HalImpl.h"
     8 #include "nsITimer.h"
     9 #include "mozilla/Preferences.h"
    10 #include "mozilla/dom/battery/Constants.h"
    11 #include "nsComponentManagerUtils.h"
    13 #include <windows.h>
    14 #include "mozilla/WindowsVersion.h"
    16 using namespace mozilla::dom::battery;
    18 namespace mozilla {
    19 namespace hal_impl {
    21 static nsCOMPtr<nsITimer> sUpdateTimer;
    23 /* Power Event API is Vista or later */
    24 static decltype(RegisterPowerSettingNotification)* sRegisterPowerSettingNotification = nullptr;
    25 static decltype(UnregisterPowerSettingNotification)* sUnregisterPowerSettingNotification = nullptr;
    26 static HPOWERNOTIFY sPowerHandle = nullptr;
    27 static HPOWERNOTIFY sCapacityHandle = nullptr;
    28 static HWND sHWnd = nullptr;
    30 static void
    31 UpdateHandler(nsITimer* aTimer, void* aClosure) {
    32   NS_ASSERTION(!IsVistaOrLater(),
    33                "We shouldn't call this function for Vista or later version!");
    35   static hal::BatteryInformation sLastInfo;
    36   hal::BatteryInformation currentInfo;
    38   hal_impl::GetCurrentBatteryInformation(&currentInfo);
    39   if (sLastInfo.level() != currentInfo.level() ||
    40       sLastInfo.charging() != currentInfo.charging() ||
    41       sLastInfo.remainingTime() != currentInfo.remainingTime()) {
    42     hal::NotifyBatteryChange(currentInfo);
    43     sLastInfo = currentInfo;
    44   }
    45 }
    47 static
    48 LRESULT CALLBACK
    49 BatteryWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    50   if (msg != WM_POWERBROADCAST || wParam != PBT_POWERSETTINGCHANGE) {
    51     return DefWindowProc(hwnd, msg, wParam, lParam);
    52   }
    54   hal::BatteryInformation currentInfo;
    56   // Since we need update remainingTime, we cannot use LPARAM.
    57   hal_impl::GetCurrentBatteryInformation(&currentInfo);
    59   hal::NotifyBatteryChange(currentInfo);
    60   return TRUE;
    61 }
    63 void
    64 EnableBatteryNotifications()
    65 {
    66   if (IsVistaOrLater()) {
    67     // RegisterPowerSettingNotification is from Vista or later.
    68     // Use this API if available.
    69     HMODULE hUser32 = GetModuleHandleW(L"USER32.DLL");
    70     if (!sRegisterPowerSettingNotification)
    71       sRegisterPowerSettingNotification = (decltype(RegisterPowerSettingNotification)*)
    72         GetProcAddress(hUser32, "RegisterPowerSettingNotification");
    73     if (!sUnregisterPowerSettingNotification)
    74       sUnregisterPowerSettingNotification = (decltype(UnregisterPowerSettingNotification)*)
    75         GetProcAddress(hUser32, "UnregisterPowerSettingNotification");
    77     if (!sRegisterPowerSettingNotification ||
    78         !sUnregisterPowerSettingNotification) {
    79       NS_ASSERTION(false, "Canot find PowerSettingNotification functions.");
    80       return;
    81     }
    83     // Create custom window to watch battery event
    84     // If we can get Gecko's window handle, this is unnecessary.
    86     if (sHWnd == nullptr) {
    87       WNDCLASSW wc;
    88       HMODULE hSelf = GetModuleHandle(nullptr);
    90       if (!GetClassInfoW(hSelf, L"MozillaBatteryClass", &wc)) {
    91         ZeroMemory(&wc, sizeof(WNDCLASSW));
    92         wc.hInstance = hSelf;
    93         wc.lpfnWndProc = BatteryWindowProc;
    94         wc.lpszClassName = L"MozillaBatteryClass";
    95         RegisterClassW(&wc);
    96       }
    98       sHWnd = CreateWindowW(L"MozillaBatteryClass", L"Battery Watcher",
    99                             0, 0, 0, 0, 0,
   100                             nullptr, nullptr, hSelf, nullptr);
   101     }
   103     if (sHWnd == nullptr) {
   104       return;
   105     }
   107     sPowerHandle =
   108       sRegisterPowerSettingNotification(sHWnd,
   109                                         &GUID_ACDC_POWER_SOURCE,
   110                                         DEVICE_NOTIFY_WINDOW_HANDLE);
   111     sCapacityHandle =
   112       sRegisterPowerSettingNotification(sHWnd,
   113                                         &GUID_BATTERY_PERCENTAGE_REMAINING,
   114                                         DEVICE_NOTIFY_WINDOW_HANDLE);
   115   } else
   116   {
   117     // for Windows XP.  If we remove Windows XP support,
   118     // we should remove timer-based power notification
   119     sUpdateTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
   120     if (sUpdateTimer) {
   121       sUpdateTimer->InitWithFuncCallback(UpdateHandler,
   122                                          nullptr,
   123                                          Preferences::GetInt("dom.battery.timer",
   124                                                              30000 /* 30s */),
   125                                          nsITimer::TYPE_REPEATING_SLACK);
   126     } 
   127   }
   128 }
   130 void
   131 DisableBatteryNotifications()
   132 {
   133   if (IsVistaOrLater()) {
   134     if (sPowerHandle) {
   135       sUnregisterPowerSettingNotification(sPowerHandle);
   136       sPowerHandle = nullptr;
   137     }
   139     if (sCapacityHandle) {
   140       sUnregisterPowerSettingNotification(sCapacityHandle);
   141       sCapacityHandle = nullptr;
   142     }
   144     if (sHWnd) {
   145       DestroyWindow(sHWnd);
   146       sHWnd = nullptr;
   147     }
   148   } else
   149   {
   150     if (sUpdateTimer) {
   151       sUpdateTimer->Cancel();
   152       sUpdateTimer = nullptr;
   153     }
   154   }
   155 }
   157 void
   158 GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInfo)
   159 {
   160   SYSTEM_POWER_STATUS status;
   161   if (!GetSystemPowerStatus(&status)) {
   162     aBatteryInfo->level() = kDefaultLevel;
   163     aBatteryInfo->charging() = kDefaultCharging;
   164     aBatteryInfo->remainingTime() = kDefaultRemainingTime;
   165     return;
   166   }
   168   aBatteryInfo->level() =
   169     status.BatteryLifePercent == 255 ? kDefaultLevel
   170                                      : ((double)status.BatteryLifePercent) / 100.0;
   171   aBatteryInfo->charging() = (status.ACLineStatus != 0);
   172   if (status.ACLineStatus != 0) {
   173     if (aBatteryInfo->level() == 1.0) {
   174       // GetSystemPowerStatus API may returns -1 for BatteryFullLifeTime.
   175       // So, if battery is 100%, set kDefaultRemainingTime at force.
   176       aBatteryInfo->remainingTime() = kDefaultRemainingTime;
   177     } else {
   178       aBatteryInfo->remainingTime() =
   179         status.BatteryFullLifeTime == (DWORD)-1 ? kUnknownRemainingTime
   180                                                 : status.BatteryFullLifeTime;
   181     }
   182   } else {
   183     aBatteryInfo->remainingTime() =
   184       status.BatteryLifeTime == (DWORD)-1 ? kUnknownRemainingTime
   185                                           : status.BatteryLifeTime;
   186   }
   187 }
   189 } // hal_impl
   190 } // mozilla

mercurial