summaryrefslogtreecommitdiffstats
path: root/chrome/browser/upgrade_detector.cc
diff options
context:
space:
mode:
authorestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-03 00:17:22 +0000
committerestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-03 00:17:22 +0000
commit8fcec3c79f1c8f2edae6a1b064cf60c39720ba54 (patch)
treed2949c5b8fc3a926940366ca3a7fe4eaacdc36e7 /chrome/browser/upgrade_detector.cc
parent8622c0c034073504735808dc83dd509ce444b4ae (diff)
downloadchromium_src-8fcec3c79f1c8f2edae6a1b064cf60c39720ba54.zip
chromium_src-8fcec3c79f1c8f2edae6a1b064cf60c39720ba54.tar.gz
chromium_src-8fcec3c79f1c8f2edae6a1b064cf60c39720ba54.tar.bz2
Linux/GTK: implement update notification.
BUG=45148 TEST=compile chrome with PRODUCT_VERSION manually set to something higher than the current version (e.g. 7.0.0.0), and manually set the upgrade detector time to something short (like 10 seconds). Launch chrome and wait a short time for the update notification to appear. The update notification should pulse every few seconds, and should stop pulsing when the user opens the wrench menu. The about menu item should launch a dialog that allows the user to restart chrome, restoring the current session. Review URL: http://codereview.chromium.org/2365003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@48795 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/upgrade_detector.cc')
-rw-r--r--chrome/browser/upgrade_detector.cc167
1 files changed, 123 insertions, 44 deletions
diff --git a/chrome/browser/upgrade_detector.cc b/chrome/browser/upgrade_detector.cc
index 77f865a..ae92c99 100644
--- a/chrome/browser/upgrade_detector.cc
+++ b/chrome/browser/upgrade_detector.cc
@@ -4,17 +4,27 @@
#include "chrome/browser/upgrade_detector.h"
+#include "base/command_line.h"
#include "base/file_version_info.h"
#include "base/scoped_ptr.h"
#include "base/time.h"
+#include "base/task.h"
+#include "base/utf_string_conversions.h"
#include "base/version.h"
#include "chrome/app/chrome_version_info.h"
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/pref_service.h"
+#include "chrome/common/chrome_switches.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
+#include "chrome/common/pref_names.h"
#include "chrome/installer/util/browser_distribution.h"
#if defined(OS_WIN)
#include "chrome/installer/util/install_util.h"
+#elif defined(OS_LINUX)
+#include "base/process_util.h"
+#include "chrome/installer/util/version.h"
#endif
// TODO(finnur): For the stable channel we want to check daily and notify
@@ -23,69 +33,138 @@
// on how the feature works so I'm checking every hour and notifying the
// user immediately.
+namespace {
+
// How often to check for an upgrade.
-static int kCheckForUpgradeEveryMs = 60 * 60 * 1000; // 1 hour.
+const int kCheckForUpgradeEveryMs = 60 * 60 * 1000; // 1 hour.
// How long to wait before notifying the user about the upgrade.
-static int kNotifyUserAfterMs = 0;
+const int kNotifyUserAfterMs = 0;
+
+// The thread to run the upgrade detection code on. We use FILE for Linux
+// because we don't want to block the UI thread while launching a background
+// process and reading its output.
+const ChromeThread::ID kDetectUpgradeTaskID =
+#if defined(OS_LINUX)
+ ChromeThread::FILE;
+#else
+ ChromeThread::UI;
+#endif
-UpgradeDetector::UpgradeDetector()
- : upgrade_detected_(false),
- notify_upgrade_(false) {
-#if !defined(OS_WIN) || !defined(GOOGLE_CHROME_BUILD)
- return;
+// 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.
+class DetectUpgradeTask : public Task {
+ public:
+ explicit DetectUpgradeTask(Task* upgrade_detected_task)
+ : upgrade_detected_task_(upgrade_detected_task) {
+ }
+
+ virtual ~DetectUpgradeTask() {
+ if (upgrade_detected_task_) {
+ // This has to get deleted on the same thread it was created.
+ ChromeThread::PostTask(ChromeThread::UI, FROM_HERE,
+ new DeleteTask<Task>(upgrade_detected_task_));
+ }
+ }
+
+ virtual void Run() {
+ DCHECK(ChromeThread::CurrentlyOn(kDetectUpgradeTaskID));
+
+#if defined(OS_WIN) || defined(OS_LINUX)
+ using installer::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.
+ Version* installed_version = InstallUtil::GetChromeVersion(false);
+ if (!installed_version) {
+ // User level Chrome is not installed, check system level.
+ installed_version = InstallUtil::GetChromeVersion(true);
+ }
+#elif defined(OS_LINUX)
+ 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;
+ }
+
+ scoped_ptr<Version> installed_version(
+ Version::GetVersionFromString(ASCIIToUTF16(reply)));
+#endif
+
+ // Get the version of the currently *running* instance of Chrome.
+ scoped_ptr<FileVersionInfo> version(chrome_app::GetChromeVersionInfo());
+ if (version.get() == NULL) {
+ NOTREACHED() << "Failed to get current file version";
+ return;
+ }
+ scoped_ptr<Version> running_version(Version::GetVersionFromString(
+ WideToUTF16(version->file_version())));
+
+ if (installed_version->IsHigherThan(running_version.get())) {
+ ChromeThread::PostTask(ChromeThread::UI, FROM_HERE,
+ upgrade_detected_task_);
+ upgrade_detected_task_ = NULL;
+ }
+#else // !(defined(OS_WIN) || defined(OS_LINUX))
+ DCHECK(kNotifyUserAfterMs >= 0); // Avoid error: var defined but not used.
+ NOTIMPLEMENTED();
#endif
+ }
+
+ private:
+ Task* upgrade_detected_task_;
+};
+
+} // namespace
+// static
+void UpgradeDetector::RegisterPrefs(PrefService* prefs) {
+ prefs->RegisterBooleanPref(prefs::kRestartLastSessionOnShutdown, false);
+}
+
+UpgradeDetector::UpgradeDetector()
+ : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)),
+ notify_upgrade_(false) {
+ // Upgrade notifications work on Windows (only Google Chrome) and Linux
+ // (chromium and Google Chrome).
+#if (defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)) || defined(OS_LINUX)
detect_upgrade_timer_.Start(
base::TimeDelta::FromMilliseconds(kCheckForUpgradeEveryMs),
this, &UpgradeDetector::CheckForUpgrade);
+#endif
}
UpgradeDetector::~UpgradeDetector() {
}
void UpgradeDetector::CheckForUpgrade() {
-#if defined(OS_WIN)
- using installer::Version;
-
- // 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.
- Version* installed_version = InstallUtil::GetChromeVersion(false);
- if (!installed_version) {
- // User level Chrome is not installed, check system level.
- installed_version = InstallUtil::GetChromeVersion(true);
- }
-
- // Get the version of the currently *running* instance of Chrome.
- scoped_ptr<FileVersionInfo> version(chrome_app::GetChromeVersionInfo());
- if (version.get() == NULL) {
- NOTREACHED() << L"Failed to get current file version";
- return;
- }
- scoped_ptr<Version> running_version(Version::GetVersionFromString(
- version->file_version()));
+ method_factory_.RevokeAll();
+ Task* callback_task =
+ method_factory_.NewRunnableMethod(&UpgradeDetector::UpgradeDetected);
+ ChromeThread::PostTask(kDetectUpgradeTaskID, FROM_HERE,
+ new DetectUpgradeTask(callback_task));
+}
- if (installed_version->IsHigherThan(running_version.get())) {
- // Stop the recurring timer (that is checking for changes).
- detect_upgrade_timer_.Stop();
+void UpgradeDetector::UpgradeDetected() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
- upgrade_detected_ = true;
+ // Stop the recurring timer (that is checking for changes).
+ detect_upgrade_timer_.Stop();
- NotificationService::current()->Notify(
- NotificationType::UPGRADE_DETECTED,
- Source<UpgradeDetector>(this),
- NotificationService::NoDetails());
+ NotificationService::current()->Notify(
+ NotificationType::UPGRADE_DETECTED,
+ Source<UpgradeDetector>(this),
+ NotificationService::NoDetails());
- // Start the OneShot timer for notifying the user after a certain period.
- upgrade_notification_timer_.Start(
- base::TimeDelta::FromMilliseconds(kNotifyUserAfterMs),
- this, &UpgradeDetector::NotifyOnUpgrade);
- }
-#else
- DCHECK(kNotifyUserAfterMs > 0); // Avoid error: var defined but not used.
- NOTIMPLEMENTED();
-#endif
+ // Start the OneShot timer for notifying the user after a certain period.
+ upgrade_notification_timer_.Start(
+ base::TimeDelta::FromMilliseconds(kNotifyUserAfterMs),
+ this, &UpgradeDetector::NotifyOnUpgrade);
}
void UpgradeDetector::NotifyOnUpgrade() {