upgrade_detector.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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  bool badge = type == UPGRADE_ICON_TYPE_BADGE;
42  switch (upgrade_notification_stage_) {
43    case UPGRADE_ANNOYANCE_CRITICAL:
44      // The critical annoyance state, somewhat ironically, re-purposes the
45      // icon for the second highest severity state, since that state has the
46      // icon most closely resembling the one requested of this feature and the
47      // critical annoyance is never part of the sliding scale of severity
48      // anyway (always shown on its own).
49      return badge ? IDR_UPDATE_BADGE3 : IDR_UPDATE_MENU3;
50    case UPGRADE_ANNOYANCE_SEVERE:
51      return badge ? IDR_UPDATE_BADGE4 : IDR_UPDATE_MENU4;
52    case UPGRADE_ANNOYANCE_HIGH:
53      return badge ? IDR_UPDATE_BADGE3 : IDR_UPDATE_MENU3;
54    case UPGRADE_ANNOYANCE_ELEVATED:
55      return badge ? IDR_UPDATE_BADGE2 : IDR_UPDATE_MENU2;
56    case UPGRADE_ANNOYANCE_LOW:
57      return badge ? IDR_UPDATE_BADGE : IDR_UPDATE_MENU;
58    default:
59      return 0;
60  }
61}
62
63UpgradeDetector::UpgradeDetector()
64    : upgrade_available_(UPGRADE_AVAILABLE_NONE),
65      critical_update_acknowledged_(false),
66      upgrade_notification_stage_(UPGRADE_ANNOYANCE_NONE),
67      notify_upgrade_(false) {
68}
69
70UpgradeDetector::~UpgradeDetector() {
71}
72
73void UpgradeDetector::NotifyUpgradeDetected() {
74  upgrade_detected_time_ = base::Time::Now();
75  critical_update_acknowledged_ = false;
76}
77
78void UpgradeDetector::NotifyUpgradeRecommended() {
79  notify_upgrade_ = true;
80
81  content::NotificationService::current()->Notify(
82      chrome::NOTIFICATION_UPGRADE_RECOMMENDED,
83      content::Source<UpgradeDetector>(this),
84      content::NotificationService::NoDetails());
85
86  switch (upgrade_available_) {
87    case UPGRADE_NEEDED_OUTDATED_INSTALL: {
88      content::NotificationService::current()->Notify(
89          chrome::NOTIFICATION_OUTDATED_INSTALL,
90          content::Source<UpgradeDetector>(this),
91          content::NotificationService::NoDetails());
92      break;
93    }
94    case UPGRADE_AVAILABLE_CRITICAL: {
95      int idle_timer = UseTestingIntervals() ?
96          kIdleRepeatingTimerWait :
97          kIdleRepeatingTimerWait * 60;  // To minutes.
98      idle_check_timer_.Start(FROM_HERE,
99          base::TimeDelta::FromSeconds(idle_timer),
100          this, &UpgradeDetector::CheckIdle);
101      break;
102    }
103    default:
104      break;
105  }
106}
107
108void UpgradeDetector::CheckIdle() {
109  // CalculateIdleState expects an interval in seconds.
110  int idle_time_allowed = UseTestingIntervals() ? kIdleAmount :
111                                                  kIdleAmount * 60 * 60;
112
113  CalculateIdleState(
114      idle_time_allowed, base::Bind(&UpgradeDetector::IdleCallback,
115                                    base::Unretained(this)));
116}
117
118void UpgradeDetector::IdleCallback(IdleState state) {
119  // Don't proceed while an incognito window is open. The timer will still
120  // keep firing, so this function will get a chance to re-evaluate this.
121  if (chrome::IsOffTheRecordSessionActive())
122    return;
123
124  switch (state) {
125    case IDLE_STATE_LOCKED:
126      // Computer is locked, auto-restart.
127      idle_check_timer_.Stop();
128      chrome::AttemptRestart();
129      break;
130    case IDLE_STATE_IDLE:
131      // Computer has been idle for long enough, show warning.
132      idle_check_timer_.Stop();
133      content::NotificationService::current()->Notify(
134          chrome::NOTIFICATION_CRITICAL_UPGRADE_INSTALLED,
135          content::Source<UpgradeDetector>(this),
136          content::NotificationService::NoDetails());
137      break;
138    case IDLE_STATE_ACTIVE:
139    case IDLE_STATE_UNKNOWN:
140      break;
141    default:
142      NOTREACHED();  // Need to add any new value above (either providing
143                     // automatic restart or show notification to user).
144      break;
145  }
146}
147