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_service.h"
6
7#include "base/bind.h"
8#include "content/browser/battery_status/battery_status_manager.h"
9#include "content/public/browser/browser_thread.h"
10
11namespace content {
12
13BatteryStatusService::BatteryStatusService()
14    : update_callback_(base::Bind(&BatteryStatusService::UpdateBatteryStatus,
15                                  base::Unretained(this))),
16      status_updated_(false),
17      is_shutdown_(false) {
18  callback_list_.set_removal_callback(
19      base::Bind(&BatteryStatusService::ConsumersChanged,
20                 base::Unretained(this)));
21}
22
23BatteryStatusService::~BatteryStatusService() {
24}
25
26BatteryStatusService* BatteryStatusService::GetInstance() {
27  return Singleton<BatteryStatusService,
28                   LeakySingletonTraits<BatteryStatusService> >::get();
29}
30
31scoped_ptr<BatteryStatusService::BatteryUpdateSubscription>
32BatteryStatusService::AddCallback(const BatteryUpdateCallback& callback) {
33  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
34  DCHECK(!is_shutdown_);
35
36  if (!battery_fetcher_)
37    battery_fetcher_ = BatteryStatusManager::Create(update_callback_);
38
39  if (callback_list_.empty()) {
40    bool success = battery_fetcher_->StartListeningBatteryChange();
41    if (!success) {
42        // Make sure the promise resolves with the default values in Blink.
43        callback.Run(blink::WebBatteryStatus());
44    }
45  }
46
47  if (status_updated_) {
48    // Send recent status to the new callback if already available.
49    callback.Run(status_);
50  }
51
52  return callback_list_.Add(callback);
53}
54
55void BatteryStatusService::ConsumersChanged() {
56  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
57  DCHECK(!is_shutdown_);
58
59  if (callback_list_.empty()) {
60      battery_fetcher_->StopListeningBatteryChange();
61      status_updated_ = false;
62  }
63}
64
65void BatteryStatusService::UpdateBatteryStatus(
66    const blink::WebBatteryStatus& status) {
67  DCHECK(!is_shutdown_);
68  BrowserThread::PostTask(BrowserThread::IO,
69                          FROM_HERE,
70                          base::Bind(&BatteryStatusService::NotifyConsumers,
71                                     base::Unretained(this), status));
72}
73
74void BatteryStatusService::NotifyConsumers(
75    const blink::WebBatteryStatus& status) {
76  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
77
78  if (callback_list_.empty())
79    return;
80
81  status_ = status;
82  status_updated_ = true;
83  callback_list_.Notify(status);
84}
85
86void BatteryStatusService::Shutdown() {
87  if (!callback_list_.empty())
88    battery_fetcher_->StopListeningBatteryChange();
89  battery_fetcher_.reset();
90  is_shutdown_ = true;
91}
92
93const BatteryStatusService::BatteryUpdateCallback&
94BatteryStatusService::GetUpdateCallbackForTesting() const {
95  return update_callback_;
96}
97
98void BatteryStatusService::SetBatteryManagerForTesting(
99    BatteryStatusManager* test_battery_manager) {
100  battery_fetcher_.reset(test_battery_manager);
101  blink::WebBatteryStatus status;
102  status_ = status;
103  status_updated_ = false;
104}
105
106}  // namespace content
107