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

Side by Side Diff: content/browser/battery_status/battery_status_manager_mac.cc

Issue 398683006: Battery Status API: implementation for Mac OS. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix browsertests Created 6 years, 5 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | content/content_browser.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 <CoreFoundation/CoreFoundation.h>
8 #include <IOKit/ps/IOPowerSources.h>
9 #include <IOKit/ps/IOPSKeys.h>
10
11 #include "base/memory/ref_counted.h"
12 #include "base/threading/thread.h"
13 #include "base/time/time.h"
14 #include "content/public/browser/browser_thread.h"
15 #include "third_party/WebKit/public/platform/WebBatteryStatus.h"
16
17 namespace content {
18
19 namespace {
20
21 typedef const BatteryStatusService::BatteryUpdateCallback BatteryCallback;
22
23 // Returns the value corresponding to |key| in the dictionary |description|.
24 // Returns |default_value| if the dictionary does not contain |key|, the
25 // corresponding value is NULL or it could not be converted to CFIndexType.
26 static CFIndex GetValueAsCFIndex(CFDictionaryRef description,
27 CFStringRef key,
28 CFIndex default_value) {
29 CFNumberRef value_number =
30 (CFNumberRef)CFDictionaryGetValue(description, key);
Mark Mentovai 2014/07/17 14:08:31 CFCast<CFNumberRef>.
Robert Sesek 2014/07/17 15:16:41 Better yet: base::mac::GetValueFromDictionary<T>(d
timvolodine 2014/07/22 18:04:43 Done.
timvolodine 2014/07/22 18:04:43 Done.
31 CFIndex value;
32
33 if (value_number &&
34 CFNumberGetValue(value_number, kCFNumberCFIndexType, &value))
35 return value;
36
37 return default_value;
38 }
39
40 static void FetchBatteryStatus(CFDictionaryRef description,
41 blink::WebBatteryStatus& status) {
42 CFStringRef currentState =
43 (CFStringRef)CFDictionaryGetValue(description,
Mark Mentovai 2014/07/17 14:08:31 CFCast<CFStringRef>.
timvolodine 2014/07/22 18:04:44 Done.
44 CFSTR(kIOPSPowerSourceStateKey));
45 bool on_battery_power =
46 CFStringCompare(currentState, CFSTR(kIOPSBatteryPowerValue), 0)
47 == kCFCompareEqualTo;
48 bool is_charging =
49 CFDictionaryGetValue(description, CFSTR(kIOPSIsChargingKey))
Mark Mentovai 2014/07/17 14:08:31 This just tells you if kIOPSIsChargingKey was foun
timvolodine 2014/07/22 18:04:44 I've changed this to use CFBooleanGetValue, as you
50 == kCFBooleanTrue;
51 bool is_charged =
52 CFDictionaryGetValue(description, CFSTR(kIOPSIsChargedKey))
53 == kCFBooleanTrue;
54
55 // Set charging to false if on battery power and not charging.
Mark Mentovai 2014/07/17 14:08:31 Why not set status.charging to is_charging? Why h
timvolodine 2014/07/22 18:04:44 yes this is on purpose. I've added a comment expla
56 if (on_battery_power && !is_charging)
57 status.charging = false;
58
59 CFIndex current_capacity =
60 GetValueAsCFIndex(description, CFSTR(kIOPSCurrentCapacityKey), -1);
61 CFIndex max_capacity =
62 GetValueAsCFIndex(description, CFSTR(kIOPSMaxCapacityKey), -1);
63
64 if (current_capacity != -1 && max_capacity != -1)
Mark Mentovai 2014/07/17 14:08:31 && current_capacity <= max_capacity? && max_capaci
timvolodine 2014/07/22 18:04:44 Done.
65 status.level = (double)current_capacity/(double)max_capacity;
Mark Mentovai 2014/07/17 14:08:31 Don’t use (C_style)casts, use Cplusplus<style>(cas
timvolodine 2014/07/22 18:04:43 Done.
66
67 if (is_charging) {
68 CFIndex charging_time =
69 GetValueAsCFIndex(description, CFSTR(kIOPSTimeToFullChargeKey), -1);
70
71 // Battery is charging: set the charging time if it's available, otherwise
72 // set to +infinity.
73 status.chargingTime = (charging_time != -1)
Mark Mentovai 2014/07/17 14:08:31 WebBatteryStatus.h doesn’t have comments in it to
timvolodine 2014/07/22 18:04:44 The specification is here: https://dvcs.w3.org/hg/
74 ? base::TimeDelta::FromMinutes(charging_time).InSeconds()
75 : std::numeric_limits<double>::infinity();
76 } else {
77 // Battery is not charging.
78 // Set chargingTime to +infinity if the battery is not charged.
79 if (!is_charged)
80 status.chargingTime = std::numeric_limits<double>::infinity();
81
82 // Set dischargingTime if it's available and valid, i.e. when on battery
83 // power.
84 if (on_battery_power) {
85 CFIndex discharging_time =
86 GetValueAsCFIndex(description, CFSTR(kIOPSTimeToEmptyKey), -1);
87 if (discharging_time != -1) {
88 status.dischargingTime =
Mark Mentovai 2014/07/17 14:08:31 Should you be setting status.dischargingTime to so
timvolodine 2014/07/22 18:04:44 no garbage ;). I've added some comments regarding
89 base::TimeDelta::FromMinutes(discharging_time).InSeconds();
90 }
91 }
92 }
93 }
94
95 static void OnBatteryStatusChanged(BatteryCallback& callback) {
96 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
97 blink::WebBatteryStatus status;
98 CFTypeRef blob = IOPSCopyPowerSourcesInfo();
Mark Mentovai 2014/07/17 14:08:31 Do you need to release this or does IOPSCopyPowerS
timvolodine 2014/07/22 18:04:44 you are right, it needs to be released. added Scop
99 CFArrayRef powerSourcesList = IOPSCopyPowerSourcesList(blob);
Mark Mentovai 2014/07/17 14:08:31 This one almost definitely needs a ScopedCFTypeRef
timvolodine 2014/07/22 18:04:44 added ScopedCFTypeRef, done.
100 CFIndex count = CFArrayGetCount(powerSourcesList);
101
102 for (CFIndex i = 0; i < count; ++i) {
103 CFDictionaryRef description = IOPSGetPowerSourceDescription(blob,
104 CFArrayGetValueAtIndex(powerSourcesList, i));
105
106 bool battery_present =
107 CFDictionaryGetValue(description, CFSTR(kIOPSIsPresentKey))
Mark Mentovai 2014/07/17 14:08:31 CFDictionaryGetValue doesn’t return kCFBooleanTrue
timvolodine 2014/07/22 18:04:44 Done. (but it looks like it actually returns a poi
108 == kCFBooleanTrue;
109
110 if (!description || !battery_present)
111 continue;
112
113 FetchBatteryStatus(description, status);
114 break;
115 }
116
117 callback.Run(status);
118 }
119
120 class BatteryStatusObserver
121 : public base::RefCountedThreadSafe<BatteryStatusObserver> {
122 public:
123 explicit BatteryStatusObserver(BatteryCallback& callback)
124 : callback_(callback), notifier_run_loop_(0) {}
Mark Mentovai 2014/07/17 14:08:31 Use NULL for null CFTypeRef-family values here and
timvolodine 2014/07/22 18:04:43 not necessary anymore because I made notifier_run_
125
126 void Start() {
127 // Need thread with UI-type message loop for notifications to run.
128 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
129 StartOnUI();
130 } else {
131 BrowserThread::PostTask(
132 BrowserThread::UI,
133 FROM_HERE,
134 base::Bind(&BatteryStatusObserver::StartOnUI, this));
135 }
136 }
137
138 void Stop() {
139 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
140 StopOnUI();
141 } else {
142 BrowserThread::PostTask(
143 BrowserThread::UI,
144 FROM_HERE,
145 base::Bind(&BatteryStatusObserver::StopOnUI, this));
146 }
147 }
148
149 private:
150 friend class base::RefCountedThreadSafe<BatteryStatusObserver>;
151 virtual ~BatteryStatusObserver() {}
Mark Mentovai 2014/07/17 14:08:31 [D]CHECK that it’s stopped (by notifier_run_loop_
timvolodine 2014/07/22 18:04:44 Done.
152
153 void StartOnUI() {
154 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
155
156 if (notifier_run_loop_)
Mark Mentovai 2014/07/17 14:08:31 Might this actually happen in practice? It may be
timvolodine 2014/07/22 18:04:44 I don't think we should be that strict, users may
157 return;
158
159 OnBatteryStatusChangedUI((void*)&callback_);
160
161 notifier_run_loop_ =
162 IOPSNotificationCreateRunLoopSource(OnBatteryStatusChangedUI,
163 (void*)&callback_);
164 if (notifier_run_loop_) {
165 CFRunLoopAddSource(CFRunLoopGetCurrent(), notifier_run_loop_,
166 kCFRunLoopDefaultMode);
167 }
168 }
169
170 void StopOnUI() {
171 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
172
173 if (!notifier_run_loop_)
174 return;
175
176 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), notifier_run_loop_,
177 kCFRunLoopDefaultMode);
178 CFRelease(notifier_run_loop_);
179 notifier_run_loop_ = 0;
180 }
181
182 static void OnBatteryStatusChangedUI(void* callback) {
183 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
184 // Offload fetching of values and callback execution to the IO thread.
185 BrowserThread::PostTask(
186 BrowserThread::IO,
187 FROM_HERE,
188 base::Bind(&OnBatteryStatusChanged,
189 *static_cast<BatteryCallback*>(callback)));
190 }
191
192 BatteryCallback& callback_;
Robert Sesek 2014/07/17 15:16:41 Why is this stored by reference?
timvolodine 2014/07/22 18:04:43 technically this is ok because the callback is own
193 CFRunLoopSourceRef notifier_run_loop_;
194
195 DISALLOW_COPY_AND_ASSIGN(BatteryStatusObserver);
196 };
197
198 class BatteryStatusManagerMac : public BatteryStatusManager {
199 public:
200 explicit BatteryStatusManagerMac(BatteryCallback& callback)
201 : notifier_(new BatteryStatusObserver(callback)) {}
202
203 virtual ~BatteryStatusManagerMac() {
204 notifier_->Stop();
205 }
206
207 // BatteryStatusManager:
208 virtual bool StartListeningBatteryChange() OVERRIDE {
209 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
210 notifier_->Start();
211 return true;
212 }
213
214 virtual void StopListeningBatteryChange() OVERRIDE {
215 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
216 notifier_->Stop();
217 }
218
219 private:
220 scoped_refptr<BatteryStatusObserver> notifier_;
221
222 DISALLOW_COPY_AND_ASSIGN(BatteryStatusManagerMac);
223 };
224
225 } // end namespace
226
227 // static
228 scoped_ptr<BatteryStatusManager> BatteryStatusManager::Create(
229 const BatteryStatusService::BatteryUpdateCallback& callback) {
230 return scoped_ptr<BatteryStatusManager>(
231 new BatteryStatusManagerMac(callback));
232 }
233
234 } // namespace content
OLDNEW
« no previous file with comments | « no previous file | content/content_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698