Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / upgrade_detector_impl.cc
index 9b42d27..e61d2f8 100644 (file)
@@ -9,7 +9,6 @@
 #include "base/bind.h"
 #include "base/build_time.h"
 #include "base/command_line.h"
-#include "base/cpu.h"
 #include "base/files/file_path.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/singleton.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
-#include "base/version.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/google/google_util.h"
+#include "chrome/browser/google/google_brand.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/common/pref_names.h"
+#include "components/network_time/network_time_tracker.h"
 #include "content/public/browser/browser_thread.h"
-#include "ui/base/resource/resource_bundle.h"
 
 #if defined(OS_WIN)
 #include "base/win/win_util.h"
@@ -127,10 +125,10 @@ bool IsSystemInstall() {
   return !InstallUtil::IsPerUserInstall(exe_path.value().c_str());
 }
 
-// This task checks the update policy and calls back the task only if the
-// system is not enrolled in a domain (i.e., not in an enterprise environment).
-// It also identifies if autoupdate is enabled and whether we are running an
-// unstable channel. |is_auto_update_enabled| can be NULL.
+// Sets |is_unstable_channel| to true if the current chrome is on the dev or
+// canary channels. Sets |is_auto_update_enabled| to true if Google Update will
+// update the current chrome. Unconditionally posts |callback_task| to the UI
+// thread to continue processing.
 void DetectUpdatability(const base::Closure& callback_task,
                         bool* is_unstable_channel,
                         bool* is_auto_update_enabled) {
@@ -144,19 +142,55 @@ void DetectUpdatability(const base::Closure& callback_task,
         GoogleUpdateSettings::AreAutoupdatesEnabled(app_guid);
   }
   *is_unstable_channel = IsUnstableChannel();
-  // Don't show the update bubbles to entreprise users (i.e., on a domain).
-  if (!base::win::IsEnrolledToDomain())
-    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback_task);
+  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback_task);
 }
 #endif  // defined(OS_WIN)
 
+// Gets the currently installed version. On Windows, if |critical_update| is not
+// NULL, also retrieves the critical update version info if available.
+base::Version GetCurrentlyInstalledVersionImpl(Version* critical_update) {
+  base::ThreadRestrictions::AssertIOAllowed();
+
+  Version installed_version;
+#if defined(OS_WIN)
+  // Get the version of the currently *installed* instance of Chrome,
+  // which might be newer than the *running* instance if we have been
+  // upgraded in the background.
+  bool system_install = IsSystemInstall();
+
+  // TODO(tommi): Check if using the default distribution is always the right
+  // thing to do.
+  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
+  InstallUtil::GetChromeVersion(dist, system_install, &installed_version);
+  if (critical_update && installed_version.IsValid()) {
+    InstallUtil::GetCriticalUpdateVersion(dist, system_install,
+                                          critical_update);
+  }
+#elif defined(OS_MACOSX)
+  installed_version =
+      Version(base::UTF16ToASCII(keystone_glue::CurrentlyInstalledVersion()));
+#elif defined(OS_POSIX)
+  // POSIX but not Mac OS X: Linux, etc.
+  CommandLine command_line(*CommandLine::ForCurrentProcess());
+  command_line.AppendSwitch(switches::kProductVersion);
+  std::string reply;
+  if (!base::GetAppOutput(command_line, &reply)) {
+    DLOG(ERROR) << "Failed to get current file version";
+    return installed_version;
+  }
+
+  installed_version = Version(reply);
+#endif
+  return installed_version;
+}
+
 }  // namespace
 
 UpgradeDetectorImpl::UpgradeDetectorImpl()
-    : weak_factory_(this),
-      is_unstable_channel_(false),
+    : is_unstable_channel_(false),
       is_auto_update_enabled_(true),
-      build_date_(base::GetBuildTime()) {
+      build_date_(base::GetBuildTime()),
+      weak_factory_(this) {
   CommandLine command_line(*CommandLine::ForCurrentProcess());
   // The different command line switches that affect testing can't be used
   // simultaneously, if they do, here's the precedence order, based on the order
@@ -208,6 +242,14 @@ UpgradeDetectorImpl::UpgradeDetectorImpl()
     return;
   }
 
+  // Register for experiment notifications. Note that since this class is a
+  // singleton, it does not need to unregister for notifications when destroyed,
+  // since it outlives the VariationsService.
+  chrome_variations::VariationsService* variations_service =
+      g_browser_process->variations_service();
+  if (variations_service)
+    variations_service->AddObserver(this);
+
   base::Closure start_upgrade_check_timer_task =
       base::Bind(&UpgradeDetectorImpl::StartTimerForUpgradeCheck,
                  weak_factory_.GetWeakPtr());
@@ -248,14 +290,17 @@ UpgradeDetectorImpl::UpgradeDetectorImpl()
                                      start_upgrade_check_timer_task,
                                      &is_unstable_channel_));
 #endif
-  // Start tracking network time updates.
-  network_time_tracker_.Start();
 }
 
 UpgradeDetectorImpl::~UpgradeDetectorImpl() {
 }
 
-// Static
+// static
+base::Version UpgradeDetectorImpl::GetCurrentlyInstalledVersion() {
+  return GetCurrentlyInstalledVersionImpl(NULL);
+}
+
+// static
 // This task checks the currently running version of Chrome against the
 // installed version. If the installed version is newer, it calls back
 // UpgradeDetectorImpl::UpgradeDetected using a weak pointer so that it can
@@ -264,39 +309,9 @@ void UpgradeDetectorImpl::DetectUpgradeTask(
     base::WeakPtr<UpgradeDetectorImpl> upgrade_detector) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
 
-  Version installed_version;
   Version critical_update;
-
-#if defined(OS_WIN)
-  // Get the version of the currently *installed* instance of Chrome,
-  // which might be newer than the *running* instance if we have been
-  // upgraded in the background.
-  bool system_install = IsSystemInstall();
-
-  // TODO(tommi): Check if using the default distribution is always the right
-  // thing to do.
-  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
-  InstallUtil::GetChromeVersion(dist, system_install, &installed_version);
-
-  if (installed_version.IsValid()) {
-    InstallUtil::GetCriticalUpdateVersion(dist, system_install,
-                                          &critical_update);
-  }
-#elif defined(OS_MACOSX)
-  installed_version =
-      Version(base::UTF16ToASCII(keystone_glue::CurrentlyInstalledVersion()));
-#elif defined(OS_POSIX)
-  // POSIX but not Mac OS X: Linux, etc.
-  CommandLine command_line(*CommandLine::ForCurrentProcess());
-  command_line.AppendSwitch(switches::kProductVersion);
-  std::string reply;
-  if (!base::GetAppOutput(command_line, &reply)) {
-    DLOG(ERROR) << "Failed to get current file version";
-    return;
-  }
-
-  installed_version = Version(reply);
-#endif
+  Version installed_version =
+      GetCurrentlyInstalledVersionImpl(&critical_update);
 
   // Get the version of the currently *running* instance of Chrome.
   chrome::VersionInfo version_info;
@@ -337,6 +352,24 @@ void UpgradeDetectorImpl::StartTimerForUpgradeCheck() {
       this, &UpgradeDetectorImpl::CheckForUpgrade);
 }
 
+void UpgradeDetectorImpl::StartUpgradeNotificationTimer() {
+  // The timer may already be running (e.g. due to both a software upgrade and
+  // experiment updates being available).
+  if (upgrade_notification_timer_.IsRunning())
+    return;
+
+  upgrade_detected_time_ = base::TimeTicks::Now();
+
+  // Start the repeating timer for notifying the user after a certain period.
+  // The called function will eventually figure out that enough time has passed
+  // and stop the timer.
+  const int cycle_time_ms = IsTesting() ?
+      kNotifyCycleTimeForTestingMs : kNotifyCycleTimeMs;
+  upgrade_notification_timer_.Start(FROM_HERE,
+      base::TimeDelta::FromMilliseconds(cycle_time_ms),
+      this, &UpgradeDetectorImpl::NotifyOnUpgrade);
+}
+
 void UpgradeDetectorImpl::CheckForUpgrade() {
   // Interrupt any (unlikely) unfinished execution of DetectUpgradeTask, or at
   // least prevent the callback from being executed, because we will potentially
@@ -363,22 +396,20 @@ bool UpgradeDetectorImpl::DetectOutdatedInstall() {
   static bool simulate_outdated = SimulatingOutdated();
   if (!simulate_outdated) {
     std::string brand;
-    if (google_util::GetBrand(&brand) && !google_util::IsOrganic(brand))
+    if (google_brand::GetBrand(&brand) && !google_brand::IsOrganic(brand))
       return false;
 
 #if defined(OS_WIN)
-    // On Windows, we don't want to warn about outdated installs when the
-    // machine doesn't support SSE2, it's been deprecated starting with M35.
-    if (!base::CPU().has_sse2())
+    // Don't show the update bubbles to enterprise users (i.e., on a domain).
+    if (base::win::IsEnrolledToDomain())
       return false;
 #endif
   }
 
   base::Time network_time;
   base::TimeDelta uncertainty;
-  if (!network_time_tracker_.GetNetworkTime(base::TimeTicks::Now(),
-                                            &network_time,
-                                            &uncertainty)) {
+  if (!g_browser_process->network_time_tracker()->GetNetworkTime(
+          base::TimeTicks::Now(), &network_time, &uncertainty)) {
     // When network time has not been initialized yet, simply rely on the
     // machine's current time.
     network_time = base::Time::Now();
@@ -402,43 +433,38 @@ bool UpgradeDetectorImpl::DetectOutdatedInstall() {
   return simulate_outdated;
 }
 
+void UpgradeDetectorImpl::OnExperimentChangesDetected(Severity severity) {
+  set_best_effort_experiment_updates_available(severity == BEST_EFFORT);
+  set_critical_experiment_updates_available(severity == CRITICAL);
+  StartUpgradeNotificationTimer();
+}
+
 void UpgradeDetectorImpl::UpgradeDetected(UpgradeAvailable upgrade_available) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  upgrade_available_ = upgrade_available;
+  set_upgrade_available(upgrade_available);
 
   // Stop the recurring timer (that is checking for changes).
   detect_upgrade_timer_.Stop();
+  set_critical_update_acknowledged(false);
 
-  NotifyUpgradeDetected();
-
-  // Start the repeating timer for notifying the user after a certain period.
-  // The called function will eventually figure out that enough time has passed
-  // and stop the timer.
-  int cycle_time = IsTesting() ?
-      kNotifyCycleTimeForTestingMs : kNotifyCycleTimeMs;
-  upgrade_notification_timer_.Start(FROM_HERE,
-      base::TimeDelta::FromMilliseconds(cycle_time),
-      this, &UpgradeDetectorImpl::NotifyOnUpgrade);
+  StartUpgradeNotificationTimer();
 }
 
-void UpgradeDetectorImpl::NotifyOnUpgrade() {
-  base::TimeDelta delta = base::Time::Now() - upgrade_detected_time();
-
-  // We'll make testing more convenient by switching to seconds of waiting
-  // instead of days between flipping severity.
-  bool is_testing = IsTesting();
-  int64 time_passed = is_testing ? delta.InSeconds() : delta.InHours();
-
-  bool is_critical_or_outdated = upgrade_available_ > UPGRADE_AVAILABLE_REGULAR;
+void UpgradeDetectorImpl::NotifyOnUpgradeWithTimePassed(
+    base::TimeDelta time_passed) {
+  const bool is_critical_or_outdated =
+      upgrade_available() > UPGRADE_AVAILABLE_REGULAR ||
+      critical_experiment_updates_available();
   if (is_unstable_channel_) {
     // There's only one threat level for unstable channels like dev and
     // canary, and it hits after one hour. During testing, it hits after one
     // second.
-    const int kUnstableThreshold = 1;
+    const base::TimeDelta unstable_threshold = IsTesting() ?
+        base::TimeDelta::FromSeconds(1) : base::TimeDelta::FromHours(1);
 
-    if (is_critical_or_outdated)
+    if (is_critical_or_outdated) {
       set_upgrade_notification_stage(UPGRADE_ANNOYANCE_CRITICAL);
-    else if (time_passed >= kUnstableThreshold) {
+    } else if (time_passed >= unstable_threshold) {
       set_upgrade_notification_stage(UPGRADE_ANNOYANCE_LOW);
 
       // That's as high as it goes.
@@ -447,26 +473,28 @@ void UpgradeDetectorImpl::NotifyOnUpgrade() {
       return;  // Not ready to recommend upgrade.
     }
   } else {
-    const int kMultiplier = is_testing ? 10 : 24;
-    // 14 days when not testing, otherwise 14 seconds.
-    const int kSevereThreshold = 14 * kMultiplier;
-    const int kHighThreshold = 7 * kMultiplier;
-    const int kElevatedThreshold = 4 * kMultiplier;
-    const int kLowThreshold = 2 * kMultiplier;
+    const base::TimeDelta multiplier = IsTesting() ?
+        base::TimeDelta::FromSeconds(10) : base::TimeDelta::FromDays(1);
+
+    // 14 days when not testing, otherwise 140 seconds.
+    const base::TimeDelta severe_threshold = 14 * multiplier;
+    const base::TimeDelta high_threshold = 7 * multiplier;
+    const base::TimeDelta elevated_threshold = 4 * multiplier;
+    const base::TimeDelta low_threshold = 2 * multiplier;
 
     // These if statements must be sorted (highest interval first).
-    if (time_passed >= kSevereThreshold || is_critical_or_outdated) {
+    if (time_passed >= severe_threshold || is_critical_or_outdated) {
       set_upgrade_notification_stage(
           is_critical_or_outdated ? UPGRADE_ANNOYANCE_CRITICAL :
                                     UPGRADE_ANNOYANCE_SEVERE);
 
       // We can't get any higher, baby.
       upgrade_notification_timer_.Stop();
-    } else if (time_passed >= kHighThreshold) {
+    } else if (time_passed >= high_threshold) {
       set_upgrade_notification_stage(UPGRADE_ANNOYANCE_HIGH);
-    } else if (time_passed >= kElevatedThreshold) {
+    } else if (time_passed >= elevated_threshold) {
       set_upgrade_notification_stage(UPGRADE_ANNOYANCE_ELEVATED);
-    } else if (time_passed >= kLowThreshold) {
+    } else if (time_passed >= low_threshold) {
       set_upgrade_notification_stage(UPGRADE_ANNOYANCE_LOW);
     } else {
       return;  // Not ready to recommend upgrade.
@@ -476,6 +504,12 @@ void UpgradeDetectorImpl::NotifyOnUpgrade() {
   NotifyUpgradeRecommended();
 }
 
+void UpgradeDetectorImpl::NotifyOnUpgrade() {
+  const base::TimeDelta time_passed =
+      base::TimeTicks::Now() - upgrade_detected_time_;
+  NotifyOnUpgradeWithTimePassed(time_passed);
+}
+
 // static
 UpgradeDetectorImpl* UpgradeDetectorImpl::GetInstance() {
   return Singleton<UpgradeDetectorImpl>::get();