| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2013 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 "chrome/browser/chromeos/power/peripheral_battery_observer.h" |
| 6 |
| 7 #include "ash/shell.h" |
| 8 #include "base/stringprintf.h" |
| 9 #include "base/utf_string_conversions.h" |
| 10 #include "chrome/browser/browser_process.h" |
| 11 #include "chrome/browser/notifications/notification.h" |
| 12 #include "chrome/browser/notifications/notification_ui_manager.h" |
| 13 #include "chrome/browser/profiles/profile_manager.h" |
| 14 #include "chromeos/dbus/dbus_thread_manager.h" |
| 15 #include "grit/ash_strings.h" |
| 16 #include "grit/theme_resources.h" |
| 17 #include "ui/base/l10n/l10n_util.h" |
| 18 #include "ui/base/resource/resource_bundle.h" |
| 19 #include "ui/gfx/image/image.h" |
| 20 |
| 21 namespace chromeos { |
| 22 |
| 23 namespace { |
| 24 |
| 25 const int kLowBatteryLevel = 15; |
| 26 const int kNotificationInterval = 60; |
| 27 const int kNoUpdateLimit = 120; |
| 28 |
| 29 class PeripheralBatteryNotificationDelegate : public NotificationDelegate { |
| 30 public: |
| 31 |
| 32 explict PeripheralBatteryNotificationDelegate(const std::string& id) |
| 33 : id_(id) {} |
| 34 |
| 35 // Overridden from NotificationDelegate: |
| 36 virtual void Display() OVERRIDE {} |
| 37 virtual void Error() OVERRIDE {} |
| 38 virtual void Close(bool by_user) OVERRIDE {} |
| 39 virtual void Click() OVERRIDE {} |
| 40 virtual std::string id() const OVERRIDE { return id_; } |
| 41 virtual content::RenderViewHost* GetRenderViewHost() const OVERRIDE { |
| 42 return NULL; |
| 43 } |
| 44 |
| 45 private: |
| 46 const std::string id_; |
| 47 |
| 48 DISALLOW_COPY_AND_ASSIGN(PeripheralBatteryNotificationDelegate); |
| 49 }; |
| 50 |
| 51 base::TimeDelta TimeNow() { |
| 52 return base::TimeDelta::FromInternalValue( |
| 53 base::TimeTicks::Now().ToInternalValue()); |
| 54 } |
| 55 |
| 56 } // namespace |
| 57 |
| 58 PeripheralBatteryObserver::PeripheralBatteryObserver() { |
| 59 DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver(this); |
| 60 } |
| 61 |
| 62 PeripheralBatteryObserver::~PeripheralBatteryObserver() { |
| 63 DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver(this); |
| 64 } |
| 65 |
| 66 void PeripheralBatteryObserver::PeripheralBatteryStatusReceived( |
| 67 const std::string& path, const std::string& name, int level) { |
| 68 if (level < -1 || level > 100) { |
| 69 LOG(ERROR) << "Invalid battery level " << level |
| 70 << " for device " << name << " at path " << path; |
| 71 return; |
| 72 } |
| 73 // If unknown battery level received, cancel any existing notification. |
| 74 if (level == -1) |
| 75 g_browser_process->notification_ui_manager()->CancelById(path); |
| 76 |
| 77 // Post the notification in 2 cases: |
| 78 // 1. It's the first time the battery level is received, and it is |
| 79 // below kLowBatteryLevel. |
| 80 // 2. The battery level is in record and it drops below kLowBatteryLevel. |
| 81 if (batteries_.find(path) == batteries_.end()) { |
| 82 BatteryInfo battery(path, name, level, base::TimeDelta(), TimeNow()); |
| 83 if (level >= 0 && level < kLowBatteryLevel) |
| 84 PostNotification(&battery); |
| 85 batteries_[path] = battery; |
| 86 } else { |
| 87 BatteryInfo* battery = &batteries_[path]; |
| 88 battery->set_name(name); |
| 89 int old_level = battery->level(); |
| 90 battery->set_level(level); |
| 91 battery->set_update_timestamp(TimeNow()); |
| 92 if (old_level >= kLowBatteryLevel && level >= 0 && level < kLowBatteryLevel) |
| 93 PostNotification(battery); |
| 94 } |
| 95 |
| 96 // Go through the list to remove any battery record that hasn't been updated |
| 97 // for a long time (most likely the device is disconnected). |
| 98 std::map<std::string, BatteryInfo>::iterator it = batteries_.begin(); |
| 99 base::TimeDelta now = TimeNow(); |
| 100 while (it != batteries_.end()) { |
| 101 if (now - it->second.last_update_timestamp() > |
| 102 base::TimeDelta::FromSeconds(kNoUpdateLimit)) { |
| 103 batteries_.erase(it++); |
| 104 } else { |
| 105 it++; |
| 106 } |
| 107 } |
| 108 } |
| 109 |
| 110 void PeripheralBatteryObserver::PostNotification(BatteryInfo* battery) { |
| 111 // Only post notification if kNotificationInterval seconds have passed |
| 112 // since last notification showed, avoiding the case the battery level |
| 113 // oscillates around the threshold level. |
| 114 if (TimeNow() - battery->last_notification_timestamp() < |
| 115 base::TimeDelta::FromSeconds(kNotificationInterval)) |
| 116 return; |
| 117 |
| 118 NotificationUIManager* notification_manager = |
| 119 g_browser_process->notification_ui_manager(); |
| 120 |
| 121 std::string string_id = battery->path(); |
| 122 std::string string_text = base::StringPrintf("Battery Low (%d%%)", |
| 123 battery->level()); |
| 124 |
| 125 if (notification_manager->DoesIdExist(string_id)) { |
| 126 if (!notification_manager->CancelById(string_id)) { |
| 127 LOG(ERROR) << "Can't cancel notification for ID " << string_id; |
| 128 return; |
| 129 } |
| 130 } |
| 131 |
| 132 Notification notification( |
| 133 GURL(), |
| 134 ui::ResourceBundle::GetSharedInstance().GetImageNamed( |
| 135 IDR_NOTIFICATION_PERIPHERAL_BATTERY_LOW), |
| 136 UTF8ToUTF16(battery->name()), |
| 137 UTF8ToUTF16(string_text), |
| 138 WebKit::WebTextDirectionDefault, |
| 139 string16(), |
| 140 UTF8ToUTF16(string_id), |
| 141 new PeripheralBatteryNotificationDelegate(string_id)); |
| 142 |
| 143 notification_manager->Add(notification, |
| 144 ProfileManager::GetDefaultProfileOrOffTheRecord()); |
| 145 |
| 146 battery->set_notification_timestamp(TimeNow()); |
| 147 } |
| 148 |
| 149 } // namespace chromeos |
| OLD | NEW |