Issue #1391 - Remove the DOM battery API

pull/24/head
Moonchild 2 years ago committed by Roy Tam
parent d97bcfb97a
commit b33e80b186
  1. 43
      dom/base/Navigator.cpp
  2. 7
      dom/base/Navigator.h
  3. 1
      dom/base/moz.build
  4. 212
      dom/battery/BatteryManager.cpp
  5. 84
      dom/battery/BatteryManager.h
  6. 27
      dom/battery/Constants.h
  7. 23
      dom/battery/Types.h
  8. 21
      dom/battery/moz.build
  9. 3
      dom/battery/test/chrome.ini
  10. 1
      dom/battery/test/mochitest.ini
  11. 39
      dom/battery/test/test_battery_basics.html
  12. 35
      dom/battery/test/test_battery_charging.html
  13. 35
      dom/battery/test/test_battery_discharging.html
  14. 24
      dom/battery/test/test_battery_unprivileged.html
  15. 1
      dom/bindings/moz.build
  16. 1
      dom/moz.build
  17. 24
      dom/quota/QuotaManagerService.cpp
  18. 23
      dom/webidl/BatteryManager.webidl
  19. 8
      dom/webidl/Navigator.webidl
  20. 1
      dom/webidl/moz.build
  21. 53
      hal/Hal.cpp
  22. 24
      hal/Hal.h
  23. 325
      hal/cocoa/CocoaBattery.cpp
  24. 30
      hal/fallback/FallbackBattery.cpp
  25. 508
      hal/linux/UPowerClient.cpp
  26. 22
      hal/moz.build
  27. 12
      hal/sandbox/PHal.ipdl
  28. 51
      hal/sandbox/SandboxHal.cpp
  29. 190
      hal/windows/WindowsBattery.cpp
  30. 5
      modules/libpref/init/all.js

@ -30,7 +30,6 @@
#include "nsUnicharUtils.h"
#include "mozilla/Preferences.h"
#include "mozilla/Telemetry.h"
#include "BatteryManager.h"
#ifdef MOZ_GAMEPAD
#include "mozilla/dom/GamepadServiceTest.h"
#endif
@ -197,8 +196,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPermissions)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGeolocation)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNotification)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryPromise)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPowerManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConnection)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStorageManager)
@ -249,13 +246,6 @@ Navigator::Invalidate()
mNotification = nullptr;
}
if (mBatteryManager) {
mBatteryManager->Shutdown();
mBatteryManager = nullptr;
}
mBatteryPromise = nullptr;
if (mPowerManager) {
mPowerManager->Shutdown();
mPowerManager = nullptr;
@ -1321,39 +1311,6 @@ Navigator::GetMozNotification(ErrorResult& aRv)
return mNotification;
}
//*****************************************************************************
// Navigator::nsINavigatorBattery
//*****************************************************************************
Promise*
Navigator::GetBattery(ErrorResult& aRv)
{
if (mBatteryPromise) {
return mBatteryPromise;
}
if (!mWindow || !mWindow->GetDocShell()) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(mWindow);
RefPtr<Promise> batteryPromise = Promise::Create(go, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
mBatteryPromise = batteryPromise;
if (!mBatteryManager) {
mBatteryManager = new battery::BatteryManager(mWindow);
mBatteryManager->Init();
}
mBatteryPromise->MaybeResolve(mBatteryManager);
return mBatteryPromise;
}
PowerManager*
Navigator::GetMozPower(ErrorResult& aRv)
{

@ -51,10 +51,6 @@ namespace dom {
class Permissions;
namespace battery {
class BatteryManager;
} // namespace battery
class Promise;
class DesktopNotificationCenter;
@ -136,7 +132,6 @@ public:
Permissions* GetPermissions(ErrorResult& aRv);
// The XPCOM GetDoNotTrack is ok
Geolocation* GetGeolocation(ErrorResult& aRv);
Promise* GetBattery(ErrorResult& aRv);
static void AppName(nsAString& aAppName, bool aUsePrefOverriddenValue);
@ -269,8 +264,6 @@ private:
RefPtr<Permissions> mPermissions;
RefPtr<Geolocation> mGeolocation;
RefPtr<DesktopNotificationCenter> mNotification;
RefPtr<battery::BatteryManager> mBatteryManager;
RefPtr<Promise> mBatteryPromise;
RefPtr<PowerManager> mPowerManager;
RefPtr<network::Connection> mConnection;
#ifdef MOZ_AUDIO_CHANNEL_MANAGER

@ -419,7 +419,6 @@ EXTRA_JS_MODULES += [
]
LOCAL_INCLUDES += [
'../battery',
'../events',
'../media',
'../network',

@ -1,212 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <cmath>
#include <limits>
#include "BatteryManager.h"
#include "Constants.h"
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/Hal.h"
#include "mozilla/dom/BatteryManagerBinding.h"
#include "mozilla/Preferences.h"
#include "nsContentUtils.h"
#include "nsIDOMClassInfo.h"
#include "nsIDocument.h"
/**
* We have to use macros here because our leak analysis tool things we are
* leaking strings when we have |static const nsString|. Sad :(
*/
#define LEVELCHANGE_EVENT_NAME NS_LITERAL_STRING("levelchange")
#define CHARGINGCHANGE_EVENT_NAME NS_LITERAL_STRING("chargingchange")
#define DISCHARGINGTIMECHANGE_EVENT_NAME NS_LITERAL_STRING("dischargingtimechange")
#define CHARGINGTIMECHANGE_EVENT_NAME NS_LITERAL_STRING("chargingtimechange")
namespace mozilla {
namespace dom {
namespace battery {
BatteryManager::BatteryManager(nsPIDOMWindowInner* aWindow)
: DOMEventTargetHelper(aWindow)
, mLevel(kDefaultLevel)
, mCharging(kDefaultCharging)
, mRemainingTime(kDefaultRemainingTime)
{
}
void
BatteryManager::Init()
{
hal::RegisterBatteryObserver(this);
hal::BatteryInformation batteryInfo;
hal::GetCurrentBatteryInformation(&batteryInfo);
UpdateFromBatteryInfo(batteryInfo);
}
void
BatteryManager::Shutdown()
{
hal::UnregisterBatteryObserver(this);
}
JSObject*
BatteryManager::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return BatteryManagerBinding::Wrap(aCx, this, aGivenProto);
}
bool
BatteryManager::Charging() const
{
MOZ_ASSERT(NS_IsMainThread());
// For testing, unable to report the battery status information
if (Preferences::GetBool("dom.battery.test.default", false)) {
return true;
}
if (Preferences::GetBool("dom.battery.test.charging", false)) {
return true;
}
if (Preferences::GetBool("dom.battery.test.discharging", false)) {
return false;
}
return mCharging;
}
double
BatteryManager::DischargingTime() const
{
MOZ_ASSERT(NS_IsMainThread());
// For testing, unable to report the battery status information
if (Preferences::GetBool("dom.battery.test.default", false)) {
return std::numeric_limits<double>::infinity();
}
if (Preferences::GetBool("dom.battery.test.discharging", false)) {
return 42.0;
}
if (Charging() || mRemainingTime == kUnknownRemainingTime) {
return std::numeric_limits<double>::infinity();
}
return mRemainingTime;
}
double
BatteryManager::ChargingTime() const
{
MOZ_ASSERT(NS_IsMainThread());
// For testing, unable to report the battery status information
if (Preferences::GetBool("dom.battery.test.default", false)) {
return 0.0;
}
if (Preferences::GetBool("dom.battery.test.charging", false)) {
return 42.0;
}
if (!Charging() || mRemainingTime == kUnknownRemainingTime) {
return std::numeric_limits<double>::infinity();
}
return mRemainingTime;
}
double
BatteryManager::Level() const
{
MOZ_ASSERT(NS_IsMainThread());
// For testing, unable to report the battery status information
if (Preferences::GetBool("dom.battery.test.default")) {
return 1.0;
}
return mLevel;
}
void
BatteryManager::UpdateFromBatteryInfo(const hal::BatteryInformation& aBatteryInfo)
{
mLevel = aBatteryInfo.level();
// Round to the nearest ten percent for non-chrome and non-certified apps
nsIDocument* doc = GetOwner() ? GetOwner()->GetDoc() : nullptr;
uint16_t status = nsIPrincipal::APP_STATUS_NOT_INSTALLED;
if (doc) {
status = doc->NodePrincipal()->GetAppStatus();
}
mCharging = aBatteryInfo.charging();
mRemainingTime = aBatteryInfo.remainingTime();
if (!nsContentUtils::IsChromeDoc(doc) &&
status != nsIPrincipal::APP_STATUS_CERTIFIED)
{
mLevel = lround(mLevel * 10.0) / 10.0;
if (mLevel == 1.0) {
mRemainingTime = mCharging ? kDefaultRemainingTime : kUnknownRemainingTime;
} else if (mRemainingTime != kUnknownRemainingTime) {
// Round the remaining time to a multiple of 15 minutes and never zero
const double MINUTES_15 = 15.0 * 60.0;
mRemainingTime = fmax(lround(mRemainingTime / MINUTES_15) * MINUTES_15,
MINUTES_15);
}
}
// Add some guards to make sure the values are coherent.
if (mLevel == 1.0 && mCharging == true &&
mRemainingTime != kDefaultRemainingTime) {
mRemainingTime = kDefaultRemainingTime;
NS_ERROR("Battery API: When charging and level at 1.0, remaining time "
"should be 0. Please fix your backend!");
}
}
void
BatteryManager::Notify(const hal::BatteryInformation& aBatteryInfo)
{
double previousLevel = mLevel;
bool previousCharging = mCharging;
double previousRemainingTime = mRemainingTime;
UpdateFromBatteryInfo(aBatteryInfo);
if (previousCharging != mCharging) {
DispatchTrustedEvent(CHARGINGCHANGE_EVENT_NAME);
}
if (previousLevel != mLevel) {
DispatchTrustedEvent(LEVELCHANGE_EVENT_NAME);
}
/*
* There are a few situations that could happen here:
* 1. Charging state changed:
* a. Previous remaining time wasn't unkwonw, we have to fire an event for
* the change.
* b. New remaining time isn't unkwonw, we have to fire an event for it.
* 2. Charging state didn't change but remainingTime did, we have to fire
* the event that correspond to the current charging state.
*/
if (mCharging != previousCharging) {
if (previousRemainingTime != kUnknownRemainingTime) {
DispatchTrustedEvent(previousCharging ? CHARGINGTIMECHANGE_EVENT_NAME
: DISCHARGINGTIMECHANGE_EVENT_NAME);
}
if (mRemainingTime != kUnknownRemainingTime) {
DispatchTrustedEvent(mCharging ? CHARGINGTIMECHANGE_EVENT_NAME
: DISCHARGINGTIMECHANGE_EVENT_NAME);
}
} else if (previousRemainingTime != mRemainingTime) {
DispatchTrustedEvent(mCharging ? CHARGINGTIMECHANGE_EVENT_NAME
: DISCHARGINGTIMECHANGE_EVENT_NAME);
}
}
} // namespace battery
} // namespace dom
} // namespace mozilla

@ -1,84 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_battery_BatteryManager_h
#define mozilla_dom_battery_BatteryManager_h
#include "Types.h"
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/Observer.h"
#include "nsCycleCollectionParticipant.h"
namespace mozilla {
namespace hal {
class BatteryInformation;
} // namespace hal
namespace dom {
namespace battery {
class BatteryManager : public DOMEventTargetHelper
, public BatteryObserver
{
public:
explicit BatteryManager(nsPIDOMWindowInner* aWindow);
void Init();
void Shutdown();
// For IObserver.
void Notify(const hal::BatteryInformation& aBatteryInfo) override;
/**
* WebIDL Interface
*/
nsPIDOMWindowInner* GetParentObject() const
{
return GetOwner();
}
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
bool Charging() const;
double ChargingTime() const;
double DischargingTime() const;
double Level() const;
IMPL_EVENT_HANDLER(chargingchange)
IMPL_EVENT_HANDLER(chargingtimechange)
IMPL_EVENT_HANDLER(dischargingtimechange)
IMPL_EVENT_HANDLER(levelchange)
private:
/**
* Update the battery information stored in the battery manager object using
* a battery information object.
*/
void UpdateFromBatteryInfo(const hal::BatteryInformation& aBatteryInfo);
/**
* Represents the battery level, ranging from 0.0 (dead or removed?)
* to 1.0 (fully charged)
*/
double mLevel;
bool mCharging;
/**
* Represents the discharging time or the charging time, depending on the
* current battery status (charging or not).
*/
double mRemainingTime;
};
} // namespace battery
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_battery_BatteryManager_h

@ -1,27 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_battery_Constants_h__
#define mozilla_dom_battery_Constants_h__
/**
* A set of constants that might need to be used by battery backends.
* It's not part of BatteryManager.h to prevent those backends to include it.
*/
namespace mozilla {
namespace dom {
namespace battery {
static const double kDefaultLevel = 1.0;
static const bool kDefaultCharging = true;
static const double kDefaultRemainingTime = 0;
static const double kUnknownRemainingTime = -1;
} // namespace battery
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_battery_Constants_h__

@ -1,23 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#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

@ -1,21 +0,0 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXPORTS.mozilla.dom.battery += [
'Constants.h',
'Types.h',
]
SOURCES += [
'BatteryManager.cpp',
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
MOCHITEST_MANIFESTS += ['test/mochitest.ini']

@ -1,3 +0,0 @@
[test_battery_basics.html]
[test_battery_charging.html]
[test_battery_discharging.html]

@ -1 +0,0 @@
[test_battery_unprivileged.html]

@ -1,39 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Battery API</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
"use strict";
SimpleTest.waitForExplicitFinish();
/** Test for Battery API **/
ok("getBattery" in navigator, "navigator.getBattery should exist");
ok(!("battery" in navigator), "navigator.battery should not exist");
navigator.getBattery().then(function (battery) {
ok(battery.level >= 0.0 && battery.level <= 1.0, "Battery level " + battery.level + " should be in the range [0.0, 1.0]");
SpecialPowers.pushPrefEnv({"set": [["dom.battery.test.default", true]]}, function () {
ok(battery.charging, "Battery should be charging by default");
is(battery.chargingTime, 0, "Battery chargingTime " + battery.chargingTime + " should be zero by default");
is(battery.dischargingTime, Infinity, "Battery dischargingTime should be Infinity by default");
is(battery.level, 1.0, "Battery level " + battery.level + " should be 1.0 by default");
SimpleTest.finish();
});
});
</script>
</pre>
</body>
</html>

@ -1,35 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Battery API</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
"use strict";
SimpleTest.waitForExplicitFinish();
/** Test for Battery API **/
navigator.getBattery().then(function (battery) {
ok(battery.level >= 0.0 && battery.level <= 1.0, "Battery level " + battery.level + " should be in the range [0.0, 1.0]");
SpecialPowers.pushPrefEnv({"set": [["dom.battery.test.charging", true]]}, function () {
is(battery.charging, true, "Battery should be charging");
ok(battery.chargingTime >= 0, "Battery chargingTime " + battery.chargingTime + " should be nonnegative when charging");
is(battery.dischargingTime, Infinity, "Battery dischargingTime should be Infinity when charging");
SimpleTest.finish();
});
});
</script>
</pre>
</body>
</html>

@ -1,35 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Battery API</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
"use strict";
SimpleTest.waitForExplicitFinish();
/** Test for Battery API **/
navigator.getBattery().then(function (battery) {
ok(battery.level >= 0.0 && battery.level <= 1.0, "Battery level " + battery.level + " should be in the range [0.0, 1.0]");
SpecialPowers.pushPrefEnv({"set": [["dom.battery.test.discharging", true]]}, function () {
is(battery.charging, false, "Battery should be discharging");
is(battery.chargingTime, Infinity, "Battery chargingTime should be Infinity when discharging");
ok(battery.dischargingTime > 0, "Battery dischargingTime " + battery.dischargingTime + " should be positive when discharging");
SimpleTest.finish();
});
});
</script>
</pre>
</body>
</html>

@ -1,24 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Battery API</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
"use strict";
/** Test for Battery API **/
ok(!("getBattery" in navigator), "navigator.getBattery should not exist for unprivileged web content");
ok(!("battery" in navigator), "navigator.battery should not exist");
</script>
</pre>
</body>
</html>

@ -62,7 +62,6 @@ LOCAL_INCLUDES += [
LOCAL_INCLUDES += [
'/dom/base',
'/dom/battery',
'/dom/canvas',
'/dom/geolocation',
'/dom/html',

@ -43,7 +43,6 @@ DIRS += [
'base',
'archivereader',
'bindings',
'battery',
'browser-element',
'cache',
'canvas',

@ -432,30 +432,6 @@ QuotaManagerService::PerformIdleMaintenance()
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
// If we're running on battery power then skip all idle maintenance since we
// would otherwise be doing lots of disk I/O.
BatteryInformation batteryInfo;
#ifdef MOZ_WIDGET_ANDROID
// Android XPCShell doesn't load the AndroidBridge that is needed to make
// GetCurrentBatteryInformation work...
if (!QuotaManager::IsRunningXPCShellTests())
#endif
{
GetCurrentBatteryInformation(&batteryInfo);
}
// If we're running XPCShell because we always want to be able to test this
// code so pretend that we're always charging.
if (QuotaManager::IsRunningXPCShellTests()) {
batteryInfo.level() = 100;
batteryInfo.charging() = true;
}
if (NS_WARN_IF(!batteryInfo.charging())) {
return;
}
if (QuotaManager::IsRunningXPCShellTests()) {
// We don't want user activity to impact this code if we're running tests.
Unused << Observe(nullptr, OBSERVER_TOPIC_IDLE, nullptr);

@ -1,23 +0,0 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* The origin of this IDL file is
* http://www.w3.org/TR/battery-status/
*
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
* liability, trademark and document use rules apply.
*/
interface BatteryManager : EventTarget {
readonly attribute boolean charging;
readonly attribute unrestricted double chargingTime;
readonly attribute unrestricted double dischargingTime;
readonly attribute double level;
attribute EventHandler onchargingchange;
attribute EventHandler onchargingtimechange;
attribute EventHandler ondischargingtimechange;
attribute EventHandler onlevelchange;
};

@ -7,7 +7,6 @@
* http://www.whatwg.org/specs/web-apps/current-work/#the-navigator-object
* http://www.w3.org/TR/tracking-dnt/
* http://www.w3.org/TR/geolocation-API/#geolocation_interface
* http://www.w3.org/TR/battery-status/#navigatorbattery-interface
* http://www.w3.org/TR/vibration/#vibration-interface
* http://www.w3.org/2012/sysapps/runtime/#extension-to-the-navigator-interface-1
* https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html#navigator-interface-extension
@ -125,13 +124,6 @@ interface NavigatorGeolocation {
};
Navigator implements NavigatorGeolocation;
// http://www.w3.org/TR/battery-status/#navigatorbattery-interface
partial interface Navigator {
// ChromeOnly to prevent web content from fingerprinting users' batteries.
[Throws, ChromeOnly, Pref="dom.battery.enabled"]
Promise<BatteryManager> getBattery();
};
// http://www.w3.org/TR/vibration/#vibration-interface
partial interface Navigator {
// We don't support sequences in unions yet

@ -50,7 +50,6 @@ WEBIDL_FILES = [
'AutocompleteInfo.webidl',
'BarProp.webidl',
'BaseKeyframeTypes.webidl',
'BatteryManager.webidl',
'BeforeAfterKeyboardEvent.webidl',
'BeforeUnloadEvent.webidl',
'BiquadFilterNode.webidl',

@ -264,30 +264,6 @@ private:
bool mHasValidCache;
};
class BatteryObserversManager : public CachingObserversManager<BatteryInformation>
{
protected:
void EnableNotifications() {
PROXY_IF_SANDBOXED(EnableBatteryNotifications());
}
void DisableNotifications() {
PROXY_IF_SANDBOXED(DisableBatteryNotifications());
}
void GetCurrentInformationInternal(BatteryInformation* aInfo) {
PROXY_IF_SANDBOXED(GetCurrentBatteryInformation(aInfo));
}
};
static BatteryObserversManager&
BatteryObservers()
{
static BatteryObserversManager sBatteryObservers;
AssertMainThread();
return sBatteryObservers;
}
class NetworkObserversManager : public CachingObserversManager<NetworkInformation>
{
protected:
@ -356,35 +332,6 @@ ScreenConfigurationObservers()
return sScreenConfigurationObservers;
}
void
RegisterBatteryObserver(BatteryObserver* aObserver)
{
AssertMainThread();
BatteryObservers().AddObserver(aObserver);
}
void
UnregisterBatteryObserver(BatteryObserver* aObserver)
{
AssertMainThread();
BatteryObservers().RemoveObserver(aObserver);
}
void
GetCurrentBatteryInformation(BatteryInformation* aInfo)
{
AssertMainThread();
*aInfo = BatteryObservers().GetCurrentInformation();
}
void
NotifyBatteryChange(const BatteryInformation& aInfo)
{
AssertMainThread();
BatteryObservers().CacheInformation(aInfo);
BatteryObservers().BroadcastCachedInformation();
}
bool GetScreenEnabled()
{
AssertMainThread();

@ -10,7 +10,6 @@
#include "base/basictypes.h"
#include "base/platform_thread.h"
#include "nsTArray.h"
#include "mozilla/dom/battery/Types.h"
#include "mozilla/dom/MozPowerManagerBinding.h"
#include "mozilla/dom/network/Types.h"
#include "mozilla/dom/power/Types.h"
@ -87,29 +86,6 @@ void Vibrate(const nsTArray<uint32_t>& pattern,
void CancelVibrate(nsPIDOMWindowInner* aWindow);
void CancelVibrate(const hal::WindowIdentifier &id);
/**
* 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);
/**
* 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);
/**
* Determine whether the device's screen is currently enabled.
*/

@ -1,325 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim set: sw=2 ts=2 et lcs=trail\:.,tab\:>~ : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#import <CoreFoundation/CoreFoundation.h>
#import <IOKit/ps/IOPowerSources.h>
#import <IOKit/ps/IOPSKeys.h>
#include <mozilla/Hal.h>
#include <mozilla/dom/battery/Constants.h>
#include <mozilla/Services.h>
#include <nsIObserverService.h>
#include <nsIObserver.h>
#include <dlfcn.h>
#define IOKIT_FRAMEWORK_PATH "/System/Library/Frameworks/IOKit.framework/IOKit"
#ifndef kIOPSTimeRemainingUnknown
#define kIOPSTimeRemainingUnknown ((CFTimeInterval)-1.0)
#endif
#ifndef kIOPSTimeRemainingUnlimited
#define kIOPSTimeRemainingUnlimited ((CFTimeInterval)-2.0)
#endif
using namespace mozilla::dom::battery;
namespace mozilla {
namespace hal_impl {
typedef CFTimeInterval (*IOPSGetTimeRemainingEstimateFunc)(void);
class MacPowerInformationService
{
public:
static MacPowerInformationService* GetInstance();
static void Shutdown();
static bool IsShuttingDown();
void BeginListening();
void StopListening();
static void HandleChange(void *aContext);
~MacPowerInformationService();
private:
MacPowerInformationService();
// The reference to the runloop that is notified of power changes.
CFRunLoopSourceRef mRunLoopSource;
double mLevel;
bool mCharging;
double mRemainingTime;
bool mShouldNotify;
friend void GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInfo);
static MacPowerInformationService* sInstance;
static bool sShuttingDown;
static void* sIOKitFramework;
static IOPSGetTimeRemainingEstimateFunc sIOPSGetTimeRemainingEstimate;
};
void* MacPowerInformationService::sIOKitFramework;
IOPSGetTimeRemainingEstimateFunc MacPowerInformationService::sIOPSGetTimeRemainingEstimate;
/*
* Implementation of mozilla::hal_impl::EnableBatteryNotifications,
* mozilla::hal_impl::DisableBatteryNotifications,
* and mozilla::hal_impl::GetCurrentBatteryInformation.
*/
void
EnableBatteryNotifications()
{
if (!MacPowerInformationService::IsShuttingDown()) {
MacPowerInformationService::GetInstance()->BeginListening();
}
}
void
DisableBatteryNotifications()
{
if (!MacPowerInformationService::IsShuttingDown()) {
MacPowerInformationService::GetInstance()->StopListening();
}
}
void
GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInfo)
{
MacPowerInformationService* powerService = MacPowerInformationService::GetInstance();
aBatteryInfo->level() = powerService->mLevel;
aBatteryInfo->charging() = powerService->mCharging;
aBatteryInfo->remainingTime() = powerService->mRemainingTime;
}
bool MacPowerInformationService::sShuttingDown = false;
/*
* Following is the implementation of MacPowerInformationService.
*/
MacPowerInformationService* MacPowerInformationService::sInstance = nullptr;
namespace {
struct SingletonDestroyer final : public nsIObserver
{
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
private:
~SingletonDestroyer() {}
};
NS_IMPL_ISUPPORTS(SingletonDestroyer, nsIObserver)
NS_IMETHODIMP
SingletonDestroyer::Observe(nsISupports*, const char* aTopic, const char16_t*)
{
MOZ_ASSERT(!strcmp(aTopic, "xpcom-shutdown"));
MacPowerInformationService::Shutdown();
return NS_OK;
}
} // namespace
/* static */ MacPowerInformationService*
MacPowerInformationService::GetInstance()
{
if (sInstance) {
return sInstance;
}
sInstance = new MacPowerInformationService();
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
obs->AddObserver(new SingletonDestroyer(), "xpcom-shutdown", false);
}
return sInstance;
}
bool
MacPowerInformationService::IsShuttingDown()
{
return sShuttingDown;
}
void
MacPowerInformationService::Shutdown()
{
sShuttingDown = true;
delete sInstance;
sInstance = nullptr;
}
MacPowerInformationService::MacPowerInformationService()
: mRunLoopSource(nullptr)
, mLevel(kDefaultLevel)
, mCharging(kDefaultCharging)
, mRemainingTime(kDefaultRemainingTime)
, mShouldNotify(false)
{
// IOPSGetTimeRemainingEstimate (and the related constants) are only available
// on 10.7, so we test for their presence at runtime.
sIOKitFramework = dlopen(IOKIT_FRAMEWORK_PATH, RTLD_LAZY | RTLD_LOCAL);
if (sIOKitFramework) {
sIOPSGetTimeRemainingEstimate =
(IOPSGetTimeRemainingEstimateFunc)dlsym(sIOKitFramework, "IOPSGetTimeRemainingEstimate");
} else {
sIOPSGetTimeRemainingEstimate = nullptr;
}
}
MacPowerInformationService::~MacPowerInformationService()
{
MOZ_ASSERT(!mRunLoopSource,
"The observers have not been correctly removed! "
"(StopListening should have been called)");
if (sIOKitFramework) {
dlclose(sIOKitFramework);
}
}
void
MacPowerInformationService::BeginListening()
{
// Set ourselves up to be notified about changes.
MOZ_ASSERT(!mRunLoopSource, "IOPS Notification Loop Source already set up. "
"(StopListening should have been called)");
mRunLoopSource = ::IOPSNotificationCreateRunLoopSource(HandleChange, this);
if (mRunLoopSource) {
::CFRunLoopAddSource(::CFRunLoopGetCurrent(), mRunLoopSource,
kCFRunLoopDefaultMode);
// Invoke our callback now so we have data if GetCurrentBatteryInformation is
// called before a change happens.
HandleChange(this);
mShouldNotify = true;
}
}
void
MacPowerInformationService::StopListening()
{
MOZ_ASSERT(mRunLoopSource, "IOPS Notification Loop Source not set up. "
"(StopListening without BeginListening)");
::CFRunLoopRemoveSource(::CFRunLoopGetCurrent(), mRunLoopSource,
kCFRunLoopDefaultMode);
mRunLoopSource = nullptr;
}
void
MacPowerInformationService::HandleChange(void* aContext) {
MacPowerInformationService* power =
static_cast<MacPowerInformationService*>(aContext);
CFTypeRef data = ::IOPSCopyPowerSourcesInfo();
if (!data) {
::CFRelease(data);
return;
}
// Get the list of power sources.
CFArrayRef list = ::IOPSCopyPowerSourcesList(data);
if (!list) {
::CFRelease(list);
return;
}
// Default values. These will be used if there are 0 sources or we can't find
// better information.
double level = kDefaultLevel;
double charging = kDefaultCharging;
double remainingTime = kDefaultRemainingTime;
// Look for the first battery power source to give us the information we need.
// Usually there's only 1 available, depending on current power source.
for (CFIndex i = 0; i < ::CFArrayGetCount(list); ++i) {
CFTypeRef source = ::CFArrayGetValueAtIndex(list, i);
CFDictionaryRef currPowerSourceDesc = ::IOPSGetPowerSourceDescription(data, source);
if (!currPowerSourceDesc) {
continue;
}
// Get a battery level estimate. This key is required.
int currentCapacity = 0;
const void* cfRef = ::CFDictionaryGetValue(currPowerSourceDesc, CFSTR(kIOPSCurrentCapacityKey));
::CFNumberGetValue((CFNumberRef)cfRef, kCFNumberSInt32Type, &currentCapacity);
// This key is also required.
int maxCapacity = 0;
cfRef = ::CFDictionaryGetValue(currPowerSourceDesc, CFSTR(kIOPSMaxCapacityKey));
::CFNumberGetValue((CFNumberRef)cfRef, kCFNumberSInt32Type, &maxCapacity);
if (maxCapacity > 0) {
level = static_cast<double>(currentCapacity)/static_cast<double>(maxCapacity);
}
// Find out if we're charging.
// This key is optional, we fallback to kDefaultCharging if the current power
// source doesn't have that info.
if(::CFDictionaryGetValueIfPresent(currPowerSourceDesc, CFSTR(kIOPSIsChargingKey), &cfRef)) {
charging = ::CFBooleanGetValue((CFBooleanRef)cfRef);
// Get an estimate of how long it's going to take until we're fully charged.
// This key is optional.
if (charging) {
// Default value that will be changed if we happen to find the actual
// remaining time.
remainingTime = level == 1.0 ? kDefaultRemainingTime : kUnknownRemainingTime;
if (::CFDictionaryGetValueIfPresent(currPowerSourceDesc,
CFSTR(kIOPSTimeToFullChargeKey), &cfRef)) {
int timeToCharge;
::CFNumberGetValue((CFNumberRef)cfRef, kCFNumberIntType, &timeToCharge);
if (timeToCharge != kIOPSTimeRemainingUnknown) {
remainingTime = timeToCharge*60;
}
}
} else if (sIOPSGetTimeRemainingEstimate) { // not charging
// See if we can get a time estimate.
CFTimeInterval estimate = sIOPSGetTimeRemainingEstimate();
if (estimate == kIOPSTimeRemainingUnlimited || estimate == kIOPSTimeRemainingUnknown) {
remainingTime = kUnknownRemainingTime;
} else {
remainingTime = estimate;
}
}
}
break;
}
bool isNewData = level != power->mLevel || charging != power->mCharging ||
remainingTime != power->mRemainingTime;
power->mRemainingTime = remainingTime;
power->mCharging = charging;
power->mLevel = level;
// Notify the observers if stuff changed.
if (power->mShouldNotify && isNewData) {
hal::NotifyBatteryChange(hal::BatteryInformation(power->mLevel,
power->mCharging,
power->mRemainingTime));
}
::CFRelease(data);
::CFRelease(list);
}
} // namespace hal_impl
} // namespace mozilla

@ -1,30 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et ft=cpp : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "Hal.h"
#include "mozilla/dom/battery/Constants.h"
namespace mozilla {
namespace hal_impl {
void
EnableBatteryNotifications()
{}
void
DisableBatteryNotifications()
{}
void
GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInfo)
{
aBatteryInfo->level() = dom::battery::kDefaultLevel;
aBatteryInfo->charging() = dom::battery::kDefaultCharging;
aBatteryInfo->remainingTime() = dom::battery::kDefaultRemainingTime;
}
} // hal_impl
} // namespace mozilla

@ -1,508 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "Hal.h"
#include "HalLog.h"
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
#include <mozilla/Attributes.h>
#include <mozilla/dom/battery/Constants.h>
#include "nsAutoRef.h"
#include <cmath>
/*
* Helper that manages the destruction of glib objects as soon as they leave
* the current scope.
*
* We are specializing nsAutoRef class.
*/
template <>
class nsAutoRefTraits<GHashTable> : public nsPointerRefTraits<GHashTable>
{
public:
static void Release(GHashTable* ptr) { g_hash_table_unref(ptr); }
};
using namespace mozilla::dom::battery;
namespace mozilla {
namespace hal_impl {
/**
* This is the declaration of UPowerClient class. This class is listening and
* communicating to upower daemon through DBus.
* There is no header file because this class shouldn't be public.
*/
class UPowerClient
{
public:
static UPowerClient* GetInstance();
void BeginListening();
void StopListening();
double GetLevel();
bool IsCharging();
double GetRemainingTime();
~UPowerClient();
private:
UPowerClient();
enum States {
eState_Unknown = 0,
eState_Charging,
eState_Discharging,
eState_Empty,
eState_FullyCharged,
eState_PendingCharge,
eState_PendingDischarge
};
/**
* Update the currently tracked device.
* @return whether everything went ok.
*/
void UpdateTrackedDeviceSync();
/**
* Returns a hash table with the properties of aDevice.
* Note: the caller has to unref the hash table.
*/
GHashTable* GetDevicePropertiesSync(DBusGProxy* aProxy);
void GetDevicePropertiesAsync(DBusGProxy* aProxy);
static void GetDevicePropertiesCallback(DBusGProxy* aProxy,
DBusGProxyCall* aCall,
void* aData);
/**
* Using the device properties (aHashTable), this method updates the member
* variable storing the values we care about.
*/
void UpdateSavedInfo(GHashTable* aHashTable);
/**
* Callback used by 'DeviceChanged' signal.
*/
static void DeviceChanged(DBusGProxy* aProxy, const gchar* aObjectPath,
UPowerClient* aListener);
/**
* Callback used by 'PropertiesChanged' signal.
* This method is called when the the battery level changes.
* (Only with upower >= 0.99)
*/
static void PropertiesChanged(DBusGProxy* aProxy, const gchar*,
GHashTable*, char**,
UPowerClient* aListener);
/**
* Callback called when mDBusConnection gets a signal.
*/
static DBusHandlerResult ConnectionSignalFilter(DBusConnection* aConnection,
DBusMessage* aMessage,
void* aData);
// The DBus connection object.
DBusGConnection* mDBusConnection;
// The DBus proxy object to upower.
DBusGProxy* mUPowerProxy;
// The path of the tracked device.
gchar* mTrackedDevice;
// The DBusGProxy for the tracked device.
DBusGProxy* mTrackedDeviceProxy;
double mLevel;
bool mCharging;
double mRemainingTime;
static UPowerClient* sInstance;
static const guint sDeviceTypeBattery = 2;
static const guint64 kUPowerUnknownRemainingTime = 0;
};
/*
* Implementation of mozilla::hal_impl::EnableBatteryNotifications,
* mozilla::hal_impl::DisableBatteryNotifications,
* and mozilla::hal_impl::GetCurrentBatteryInformation.
*/
void
EnableBatteryNotifications()
{
UPowerClient::GetInstance()->BeginListening();
}
void
DisableBatteryNotifications()
{
UPowerClient::GetInstance()->StopListening();
}
void
GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInfo)
{
UPowerClient* upowerClient = UPowerClient::GetInstance();
aBatteryInfo->level() = upowerClient->GetLevel();
aBatteryInfo->charging() = upowerClient->IsCharging();
aBatteryInfo->remainingTime() = upowerClient->GetRemainingTime();
}
/*
* Following is the implementation of UPowerClient.
*/
UPowerClient* UPowerClient::sInstance = nullptr;
/* static */ UPowerClient*
UPowerClient::GetInstance()
{
if (!sInstance) {
sInstance = new UPowerClient();
}