summaryrefslogtreecommitdiffstats
path: root/chrome/browser/chromeos/upgrade_detector_chromeos.cc
blob: 546558429d9eeafe6bb29f3c6b61046bfe50f617 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// Copyright (c) 2012 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/upgrade_detector_chromeos.h"

#include "base/memory/singleton.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/update_engine_client.h"

using chromeos::DBusThreadManager;
using chromeos::UpdateEngineClient;

namespace {

// How long to wait (each cycle) before checking which severity level we should
// be at. Once we reach the highest severity, the timer will stop.
const int kNotifyCycleTimeMs = 20 * 60 * 1000;  // 20 minutes.

}  // namespace

class UpgradeDetectorChromeos::ChannelsRequester {
 public:
  typedef base::Callback<void(const std::string&, const std::string&)>
      OnChannelsReceivedCallback;

  ChannelsRequester() : weak_factory_(this) {}

  void RequestChannels(const OnChannelsReceivedCallback& callback) {
    UpdateEngineClient* client =
        DBusThreadManager::Get()->GetUpdateEngineClient();
    callback_ = callback;
    client->GetChannel(true /* get_current_channel */,
                       base::Bind(&ChannelsRequester::SetCurrentChannel,
                                  weak_factory_.GetWeakPtr()));
    client->GetChannel(false /* get_current_channel */,
                       base::Bind(&ChannelsRequester::SetTargetChannel,
                                  weak_factory_.GetWeakPtr()));
  }

 private:
  void SetCurrentChannel(const std::string& current_channel) {
    DCHECK(!current_channel.empty());
    current_channel_ = current_channel;
    TriggerCallbackIfReady();
  }

  void SetTargetChannel(const std::string& target_channel) {
    DCHECK(!target_channel.empty());
    target_channel_ = target_channel;
    TriggerCallbackIfReady();
  }

  void TriggerCallbackIfReady() {
    if (current_channel_.empty() || target_channel_.empty())
      return;
    if (!callback_.is_null())
      callback_.Run(current_channel_, target_channel_);
  }

  std::string current_channel_;
  std::string target_channel_;

  OnChannelsReceivedCallback callback_;

  base::WeakPtrFactory<ChannelsRequester> weak_factory_;

  DISALLOW_COPY_AND_ASSIGN(ChannelsRequester);
};

UpgradeDetectorChromeos::UpgradeDetectorChromeos()
    : initialized_(false), weak_factory_(this) {
}

UpgradeDetectorChromeos::~UpgradeDetectorChromeos() {
}

void UpgradeDetectorChromeos::Init() {
  DBusThreadManager::Get()->GetUpdateEngineClient()->AddObserver(this);
  initialized_ = true;
}

void UpgradeDetectorChromeos::Shutdown() {
  // Init() may not be called from tests.
  if (!initialized_)
    return;
  DBusThreadManager::Get()->GetUpdateEngineClient()->RemoveObserver(this);
}

void UpgradeDetectorChromeos::UpdateStatusChanged(
    const UpdateEngineClient::Status& status) {
  if (status.status != UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT)
    return;

  upgrade_detected_time_ = base::Time::Now();

  channels_requester_.reset(new UpgradeDetectorChromeos::ChannelsRequester());
  channels_requester_->RequestChannels(
      base::Bind(&UpgradeDetectorChromeos::OnChannelsReceived,
                 weak_factory_.GetWeakPtr()));
}

void UpgradeDetectorChromeos::NotifyOnUpgrade() {
  base::TimeDelta delta = base::Time::Now() - upgrade_detected_time_;
  int64 time_passed = delta.InDays();

  const int kSevereThreshold = 7;
  const int kHighThreshold = 4;
  const int kElevatedThreshold = 2;
  const int kLowThreshold = 0;

  // These if statements must be sorted (highest interval first).
  if (time_passed >= kSevereThreshold) {
    set_upgrade_notification_stage(UPGRADE_ANNOYANCE_SEVERE);

    // We can't get any higher, baby.
    upgrade_notification_timer_.Stop();
  } else if (time_passed >= kHighThreshold) {
    set_upgrade_notification_stage(UPGRADE_ANNOYANCE_HIGH);
  } else if (time_passed >= kElevatedThreshold) {
    set_upgrade_notification_stage(UPGRADE_ANNOYANCE_ELEVATED);
  } else if (time_passed >= kLowThreshold) {
    set_upgrade_notification_stage(UPGRADE_ANNOYANCE_LOW);
  } else {
    return;  // Not ready to recommend upgrade.
  }

  NotifyUpgradeRecommended();
}

void UpgradeDetectorChromeos::OnChannelsReceived(
    const std::string& current_channel,
    const std::string& target_channel) {
  // As current update engine status is UPDATE_STATUS_UPDATED_NEED_REBOOT
  // and target channel is more stable than current channel, powerwash
  // will be performed after reboot.
  set_is_factory_reset_required(UpdateEngineClient::IsTargetChannelMoreStable(
      current_channel, target_channel));

  // ChromeOS shows upgrade arrow once the upgrade becomes available.
  NotifyOnUpgrade();

  // Setup timer to to move along the upgrade advisory system.
  upgrade_notification_timer_.Start(
      FROM_HERE,
      base::TimeDelta::FromMilliseconds(kNotifyCycleTimeMs),
      this,
      &UpgradeDetectorChromeos::NotifyOnUpgrade);
}

// static
UpgradeDetectorChromeos* UpgradeDetectorChromeos::GetInstance() {
  return Singleton<UpgradeDetectorChromeos>::get();
}

// static
UpgradeDetector* UpgradeDetector::GetInstance() {
  return UpgradeDetectorChromeos::GetInstance();
}