| Index: chrome/browser/chromeos/power/peripheral_battery_observer.cc
|
| diff --git a/chrome/browser/chromeos/power/peripheral_battery_observer.cc b/chrome/browser/chromeos/power/peripheral_battery_observer.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..fb458b2d3f1ddf9e3072ed27cd1f9bd3db784406
|
| --- /dev/null
|
| +++ b/chrome/browser/chromeos/power/peripheral_battery_observer.cc
|
| @@ -0,0 +1,149 @@
|
| +// Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "chrome/browser/chromeos/power/peripheral_battery_observer.h"
|
| +
|
| +#include "ash/shell.h"
|
| +#include "base/stringprintf.h"
|
| +#include "base/utf_string_conversions.h"
|
| +#include "chrome/browser/browser_process.h"
|
| +#include "chrome/browser/notifications/notification.h"
|
| +#include "chrome/browser/notifications/notification_ui_manager.h"
|
| +#include "chrome/browser/profiles/profile_manager.h"
|
| +#include "chromeos/dbus/dbus_thread_manager.h"
|
| +#include "grit/ash_strings.h"
|
| +#include "grit/theme_resources.h"
|
| +#include "ui/base/l10n/l10n_util.h"
|
| +#include "ui/base/resource/resource_bundle.h"
|
| +#include "ui/gfx/image/image.h"
|
| +
|
| +namespace chromeos {
|
| +
|
| +namespace {
|
| +
|
| +const int kLowBatteryLevel = 15;
|
| +const int kNotificationInterval = 60;
|
| +const int kNoUpdateLimit = 120;
|
| +
|
| +class PeripheralBatteryNotificationDelegate : public NotificationDelegate {
|
| + public:
|
| +
|
| + explict PeripheralBatteryNotificationDelegate(const std::string& id)
|
| + : id_(id) {}
|
| +
|
| + // Overridden from NotificationDelegate:
|
| + virtual void Display() OVERRIDE {}
|
| + virtual void Error() OVERRIDE {}
|
| + virtual void Close(bool by_user) OVERRIDE {}
|
| + virtual void Click() OVERRIDE {}
|
| + virtual std::string id() const OVERRIDE { return id_; }
|
| + virtual content::RenderViewHost* GetRenderViewHost() const OVERRIDE {
|
| + return NULL;
|
| + }
|
| +
|
| + private:
|
| + const std::string id_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(PeripheralBatteryNotificationDelegate);
|
| +};
|
| +
|
| +base::TimeDelta TimeNow() {
|
| + return base::TimeDelta::FromInternalValue(
|
| + base::TimeTicks::Now().ToInternalValue());
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +PeripheralBatteryObserver::PeripheralBatteryObserver() {
|
| + DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver(this);
|
| +}
|
| +
|
| +PeripheralBatteryObserver::~PeripheralBatteryObserver() {
|
| + DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver(this);
|
| +}
|
| +
|
| +void PeripheralBatteryObserver::PeripheralBatteryStatusReceived(
|
| + const std::string& path, const std::string& name, int level) {
|
| + if (level < -1 || level > 100) {
|
| + LOG(ERROR) << "Invalid battery level " << level
|
| + << " for device " << name << " at path " << path;
|
| + return;
|
| + }
|
| + // If unknown battery level received, cancel any existing notification.
|
| + if (level == -1)
|
| + g_browser_process->notification_ui_manager()->CancelById(path);
|
| +
|
| + // Post the notification in 2 cases:
|
| + // 1. It's the first time the battery level is received, and it is
|
| + // below kLowBatteryLevel.
|
| + // 2. The battery level is in record and it drops below kLowBatteryLevel.
|
| + if (batteries_.find(path) == batteries_.end()) {
|
| + BatteryInfo battery(path, name, level, base::TimeDelta(), TimeNow());
|
| + if (level >= 0 && level < kLowBatteryLevel)
|
| + PostNotification(&battery);
|
| + batteries_[path] = battery;
|
| + } else {
|
| + BatteryInfo* battery = &batteries_[path];
|
| + battery->set_name(name);
|
| + int old_level = battery->level();
|
| + battery->set_level(level);
|
| + battery->set_update_timestamp(TimeNow());
|
| + if (old_level >= kLowBatteryLevel && level >= 0 && level < kLowBatteryLevel)
|
| + PostNotification(battery);
|
| + }
|
| +
|
| + // Go through the list to remove any battery record that hasn't been updated
|
| + // for a long time (most likely the device is disconnected).
|
| + std::map<std::string, BatteryInfo>::iterator it = batteries_.begin();
|
| + base::TimeDelta now = TimeNow();
|
| + while (it != batteries_.end()) {
|
| + if (now - it->second.last_update_timestamp() >
|
| + base::TimeDelta::FromSeconds(kNoUpdateLimit)) {
|
| + batteries_.erase(it++);
|
| + } else {
|
| + it++;
|
| + }
|
| + }
|
| +}
|
| +
|
| +void PeripheralBatteryObserver::PostNotification(BatteryInfo* battery) {
|
| + // Only post notification if kNotificationInterval seconds have passed
|
| + // since last notification showed, avoiding the case the battery level
|
| + // oscillates around the threshold level.
|
| + if (TimeNow() - battery->last_notification_timestamp() <
|
| + base::TimeDelta::FromSeconds(kNotificationInterval))
|
| + return;
|
| +
|
| + NotificationUIManager* notification_manager =
|
| + g_browser_process->notification_ui_manager();
|
| +
|
| + std::string string_id = battery->path();
|
| + std::string string_text = base::StringPrintf("Battery Low (%d%%)",
|
| + battery->level());
|
| +
|
| + if (notification_manager->DoesIdExist(string_id)) {
|
| + if (!notification_manager->CancelById(string_id)) {
|
| + LOG(ERROR) << "Can't cancel notification for ID " << string_id;
|
| + return;
|
| + }
|
| + }
|
| +
|
| + Notification notification(
|
| + GURL(),
|
| + ui::ResourceBundle::GetSharedInstance().GetImageNamed(
|
| + IDR_NOTIFICATION_PERIPHERAL_BATTERY_LOW),
|
| + UTF8ToUTF16(battery->name()),
|
| + UTF8ToUTF16(string_text),
|
| + WebKit::WebTextDirectionDefault,
|
| + string16(),
|
| + UTF8ToUTF16(string_id),
|
| + new PeripheralBatteryNotificationDelegate(string_id));
|
| +
|
| + notification_manager->Add(notification,
|
| + ProfileManager::GetDefaultProfileOrOffTheRecord());
|
| +
|
| + battery->set_notification_timestamp(TimeNow());
|
| +}
|
| +
|
| +} // namespace chromeos
|
|
|