upgrade_detector.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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/lifetime/application_lifetime.h"
11#include "chrome/browser/ui/browser_otr_state.h"
12#include "chrome/common/chrome_notification_types.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}
39
40int UpgradeDetector::GetIconResourceID(UpgradeNotificationIconType type) {
41  if (type == UPGRADE_ICON_TYPE_BADGE) {
42    // Badges do not exist on Views and Mac OS X.
43#if !defined(TOOLKIT_VIEWS) && !defined(OS_MACOSX)
44    switch (upgrade_notification_stage_) {
45      case UPGRADE_ANNOYANCE_NONE:
46        return 0;
47      case UPGRADE_ANNOYANCE_LOW:
48        return IDR_UPDATE_BADGE;
49      case UPGRADE_ANNOYANCE_ELEVATED:
50        return IDR_UPDATE_BADGE2;
51      case UPGRADE_ANNOYANCE_HIGH:
52        return IDR_UPDATE_BADGE3;
53      case UPGRADE_ANNOYANCE_SEVERE:
54        return IDR_UPDATE_BADGE3;
55      case UPGRADE_ANNOYANCE_CRITICAL:
56        return IDR_UPDATE_BADGE3;
57    }
58#endif
59    NOTREACHED();
60    return 0;
61  }
62
63  switch (upgrade_notification_stage_) {
64    case UPGRADE_ANNOYANCE_NONE:
65      return 0;
66    case UPGRADE_ANNOYANCE_LOW:
67      return IDR_UPDATE_MENU_SEVERITY_LOW;
68    case UPGRADE_ANNOYANCE_ELEVATED:
69      return IDR_UPDATE_MENU_SEVERITY_MEDIUM;
70    case UPGRADE_ANNOYANCE_HIGH:
71      return IDR_UPDATE_MENU_SEVERITY_HIGH;
72    case UPGRADE_ANNOYANCE_SEVERE:
73      return IDR_UPDATE_MENU_SEVERITY_HIGH;
74    case UPGRADE_ANNOYANCE_CRITICAL:
75      return IDR_UPDATE_MENU_SEVERITY_HIGH;
76  }
77  NOTREACHED();
78  return 0;
79}
80
81UpgradeDetector::UpgradeDetector()
82    : upgrade_available_(UPGRADE_AVAILABLE_NONE),
83      critical_update_acknowledged_(false),
84      upgrade_notification_stage_(UPGRADE_ANNOYANCE_NONE),
85      notify_upgrade_(false) {
86}
87
88UpgradeDetector::~UpgradeDetector() {
89}
90
91void UpgradeDetector::NotifyUpgradeDetected() {
92  upgrade_detected_time_ = base::Time::Now();
93  critical_update_acknowledged_ = false;
94}
95
96void UpgradeDetector::NotifyUpgradeRecommended() {
97  notify_upgrade_ = true;
98
99  content::NotificationService::current()->Notify(
100      chrome::NOTIFICATION_UPGRADE_RECOMMENDED,
101      content::Source<UpgradeDetector>(this),
102      content::NotificationService::NoDetails());
103
104  switch (upgrade_available_) {
105    case UPGRADE_NEEDED_OUTDATED_INSTALL: {
106      content::NotificationService::current()->Notify(
107          chrome::NOTIFICATION_OUTDATED_INSTALL,
108          content::Source<UpgradeDetector>(this),
109          content::NotificationService::NoDetails());
110      break;
111    }
112    case UPGRADE_AVAILABLE_CRITICAL: {
113      int idle_timer = UseTestingIntervals() ?
114          kIdleRepeatingTimerWait :
115          kIdleRepeatingTimerWait * 60;  // To minutes.
116      idle_check_timer_.Start(FROM_HERE,
117          base::TimeDelta::FromSeconds(idle_timer),
118          this, &UpgradeDetector::CheckIdle);
119      break;
120    }
121    default:
122      break;
123  }
124}
125
126void UpgradeDetector::CheckIdle() {
127  // CalculateIdleState expects an interval in seconds.
128  int idle_time_allowed = UseTestingIntervals() ? kIdleAmount :
129                                                  kIdleAmount * 60 * 60;
130
131  CalculateIdleState(
132      idle_time_allowed, base::Bind(&UpgradeDetector::IdleCallback,
133                                    base::Unretained(this)));
134}
135
136void UpgradeDetector::IdleCallback(IdleState state) {
137  // Don't proceed while an incognito window is open. The timer will still
138  // keep firing, so this function will get a chance to re-evaluate this.
139  if (chrome::IsOffTheRecordSessionActive())
140    return;
141
142  switch (state) {
143    case IDLE_STATE_LOCKED:
144      // Computer is locked, auto-restart.
145      idle_check_timer_.Stop();
146      chrome::AttemptRestart();
147      break;
148    case IDLE_STATE_IDLE:
149      // Computer has been idle for long enough, show warning.
150      idle_check_timer_.Stop();
151      content::NotificationService::current()->Notify(
152          chrome::NOTIFICATION_CRITICAL_UPGRADE_INSTALLED,
153          content::Source<UpgradeDetector>(this),
154          content::NotificationService::NoDetails());
155      break;
156    case IDLE_STATE_ACTIVE:
157    case IDLE_STATE_UNKNOWN:
158      break;
159    default:
160      NOTREACHED();  // Need to add any new value above (either providing
161                     // automatic restart or show notification to user).
162      break;
163  }
164}
165