15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/upgrade_detector.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_registry_simple.h"
107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/lifetime/application_lifetime.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_otr_state.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/theme_resources.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// How long to wait between checks for whether the user has been idle.
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kIdleRepeatingTimerWait = 10;  // Minutes (seconds if testing).
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// How much idle time (since last input even was detected) must have passed
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// until we notify that a critical update has occurred.
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kIdleAmount = 2;  // Hours (or seconds, if testing).
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool UseTestingIntervals() {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If a command line parameter specifying how long the upgrade check should
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // be, we assume it is for testing and switch to using seconds instead of
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // hours.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !cmd_line.GetSwitchValueASCII(
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switches::kCheckForUpdateIntervalSec).empty();
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void UpgradeDetector::RegisterPrefs(PrefRegistrySimple* registry) {
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  registry->RegisterBooleanPref(prefs::kRestartLastSessionOnShutdown, false);
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  registry->RegisterBooleanPref(prefs::kWasRestarted, false);
38effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  registry->RegisterBooleanPref(prefs::kAttemptedToEnableAutoupdate, false);
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)int UpgradeDetector::GetIconResourceID() {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (upgrade_notification_stage_) {
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case UPGRADE_ANNOYANCE_NONE:
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 0;
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case UPGRADE_ANNOYANCE_LOW:
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return IDR_UPDATE_MENU_SEVERITY_LOW;
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case UPGRADE_ANNOYANCE_ELEVATED:
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return IDR_UPDATE_MENU_SEVERITY_MEDIUM;
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case UPGRADE_ANNOYANCE_HIGH:
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return IDR_UPDATE_MENU_SEVERITY_HIGH;
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case UPGRADE_ANNOYANCE_SEVERE:
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return IDR_UPDATE_MENU_SEVERITY_HIGH;
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case UPGRADE_ANNOYANCE_CRITICAL:
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return IDR_UPDATE_MENU_SEVERITY_HIGH;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  NOTREACHED();
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return 0;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UpgradeDetector::UpgradeDetector()
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : upgrade_available_(UPGRADE_AVAILABLE_NONE),
626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      best_effort_experiment_updates_available_(false),
636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      critical_experiment_updates_available_(false),
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      critical_update_acknowledged_(false),
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      upgrade_notification_stage_(UPGRADE_ANNOYANCE_NONE),
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      notify_upgrade_(false) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UpgradeDetector::~UpgradeDetector() {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UpgradeDetector::NotifyUpgradeRecommended() {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notify_upgrade_ = true;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  TriggerNotification(chrome::NOTIFICATION_UPGRADE_RECOMMENDED);
766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (upgrade_available_ == UPGRADE_NEEDED_OUTDATED_INSTALL) {
776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    TriggerNotification(chrome::NOTIFICATION_OUTDATED_INSTALL);
786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  } else if (upgrade_available_ == UPGRADE_NEEDED_OUTDATED_INSTALL_NO_AU) {
796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    TriggerNotification(chrome::NOTIFICATION_OUTDATED_INSTALL_NO_AU);
806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  } else if (upgrade_available_ == UPGRADE_AVAILABLE_CRITICAL ||
816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)             critical_experiment_updates_available_) {
826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    TriggerCriticalUpdate();
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void UpgradeDetector::TriggerCriticalUpdate() {
876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  const base::TimeDelta idle_timer = UseTestingIntervals() ?
886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      base::TimeDelta::FromSeconds(kIdleRepeatingTimerWait) :
896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      base::TimeDelta::FromMinutes(kIdleRepeatingTimerWait);
906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  idle_check_timer_.Start(FROM_HERE, idle_timer, this,
916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                          &UpgradeDetector::CheckIdle);
926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UpgradeDetector::CheckIdle() {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // CalculateIdleState expects an interval in seconds.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int idle_time_allowed = UseTestingIntervals() ? kIdleAmount :
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  kIdleAmount * 60 * 60;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CalculateIdleState(
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      idle_time_allowed, base::Bind(&UpgradeDetector::IdleCallback,
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    base::Unretained(this)));
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void UpgradeDetector::TriggerNotification(chrome::NotificationType type) {
1056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  content::NotificationService::current()->Notify(
1066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      type,
1076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      content::Source<UpgradeDetector>(this),
1086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      content::NotificationService::NoDetails());
1096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UpgradeDetector::IdleCallback(IdleState state) {
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't proceed while an incognito window is open. The timer will still
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // keep firing, so this function will get a chance to re-evaluate this.
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (chrome::IsOffTheRecordSessionActive())
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (state) {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case IDLE_STATE_LOCKED:
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Computer is locked, auto-restart.
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      idle_check_timer_.Stop();
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      chrome::AttemptRestart();
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case IDLE_STATE_IDLE:
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Computer has been idle for long enough, show warning.
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      idle_check_timer_.Stop();
1266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      TriggerNotification(chrome::NOTIFICATION_CRITICAL_UPGRADE_INSTALLED);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case IDLE_STATE_ACTIVE:
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case IDLE_STATE_UNKNOWN:
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();  // Need to add any new value above (either providing
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     // automatic restart or show notification to user).
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
137