summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/throb_animation.cc4
-rw-r--r--app/throb_animation.h2
-rw-r--r--chrome/app/chrome_dll_main.cc11
-rw-r--r--chrome/browser/browser_prefs.cc6
-rw-r--r--chrome/browser/browser_shutdown.cc11
-rw-r--r--chrome/browser/first_run.h8
-rw-r--r--chrome/browser/first_run_gtk.cc6
-rw-r--r--chrome/browser/gtk/browser_toolbar_gtk.cc80
-rw-r--r--chrome/browser/gtk/browser_toolbar_gtk.h21
-rw-r--r--chrome/browser/gtk/browser_window_gtk.cc3
-rw-r--r--chrome/browser/gtk/update_recommended_dialog.cc75
-rw-r--r--chrome/browser/gtk/update_recommended_dialog.h27
-rw-r--r--chrome/browser/shell_integration_linux.cc2
-rw-r--r--chrome/browser/upgrade_detector.cc167
-rw-r--r--chrome/browser/upgrade_detector.h18
-rw-r--r--chrome/browser/views/update_recommended_message_box.cc5
-rw-r--r--chrome/browser/views/update_recommended_message_box.h4
-rw-r--r--chrome/chrome_browser.gypi2
-rw-r--r--chrome/chrome_installer_util.gypi2
-rw-r--r--chrome/common/chrome_switches.cc4
-rw-r--r--chrome/common/chrome_switches.h1
-rw-r--r--chrome/installer/util/version.cc22
-rw-r--r--chrome/installer/util/version.h9
23 files changed, 398 insertions, 92 deletions
diff --git a/app/throb_animation.cc b/app/throb_animation.cc
index 922d77d..65596b3 100644
--- a/app/throb_animation.cc
+++ b/app/throb_animation.cc
@@ -4,6 +4,8 @@
#include "app/throb_animation.h"
+#include <limits>
+
static const int kDefaultThrobDurationMS = 400;
ThrobAnimation::ThrobAnimation(AnimationDelegate* target)
@@ -15,6 +17,8 @@ ThrobAnimation::ThrobAnimation(AnimationDelegate* target)
}
void ThrobAnimation::StartThrobbing(int cycles_til_stop) {
+ cycles_til_stop = cycles_til_stop >= 0 ? cycles_til_stop :
+ std::numeric_limits<int>::max();
cycles_remaining_ = cycles_til_stop;
throbbing_ = true;
SlideAnimation::SetSlideDuration(throb_duration_);
diff --git a/app/throb_animation.h b/app/throb_animation.h
index 2405724..7dc67b3 100644
--- a/app/throb_animation.h
+++ b/app/throb_animation.h
@@ -20,7 +20,7 @@ class ThrobAnimation : public SlideAnimation {
virtual ~ThrobAnimation() {}
// Starts throbbing. cycles_til_stop gives the number of cycles to do before
- // stopping.
+ // stopping. A negative value means "throb indefinitely".
void StartThrobbing(int cycles_til_stop);
// Sets the duration of the slide animation when throbbing.
diff --git a/chrome/app/chrome_dll_main.cc b/chrome/app/chrome_dll_main.cc
index ca682a5..1a39c5e 100644
--- a/chrome/app/chrome_dll_main.cc
+++ b/chrome/app/chrome_dll_main.cc
@@ -37,6 +37,7 @@
#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/debug_util.h"
+#include "base/file_version_info.h"
#include "base/i18n/icu_util.h"
#include "base/message_loop.h"
#include "base/path_service.h"
@@ -45,6 +46,7 @@
#include "base/stats_counters.h"
#include "base/stats_table.h"
#include "base/string_util.h"
+#include "chrome/app/chrome_version_info.h"
#include "chrome/browser/diagnostics/diagnostics_main.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/common/chrome_constants.h"
@@ -475,6 +477,15 @@ int ChromeMain(int argc, char** argv) {
#endif
const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
+
+#if defined(OS_POSIX) && !defined(OS_MACOSX)
+ if (parsed_command_line.HasSwitch(switches::kProductVersion)) {
+ scoped_ptr<FileVersionInfo> version(chrome_app::GetChromeVersionInfo());
+ printf("%s\n", WideToASCII(version->product_version()).c_str());
+ return 0;
+ }
+#endif
+
std::string process_type =
parsed_command_line.GetSwitchValueASCII(switches::kProcessType);
diff --git a/chrome/browser/browser_prefs.cc b/chrome/browser/browser_prefs.cc
index 0ad895a..7864ad5 100644
--- a/chrome/browser/browser_prefs.cc
+++ b/chrome/browser/browser_prefs.cc
@@ -40,11 +40,11 @@
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/task_manager.h"
#include "chrome/browser/translate/translate_prefs.h"
+#include "chrome/browser/upgrade_detector.h"
#if defined(TOOLKIT_VIEWS) // TODO(port): whittle this down as we port
#include "chrome/browser/views/browser_actions_container.h"
#include "chrome/browser/views/frame/browser_view.h"
-#include "chrome/browser/views/update_recommended_message_box.h"
#endif
#if defined(TOOLKIT_GTK)
@@ -81,9 +81,7 @@ void RegisterLocalState(PrefService* local_state) {
#if defined(TOOLKIT_VIEWS)
BrowserView::RegisterBrowserViewPrefs(local_state);
#endif
-#if defined(OS_WIN)
- UpdateRecommendedMessageBox::RegisterUpdateRecommendedPrefs(local_state);
-#endif
+ UpgradeDetector::RegisterPrefs(local_state);
TaskManager::RegisterPrefs(local_state);
CookiePromptModalDialog::RegisterPrefs(local_state);
geolocation::RegisterPrefs(local_state);
diff --git a/chrome/browser/browser_shutdown.cc b/chrome/browser/browser_shutdown.cc
index af5bc26..dc55853 100644
--- a/chrome/browser/browser_shutdown.cc
+++ b/chrome/browser/browser_shutdown.cc
@@ -161,21 +161,20 @@ void Shutdown() {
shutdown_type_ != browser_shutdown::END_SESSION) {
Upgrade::SwapNewChromeExeIfPresent();
}
+#endif
if (restart_last_session) {
+#if defined(OS_WIN) || defined(OS_LINUX)
// Make sure to relaunch the browser with the same command line and add
// Restore Last Session flag if session restore is not set.
- CommandLine command_line = CommandLine::FromString(
- CommandLine::ForCurrentProcess()->command_line_string());
+ CommandLine command_line(*CommandLine::ForCurrentProcess());
if (!command_line.HasSwitch(switches::kRestoreLastSession))
command_line.AppendSwitch(switches::kRestoreLastSession);
Upgrade::RelaunchChromeBrowser(command_line);
- }
-#endif
-#if !defined(OS_WIN)
- if (restart_last_session)
+#else
NOTIMPLEMENTED();
#endif
+ }
if (shutdown_type_ > NOT_VALID && shutdown_num_processes_ > 0) {
// Measure total shutdown time as late in the process as possible
diff --git a/chrome/browser/first_run.h b/chrome/browser/first_run.h
index a08e753..92c80c0 100644
--- a/chrome/browser/first_run.h
+++ b/chrome/browser/first_run.h
@@ -157,10 +157,6 @@ class Upgrade {
// handle to the event.
static bool IsBrowserAlreadyRunning();
- // Launches chrome again simulating a 'user' launch. If chrome could not
- // be launched the return is false.
- static bool RelaunchChromeBrowser(const CommandLine& command_line);
-
// If the new_chrome.exe exists (placed by the installer then is swapped
// to chrome.exe and the old chrome is renamed to old_chrome.exe. If there
// is no new_chrome.exe or the swap fails the return is false;
@@ -180,6 +176,10 @@ class Upgrade {
static TryResult ShowTryChromeDialog(size_t version);
#endif // OS_WIN
+ // Launches chrome again simulating a 'user' launch. If chrome could not
+ // be launched the return is false.
+ static bool RelaunchChromeBrowser(const CommandLine& command_line);
+
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
static void SaveLastModifiedTimeOfExe();
#endif
diff --git a/chrome/browser/first_run_gtk.cc b/chrome/browser/first_run_gtk.cc
index 4183fe3..202d095 100644
--- a/chrome/browser/first_run_gtk.cc
+++ b/chrome/browser/first_run_gtk.cc
@@ -9,6 +9,7 @@
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/path_service.h"
+#include "base/process_util.h"
#include "chrome/browser/gtk/first_run_dialog.h"
#include "chrome/browser/profile_manager.h"
#include "chrome/browser/shell_integration.h"
@@ -153,6 +154,11 @@ void Upgrade::SaveLastModifiedTimeOfExe() {
}
// static
+bool Upgrade::RelaunchChromeBrowser(const CommandLine& command_line) {
+ return base::LaunchApp(command_line, false, false, NULL);
+}
+
+// static
void Upgrade::RelaunchChromeBrowserWithNewCommandLineIfNeeded() {
if (new_command_line_) {
if (!base::LaunchApp(*new_command_line_, false, false, NULL)) {
diff --git a/chrome/browser/gtk/browser_toolbar_gtk.cc b/chrome/browser/gtk/browser_toolbar_gtk.cc
index 822bf22..a73b1db 100644
--- a/chrome/browser/gtk/browser_toolbar_gtk.cc
+++ b/chrome/browser/gtk/browser_toolbar_gtk.cc
@@ -41,12 +41,15 @@
#include "chrome/browser/profile.h"
#include "chrome/browser/sync/sync_ui_util.h"
#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/upgrade_detector.h"
#include "chrome/common/notification_details.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
+#include "gfx/canvas_paint.h"
#include "gfx/gtk_util.h"
+#include "gfx/skbitmap_operations.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
@@ -68,6 +71,13 @@ const int kToolbarWidgetSpacing = 2;
// Amount of rounding on top corners of toolbar. Only used in Gtk theme mode.
const int kToolbarCornerSize = 3;
+// The offset in pixels of the upgrade dot on the app menu.
+const int kUpgradeDotOffset = 11;
+
+// The duration of the upgrade notification animation (actually the duration
+// of a half-throb).
+const int kThrobDuration = 1000;
+
} // namespace
// BrowserToolbarGtk, public ---------------------------------------------------
@@ -82,7 +92,8 @@ BrowserToolbarGtk::BrowserToolbarGtk(Browser* browser, BrowserWindowGtk* window)
window_(window),
profile_(NULL),
sync_service_(NULL),
- menu_bar_helper_(this) {
+ menu_bar_helper_(this),
+ upgrade_reminder_animation_(this) {
browser_->command_updater()->AddCommandObserver(IDC_BACK, this);
browser_->command_updater()->AddCommandObserver(IDC_FORWARD, this);
browser_->command_updater()->AddCommandObserver(IDC_RELOAD, this);
@@ -92,6 +103,14 @@ BrowserToolbarGtk::BrowserToolbarGtk(Browser* browser, BrowserWindowGtk* window)
registrar_.Add(this,
NotificationType::BROWSER_THEME_CHANGED,
NotificationService::AllSources());
+ registrar_.Add(this,
+ NotificationType::UPGRADE_RECOMMENDED,
+ NotificationService::AllSources());
+
+ upgrade_reminder_animation_.SetThrobDuration(kThrobDuration);
+
+ if (Singleton<UpgradeDetector>::get()->notify_upgrade())
+ ShowUpgradeReminder();
}
BrowserToolbarGtk::~BrowserToolbarGtk() {
@@ -213,11 +232,15 @@ void BrowserToolbarGtk::Init(Profile* profile,
app_menu_image_ = gtk_image_new_from_pixbuf(
theme_provider_->GetRTLEnabledPixbufNamed(IDR_MENU_CHROME));
gtk_container_add(GTK_CONTAINER(chrome_menu), app_menu_image_);
+ g_signal_connect_after(app_menu_image_, "expose-event",
+ G_CALLBACK(OnAppMenuImageExposeThunk), this);
app_menu_.reset(new MenuGtk(this, &app_menu_model_));
gtk_box_pack_start(GTK_BOX(menus_hbox), chrome_menu, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(toolbar_right_), menus_hbox, FALSE, FALSE,
kToolbarWidgetSpacing);
+ g_signal_connect(app_menu_->widget(), "show",
+ G_CALLBACK(OnAppMenuShowThunk), this);
gtk_box_pack_start(GTK_BOX(toolbar_), toolbar_right_, FALSE, FALSE, 0);
@@ -425,6 +448,8 @@ void BrowserToolbarGtk::Observe(NotificationType type,
gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_), use_gtk);
UpdateRoundedness();
+ } else if (type == NotificationType::UPGRADE_RECOMMENDED) {
+ ShowUpgradeReminder();
} else {
NOTREACHED();
}
@@ -750,6 +775,10 @@ void BrowserToolbarGtk::NotifyPrefChanged(const std::wstring* pref) {
!home_page_is_new_tab_page_.IsManaged());
}
+void BrowserToolbarGtk::ShowUpgradeReminder() {
+ upgrade_reminder_animation_.StartThrobbing(-1);
+}
+
bool BrowserToolbarGtk::ShouldOnlyShowLocation() const {
// If we're a popup window, only show the location bar (omnibox).
return browser_->type() != Browser::TYPE_NORMAL;
@@ -763,6 +792,7 @@ void BrowserToolbarGtk::PopupForButton(GtkWidget* button) {
GTK_STATE_ACTIVE);
MenuGtk* menu = button == page_menu_button_.get() ?
page_menu_.get() : app_menu_.get();
+
menu->PopupAsFromKeyEvent(button);
menu_bar_helper_.MenuStartedShowing(button, menu->widget());
}
@@ -773,3 +803,51 @@ void BrowserToolbarGtk::PopupForButtonNextTo(GtkWidget* button,
app_menu_button_.get() : page_menu_button_.get();
PopupForButton(other_button);
}
+
+void BrowserToolbarGtk::AnimationEnded(const Animation* animation) {
+ AnimationProgressed(animation);
+}
+
+void BrowserToolbarGtk::AnimationProgressed(const Animation* animation) {
+ DCHECK_EQ(animation, &upgrade_reminder_animation_);
+ gtk_widget_queue_draw(app_menu_image_);
+}
+
+void BrowserToolbarGtk::AnimationCanceled(const Animation* animation) {
+ AnimationProgressed(animation);
+}
+
+void BrowserToolbarGtk::OnAppMenuShow(GtkWidget* sender) {
+ upgrade_reminder_animation_.Reset();
+}
+
+gboolean BrowserToolbarGtk::OnAppMenuImageExpose(GtkWidget* sender,
+ GdkEventExpose* expose) {
+ if (!Singleton<UpgradeDetector>::get()->notify_upgrade())
+ return FALSE;
+
+ SkBitmap badge;
+ if (upgrade_reminder_animation_.cycles_remaining() > 0 &&
+ // This funky looking math makes the badge throb for 2 seconds once
+ // every 8 seconds.
+ ((upgrade_reminder_animation_.cycles_remaining() - 1) / 2) % 4 == 0) {
+ badge = SkBitmapOperations::CreateBlendedBitmap(
+ *theme_provider_->GetBitmapNamed(IDR_UPGRADE_DOT_ACTIVE),
+ *theme_provider_->GetBitmapNamed(IDR_UPGRADE_DOT_INACTIVE),
+ upgrade_reminder_animation_.GetCurrentValue());
+ } else {
+ badge = *theme_provider_->GetBitmapNamed(IDR_UPGRADE_DOT_INACTIVE);
+ }
+
+ // Draw the chrome app menu icon onto the canvas.
+ gfx::CanvasPaint canvas(expose, false);
+ int x_offset = base::i18n::IsRTL() ?
+ sender->allocation.width - kUpgradeDotOffset - badge.width() :
+ kUpgradeDotOffset;
+ canvas.DrawBitmapInt(
+ badge,
+ sender->allocation.x + x_offset,
+ sender->allocation.y + sender->allocation.height - badge.height());
+
+ return FALSE;
+}
diff --git a/chrome/browser/gtk/browser_toolbar_gtk.h b/chrome/browser/gtk/browser_toolbar_gtk.h
index 2627ac2..26df479 100644
--- a/chrome/browser/gtk/browser_toolbar_gtk.h
+++ b/chrome/browser/gtk/browser_toolbar_gtk.h
@@ -10,6 +10,7 @@
#include "app/gtk_signal.h"
#include "app/menus/simple_menu_model.h"
+#include "app/throb_animation.h"
#include "base/scoped_ptr.h"
#include "chrome/browser/app_menu_model.h"
#include "chrome/browser/command_updater.h"
@@ -43,7 +44,8 @@ class BrowserToolbarGtk : public CommandUpdater::CommandObserver,
public menus::SimpleMenuModel::Delegate,
public MenuGtk::Delegate,
public NotificationObserver,
- public MenuBarHelper::Delegate {
+ public MenuBarHelper::Delegate,
+ public AnimationDelegate {
public:
explicit BrowserToolbarGtk(Browser* browser, BrowserWindowGtk* window);
virtual ~BrowserToolbarGtk();
@@ -116,6 +118,11 @@ class BrowserToolbarGtk : public CommandUpdater::CommandObserver,
virtual void PopupForButtonNextTo(GtkWidget* button,
GtkMenuDirectionType dir);
+ // AnimationDelegate implementation ------------------------------------------
+ virtual void AnimationEnded(const Animation* animation);
+ virtual void AnimationProgressed(const Animation* animation);
+ virtual void AnimationCanceled(const Animation* animation);
+
private:
// Builds a toolbar button with all the properties set.
// |spacing| is the width of padding (in pixels) on the left and right of the
@@ -165,12 +172,22 @@ class BrowserToolbarGtk : public CommandUpdater::CommandObserver,
GdkDragContext*, gint, gint, GtkSelectionData*,
guint, guint);
+ // Used to stop the upgrade notification animation.
+ CHROMEGTK_CALLBACK_0(BrowserToolbarGtk, void, OnAppMenuShow);
+
+ // Used to draw the upgrade notification badge.
+ CHROMEGTK_CALLBACK_1(BrowserToolbarGtk, gboolean, OnAppMenuImageExpose,
+ GdkEventExpose*);
+
// ProfileSyncServiceObserver method.
virtual void OnStateChanged();
// Updates preference-dependent state.
void NotifyPrefChanged(const std::wstring* pref);
+ // Start the upgrade notification animation.
+ void ShowUpgradeReminder();
+
static void SetSyncMenuLabel(GtkWidget* widget, gpointer userdata);
// Sometimes we only want to show the location w/o the toolbar buttons (e.g.,
@@ -252,6 +269,8 @@ class BrowserToolbarGtk : public CommandUpdater::CommandObserver,
// Manages the home button drop signal handler.
scoped_ptr<GtkSignalRegistrar> drop_handler_;
+ ThrobAnimation upgrade_reminder_animation_;
+
DISALLOW_COPY_AND_ASSIGN(BrowserToolbarGtk);
};
diff --git a/chrome/browser/gtk/browser_window_gtk.cc b/chrome/browser/gtk/browser_window_gtk.cc
index 5c32ca7..d7fbfb6 100644
--- a/chrome/browser/gtk/browser_window_gtk.cc
+++ b/chrome/browser/gtk/browser_window_gtk.cc
@@ -65,6 +65,7 @@
#include "chrome/browser/gtk/tabs/tab_strip_gtk.h"
#include "chrome/browser/gtk/task_manager_gtk.h"
#include "chrome/browser/gtk/theme_install_bubble_view_gtk.h"
+#include "chrome/browser/gtk/update_recommended_dialog.h"
#include "chrome/browser/location_bar.h"
#include "chrome/browser/page_info_window.h"
#include "chrome/browser/pref_service.h"
@@ -884,7 +885,7 @@ views::Window* BrowserWindowGtk::ShowAboutChromeDialog() {
}
void BrowserWindowGtk::ShowUpdateChromeDialog() {
- NOTIMPLEMENTED();
+ UpdateRecommendedDialog::Show(window_);
}
void BrowserWindowGtk::ShowTaskManager() {
diff --git a/chrome/browser/gtk/update_recommended_dialog.cc b/chrome/browser/gtk/update_recommended_dialog.cc
new file mode 100644
index 0000000..6264639
--- /dev/null
+++ b/chrome/browser/gtk/update_recommended_dialog.cc
@@ -0,0 +1,75 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/gtk/update_recommended_dialog.h"
+
+#include "app/l10n_util.h"
+#include "app/message_box_flags.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/gtk/gtk_util.h"
+#include "chrome/browser/pref_service.h"
+#include "chrome/common/pref_names.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+
+static const int kMessageWidth = 400;
+
+// static
+void UpdateRecommendedDialog::Show(GtkWindow* parent) {
+ new UpdateRecommendedDialog(parent);
+}
+
+UpdateRecommendedDialog::UpdateRecommendedDialog(GtkWindow* parent) {
+ dialog_ = gtk_dialog_new_with_buttons(
+ l10n_util::GetStringUTF8(IDS_PRODUCT_NAME).c_str(),
+ parent,
+ static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
+ l10n_util::GetStringUTF8(IDS_RESTART_AND_UPDATE).c_str(),
+ GTK_RESPONSE_ACCEPT,
+ l10n_util::GetStringUTF8(IDS_NOT_NOW).c_str(),
+ GTK_RESPONSE_REJECT,
+ NULL);
+
+ g_signal_connect(dialog_, "response", G_CALLBACK(OnResponseThunk), this);
+
+ // Create the content-holding vbox.
+ GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+ gtk_container_set_border_width(GTK_CONTAINER(vbox),
+ gtk_util::kContentAreaBorder);
+
+ // Add the message text.
+ std::string text(
+ l10n_util::GetStringFUTF8(IDS_UPDATE_RECOMMENDED,
+ l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
+ GtkWidget* label = gtk_label_new(text.c_str());
+ gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+ gtk_widget_set_size_request(label, kMessageWidth, -1);
+ gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
+
+ // Add our vbox to the dialog.
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), vbox,
+ FALSE, FALSE, 0);
+
+ gtk_window_set_resizable(GTK_WINDOW(dialog_), FALSE);
+
+ gtk_widget_show_all(dialog_);
+}
+
+UpdateRecommendedDialog::~UpdateRecommendedDialog() {
+}
+
+void UpdateRecommendedDialog::OnResponse(GtkWidget* sender, gint response_id) {
+ gtk_widget_destroy(dialog_);
+
+ if (response_id == GTK_RESPONSE_ACCEPT) {
+ // Set the flag to restore the last session on shutdown.
+ PrefService* pref_service = g_browser_process->local_state();
+ pref_service->SetBoolean(prefs::kRestartLastSessionOnShutdown, true);
+
+ BrowserList::CloseAllBrowsersAndExit();
+ }
+
+ delete this;
+}
diff --git a/chrome/browser/gtk/update_recommended_dialog.h b/chrome/browser/gtk/update_recommended_dialog.h
new file mode 100644
index 0000000..fd6ca4f
--- /dev/null
+++ b/chrome/browser/gtk/update_recommended_dialog.h
@@ -0,0 +1,27 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_GTK_UPDATE_RECOMMENDED_DIALOG_H_
+#define CHROME_BROWSER_GTK_UPDATE_RECOMMENDED_DIALOG_H_
+
+#include <gtk/gtk.h>
+
+#include "app/gtk_signal.h"
+
+class UpdateRecommendedDialog {
+ public:
+ static void Show(GtkWindow* parent);
+
+ private:
+ CHROMEGTK_CALLBACK_1(UpdateRecommendedDialog, void, OnResponse, gint);
+
+ explicit UpdateRecommendedDialog(GtkWindow* parent);
+ ~UpdateRecommendedDialog();
+
+ GtkWidget* dialog_;
+
+ DISALLOW_COPY_AND_ASSIGN(UpdateRecommendedDialog);
+};
+
+#endif // CHROME_BROWSER_GTK_UPDATE_RECOMMENDED_DIALOG_H_
diff --git a/chrome/browser/shell_integration_linux.cc b/chrome/browser/shell_integration_linux.cc
index 3c87350..9927d7a 100644
--- a/chrome/browser/shell_integration_linux.cc
+++ b/chrome/browser/shell_integration_linux.cc
@@ -210,6 +210,8 @@ bool ShellIntegration::SetAsDefaultBrowser() {
// static
ShellIntegration::DefaultBrowserState ShellIntegration::IsDefaultBrowser() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
+
scoped_ptr<base::EnvVarGetter> env_getter(base::EnvVarGetter::Create());
std::vector<std::string> argv;
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() {
diff --git a/chrome/browser/upgrade_detector.h b/chrome/browser/upgrade_detector.h
index 9a7da11..036d43c 100644
--- a/chrome/browser/upgrade_detector.h
+++ b/chrome/browser/upgrade_detector.h
@@ -8,6 +8,8 @@
#include "base/singleton.h"
#include "base/timer.h"
+class PrefService;
+
///////////////////////////////////////////////////////////////////////////////
// UpgradeDetector
//
@@ -22,17 +24,21 @@ class UpgradeDetector {
public:
~UpgradeDetector();
+ static void RegisterPrefs(PrefService* prefs);
+
bool notify_upgrade() { return notify_upgrade_; }
private:
UpgradeDetector();
friend struct DefaultSingletonTraits<UpgradeDetector>;
- // Checks with Omaha if we have the latest version. If not, sends out a
- // notification and starts a one shot timer to wait until notifying the
- // user.
+ // Launches a task on the file thread to check if we have the latest version.
void CheckForUpgrade();
+ // Sends out a notification and starts a one shot timer to wait until
+ // notifying the user.
+ void UpgradeDetected();
+
// The function that sends out a notification (after a certain time has
// elapsed) that lets the rest of the UI know we should start notifying the
// user that a new version is available.
@@ -44,8 +50,10 @@ class UpgradeDetector {
// After we detect an upgrade we wait a set time before notifying the user.
base::OneShotTimer<UpgradeDetector> upgrade_notification_timer_;
- // Whether we have detected an upgrade happening while we were running.
- bool upgrade_detected_;
+ // We use this factory to create callback tasks for UpgradeDetected. We pass
+ // the task to the actual upgrade detection code, which is in
+ // DetectUpgradeTask.
+ ScopedRunnableMethodFactory<UpgradeDetector> method_factory_;
// Whether we have waited long enough after detecting an upgrade (to see
// is we should start nagging about upgrading).
diff --git a/chrome/browser/views/update_recommended_message_box.cc b/chrome/browser/views/update_recommended_message_box.cc
index dc1bf05..5e66b72 100644
--- a/chrome/browser/views/update_recommended_message_box.cc
+++ b/chrome/browser/views/update_recommended_message_box.cc
@@ -25,11 +25,6 @@ void UpdateRecommendedMessageBox::ShowMessageBox(
new UpdateRecommendedMessageBox(parent_window);
}
-void UpdateRecommendedMessageBox::RegisterUpdateRecommendedPrefs(
- PrefService* prefs) {
- prefs->RegisterBooleanPref(prefs::kRestartLastSessionOnShutdown, false);
-}
-
bool UpdateRecommendedMessageBox::Accept() {
// Set the flag to restore the last session on shutdown.
PrefService* pref_service = g_browser_process->local_state();
diff --git a/chrome/browser/views/update_recommended_message_box.h b/chrome/browser/views/update_recommended_message_box.h
index 9751db4..e5e39e2 100644
--- a/chrome/browser/views/update_recommended_message_box.h
+++ b/chrome/browser/views/update_recommended_message_box.h
@@ -10,7 +10,6 @@
#include "views/window/dialog_delegate.h"
class MessageBoxView;
-class PrefService;
// A dialog box that tells the user that an update is recommended in order for
// the latest version to be put to use.
@@ -19,9 +18,6 @@ class UpdateRecommendedMessageBox : public views::DialogDelegate {
// This box is modal to |parent_window|.
static void ShowMessageBox(gfx::NativeWindow parent_window);
- // Register preferences specific to this view.
- static void RegisterUpdateRecommendedPrefs(PrefService* prefs);
-
// Overridden from views::DialogDelegate:
virtual bool Accept();
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 2474041..d5dc4d6 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1457,6 +1457,8 @@
'browser/gtk/theme_install_bubble_view_gtk.h',
'browser/gtk/translate_infobars.cc',
'browser/gtk/translate_infobars.h',
+ 'browser/gtk/update_recommended_dialog.cc',
+ 'browser/gtk/update_recommended_dialog.h',
'browser/gtk/view_id_util.cc',
'browser/gtk/view_id_util.h',
'browser/hang_monitor/hung_plugin_action.cc',
diff --git a/chrome/chrome_installer_util.gypi b/chrome/chrome_installer_util.gypi
index ed1d35e..f36a559 100644
--- a/chrome/chrome_installer_util.gypi
+++ b/chrome/chrome_installer_util.gypi
@@ -143,6 +143,8 @@
'installer/util/master_preferences.h',
'installer/util/master_preferences_constants.cc',
'installer/util/master_preferences_constants.h',
+ 'installer/util/version.cc',
+ 'installer/util/version.h',
],
'include_dirs': [
'<(DEPTH)',
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 4690749..491d6e5 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -830,6 +830,10 @@ const char kUtilityProcess[] = "utility";
// specifies the directory that can be accessed.
const char kUtilityProcessAllowedDir[] = "utility-allowed-dir";
+// Output the product version information and quit. Used as an internal api to
+// detect the installed version of Chrome on Linux.
+const char kProductVersion[] = "product-version";
+
// Will add kWaitForDebugger to every child processes. If a value is passed, it
// will be used as a filter to determine if the child process should have the
// kWaitForDebugger flag passed on or not.
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index b4df9c9..5852935 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -234,6 +234,7 @@ extern const char kUserScriptsDir[];
extern const char kUtilityCmdPrefix[];
extern const char kUtilityProcess[];
extern const char kUtilityProcessAllowedDir[];
+extern const char kProductVersion[];
extern const char kWaitForDebuggerChildren[];
extern const char kWebWorkerProcessPerCore[];
extern const char kWebWorkerShareProcesses[];
diff --git a/chrome/installer/util/version.cc b/chrome/installer/util/version.cc
index 0bd9409..2e58076 100644
--- a/chrome/installer/util/version.cc
+++ b/chrome/installer/util/version.cc
@@ -4,19 +4,19 @@
#include <vector>
+#include "base/format_macros.h"
#include "base/string_util.h"
#include "chrome/installer/util/version.h"
installer::Version::Version(int64 major, int64 minor, int64 build,
- int64 patch) :
- major_(major), minor_(minor), build_(build), patch_(patch) {
- version_str_.append(Int64ToWString(major_));
- version_str_.append(L".");
- version_str_.append(Int64ToWString(minor_));
- version_str_.append(L".");
- version_str_.append(Int64ToWString(build_));
- version_str_.append(L".");
- version_str_.append(Int64ToWString(patch_));
+ int64 patch)
+ : major_(major),
+ minor_(minor),
+ build_(build),
+ patch_(patch) {
+ version_str_ = ASCIIToUTF16(
+ StringPrintf("%" PRId64 ".%" PRId64 ".%" PRId64 ".%" PRId64,
+ major_, minor_, build_, patch_));
}
installer::Version::~Version() {
@@ -33,8 +33,8 @@ bool installer::Version::IsHigherThan(const installer::Version* other) const {
}
installer::Version* installer::Version::GetVersionFromString(
- const std::wstring& version_str) {
- std::vector<std::wstring> numbers;
+ const string16& version_str) {
+ std::vector<string16> numbers;
SplitString(version_str, '.', &numbers);
if (numbers.size() != 4) {
diff --git a/chrome/installer/util/version.h b/chrome/installer/util/version.h
index 1f02e00..980fe05 100644
--- a/chrome/installer/util/version.h
+++ b/chrome/installer/util/version.h
@@ -5,9 +5,8 @@
#ifndef CHROME_INSTALLER_UTIL_VERSION_H_
#define CHROME_INSTALLER_UTIL_VERSION_H_
-#include <string>
-
#include "base/basictypes.h"
+#include "base/string16.h"
namespace installer {
@@ -20,21 +19,21 @@ class Version {
bool IsHigherThan(const Version* other) const;
// Return the string representation of this version
- const std::wstring& GetString() const {
+ const string16& GetString() const {
return version_str_;
}
// Assume that the version string is specified by four integers separated
// by character '.'. Return NULL if string is not of this format.
// Caller is responsible for freeing the Version object once done.
- static Version* GetVersionFromString(const std::wstring& version_str);
+ static Version* GetVersionFromString(const string16& version_str);
private:
int64 major_;
int64 minor_;
int64 build_;
int64 patch_;
- std::wstring version_str_;
+ string16 version_str_;
// Classes outside this file do not have any need to create objects of
// this type so declare constructor as private.