upgrade_detector.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
1// Copyright (c) 2012 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/upgrade_detector.h"
6
7#include "base/bind.h"
8#include "base/command_line.h"
9#include "base/prefs/pref_registry_simple.h"
10#include "chrome/browser/chrome_notification_types.h"
11#include "chrome/browser/lifetime/application_lifetime.h"
12#include "chrome/browser/ui/browser_otr_state.h"
13#include "chrome/common/chrome_switches.h"
14#include "chrome/common/pref_names.h"
15#include "content/public/browser/notification_service.h"
16#include "grit/theme_resources.h"
17
18// How long to wait between checks for whether the user has been idle.
19static const int kIdleRepeatingTimerWait = 10;  // Minutes (seconds if testing).
20
21// How much idle time (since last input even was detected) must have passed
22// until we notify that a critical update has occurred.
23static const int kIdleAmount = 2;  // Hours (or seconds, if testing).
24
25bool UseTestingIntervals() {
26  // If a command line parameter specifying how long the upgrade check should
27  // be, we assume it is for testing and switch to using seconds instead of
28  // hours.
29  const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
30  return !cmd_line.GetSwitchValueASCII(
31      switches::kCheckForUpdateIntervalSec).empty();
32}
33
34// static
35void UpgradeDetector::RegisterPrefs(PrefRegistrySimple* registry) {
36  registry->RegisterBooleanPref(prefs::kRestartLastSessionOnShutdown, false);
37  registry->RegisterBooleanPref(prefs::kWasRestarted, false);
38  registry->RegisterBooleanPref(prefs::kAttemptedToEnableAutoupdate, false);
39}
40
41int UpgradeDetector::GetIconResourceID(UpgradeNotificationIconType type) {
42  if (type == UPGRADE_ICON_TYPE_BADGE) {
43    // Badges do not exist on Views and Mac OS X.
44#if !defined(TOOLKIT_VIEWS) && !defined(OS_MACOSX)
45    switch (upgrade_notification_stage_) {
46      case UPGRADE_ANNOYANCE_NONE:
47        return 0;
48      case UPGRADE_ANNOYANCE_LOW:
49        return IDR_UPDATE_BADGE;
50      case UPGRADE_ANNOYANCE_ELEVATED:
51        return IDR_UPDATE_BADGE2;
52      case UPGRADE_ANNOYANCE_HIGH:
53        return IDR_UPDATE_BADGE3;
54      case UPGRADE_ANNOYANCE_SEVERE:
55        return IDR_UPDATE_BADGE3;
56      case UPGRADE_ANNOYANCE_CRITICAL:
57        return IDR_UPDATE_BADGE3;
58    }
59#endif
60    NOTREACHED();
61    return 0;
62  }
63
64  switch (upgrade_notification_stage_) {
65    case UPGRADE_ANNOYANCE_NONE:
66      return 0;
67    case UPGRADE_ANNOYANCE_LOW:
68      return IDR_UPDATE_MENU_SEVERITY_LOW;
69    case UPGRADE_ANNOYANCE_ELEVATED:
70      return IDR_UPDATE_MENU_SEVERITY_MEDIUM;
71    case UPGRADE_ANNOYANCE_HIGH:
72      return IDR_UPDATE_MENU_SEVERITY_HIGH;
73    case UPGRADE_ANNOYANCE_SEVERE:
74      return IDR_UPDATE_MENU_SEVERITY_HIGH;
75    case UPGRADE_ANNOYANCE_CRITICAL:
76      return IDR_UPDATE_MENU_SEVERITY_HIGH;
77  }
78  NOTREACHED();
79  return 0;
80}
81
82UpgradeDetector::UpgradeDetector()
83    : upgrade_available_(UPGRADE_AVAILABLE_NONE),
84      critical_update_acknowledged_(false),
85      upgrade_notification_stage_(UPGRADE_ANNOYANCE_NONE),
86      notify_upgrade_(false) {
87}
88
89UpgradeDetector::~UpgradeDetector() {
90}
91
92void UpgradeDetector::NotifyUpgradeDetected() {
93  upgrade_detected_time_ = base::Time::Now();
94  critical_update_acknowledged_ = false;
95}
96
97void UpgradeDetector::NotifyUpgradeRecommended() {
98  notify_upgrade_ = true;
99
100  content::NotificationService::current()->Notify(
101      chrome::NOTIFICATION_UPGRADE_RECOMMENDED,
102      content::Source<UpgradeDetector>(this),
103      content::NotificationService::NoDetails());
104
105  switch (upgrade_available_) {
106    case UPGRADE_NEEDED_OUTDATED_INSTALL: {
107      content::NotificationService::current()->Notify(
108          chrome::NOTIFICATION_OUTDATED_INSTALL,
109          content::Source<UpgradeDetector>(this),
110          content::NotificationService::NoDetails());
111      break;
112    }
113    case UPGRADE_NEEDED_OUTDATED_INSTALL_NO_AU: {
114      content::NotificationService::current()->Notify(
115          chrome::NOTIFICATION_OUTDATED_INSTALL_NO_AU,
116          content::Source<UpgradeDetector>(this),
117          content::NotificationService::NoDetails());
118      break;
119    }
120    case UPGRADE_AVAILABLE_CRITICAL: {
121      int idle_timer = UseTestingIntervals() ?
122          kIdleRepeatingTimerWait :
123          kIdleRepeatingTimerWait * 60;  // To minutes.
124      idle_check_timer_.Start(FROM_HERE,
125          base::TimeDelta::FromSeconds(idle_timer),
126          this, &UpgradeDetector::CheckIdle);
127      break;
128    }
129    default:
130      break;
131  }
132}
133
134void UpgradeDetector::CheckIdle() {
135  // CalculateIdleState expects an interval in seconds.
136  int idle_time_allowed = UseTestingIntervals() ? kIdleAmount :
137                                                  kIdleAmount * 60 * 60;
138
139  CalculateIdleState(
140      idle_time_allowed, base::Bind(&UpgradeDetector::IdleCallback,
141                                    base::Unretained(this)));
142}
143
144void UpgradeDetector::IdleCallback(IdleState state) {
145  // Don't proceed while an incognito window is open. The timer will still
146  // keep firing, so this function will get a chance to re-evaluate this.
147  if (chrome::IsOffTheRecordSessionActive())
148    return;
149
150  switch (state) {
151    case IDLE_STATE_LOCKED:
152      // Computer is locked, auto-restart.
153      idle_check_timer_.Stop();
154      chrome::AttemptRestart();
155      break;
156    case IDLE_STATE_IDLE:
157      // Computer has been idle for long enough, show warning.
158      idle_check_timer_.Stop();
159      content::NotificationService::current()->Notify(
160          chrome::NOTIFICATION_CRITICAL_UPGRADE_INSTALLED,
161          content::Source<UpgradeDetector>(this),
162          content::NotificationService::NoDetails());
163      break;
164    case IDLE_STATE_ACTIVE:
165    case IDLE_STATE_UNKNOWN:
166      break;
167    default:
168      NOTREACHED();  // Need to add any new value above (either providing
169                     // automatic restart or show notification to user).
170      break;
171  }
172}
173