Bug 1828523 [wpt PR 39579] - Only restore dialog focus if focus is in the dialog...
[gecko.git] / dom / battery / BatteryManager.cpp
blob0a56f12af138fd22e45a721f964632375205657d
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/. */
7 #include <cmath>
8 #include <limits>
9 #include "BatteryManager.h"
10 #include "Constants.h"
11 #include "mozilla/DOMEventTargetHelper.h"
12 #include "mozilla/Hal.h"
13 #include "mozilla/dom/BatteryManagerBinding.h"
14 #include "mozilla/Preferences.h"
15 #include "nsContentUtils.h"
16 #include "mozilla/dom/Document.h"
18 /**
19 * We have to use macros here because our leak analysis tool things we are
20 * leaking strings when we have |static const nsString|. Sad :(
22 #define LEVELCHANGE_EVENT_NAME u"levelchange"_ns
23 #define CHARGINGCHANGE_EVENT_NAME u"chargingchange"_ns
24 #define DISCHARGINGTIMECHANGE_EVENT_NAME u"dischargingtimechange"_ns
25 #define CHARGINGTIMECHANGE_EVENT_NAME u"chargingtimechange"_ns
27 namespace mozilla::dom::battery {
29 BatteryManager::BatteryManager(nsPIDOMWindowInner* aWindow)
30 : DOMEventTargetHelper(aWindow),
31 mLevel(kDefaultLevel),
32 mCharging(kDefaultCharging),
33 mRemainingTime(kDefaultRemainingTime) {}
35 void BatteryManager::Init() {
36 hal::RegisterBatteryObserver(this);
38 hal::BatteryInformation batteryInfo;
39 hal::GetCurrentBatteryInformation(&batteryInfo);
41 UpdateFromBatteryInfo(batteryInfo);
44 void BatteryManager::Shutdown() { hal::UnregisterBatteryObserver(this); }
46 JSObject* BatteryManager::WrapObject(JSContext* aCx,
47 JS::Handle<JSObject*> aGivenProto) {
48 return BatteryManager_Binding::Wrap(aCx, this, aGivenProto);
51 bool BatteryManager::Charging() const {
52 MOZ_ASSERT(NS_IsMainThread());
53 // For testing, unable to report the battery status information
54 if (Preferences::GetBool("dom.battery.test.default", false)) {
55 return true;
57 if (Preferences::GetBool("dom.battery.test.charging", false)) {
58 return true;
60 if (Preferences::GetBool("dom.battery.test.discharging", false)) {
61 return false;
64 return mCharging;
67 double BatteryManager::DischargingTime() const {
68 MOZ_ASSERT(NS_IsMainThread());
69 // For testing, unable to report the battery status information
70 if (Preferences::GetBool("dom.battery.test.default", false)) {
71 return std::numeric_limits<double>::infinity();
73 if (Preferences::GetBool("dom.battery.test.discharging", false)) {
74 return 42.0;
77 if (Charging() || mRemainingTime == kUnknownRemainingTime) {
78 return std::numeric_limits<double>::infinity();
81 return mRemainingTime;
84 double BatteryManager::ChargingTime() const {
85 MOZ_ASSERT(NS_IsMainThread());
86 // For testing, unable to report the battery status information
87 if (Preferences::GetBool("dom.battery.test.default", false)) {
88 return 0.0;
90 if (Preferences::GetBool("dom.battery.test.charging", false)) {
91 return 42.0;
94 if (!Charging() || mRemainingTime == kUnknownRemainingTime) {
95 return std::numeric_limits<double>::infinity();
98 return mRemainingTime;
101 double BatteryManager::Level() const {
102 MOZ_ASSERT(NS_IsMainThread());
103 // For testing, unable to report the battery status information
104 if (Preferences::GetBool("dom.battery.test.default")) {
105 return 1.0;
108 return mLevel;
111 void BatteryManager::UpdateFromBatteryInfo(
112 const hal::BatteryInformation& aBatteryInfo) {
113 mLevel = aBatteryInfo.level();
115 // Round to the nearest ten percent for non-chrome.
116 Document* doc = GetOwner() ? GetOwner()->GetDoc() : nullptr;
118 mCharging = aBatteryInfo.charging();
119 mRemainingTime = aBatteryInfo.remainingTime();
121 if (!nsContentUtils::IsChromeDoc(doc)) {
122 mLevel = lround(mLevel * 10.0) / 10.0;
123 if (mLevel == 1.0) {
124 mRemainingTime =
125 mCharging ? kDefaultRemainingTime : kUnknownRemainingTime;
126 } else if (mRemainingTime != kUnknownRemainingTime) {
127 // Round the remaining time to a multiple of 15 minutes and never zero
128 const double MINUTES_15 = 15.0 * 60.0;
129 mRemainingTime =
130 fmax(lround(mRemainingTime / MINUTES_15) * MINUTES_15, MINUTES_15);
134 // Add some guards to make sure the values are coherent.
135 if (mLevel == 1.0 && mCharging == true &&
136 mRemainingTime != kDefaultRemainingTime) {
137 mRemainingTime = kDefaultRemainingTime;
138 NS_ERROR(
139 "Battery API: When charging and level at 1.0, remaining time "
140 "should be 0. Please fix your backend!");
144 void BatteryManager::Notify(const hal::BatteryInformation& aBatteryInfo) {
145 double previousLevel = mLevel;
146 bool previousCharging = mCharging;
147 double previousRemainingTime = mRemainingTime;
149 UpdateFromBatteryInfo(aBatteryInfo);
151 if (previousCharging != mCharging) {
152 DispatchTrustedEvent(CHARGINGCHANGE_EVENT_NAME);
155 if (previousLevel != mLevel) {
156 DispatchTrustedEvent(LEVELCHANGE_EVENT_NAME);
160 * There are a few situations that could happen here:
161 * 1. Charging state changed:
162 * a. Previous remaining time wasn't unkwonw, we have to fire an event for
163 * the change.
164 * b. New remaining time isn't unkwonw, we have to fire an event for it.
165 * 2. Charging state didn't change but remainingTime did, we have to fire
166 * the event that correspond to the current charging state.
168 if (mCharging != previousCharging) {
169 if (previousRemainingTime != kUnknownRemainingTime) {
170 DispatchTrustedEvent(previousCharging ? CHARGINGTIMECHANGE_EVENT_NAME
171 : DISCHARGINGTIMECHANGE_EVENT_NAME);
173 if (mRemainingTime != kUnknownRemainingTime) {
174 DispatchTrustedEvent(mCharging ? CHARGINGTIMECHANGE_EVENT_NAME
175 : DISCHARGINGTIMECHANGE_EVENT_NAME);
177 } else if (previousRemainingTime != mRemainingTime) {
178 DispatchTrustedEvent(mCharging ? CHARGINGTIMECHANGE_EVENT_NAME
179 : DISCHARGINGTIMECHANGE_EVENT_NAME);
183 } // namespace mozilla::dom::battery