| 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 |