Chromium Code Reviews| Index: chrome/browser/upgrade_detector_impl.cc |
| diff --git a/chrome/browser/upgrade_detector_impl.cc b/chrome/browser/upgrade_detector_impl.cc |
| index 570275e391ba59c8452c3de6d6861f7f4ead8e04..910ff953d10f075aa0407c041bbf5a1138def240 100644 |
| --- a/chrome/browser/upgrade_detector_impl.cc |
| +++ b/chrome/browser/upgrade_detector_impl.cc |
| @@ -16,13 +16,18 @@ |
| #include "base/string_util.h" |
| #include "base/time.h" |
| #include "base/utf_string_conversions.h" |
| +#include "chrome/common/chrome_notification_types.h" |
| #include "chrome/common/chrome_switches.h" |
| #include "chrome/common/chrome_version_info.h" |
| #include "chrome/installer/util/browser_distribution.h" |
| #include "content/public/browser/browser_thread.h" |
| +#include "content/public/browser/notification_service.h" |
| +#include "content/public/browser/user_metrics.h" |
| #include "ui/base/resource/resource_bundle.h" |
| #if defined(OS_WIN) |
| +#include "chrome/browser/google/google_update_win.h" |
| +#include "chrome/installer/util/google_update_settings.h" |
| #include "chrome/installer/util/install_util.h" |
| #elif defined(OS_MACOSX) |
| #include "chrome/browser/mac/keystone_glue.h" |
| @@ -68,18 +73,11 @@ int GetCheckForUpgradeEveryMs() { |
| return kCheckForUpgradeMs; |
| } |
| -// This task checks the currently running version of Chrome against the |
| -// installed version. If the installed version is newer, it runs the passed |
| -// callback task. Otherwise it just deletes the task. |
| -void DetectUpgradeTask(const base::Closure& upgrade_detected_task, |
| - bool* is_unstable_channel, |
| - bool* is_critical_upgrade) { |
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| - |
| - Version installed_version; |
| - Version critical_update; |
| - |
| #if defined(OS_WIN) |
| +// This code can be used by both regular and outdated upgrades. |
|
Finnur
2012/12/06 19:53:16
nit: suggest: by both regular upgrades and for che
MAD
2013/01/22 15:18:29
This is gone... Reworking the whole thing...
|
| +// |critical_update| can be NULL if not needed. |
| +void GetInstalledAndCriticalVersion(Version* installed_version, |
| + Version* critical_update) { |
| // 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. |
| @@ -95,12 +93,29 @@ void DetectUpgradeTask(const base::Closure& upgrade_detected_task, |
| // 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); |
| + DCHECK(installed_version); |
| + InstallUtil::GetChromeVersion(dist, system_install, installed_version); |
| - if (installed_version.IsValid()) { |
| + if (critical_update && installed_version->IsValid()) { |
| InstallUtil::GetCriticalUpdateVersion(dist, system_install, |
| - &critical_update); |
| + critical_update); |
| } |
| +} |
| +#endif // defined(OS_WIN) |
| + |
| +// This task checks the currently running version of Chrome against the |
| +// installed version. If the installed version is newer, it runs the passed |
| +// callback task. Otherwise it just deletes the task. |
| +void DetectUpgradeTask(const base::Closure& upgrade_detected_task, |
| + bool* is_unstable_channel, |
| + bool* is_critical_upgrade) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| + |
| + Version installed_version; |
| + Version critical_update; |
| + |
| +#if defined(OS_WIN) |
| + GetInstalledAndCriticalVersion(&installed_version, &critical_update); |
| #elif defined(OS_MACOSX) |
| installed_version = |
| Version(UTF16ToASCII(keystone_glue::CurrentlyInstalledVersion())); |
| @@ -150,6 +165,132 @@ void DetectUpgradeTask(const base::Closure& upgrade_detected_task, |
| } |
| } |
| +#if defined(OS_WIN) |
|
Finnur
2012/12/06 19:53:16
I would probably have moved this to a _win.cc file
MAD
2013/01/22 15:18:29
Gone!
|
| +// Implementation of a GoogleUpdateStatusListener (only available on Windows), |
| +// so we can get the available version and identify if we are outdated. |
| +class UpgradeStatusListener : public GoogleUpdateStatusListener { |
| + public: |
| + explicit UpgradeStatusListener(const base::Closure& notify_outdated_callback) |
| + : google_updater_(new GoogleUpdate()), |
| + got_installed_version_(false), |
| + got_available_version_(false), |
| + notify_outdated_callback_(notify_outdated_callback) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + google_updater_->set_status_listener(this); |
| + // false is for |install_if_newer|, we just want the available version. |
| + // And when we use false, we don't need to specify a |window|, so NULL. |
| + google_updater_->CheckForUpdate(false, NULL); |
| + |
| + // We use FILE as the thread to get the installed version |
| + // since it requires reading a file. And it is safe to use an unretained |
| + // this pointer since GetInstalledVersion must be called before destruction. |
| + BrowserThread::PostTask( |
| + BrowserThread::FILE, FROM_HERE, |
| + base::Bind(&UpgradeStatusListener::GetInstalledVersion, |
| + base::Unretained(this))); |
| + } |
| + |
| + virtual ~UpgradeStatusListener() { |
| + google_updater_->set_status_listener(NULL); |
| + } |
| + |
| + // GoogleUpdateStatusListener implementation. |
| + virtual void OnReportResults(GoogleUpdateUpgradeResult result, |
| + GoogleUpdateErrorCode error_code, |
| + const string16& error_message, |
| + const string16& version) OVERRIDE { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + // The google update class is never supposed to sent these two to listeners. |
|
Finnur
2012/12/06 19:53:16
nit: s/sent/send/
MAD
2013/01/22 15:18:29
Gone!
|
| + DCHECK(result != UPGRADE_STARTED && result != UPGRADE_CHECK_STARTED); |
| + |
| + // Since false was specified for |install_if_newer|, this shouldn't happen. |
| + DCHECK(result != UPGRADE_SUCCESSFUL); |
| + |
| + switch (result) { |
| + case UPGRADE_ALREADY_UP_TO_DATE: { |
| + // Nothing needs to be done. |
| + break; |
| + } |
| + case UPGRADE_ERROR: { |
| + // Record these errors in UMA to see if something should be added here. |
| + content::RecordAction(content::UserMetricsAction("UpgradeCheck_Error")); |
| + break; |
| + } |
| + case UPGRADE_IS_AVAILABLE: { |
| + available_version_ = Version(UTF16ToASCII(version)); |
| + break; |
| + } |
| + default: { |
| + NOTREACHED(); |
| + } |
| + } |
| + got_available_version_ = true; |
|
Finnur
2012/12/06 19:53:16
This variable is actually misnamed because you don
MAD
2013/01/22 15:18:29
Gone!
|
| + if (got_installed_version_) |
| + CheckForOutdated(); |
| + } |
| + |
| + private: |
| + void GetInstalledVersion() { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| + Version installed_version; |
| + // We only check for outdated when there are no group policies preventing |
|
Finnur
2012/12/06 19:53:16
s/outdated/outdated version/
MAD
2013/01/22 15:18:29
Gone!
|
| + // regular upgrades. The test is done here because it needs access to the |
| + // registry, which must be done on the FILE thread. |
| + BrowserDistribution* distribution = BrowserDistribution::GetDistribution(); |
| + DCHECK(distribution); |
| + if (GoogleUpdateSettings::GetAppUpdatePolicy(distribution->GetAppGuid(), |
| + NULL) == |
| + GoogleUpdateSettings::AUTOMATIC_UPDATES) { |
| + // An uninitialized install version prevents an outdated notification. |
|
Finnur
2012/12/06 19:53:16
Not sure I understand this comment...
MAD
2013/01/22 15:18:29
Gone!
|
| + GetInstalledAndCriticalVersion(&installed_version, NULL); |
| + } |
| + BrowserThread::PostTask( |
| + BrowserThread::UI, FROM_HERE, |
| + base::Bind(&UpgradeStatusListener::GotInstalledVersion, |
| + base::Unretained(this), installed_version)); |
| + } |
| + |
| + void GotInstalledVersion(const Version& installed_version) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + installed_version_ = installed_version; |
| + got_installed_version_ = true; |
| + if (got_available_version_) |
| + CheckForOutdated(); |
| + } |
| + |
| + void CheckForOutdated() { |
|
Finnur
2012/12/06 19:53:16
nit: Suggest: CheckIfOutdatedVersion or NotifyIfOu
MAD
2013/01/22 15:18:29
Gone!
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + DCHECK(got_available_version_ && got_installed_version_); |
| + if (available_version_.IsValid() && installed_version_.IsValid() && |
| + available_version_.components()[0] > |
| + installed_version_.components()[0] + 1) { |
| + notify_outdated_callback_.Run(); |
| + } |
| + delete this; |
| + } |
| + |
| + // The class that communicates with Google Update to find out if an update is |
| + // available and asks it to start an upgrade. |
| + scoped_refptr<GoogleUpdate> google_updater_; |
| + |
| + // The value returned by GetInstalledAndCriticalVersion might be invalid |
| + // so a bool is also needed to identify that we at least tried to read it. |
| + Version installed_version_; |
| + bool got_installed_version_; |
| + |
| + // The value returned by google_updater_ might also be invalid |
| + // so a bool is also needed to identify that we at least tried to read it. |
| + Version available_version_; |
| + bool got_available_version_; |
| + |
| + // A callback to notify of an outdated install. |
| + base::Closure notify_outdated_callback_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(UpgradeStatusListener); |
| +}; |
| + |
| +#endif // defined(OS_WIN) |
| + |
| } // namespace |
| UpgradeDetectorImpl::UpgradeDetectorImpl() |
| @@ -175,6 +316,13 @@ UpgradeDetectorImpl::UpgradeDetectorImpl() |
| this, &UpgradeDetectorImpl::CheckForUpgrade); |
| } |
| #endif |
| +#if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD) |
| + // On Windows, we also check for an outdated version so we use this listener |
| + // of Google update to asynchronously fetch the available version. |
| + // This object will self-destruct when done. |
| + new UpgradeStatusListener(base::Bind(&UpgradeDetectorImpl::NotifyOutdated, |
| + weak_factory_.GetWeakPtr())); |
| +#endif // defined(OS_WIN) |
| } |
| UpgradeDetectorImpl::~UpgradeDetectorImpl() { |
| @@ -268,6 +416,19 @@ void UpgradeDetectorImpl::NotifyOnUpgrade() { |
| NotifyUpgradeRecommended(); |
| } |
| +void UpgradeDetectorImpl::NotifyOutdated() { |
| + // Stop the recurring timer (that is checking for changes). |
| + detect_upgrade_timer_.Stop(); |
| + set_upgrade_notification_stage(UPGRADE_ANNOYANCE_CRITICAL); |
| + |
| + content::NotificationService::current()->Notify( |
| + chrome::NOTIFICATION_OUTDATED_INSTALL, |
| + content::Source<UpgradeDetector>(this), |
| + content::NotificationService::NoDetails()); |
| + |
| + NotifyUpgradeRecommended(); |
| +} |
| + |
| // static |
| UpgradeDetectorImpl* UpgradeDetectorImpl::GetInstance() { |
| return Singleton<UpgradeDetectorImpl>::get(); |