Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(51)

Unified Diff: trunk/src/content/browser/battery_status/battery_status_manager_linux.cc

Issue 472643002: Revert 289372 "Battery Status API: implementation for Linux." (Closed) Base URL: svn://svn.chromium.org/chrome/
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: trunk/src/content/browser/battery_status/battery_status_manager_linux.cc
===================================================================
--- trunk/src/content/browser/battery_status/battery_status_manager_linux.cc (revision 289378)
+++ trunk/src/content/browser/battery_status/battery_status_manager_linux.cc (working copy)
@@ -1,374 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/battery_status/battery_status_manager_linux.h"
-
-#include "base/macros.h"
-#include "base/threading/thread.h"
-#include "base/values.h"
-#include "content/browser/battery_status/battery_status_manager.h"
-#include "content/public/browser/browser_thread.h"
-#include "dbus/bus.h"
-#include "dbus/message.h"
-#include "dbus/object_path.h"
-#include "dbus/object_proxy.h"
-#include "dbus/property.h"
-#include "dbus/values_util.h"
-
-namespace content {
-
-namespace {
-
-const char kUPowerServiceName[] = "org.freedesktop.UPower";
-const char kUPowerDeviceName[] = "org.freedesktop.UPower.Device";
-const char kUPowerPath[] = "/org/freedesktop/UPower";
-const char kUPowerDeviceSignalChanged[] = "Changed";
-const char kUPowerEnumerateDevices[] = "EnumerateDevices";
-const char kBatteryNotifierThreadName[] = "BatteryStatusNotifier";
-
-// UPowerDeviceType reflects the possible UPower.Device.Type values,
-// see upower.freedesktop.org/docs/Device.html#Device:Type.
-enum UPowerDeviceType {
- UPOWER_DEVICE_TYPE_UNKNOWN = 0,
- UPOWER_DEVICE_TYPE_LINE_POWER = 1,
- UPOWER_DEVICE_TYPE_BATTERY = 2,
- UPOWER_DEVICE_TYPE_UPS = 3,
- UPOWER_DEVICE_TYPE_MONITOR = 4,
- UPOWER_DEVICE_TYPE_MOUSE = 5,
- UPOWER_DEVICE_TYPE_KEYBOARD = 6,
- UPOWER_DEVICE_TYPE_PDA = 7,
- UPOWER_DEVICE_TYPE_PHONE = 8,
-};
-
-typedef std::vector<dbus::ObjectPath> PathsVector;
-
-double GetPropertyAsDouble(const base::DictionaryValue& dictionary,
- const std::string& property_name,
- double default_value) {
- double value = default_value;
- return dictionary.GetDouble(property_name, &value) ? value : default_value;
-}
-
-bool GetPropertyAsBoolean(const base::DictionaryValue& dictionary,
- const std::string& property_name,
- bool default_value) {
- bool value = default_value;
- return dictionary.GetBoolean(property_name, &value) ? value : default_value;
-}
-
-scoped_ptr<base::DictionaryValue> GetPropertiesAsDictionary(
- dbus::ObjectProxy* proxy) {
- dbus::MethodCall method_call(dbus::kPropertiesInterface,
- dbus::kPropertiesGetAll);
- dbus::MessageWriter builder(&method_call);
- builder.AppendString(kUPowerDeviceName);
-
- scoped_ptr<dbus::Response> response(
- proxy->CallMethodAndBlock(&method_call,
- dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
- if (response) {
- dbus::MessageReader reader(response.get());
- scoped_ptr<base::Value> value(dbus::PopDataAsValue(&reader));
- base::DictionaryValue* dictionary_value = NULL;
- if (value && value->GetAsDictionary(&dictionary_value)) {
- ignore_result(value.release());
- return scoped_ptr<base::DictionaryValue>(dictionary_value);
- }
- }
- return scoped_ptr<base::DictionaryValue>();
-}
-
-scoped_ptr<PathsVector> GetPowerSourcesPaths(dbus::ObjectProxy* proxy) {
- scoped_ptr<PathsVector> paths(new PathsVector());
- if (!proxy)
- return paths.Pass();
-
- dbus::MethodCall method_call(kUPowerServiceName, kUPowerEnumerateDevices);
- scoped_ptr<dbus::Response> response(
- proxy->CallMethodAndBlock(&method_call,
- dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
-
- if (response) {
- dbus::MessageReader reader(response.get());
- reader.PopArrayOfObjectPaths(paths.get());
- }
- return paths.Pass();;
-}
-
-// Class that represents a dedicated thread which communicates with DBus to
-// obtain battery information and receives battery change notifications.
-class BatteryStatusNotificationThread : public base::Thread {
- public:
- BatteryStatusNotificationThread(
- const BatteryStatusService::BatteryUpdateCallback& callback)
- : base::Thread(kBatteryNotifierThreadName),
- callback_(callback),
- battery_proxy_(NULL) {}
-
- virtual ~BatteryStatusNotificationThread() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- // Make sure to shutdown the dbus connection if it is still open in the very
- // end. It needs to happen on the BatteryStatusNotificationThread.
- message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&BatteryStatusNotificationThread::ShutdownDBusConnection,
- base::Unretained(this)));
-
- // Drain the message queue of the BatteryStatusNotificationThread and stop.
- Stop();
- }
-
- void StartListening() {
- DCHECK(OnWatcherThread());
-
- if (system_bus_)
- return;
-
- InitDBus();
- dbus::ObjectProxy* power_proxy =
- system_bus_->GetObjectProxy(kUPowerServiceName,
- dbus::ObjectPath(kUPowerPath));
- scoped_ptr<PathsVector> device_paths = GetPowerSourcesPaths(power_proxy);
-
- for (size_t i = 0; i < device_paths->size(); ++i) {
- const dbus::ObjectPath& device_path = device_paths->at(i);
- dbus::ObjectProxy* device_proxy = system_bus_->GetObjectProxy(
- kUPowerServiceName, device_path);
- scoped_ptr<base::DictionaryValue> dictionary =
- GetPropertiesAsDictionary(device_proxy);
-
- if (!dictionary)
- continue;
-
- bool is_present = GetPropertyAsBoolean(*dictionary, "IsPresent", false);
- uint32 type = static_cast<uint32>(
- GetPropertyAsDouble(*dictionary, "Type", UPOWER_DEVICE_TYPE_UNKNOWN));
-
- if (!is_present || type != UPOWER_DEVICE_TYPE_BATTERY) {
- system_bus_->RemoveObjectProxy(kUPowerServiceName,
- device_path,
- base::Bind(&base::DoNothing));
- continue;
- }
-
- if (battery_proxy_) {
- // TODO(timvolodine): add support for multiple batteries. Currently we
- // only collect information from the first battery we encounter
- // (crbug.com/400780).
- // TODO(timvolodine): add UMA logging for this case.
- LOG(WARNING) << "multiple batteries found, "
- << "using status data of the first battery only.";
- } else {
- battery_proxy_ = device_proxy;
- }
- }
-
- if (!battery_proxy_) {
- callback_.Run(blink::WebBatteryStatus());
- return;
- }
-
- battery_proxy_->ConnectToSignal(
- kUPowerDeviceName,
- kUPowerDeviceSignalChanged,
- base::Bind(&BatteryStatusNotificationThread::BatteryChanged,
- base::Unretained(this)),
- base::Bind(&BatteryStatusNotificationThread::OnSignalConnected,
- base::Unretained(this)));
- }
-
- void StopListening() {
- DCHECK(OnWatcherThread());
- ShutdownDBusConnection();
- }
-
- private:
- bool OnWatcherThread() {
- return task_runner()->BelongsToCurrentThread();
- }
-
- void InitDBus() {
- DCHECK(OnWatcherThread());
-
- dbus::Bus::Options options;
- options.bus_type = dbus::Bus::SYSTEM;
- options.connection_type = dbus::Bus::PRIVATE;
- system_bus_ = new dbus::Bus(options);
- }
-
- void ShutdownDBusConnection() {
- DCHECK(OnWatcherThread());
-
- if (!system_bus_)
- return;
-
- // Shutdown DBus connection later because there may be pending tasks on
- // this thread.
- message_loop()->PostTask(FROM_HERE,
- base::Bind(&dbus::Bus::ShutdownAndBlock,
- system_bus_));
- system_bus_ = NULL;
- battery_proxy_ = NULL;
- }
-
- void OnSignalConnected(const std::string& interface_name,
- const std::string& signal_name,
- bool success) {
- DCHECK(OnWatcherThread());
-
- if (interface_name != kUPowerDeviceName ||
- signal_name != kUPowerDeviceSignalChanged) {
- return;
- }
-
- if (!system_bus_)
- return;
-
- if (success) {
- BatteryChanged(NULL);
- } else {
- // Failed to register for "Changed" signal, execute callback with the
- // default values.
- callback_.Run(blink::WebBatteryStatus());
- }
- }
-
- void BatteryChanged(dbus::Signal* signal /* unsused */) {
- DCHECK(OnWatcherThread());
-
- if (!system_bus_)
- return;
-
- scoped_ptr<base::DictionaryValue> dictionary =
- GetPropertiesAsDictionary(battery_proxy_);
- if (dictionary)
- callback_.Run(ComputeWebBatteryStatus(*dictionary));
- else
- callback_.Run(blink::WebBatteryStatus());
- }
-
- BatteryStatusService::BatteryUpdateCallback callback_;
- scoped_refptr<dbus::Bus> system_bus_;
- dbus::ObjectProxy* battery_proxy_; // owned by the bus
-
- DISALLOW_COPY_AND_ASSIGN(BatteryStatusNotificationThread);
-};
-
-// Runs on IO thread and creates a notification thread and delegates Start/Stop
-// calls to it.
-class BatteryStatusManagerLinux : public BatteryStatusManager {
- public:
- explicit BatteryStatusManagerLinux(
- const BatteryStatusService::BatteryUpdateCallback& callback)
- : callback_(callback) {}
-
- virtual ~BatteryStatusManagerLinux() {}
-
- private:
- // BatteryStatusManager:
- virtual bool StartListeningBatteryChange() OVERRIDE {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- if (!StartNotifierThreadIfNecessary())
- return false;
-
- notifier_thread_->message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&BatteryStatusNotificationThread::StartListening,
- base::Unretained(notifier_thread_.get())));
- return true;
- }
-
- virtual void StopListeningBatteryChange() OVERRIDE {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- if (!notifier_thread_)
- return;
-
- notifier_thread_->message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&BatteryStatusNotificationThread::StopListening,
- base::Unretained(notifier_thread_.get())));
- }
-
- // Starts the notifier thread if not already started and returns true on
- // success.
- bool StartNotifierThreadIfNecessary() {
- if (notifier_thread_)
- return true;
-
- base::Thread::Options thread_options(base::MessageLoop::TYPE_IO, 0);
- notifier_thread_.reset(new BatteryStatusNotificationThread(callback_));
- if (!notifier_thread_->StartWithOptions(thread_options)) {
- notifier_thread_.reset();
- LOG(ERROR) << "Could not start the " << kBatteryNotifierThreadName
- << " thread";
- return false;
- }
- return true;
- }
-
- BatteryStatusService::BatteryUpdateCallback callback_;
- scoped_ptr<BatteryStatusNotificationThread> notifier_thread_;
-
- DISALLOW_COPY_AND_ASSIGN(BatteryStatusManagerLinux);
-};
-
-} // namespace
-
-blink::WebBatteryStatus ComputeWebBatteryStatus(
- const base::DictionaryValue& dictionary) {
- blink::WebBatteryStatus status;
- if (!dictionary.HasKey("State"))
- return status;
-
- uint32 state = static_cast<uint32>(
- GetPropertyAsDouble(dictionary, "State", UPOWER_DEVICE_STATE_UNKNOWN));
- status.charging = state != UPOWER_DEVICE_STATE_DISCHARGING &&
- state != UPOWER_DEVICE_STATE_EMPTY;
- double percentage = GetPropertyAsDouble(dictionary, "Percentage", 100);
- // Convert percentage to a value between 0 and 1 with 2 digits of precision.
- // This is to bring it in line with other platforms like Mac and Android where
- // we report level with 1% granularity. It also serves the purpose of reducing
- // the possibility of fingerprinting and triggers less level change events on
- // the blink side.
- // TODO(timvolodine): consider moving this rounding to the blink side.
- status.level = round(percentage) / 100.f;
-
- switch (state) {
- case UPOWER_DEVICE_STATE_CHARGING : {
- double time_to_full = GetPropertyAsDouble(dictionary, "TimeToFull", 0);
- status.chargingTime =
- (time_to_full > 0) ? time_to_full
- : std::numeric_limits<double>::infinity();
- break;
- }
- case UPOWER_DEVICE_STATE_DISCHARGING : {
- double time_to_empty = GetPropertyAsDouble(dictionary, "TimeToEmpty", 0);
- // Set dischargingTime if it's available. Otherwise leave the default
- // value which is +infinity.
- if (time_to_empty > 0)
- status.dischargingTime = time_to_empty;
- status.chargingTime = std::numeric_limits<double>::infinity();
- break;
- }
- case UPOWER_DEVICE_STATE_FULL : {
- break;
- }
- default: {
- status.chargingTime = std::numeric_limits<double>::infinity();
- }
- }
- return status;
-}
-
-// static
-scoped_ptr<BatteryStatusManager> BatteryStatusManager::Create(
- const BatteryStatusService::BatteryUpdateCallback& callback) {
- return scoped_ptr<BatteryStatusManager>(
- new BatteryStatusManagerLinux(callback));
-}
-
-} // namespace content

Powered by Google App Engine
This is Rietveld 408576698