Upstream version 11.39.266.0
[platform/framework/web/crosswalk.git] / src / content / browser / battery_status / battery_status_manager_chromeos.cc
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/battery_status/battery_status_manager.h"
6
7 #include "base/memory/ref_counted.h"
8 #include "chromeos/dbus/dbus_thread_manager.h"
9 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
10 #include "chromeos/dbus/power_manager_client.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "third_party/WebKit/public/platform/WebBatteryStatus.h"
13
14 namespace content {
15
16 namespace {
17
18 class PowerManagerObserver
19     : public chromeos::PowerManagerClient::Observer,
20       public base::RefCountedThreadSafe<PowerManagerObserver> {
21  public:
22   explicit PowerManagerObserver(
23       const BatteryStatusService::BatteryUpdateCallback& callback)
24       : callback_(callback), currently_listening_(false) {}
25
26   // Starts listening for updates. It is safe to call this on any thread.
27   void Start() {
28     if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
29       StartOnUI();
30     } else {
31       BrowserThread::PostTask(
32           BrowserThread::UI,
33           FROM_HERE,
34           base::Bind(&PowerManagerObserver::StartOnUI, this));
35     }
36   }
37
38   // Stops listening for updates. It is safe to call this on any thread.
39   void Stop() {
40     if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
41       StopOnUI();
42     } else {
43       BrowserThread::PostTask(
44           BrowserThread::UI,
45           FROM_HERE,
46           base::Bind(&PowerManagerObserver::StopOnUI, this));
47     }
48   }
49
50  private:
51   friend class base::RefCountedThreadSafe<PowerManagerObserver>;
52
53   virtual ~PowerManagerObserver() {}
54
55   bool IsBatteryPresent(
56       const power_manager::PowerSupplyProperties& proto) const {
57     return proto.battery_state() !=
58            power_manager::PowerSupplyProperties_BatteryState_NOT_PRESENT;
59   }
60
61   bool IsUsbChargerConnected(
62       const power_manager::PowerSupplyProperties& proto) const {
63     return proto.external_power() ==
64            power_manager::PowerSupplyProperties_ExternalPower_USB;
65   }
66
67   bool IsBatteryCharging(
68       const power_manager::PowerSupplyProperties& proto) const {
69     return proto.battery_state() !=
70            power_manager::PowerSupplyProperties_BatteryState_DISCHARGING;
71   }
72
73   bool IsBatteryFull(const power_manager::PowerSupplyProperties& proto) const {
74     return proto.battery_state() ==
75            power_manager::PowerSupplyProperties_BatteryState_FULL;
76   }
77
78   double GetBatteryLevel(
79       const power_manager::PowerSupplyProperties& proto) const {
80     const double kMaxBatteryLevelProto = 100.f;
81     return proto.battery_percent() / kMaxBatteryLevelProto;
82   }
83
84   void StartOnUI() {
85     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
86     if (currently_listening_)
87       return;
88     chromeos::PowerManagerClient* power_client =
89         chromeos::DBusThreadManager::Get()->GetPowerManagerClient();
90     power_client->AddObserver(this);
91     power_client->RequestStatusUpdate();
92     currently_listening_ = true;
93   }
94
95   void StopOnUI() {
96     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
97     if (!currently_listening_)
98       return;
99     chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver(
100         this);
101     currently_listening_ = false;
102   }
103
104   // chromeos::PowerManagerClient::Observer:
105   virtual void PowerChanged(
106       const power_manager::PowerSupplyProperties& proto) OVERRIDE {
107     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
108     blink::WebBatteryStatus status;
109     // Use the default values if there is no battery in the system.
110     if (IsBatteryPresent(proto)) {
111       // The charging status is unreliable if a low power charger is connected
112       // (i.e. usb).
113       bool status_unreliable = IsUsbChargerConnected(proto);
114       // Battery time is unreliable if it is still being computed.
115       bool time_unreliable =
116           status_unreliable || proto.is_calculating_battery_time();
117
118       // Set |charging| only if the status is reliable. Otherwise, keep the
119       // default (which is |true|).
120       if (!status_unreliable)
121         status.charging = IsBatteryCharging(proto);
122
123       // Set |chargingTime| to +infinity if the battery is discharging, or if
124       // the time is unreliable. Keep the default value (which is 0) if the
125       // battery is full.
126       if (time_unreliable || !status.charging)
127         status.chargingTime = std::numeric_limits<double>::infinity();
128       else if (!IsBatteryFull(proto))
129         status.chargingTime = proto.battery_time_to_full_sec();
130
131       // Keep the default value for |dischargingTime| (which is +infinity) if
132       // the time is unreliable, or if the battery is charging.
133       if (!time_unreliable && !status.charging)
134         status.dischargingTime = proto.battery_time_to_empty_sec();
135
136       status.level = GetBatteryLevel(proto);
137     }
138     callback_.Run(status);
139   }
140
141   BatteryStatusService::BatteryUpdateCallback callback_;
142   bool currently_listening_;
143
144   DISALLOW_COPY_AND_ASSIGN(PowerManagerObserver);
145 };
146
147 class BatteryStatusManagerChromeOS
148     : public BatteryStatusManager,
149       public chromeos::PowerManagerClient::Observer {
150  public:
151   explicit BatteryStatusManagerChromeOS(
152       const BatteryStatusService::BatteryUpdateCallback& callback)
153       : observer_(new PowerManagerObserver(callback)) {}
154
155   virtual ~BatteryStatusManagerChromeOS() { observer_->Stop(); }
156
157  private:
158   // BatteryStatusManager:
159   virtual bool StartListeningBatteryChange() OVERRIDE {
160     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
161     observer_->Start();
162     return true;
163   }
164
165   virtual void StopListeningBatteryChange() OVERRIDE {
166     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
167     observer_->Stop();
168   }
169
170   scoped_refptr<PowerManagerObserver> observer_;
171
172   DISALLOW_COPY_AND_ASSIGN(BatteryStatusManagerChromeOS);
173 };
174
175 }  // namespace
176
177 // static
178 scoped_ptr<BatteryStatusManager> BatteryStatusManager::Create(
179     const BatteryStatusService::BatteryUpdateCallback& callback) {
180   return scoped_ptr<BatteryStatusManager>(
181       new BatteryStatusManagerChromeOS(callback));
182 }
183
184 }  // namespace content