| OLD | NEW | 
|---|
| (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_win.h" | 
|  | 6 | 
|  | 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" | 
|  | 11 #include "content/browser/battery_status/battery_status_manager.h" | 
|  | 12 #include "content/public/browser/browser_thread.h" | 
|  | 13 | 
|  | 14 namespace content { | 
|  | 15 | 
|  | 16 namespace { | 
|  | 17 | 
|  | 18 typedef BatteryStatusService::BatteryUpdateCallback BatteryCallback; | 
|  | 19 | 
|  | 20 const wchar_t kWindowClassName[] = L"BatteryStatusMessageWindow"; | 
|  | 21 | 
|  | 22 // Message-only window for handling battery changes on Windows. | 
|  | 23 class BatteryStatusObserver | 
|  | 24     : public base::RefCountedThreadSafe<BatteryStatusObserver> { | 
|  | 25  public: | 
|  | 26   explicit BatteryStatusObserver(const BatteryCallback& callback) | 
|  | 27       : power_handle_(NULL), | 
|  | 28         battery_change_handle_(NULL), | 
|  | 29         callback_(callback) { | 
|  | 30   } | 
|  | 31 | 
|  | 32   virtual ~BatteryStatusObserver() { DCHECK(!window_); } | 
|  | 33 | 
|  | 34   void Start() { | 
|  | 35     // Need to start on the UI thread to receive battery status notifications. | 
|  | 36     BrowserThread::PostTask( | 
|  | 37         BrowserThread::UI, | 
|  | 38         FROM_HERE, | 
|  | 39         base::Bind(&BatteryStatusObserver::StartOnUI, this)); | 
|  | 40   } | 
|  | 41 | 
|  | 42   void Stop() { | 
|  | 43     BrowserThread::PostTask( | 
|  | 44         BrowserThread::UI, | 
|  | 45         FROM_HERE, | 
|  | 46         base::Bind(&BatteryStatusObserver::StopOnUI, this)); | 
|  | 47   } | 
|  | 48 | 
|  | 49  private: | 
|  | 50   void StartOnUI() { | 
|  | 51     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
|  | 52     if (window_) | 
|  | 53       return; | 
|  | 54 | 
|  | 55     if (CreateMessageWindow()) { | 
|  | 56       BatteryChanged(); | 
|  | 57       // RegisterPowerSettingNotification function work from Windows Vista | 
|  | 58       // onwards. However even without them we will receive notifications, | 
|  | 59       // e.g. when a power source is connected. | 
|  | 60       // TODO(timvolodine) : consider polling for battery changes on windows | 
|  | 61       // versions prior to Vista, see crbug.com/402466. | 
|  | 62       power_handle_ = | 
|  | 63           RegisterNotification(&GUID_ACDC_POWER_SOURCE); | 
|  | 64       battery_change_handle_ = | 
|  | 65           RegisterNotification(&GUID_BATTERY_PERCENTAGE_REMAINING); | 
|  | 66     } else { | 
|  | 67       // Could not create a message window, execute callback with the default | 
|  | 68       // values. | 
|  | 69       callback_.Run(blink::WebBatteryStatus()); | 
|  | 70     } | 
|  | 71   } | 
|  | 72 | 
|  | 73   void StopOnUI() { | 
|  | 74     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
|  | 75     if (!window_) | 
|  | 76       return; | 
|  | 77 | 
|  | 78     if (power_handle_) | 
|  | 79       UnregisterNotification(power_handle_); | 
|  | 80     if (battery_change_handle_) | 
|  | 81       UnregisterNotification(battery_change_handle_); | 
|  | 82     window_.reset(); | 
|  | 83   } | 
|  | 84 | 
|  | 85   void BatteryChanged() { | 
|  | 86     SYSTEM_POWER_STATUS win_status; | 
|  | 87     if (GetSystemPowerStatus(&win_status)) | 
|  | 88       callback_.Run(ComputeWebBatteryStatus(win_status)); | 
|  | 89     else | 
|  | 90       callback_.Run(blink::WebBatteryStatus()); | 
|  | 91   } | 
|  | 92 | 
|  | 93   bool HandleMessage(UINT message, | 
|  | 94                      WPARAM wparam, | 
|  | 95                      LPARAM lparam, | 
|  | 96                      LRESULT* result) { | 
|  | 97     switch(message) { | 
|  | 98       case WM_POWERBROADCAST: | 
|  | 99         if (wparam == PBT_APMPOWERSTATUSCHANGE || | 
|  | 100             wparam == PBT_POWERSETTINGCHANGE) { | 
|  | 101           BatteryChanged(); | 
|  | 102         } | 
|  | 103         *result = NULL; | 
|  | 104         return true; | 
|  | 105       default: | 
|  | 106         return false; | 
|  | 107     } | 
|  | 108   } | 
|  | 109 | 
|  | 110   HPOWERNOTIFY RegisterNotification(LPCGUID power_setting) { | 
|  | 111     if (base::win::GetVersion() < base::win::VERSION_VISTA) | 
|  | 112       return NULL; | 
|  | 113 | 
|  | 114     return RegisterPowerSettingNotification(window_->hwnd(), power_setting, | 
|  | 115                                      DEVICE_NOTIFY_WINDOW_HANDLE); | 
|  | 116   } | 
|  | 117 | 
|  | 118   BOOL UnregisterNotification(HPOWERNOTIFY handle) { | 
|  | 119     if (base::win::GetVersion() < base::win::VERSION_VISTA) | 
|  | 120       return FALSE; | 
|  | 121 | 
|  | 122     return UnregisterPowerSettingNotification(handle); | 
|  | 123   } | 
|  | 124 | 
|  | 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_; | 
|  | 139   HPOWERNOTIFY battery_change_handle_; | 
|  | 140   BatteryCallback callback_; | 
|  | 141   scoped_ptr<base::win::MessageWindow> window_; | 
|  | 142 | 
|  | 143   DISALLOW_COPY_AND_ASSIGN(BatteryStatusObserver); | 
|  | 144 }; | 
|  | 145 | 
|  | 146 class BatteryStatusManagerWin : public BatteryStatusManager { | 
|  | 147  public: | 
|  | 148   explicit BatteryStatusManagerWin(const BatteryCallback& callback) | 
|  | 149       : battery_observer_(new BatteryStatusObserver(callback)) {} | 
|  | 150   virtual ~BatteryStatusManagerWin() { battery_observer_->Stop(); } | 
|  | 151 | 
|  | 152  public: | 
|  | 153   // BatteryStatusManager: | 
|  | 154   virtual bool StartListeningBatteryChange() OVERRIDE { | 
|  | 155     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 
|  | 156     battery_observer_->Start(); | 
|  | 157     return true; | 
|  | 158   } | 
|  | 159 | 
|  | 160   virtual void StopListeningBatteryChange() OVERRIDE { | 
|  | 161     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 
|  | 162     battery_observer_->Stop(); | 
|  | 163   } | 
|  | 164 | 
|  | 165  private: | 
|  | 166   scoped_refptr<BatteryStatusObserver> battery_observer_; | 
|  | 167 | 
|  | 168   DISALLOW_COPY_AND_ASSIGN(BatteryStatusManagerWin); | 
|  | 169 }; | 
|  | 170 | 
|  | 171 }  // namespace | 
|  | 172 | 
|  | 173 blink::WebBatteryStatus ComputeWebBatteryStatus( | 
|  | 174     const SYSTEM_POWER_STATUS& win_status) { | 
|  | 175   blink::WebBatteryStatus status; | 
|  | 176   status.charging = win_status.ACLineStatus != WIN_AC_LINE_STATUS_OFFLINE; | 
|  | 177 | 
|  | 178   // Set level if available. Otherwise keep the default value which is 1. | 
|  | 179   if (win_status.BatteryLifePercent != 255) { | 
|  | 180     // Convert percentage to a value between 0 and 1 with 2 significant digits. | 
|  | 181     status.level = static_cast<double>(win_status.BatteryLifePercent) / 100.; | 
|  | 182   } | 
|  | 183 | 
|  | 184   if (!status.charging) { | 
|  | 185     // Set dischargingTime if available otherwise keep the default value, | 
|  | 186     // which is +Infinity. | 
|  | 187     if (win_status.BatteryLifeTime != (DWORD)-1) | 
|  | 188       status.dischargingTime = win_status.BatteryLifeTime; | 
|  | 189     status.chargingTime = std::numeric_limits<double>::infinity(); | 
|  | 190   } else { | 
|  | 191     // Set chargingTime to +Infinity if not fully charged, otherwise leave the | 
|  | 192     // default value, which is 0. | 
|  | 193     if (status.level < 1) | 
|  | 194       status.chargingTime = std::numeric_limits<double>::infinity(); | 
|  | 195   } | 
|  | 196   return status; | 
|  | 197 } | 
|  | 198 | 
|  | 199 // static | 
|  | 200 scoped_ptr<BatteryStatusManager> BatteryStatusManager::Create( | 
|  | 201     const BatteryStatusService::BatteryUpdateCallback& callback) { | 
|  | 202   return scoped_ptr<BatteryStatusManager>( | 
|  | 203       new BatteryStatusManagerWin(callback)); | 
|  | 204 } | 
|  | 205 | 
|  | 206 }  // namespace content | 
| OLD | NEW | 
|---|