OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/battery_status/battery_status_manager_win.h" | 5 #include "content/browser/battery_status/battery_status_manager_win.h" |
6 | 6 |
7 #include "base/memory/ref_counted.h" | 7 #include "base/memory/ref_counted.h" |
8 #include "base/strings/string16.h" | |
9 #include "base/win/message_window.h" | |
10 #include "base/win/windows_version.h" | 8 #include "base/win/windows_version.h" |
11 #include "content/browser/battery_status/battery_status_manager.h" | 9 #include "content/browser/battery_status/battery_status_manager.h" |
12 #include "content/public/browser/browser_thread.h" | 10 #include "content/public/browser/browser_thread.h" |
| 11 #include "ui/gfx/win/singleton_hwnd.h" |
13 | 12 |
14 namespace content { | 13 namespace content { |
15 | 14 |
16 namespace { | 15 namespace { |
17 | 16 |
18 typedef BatteryStatusService::BatteryUpdateCallback BatteryCallback; | 17 typedef BatteryStatusService::BatteryUpdateCallback BatteryCallback; |
19 | 18 |
20 const wchar_t kWindowClassName[] = L"BatteryStatusMessageWindow"; | 19 // Listens to battery changes using a singleton message window. |
21 | |
22 // Message-only window for handling battery changes on Windows. | |
23 class BatteryStatusObserver | 20 class BatteryStatusObserver |
24 : public base::RefCountedThreadSafe<BatteryStatusObserver> { | 21 : public gfx::SingletonHwnd::Observer, |
| 22 public base::RefCountedThreadSafe<BatteryStatusObserver> { |
25 public: | 23 public: |
26 explicit BatteryStatusObserver(const BatteryCallback& callback) | 24 explicit BatteryStatusObserver(const BatteryCallback& callback) |
27 : power_handle_(NULL), | 25 : power_handle_(NULL), |
28 battery_change_handle_(NULL), | 26 battery_change_handle_(NULL), |
29 callback_(callback) { | 27 callback_(callback), |
| 28 started_(false) { |
30 } | 29 } |
31 | 30 |
32 virtual ~BatteryStatusObserver() { DCHECK(!window_); } | 31 virtual ~BatteryStatusObserver() { DCHECK(!started_); } |
33 | 32 |
34 void Start() { | 33 void Start() { |
35 // Need to start on the UI thread to receive battery status notifications. | 34 // Need to start on the UI thread to receive battery status notifications. |
36 BrowserThread::PostTask( | 35 BrowserThread::PostTask( |
37 BrowserThread::UI, | 36 BrowserThread::UI, |
38 FROM_HERE, | 37 FROM_HERE, |
39 base::Bind(&BatteryStatusObserver::StartOnUI, this)); | 38 base::Bind(&BatteryStatusObserver::StartOnUI, this)); |
40 } | 39 } |
41 | 40 |
42 void Stop() { | 41 void Stop() { |
43 BrowserThread::PostTask( | 42 BrowserThread::PostTask( |
44 BrowserThread::UI, | 43 BrowserThread::UI, |
45 FROM_HERE, | 44 FROM_HERE, |
46 base::Bind(&BatteryStatusObserver::StopOnUI, this)); | 45 base::Bind(&BatteryStatusObserver::StopOnUI, this)); |
47 } | 46 } |
48 | 47 |
49 private: | 48 private: |
50 void StartOnUI() { | 49 void StartOnUI() { |
51 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 50 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
52 if (window_) | 51 if (started_) |
53 return; | 52 return; |
54 | 53 |
55 if (CreateMessageWindow()) { | 54 gfx::SingletonHwnd* message_window = gfx::SingletonHwnd::GetInstance(); |
56 BatteryChanged(); | 55 message_window->AddObserver(this); |
57 // RegisterPowerSettingNotification function work from Windows Vista | 56 |
58 // onwards. However even without them we will receive notifications, | 57 // RegisterPowerSettingNotification function work from Windows Vista |
59 // e.g. when a power source is connected. | 58 // onwards. However even without them we will receive notifications, |
60 // TODO(timvolodine) : consider polling for battery changes on windows | 59 // e.g. when a power source is connected. |
61 // versions prior to Vista, see crbug.com/402466. | 60 // TODO(timvolodine) : consider polling for battery changes on windows |
62 power_handle_ = | 61 // versions prior to Vista, see crbug.com/402466. |
63 RegisterNotification(&GUID_ACDC_POWER_SOURCE); | 62 power_handle_ = RegisterNotification(&GUID_ACDC_POWER_SOURCE, |
64 battery_change_handle_ = | 63 message_window->hwnd()); |
65 RegisterNotification(&GUID_BATTERY_PERCENTAGE_REMAINING); | 64 battery_change_handle_ = |
66 } else { | 65 RegisterNotification(&GUID_BATTERY_PERCENTAGE_REMAINING, |
67 // Could not create a message window, execute callback with the default | 66 message_window->hwnd()); |
68 // values. | 67 BatteryChanged(); |
69 callback_.Run(blink::WebBatteryStatus()); | 68 started_ = true; |
70 } | |
71 } | 69 } |
72 | 70 |
73 void StopOnUI() { | 71 void StopOnUI() { |
74 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 72 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
75 if (!window_) | 73 if (!started_) |
76 return; | 74 return; |
77 | 75 |
78 if (power_handle_) | 76 if (power_handle_) |
79 UnregisterNotification(power_handle_); | 77 UnregisterNotification(power_handle_); |
80 if (battery_change_handle_) | 78 if (battery_change_handle_) |
81 UnregisterNotification(battery_change_handle_); | 79 UnregisterNotification(battery_change_handle_); |
82 window_.reset(); | 80 |
| 81 gfx::SingletonHwnd::GetInstance()->RemoveObserver(this); |
| 82 started_ = false; |
83 } | 83 } |
84 | 84 |
85 void BatteryChanged() { | 85 void BatteryChanged() { |
86 SYSTEM_POWER_STATUS win_status; | 86 SYSTEM_POWER_STATUS win_status; |
87 if (GetSystemPowerStatus(&win_status)) | 87 if (GetSystemPowerStatus(&win_status)) |
88 callback_.Run(ComputeWebBatteryStatus(win_status)); | 88 callback_.Run(ComputeWebBatteryStatus(win_status)); |
89 else | 89 else |
90 callback_.Run(blink::WebBatteryStatus()); | 90 callback_.Run(blink::WebBatteryStatus()); |
91 } | 91 } |
92 | 92 |
93 bool HandleMessage(UINT message, | 93 // SingletonHwnd::Observer |
94 WPARAM wparam, | 94 void OnWndProc(HWND hwnd, |
95 LPARAM lparam, | 95 UINT message, |
96 LRESULT* result) { | 96 WPARAM wparam, |
97 switch(message) { | 97 LPARAM lparam) OVERRIDE { |
98 case WM_POWERBROADCAST: | 98 if (message != WM_POWERBROADCAST) |
99 if (wparam == PBT_APMPOWERSTATUSCHANGE || | 99 return; |
100 wparam == PBT_POWERSETTINGCHANGE) { | 100 |
101 BatteryChanged(); | 101 if (wparam == PBT_APMPOWERSTATUSCHANGE || |
102 } | 102 wparam == PBT_POWERSETTINGCHANGE) { |
103 *result = NULL; | 103 BatteryChanged(); |
104 return true; | |
105 default: | |
106 return false; | |
107 } | 104 } |
108 } | 105 } |
109 | 106 |
110 HPOWERNOTIFY RegisterNotification(LPCGUID power_setting) { | 107 HPOWERNOTIFY RegisterNotification(LPCGUID power_setting, HWND hwnd) { |
111 if (base::win::GetVersion() < base::win::VERSION_VISTA) | 108 if (base::win::GetVersion() < base::win::VERSION_VISTA) |
112 return NULL; | 109 return NULL; |
113 | 110 |
114 return RegisterPowerSettingNotification(window_->hwnd(), power_setting, | 111 return RegisterPowerSettingNotification(hwnd, |
115 DEVICE_NOTIFY_WINDOW_HANDLE); | 112 power_setting, |
| 113 DEVICE_NOTIFY_WINDOW_HANDLE); |
116 } | 114 } |
117 | 115 |
118 BOOL UnregisterNotification(HPOWERNOTIFY handle) { | 116 BOOL UnregisterNotification(HPOWERNOTIFY handle) { |
119 if (base::win::GetVersion() < base::win::VERSION_VISTA) | 117 if (base::win::GetVersion() < base::win::VERSION_VISTA) |
120 return FALSE; | 118 return FALSE; |
121 | 119 |
122 return UnregisterPowerSettingNotification(handle); | 120 return UnregisterPowerSettingNotification(handle); |
123 } | 121 } |
124 | 122 |
125 bool CreateMessageWindow() { | |
126 // TODO(timvolodine): consider reusing the message window of PowerMonitor. | |
127 window_.reset(new base::win::MessageWindow()); | |
128 if (!window_->CreateNamed(base::Bind(&BatteryStatusObserver::HandleMessage, | |
129 base::Unretained(this)), | |
130 base::string16(kWindowClassName))) { | |
131 LOG(ERROR) << "Failed to create message window: " << kWindowClassName; | |
132 window_.reset(); | |
133 return false; | |
134 } | |
135 return true; | |
136 } | |
137 | |
138 HPOWERNOTIFY power_handle_; | 123 HPOWERNOTIFY power_handle_; |
139 HPOWERNOTIFY battery_change_handle_; | 124 HPOWERNOTIFY battery_change_handle_; |
140 BatteryCallback callback_; | 125 BatteryCallback callback_; |
141 scoped_ptr<base::win::MessageWindow> window_; | 126 bool started_; |
142 | 127 |
143 DISALLOW_COPY_AND_ASSIGN(BatteryStatusObserver); | 128 DISALLOW_COPY_AND_ASSIGN(BatteryStatusObserver); |
144 }; | 129 }; |
145 | 130 |
146 class BatteryStatusManagerWin : public BatteryStatusManager { | 131 class BatteryStatusManagerWin : public BatteryStatusManager { |
147 public: | 132 public: |
148 explicit BatteryStatusManagerWin(const BatteryCallback& callback) | 133 explicit BatteryStatusManagerWin(const BatteryCallback& callback) |
149 : battery_observer_(new BatteryStatusObserver(callback)) {} | 134 : battery_observer_(new BatteryStatusObserver(callback)) {} |
150 virtual ~BatteryStatusManagerWin() { battery_observer_->Stop(); } | 135 virtual ~BatteryStatusManagerWin() { battery_observer_->Stop(); } |
151 | 136 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
197 } | 182 } |
198 | 183 |
199 // static | 184 // static |
200 scoped_ptr<BatteryStatusManager> BatteryStatusManager::Create( | 185 scoped_ptr<BatteryStatusManager> BatteryStatusManager::Create( |
201 const BatteryStatusService::BatteryUpdateCallback& callback) { | 186 const BatteryStatusService::BatteryUpdateCallback& callback) { |
202 return scoped_ptr<BatteryStatusManager>( | 187 return scoped_ptr<BatteryStatusManager>( |
203 new BatteryStatusManagerWin(callback)); | 188 new BatteryStatusManagerWin(callback)); |
204 } | 189 } |
205 | 190 |
206 } // namespace content | 191 } // namespace content |
OLD | NEW |