summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormad@chromium.org <mad@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-28 21:46:24 +0000
committermad@chromium.org <mad@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-28 21:46:24 +0000
commitd50dd9d9667f83853afb9e37387d7a65887dd9cc (patch)
tree81d654b7e0df9f092a9d76c383b87f877880e8c4
parent4a5c4971f2098b926adce1ae31e5d1950135c12e (diff)
downloadchromium_src-d50dd9d9667f83853afb9e37387d7a65887dd9cc.zip
chromium_src-d50dd9d9667f83853afb9e37387d7a65887dd9cc.tar.gz
chromium_src-d50dd9d9667f83853afb9e37387d7a65887dd9cc.tar.bz2
Show a modified outdated upgrade Bubble for non-enterprise users without auto-update
BUG=164681, 171271 Review URL: https://codereview.chromium.org/211543008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@260289 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/chrome_notification_types.h4
-rw-r--r--chrome/browser/ui/browser_commands.cc5
-rw-r--r--chrome/browser/ui/toolbar/wrench_menu_model.cc7
-rw-r--r--chrome/browser/ui/views/outdated_upgrade_bubble_view.cc138
-rw-r--r--chrome/browser/ui/views/outdated_upgrade_bubble_view.h19
-rw-r--r--chrome/browser/ui/views/toolbar/toolbar_view.cc15
-rw-r--r--chrome/browser/ui/views/toolbar/toolbar_view.h3
-rw-r--r--chrome/browser/upgrade_detector.cc8
-rw-r--r--chrome/browser/upgrade_detector.h9
-rw-r--r--chrome/browser/upgrade_detector_impl.cc92
-rw-r--r--chrome/browser/upgrade_detector_impl.h3
-rw-r--r--chrome/common/chrome_switches.cc3
-rw-r--r--chrome/common/chrome_switches.h1
-rw-r--r--chrome/common/pref_names.cc7
-rw-r--r--chrome/common/pref_names.h1
-rw-r--r--tools/metrics/actions/actions.xml33
-rw-r--r--tools/metrics/histograms/histograms.xml9
17 files changed, 279 insertions, 78 deletions
diff --git a/chrome/browser/chrome_notification_types.h b/chrome/browser/chrome_notification_types.h
index faa0fb3..3c8209b 100644
--- a/chrome/browser/chrome_notification_types.h
+++ b/chrome/browser/chrome_notification_types.h
@@ -630,6 +630,10 @@ enum NotificationType {
// Sent when the current install is outdated. No details are expected.
NOTIFICATION_OUTDATED_INSTALL,
+ // Sent when the current install is outdated and auto-update (AU) is disabled.
+ // No details are expected.
+ NOTIFICATION_OUTDATED_INSTALL_NO_AU,
+
// Software incompatibility notifications ----------------------------------
// Sent when Chrome has finished compiling the list of loaded modules (and
diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc
index 25aa1a3..94d132e 100644
--- a/chrome/browser/ui/browser_commands.cc
+++ b/chrome/browser/ui/browser_commands.cc
@@ -1061,6 +1061,11 @@ void OpenUpdateChromeDialog(Browser* browser) {
chrome::NOTIFICATION_OUTDATED_INSTALL,
content::NotificationService::AllSources(),
content::NotificationService::NoDetails());
+ } else if (UpgradeDetector::GetInstance()->is_outdated_install_no_au()) {
+ content::NotificationService::current()->Notify(
+ chrome::NOTIFICATION_OUTDATED_INSTALL_NO_AU,
+ content::NotificationService::AllSources(),
+ content::NotificationService::NoDetails());
} else {
content::RecordAction(UserMetricsAction("UpdateChrome"));
browser->window()->ShowUpdateChromeDialog();
diff --git a/chrome/browser/ui/toolbar/wrench_menu_model.cc b/chrome/browser/ui/toolbar/wrench_menu_model.cc
index 2c352cb..08c7c35 100644
--- a/chrome/browser/ui/toolbar/wrench_menu_model.cc
+++ b/chrome/browser/ui/toolbar/wrench_menu_model.cc
@@ -81,10 +81,9 @@ namespace {
// Conditionally return the update app menu item title based on upgrade detector
// state.
base::string16 GetUpgradeDialogMenuItemName() {
- if (UpgradeDetector::GetInstance()->is_outdated_install()) {
- return l10n_util::GetStringFUTF16(
- IDS_UPGRADE_BUBBLE_MENU_ITEM,
- l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME));
+ if (UpgradeDetector::GetInstance()->is_outdated_install() ||
+ UpgradeDetector::GetInstance()->is_outdated_install_no_au()) {
+ return l10n_util::GetStringUTF16(IDS_UPGRADE_BUBBLE_MENU_ITEM);
} else {
return l10n_util::GetStringUTF16(IDS_UPDATE_NOW);
}
diff --git a/chrome/browser/ui/views/outdated_upgrade_bubble_view.cc b/chrome/browser/ui/views/outdated_upgrade_bubble_view.cc
index 5c741b9..fcb1ebb 100644
--- a/chrome/browser/ui/views/outdated_upgrade_bubble_view.cc
+++ b/chrome/browser/ui/views/outdated_upgrade_bubble_view.cc
@@ -4,8 +4,16 @@
#include "chrome/browser/ui/views/outdated_upgrade_bubble_view.h"
+#if defined(OS_WIN)
+#include <shellapi.h>
+#endif
+
#include "base/metrics/histogram.h"
+#include "base/path_service.h"
+#include "base/prefs/pref_service.h"
+#include "chrome/browser/browser_process.h"
#include "chrome/browser/upgrade_detector.h"
+#include "chrome/common/pref_names.h"
#include "content/public/browser/page_navigator.h"
#include "content/public/browser/user_metrics.h"
#include "grit/chromium_strings.h"
@@ -21,6 +29,13 @@
#include "ui/views/widget/widget.h"
#include "url/gurl.h"
+#if defined(OS_WIN)
+#include "base/win/win_util.h"
+#include "base/win/windows_version.h"
+#include "chrome/installer/util/install_util.h"
+#include "ui/gfx/icon_util.h"
+#endif
+
using views::GridLayout;
namespace {
@@ -44,6 +59,41 @@ const int kMaxIgnored = 50;
// The number of buckets we want the NumLaterPerReinstall histogram to use.
const int kNumIgnoredBuckets = 5;
+// Adds an elevation icon to |button| when running a system level install.
+void AddElevationIconIfNeeded(views::LabelButton* button) {
+#if defined(OS_WIN)
+ if ((base::win::GetVersion() >= base::win::VERSION_VISTA) &&
+ base::win::UserAccountControlIsEnabled()) {
+ base::FilePath exe_path;
+ PathService::Get(base::FILE_EXE, &exe_path);
+ if (InstallUtil::IsPerUserInstall(exe_path.value().c_str()))
+ return;
+
+ // This code was lifted from chrome/browser/ui/views/infobars/infobar_view.
+ // TODO(mad): Investigate the possibility of moving it to a common place.
+ SHSTOCKICONINFO icon_info = { sizeof(SHSTOCKICONINFO) };
+ // Even with the runtime guard above, we have to use GetProcAddress() here,
+ // because otherwise the loader will try to resolve the function address on
+ // startup, which will break on XP.
+ typedef HRESULT (STDAPICALLTYPE *GetStockIconInfo)(SHSTOCKICONID, UINT,
+ SHSTOCKICONINFO*);
+ GetStockIconInfo func = reinterpret_cast<GetStockIconInfo>(
+ GetProcAddress(GetModuleHandle(L"shell32.dll"), "SHGetStockIconInfo"));
+ if (SUCCEEDED((*func)(SIID_SHIELD, SHGSI_ICON | SHGSI_SMALLICON,
+ &icon_info))) {
+ scoped_ptr<SkBitmap> icon(IconUtil::CreateSkBitmapFromHICON(
+ icon_info.hIcon, gfx::Size(GetSystemMetrics(SM_CXSMICON),
+ GetSystemMetrics(SM_CYSMICON))));
+ if (icon.get()) {
+ button->SetImage(views::Button::STATE_NORMAL,
+ gfx::ImageSkia::CreateFrom1xBitmap(*icon));
+ }
+ DestroyIcon(icon_info.hIcon);
+ }
+ }
+#endif
+}
+
} // namespace
// OutdatedUpgradeBubbleView ---------------------------------------------------
@@ -53,13 +103,16 @@ int OutdatedUpgradeBubbleView::num_ignored_bubbles_ = 0;
// static
void OutdatedUpgradeBubbleView::ShowBubble(views::View* anchor_view,
- content::PageNavigator* navigator) {
+ content::PageNavigator* navigator,
+ bool auto_update_enabled) {
if (IsShowing())
return;
- upgrade_bubble_ = new OutdatedUpgradeBubbleView(anchor_view, navigator);
+ upgrade_bubble_ = new OutdatedUpgradeBubbleView(
+ anchor_view, navigator, auto_update_enabled);
views::BubbleDelegateView::CreateBubble(upgrade_bubble_)->Show();
- content::RecordAction(
- base::UserMetricsAction("OutdatedUpgradeBubble.Show"));
+ content::RecordAction(base::UserMetricsAction(
+ auto_update_enabled ? "OutdatedUpgradeBubble.Show"
+ : "OutdatedUpgradeBubble.ShowNoAU"));
}
bool OutdatedUpgradeBubbleView::IsAvailable() {
@@ -73,12 +126,12 @@ bool OutdatedUpgradeBubbleView::IsAvailable() {
}
OutdatedUpgradeBubbleView::~OutdatedUpgradeBubbleView() {
- if (!chose_to_reinstall_ && num_ignored_bubbles_ < kMaxIgnored)
+ if (!accepted_ && num_ignored_bubbles_ < kMaxIgnored)
++num_ignored_bubbles_;
}
views::View* OutdatedUpgradeBubbleView::GetInitiallyFocusedView() {
- return reinstall_button_;
+ return accept_button_;
}
void OutdatedUpgradeBubbleView::WindowClosing() {
@@ -90,26 +143,27 @@ void OutdatedUpgradeBubbleView::WindowClosing() {
}
void OutdatedUpgradeBubbleView::Init() {
- base::string16 product_name(
- l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME));
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
- reinstall_button_ = new views::LabelButton(
- this, l10n_util::GetStringFUTF16(IDS_REINSTALL_APP, product_name));
- reinstall_button_->SetStyle(views::Button::STYLE_BUTTON);
- reinstall_button_->SetIsDefault(true);
- reinstall_button_->SetFontList(rb.GetFontList(ui::ResourceBundle::BoldFont));
+ accept_button_ = new views::LabelButton(
+ this, l10n_util::GetStringUTF16(
+ auto_update_enabled_ ? IDS_REINSTALL_APP : IDS_REENABLE_UPDATES));
+ accept_button_->SetStyle(views::Button::STYLE_BUTTON);
+ accept_button_->SetIsDefault(true);
+ accept_button_->SetFontList(rb.GetFontList(ui::ResourceBundle::BoldFont));
+ AddElevationIconIfNeeded(accept_button_);
later_button_ = new views::LabelButton(
this, l10n_util::GetStringUTF16(IDS_LATER));
later_button_->SetStyle(views::Button::STYLE_BUTTON);
views::Label* title_label = new views::Label(
- l10n_util::GetStringFUTF16(IDS_UPGRADE_BUBBLE_TITLE, product_name));
+ l10n_util::GetStringUTF16(IDS_UPGRADE_BUBBLE_TITLE));
title_label->SetFontList(rb.GetFontList(ui::ResourceBundle::MediumFont));
title_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
- views::Label* text_label = new views::Label(
- l10n_util::GetStringFUTF16(IDS_UPGRADE_BUBBLE_TEXT, product_name));
+ views::Label* text_label = new views::Label(l10n_util::GetStringUTF16(
+ auto_update_enabled_ ? IDS_UPGRADE_BUBBLE_TEXT
+ : IDS_UPGRADE_BUBBLE_REENABLE_TEXT));
text_label->SetMultiLine(true);
text_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
@@ -157,17 +211,20 @@ void OutdatedUpgradeBubbleView::Init() {
layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
layout->StartRow(0, kButtonsColumnSetId);
- layout->AddView(reinstall_button_);
+ layout->AddView(accept_button_);
layout->AddView(later_button_);
AddAccelerator(ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE));
}
OutdatedUpgradeBubbleView::OutdatedUpgradeBubbleView(
- views::View* anchor_view, content::PageNavigator* navigator)
+ views::View* anchor_view,
+ content::PageNavigator* navigator,
+ bool auto_update_enabled)
: BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT),
- chose_to_reinstall_(false),
- reinstall_button_(NULL),
+ auto_update_enabled_(auto_update_enabled),
+ accepted_(false),
+ accept_button_(NULL),
later_button_(NULL),
navigator_(navigator) {
// Compensate for built-in vertical padding in the anchor view's image.
@@ -184,19 +241,34 @@ void OutdatedUpgradeBubbleView::ButtonPressed(
}
void OutdatedUpgradeBubbleView::HandleButtonPressed(views::Button* sender) {
- if (sender == reinstall_button_) {
- DCHECK(UpgradeDetector::GetInstance()->is_outdated_install());
- chose_to_reinstall_ = true;
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "OutdatedUpgradeBubble.NumLaterPerReinstall", num_ignored_bubbles_,
- 0, kMaxIgnored, kNumIgnoredBuckets);
- content::RecordAction(
- base::UserMetricsAction("OutdatedUpgradeBubble.Reinstall"));
- navigator_->OpenURL(content::OpenURLParams(GURL(kDownloadChromeUrl),
- content::Referrer(),
- NEW_FOREGROUND_TAB,
- content::PAGE_TRANSITION_LINK,
- false));
+ if (sender == accept_button_) {
+ accepted_ = true;
+ if (auto_update_enabled_) {
+ DCHECK(UpgradeDetector::GetInstance()->is_outdated_install());
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "OutdatedUpgradeBubble.NumLaterPerReinstall", num_ignored_bubbles_,
+ 0, kMaxIgnored, kNumIgnoredBuckets);
+ content::RecordAction(
+ base::UserMetricsAction("OutdatedUpgradeBubble.Reinstall"));
+ navigator_->OpenURL(content::OpenURLParams(GURL(kDownloadChromeUrl),
+ content::Referrer(),
+ NEW_FOREGROUND_TAB,
+ content::PAGE_TRANSITION_LINK,
+ false));
+ } else {
+ DCHECK(UpgradeDetector::GetInstance()->is_outdated_install_no_au());
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "OutdatedUpgradeBubble.NumLaterPerEnableAU", num_ignored_bubbles_,
+ 0, kMaxIgnored, kNumIgnoredBuckets);
+ content::RecordAction(
+ base::UserMetricsAction("OutdatedUpgradeBubble.EnableAU"));
+ // TODO(robertshield): Make a call to GoogleUpdateSettings to enable
+ // auto-update.
+ if (g_browser_process->local_state()) {
+ g_browser_process->local_state()->SetBoolean(
+ prefs::kAttemptedToEnableAutoupdate, true);
+ }
+ }
} else {
DCHECK_EQ(later_button_, sender);
content::RecordAction(
diff --git a/chrome/browser/ui/views/outdated_upgrade_bubble_view.h b/chrome/browser/ui/views/outdated_upgrade_bubble_view.h
index 7a66a69..8c410c8 100644
--- a/chrome/browser/ui/views/outdated_upgrade_bubble_view.h
+++ b/chrome/browser/ui/views/outdated_upgrade_bubble_view.h
@@ -24,7 +24,8 @@ class OutdatedUpgradeBubbleView : public views::BubbleDelegateView,
public views::ButtonListener {
public:
static void ShowBubble(views::View* anchor_view,
- content::PageNavigator* navigator);
+ content::PageNavigator* navigator,
+ bool auto_update_enabled);
// Identifies if we are running a build that supports the
// outdated upgrade bubble view.
@@ -38,7 +39,8 @@ class OutdatedUpgradeBubbleView : public views::BubbleDelegateView,
private:
OutdatedUpgradeBubbleView(views::View* anchor_view,
- content::PageNavigator* navigator);
+ content::PageNavigator* navigator,
+ bool auto_update_enabled);
virtual ~OutdatedUpgradeBubbleView();
static bool IsShowing() { return upgrade_bubble_ != NULL; }
@@ -60,11 +62,16 @@ class OutdatedUpgradeBubbleView : public views::BubbleDelegateView,
// reinstall.
static int num_ignored_bubbles_;
- // Identifies if the reinstall button was hit before closing the bubble.
- bool chose_to_reinstall_;
+ // Identifies if auto-update is enabled or not.
+ bool auto_update_enabled_;
- // Button that takes the user to the Chrome download page.
- views::LabelButton* reinstall_button_;
+ // Identifies if the accept button was hit before closing the bubble.
+ bool accepted_;
+
+ // Button that lets the user accept the proposal, which is to navigate to a
+ // Chrome download page when |auto_update_enabled_| is true, or attempt to
+ // re-enable auto-update otherwise.
+ views::LabelButton* accept_button_;
// Button for the user to be reminded later about the outdated upgrade.
views::LabelButton* later_button_;
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc
index ad4af91..4556ad0 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -168,6 +168,8 @@ ToolbarView::ToolbarView(Browser* browser)
if (OutdatedUpgradeBubbleView::IsAvailable()) {
registrar_.Add(this, chrome::NOTIFICATION_OUTDATED_INSTALL,
content::NotificationService::AllSources());
+ registrar_.Add(this, chrome::NOTIFICATION_OUTDATED_INSTALL_NO_AU,
+ content::NotificationService::AllSources());
}
#if defined(OS_WIN)
registrar_.Add(this, chrome::NOTIFICATION_CRITICAL_UPGRADE_INSTALLED,
@@ -518,7 +520,10 @@ void ToolbarView::Observe(int type,
UpdateAppMenuState();
break;
case chrome::NOTIFICATION_OUTDATED_INSTALL:
- ShowOutdatedInstallNotification();
+ ShowOutdatedInstallNotification(true);
+ break;
+ case chrome::NOTIFICATION_OUTDATED_INSTALL_NO_AU:
+ ShowOutdatedInstallNotification(false);
break;
#if defined(OS_WIN)
case chrome::NOTIFICATION_CRITICAL_UPGRADE_INSTALLED:
@@ -817,9 +822,11 @@ void ToolbarView::ShowCriticalNotification() {
#endif
}
-void ToolbarView::ShowOutdatedInstallNotification() {
- if (OutdatedUpgradeBubbleView::IsAvailable())
- OutdatedUpgradeBubbleView::ShowBubble(app_menu_, browser_);
+void ToolbarView::ShowOutdatedInstallNotification(bool auto_update_enabled) {
+ if (OutdatedUpgradeBubbleView::IsAvailable()) {
+ OutdatedUpgradeBubbleView::ShowBubble(
+ app_menu_, browser_, auto_update_enabled);
+ }
}
void ToolbarView::UpdateAppMenuState() {
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.h b/chrome/browser/ui/views/toolbar/toolbar_view.h
index 2e7c586..6a02f5a 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view.h
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.h
@@ -212,7 +212,8 @@ class ToolbarView : public views::AccessiblePaneView,
void ShowCriticalNotification();
// Shows the outdated install notification bubble against the wrench menu.
- void ShowOutdatedInstallNotification();
+ // |auto_update_enabled| is set to true when auto-upate is on.
+ void ShowOutdatedInstallNotification(bool auto_update_enabled);
// Updates the badge and the accessible name of the app menu (Wrench).
void UpdateAppMenuState();
diff --git a/chrome/browser/upgrade_detector.cc b/chrome/browser/upgrade_detector.cc
index f6b68bc..55327bd 100644
--- a/chrome/browser/upgrade_detector.cc
+++ b/chrome/browser/upgrade_detector.cc
@@ -35,6 +35,7 @@ bool UseTestingIntervals() {
void UpgradeDetector::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterBooleanPref(prefs::kRestartLastSessionOnShutdown, false);
registry->RegisterBooleanPref(prefs::kWasRestarted, false);
+ registry->RegisterBooleanPref(prefs::kAttemptedToEnableAutoupdate, false);
}
int UpgradeDetector::GetIconResourceID(UpgradeNotificationIconType type) {
@@ -109,6 +110,13 @@ void UpgradeDetector::NotifyUpgradeRecommended() {
content::NotificationService::NoDetails());
break;
}
+ case UPGRADE_NEEDED_OUTDATED_INSTALL_NO_AU: {
+ content::NotificationService::current()->Notify(
+ chrome::NOTIFICATION_OUTDATED_INSTALL_NO_AU,
+ content::Source<UpgradeDetector>(this),
+ content::NotificationService::NoDetails());
+ break;
+ }
case UPGRADE_AVAILABLE_CRITICAL: {
int idle_timer = UseTestingIntervals() ?
kIdleRepeatingTimerWait :
diff --git a/chrome/browser/upgrade_detector.h b/chrome/browser/upgrade_detector.h
index 9c1826e..cd84b27 100644
--- a/chrome/browser/upgrade_detector.h
+++ b/chrome/browser/upgrade_detector.h
@@ -54,6 +54,12 @@ class UpgradeDetector {
return upgrade_available_ == UPGRADE_NEEDED_OUTDATED_INSTALL;
}
+ // Whether the upgrade recommendation is due to Chrome being outdated AND
+ // auto-update is turned off.
+ bool is_outdated_install_no_au() const {
+ return upgrade_available_ == UPGRADE_NEEDED_OUTDATED_INSTALL_NO_AU;
+ }
+
// Notifify this object that the user has acknowledged the critical update
// so we don't need to complain about it for now.
void acknowledge_critical_update() {
@@ -105,6 +111,9 @@ class UpgradeDetector {
// If no update to Chrome has been installed for more than the recommended
// time.
UPGRADE_NEEDED_OUTDATED_INSTALL,
+ // If no update to Chrome has been installed for more than the recommended
+ // time AND auto-update is turned off.
+ UPGRADE_NEEDED_OUTDATED_INSTALL_NO_AU,
} upgrade_available_;
// Whether the user has acknowledged the critical update.
diff --git a/chrome/browser/upgrade_detector_impl.cc b/chrome/browser/upgrade_detector_impl.cc
index f3a7180..cf56ba7 100644
--- a/chrome/browser/upgrade_detector_impl.cc
+++ b/chrome/browser/upgrade_detector_impl.cc
@@ -13,6 +13,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
#include "base/path_service.h"
+#include "base/prefs/pref_service.h"
#include "base/process/launch.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
@@ -23,10 +24,12 @@
#include "chrome/browser/google/google_util.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_version_info.h"
+#include "chrome/common/pref_names.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"
#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/google_update_settings.h"
#include "chrome/installer/util/helper.h"
@@ -53,17 +56,28 @@ const int kNotifyCycleTimeForTestingMs = 500; // Half a second.
// The number of days after which we identify a build/install as outdated.
const uint64 kOutdatedBuildAgeInDays = 12 * 7;
+// Return the string that was passed as a value for the
+// kCheckForUpdateIntervalSec switch.
std::string CmdLineInterval() {
const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
return cmd_line.GetSwitchValueASCII(switches::kCheckForUpdateIntervalSec);
}
+// Check if one of the outdated simulation switches was present on the command
+// line.
+bool SimulatingOutdated() {
+ const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
+ return cmd_line.HasSwitch(switches::kSimulateOutdated) ||
+ cmd_line.HasSwitch(switches::kSimulateOutdatedNoAU);
+}
+
+// Check if any of the testing switches was present on the command line.
bool IsTesting() {
const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
return cmd_line.HasSwitch(switches::kSimulateUpgrade) ||
cmd_line.HasSwitch(switches::kCheckForUpdateIntervalSec) ||
cmd_line.HasSwitch(switches::kSimulateCriticalUpdate) ||
- cmd_line.HasSwitch(switches::kSimulateOutdated);
+ SimulatingOutdated();
}
// How often to check for an upgrade.
@@ -77,6 +91,7 @@ int GetCheckForUpgradeEveryMs() {
return kCheckForUpgradeMs;
}
+// Return true if the current build is one of the unstable channels.
bool IsUnstableChannel() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
@@ -94,6 +109,7 @@ void CheckForUnstableChannel(const base::Closure& callback_task,
}
#if defined(OS_WIN)
+// Return true if the currently running Chrome is a system install.
bool IsSystemInstall() {
// Get the version of the currently *installed* instance of Chrome,
// which might be newer than the *running* instance if we have been
@@ -107,16 +123,24 @@ bool IsSystemInstall() {
return !InstallUtil::IsPerUserInstall(exe_path.value().c_str());
}
-// This task checks the update policy and calls back the task only if automatic
-// updates are allowed. It also identifies whether we are running an unstable
-// channel.
+// 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.
void DetectUpdatability(const base::Closure& callback_task,
- bool* is_unstable_channel) {
+ bool* is_unstable_channel,
+ bool* is_auto_update_enabled) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
base::string16 app_guid = installer::GetAppGuidForUpdates(IsSystemInstall());
DCHECK(!app_guid.empty());
- if (GoogleUpdateSettings::AreAutoupdatesEnabled(app_guid))
+ // Don't try to turn on autoupdate when we failed previously.
+ if (is_auto_update_enabled) {
+ *is_auto_update_enabled =
+ GoogleUpdateSettings::AreAutoupdatesEnabled(app_guid);
+ }
+ // Don't show the update bubbles to entreprise users (i.e., on a domain).
+ if (!base::win::IsEnrolledToDomain())
CheckForUnstableChannel(callback_task, is_unstable_channel);
}
#endif // defined(OS_WIN)
@@ -126,6 +150,7 @@ void DetectUpdatability(const base::Closure& callback_task,
UpgradeDetectorImpl::UpgradeDetectorImpl()
: weak_factory_(this),
is_unstable_channel_(false),
+ is_auto_update_enabled_(true),
build_date_(base::GetBuildTime()) {
CommandLine command_line(*CommandLine::ForCurrentProcess());
// The different command line switches that affect testing can't be used
@@ -135,7 +160,8 @@ UpgradeDetectorImpl::UpgradeDetectorImpl()
// switch from being taken into account.
// - kSimulateUpgrade supersedes critical or outdated upgrade switches.
// - kSimulateCriticalUpdate has precedence over kSimulateOutdated.
- // - kSimulateOutdated can work on its own, or with a specified date.
+ // - kSimulateOutdatedNoAU has precedence over kSimulateOutdated.
+ // - kSimulateOutdated[NoAu] can work on its own, or with a specified date.
if (command_line.HasSwitch(switches::kDisableBackgroundNetworking))
return;
if (command_line.HasSwitch(switches::kSimulateUpgrade)) {
@@ -146,7 +172,7 @@ UpgradeDetectorImpl::UpgradeDetectorImpl()
UpgradeDetected(UPGRADE_AVAILABLE_CRITICAL);
return;
}
- if (command_line.HasSwitch(switches::kSimulateOutdated)) {
+ if (SimulatingOutdated()) {
// The outdated simulation can work without a value, which means outdated
// now, or with a value that must be a well formed date/time string that
// overrides the build date.
@@ -154,8 +180,14 @@ UpgradeDetectorImpl::UpgradeDetectorImpl()
// tracking moves off of the VariationsService, the "variations-server-url"
// command line switch must also be specified for the service to be
// available on non GOOGLE_CHROME_BUILD.
- std::string build_date = command_line.GetSwitchValueASCII(
- switches::kSimulateOutdated);
+ std::string switch_name;
+ if (command_line.HasSwitch(switches::kSimulateOutdatedNoAU)) {
+ is_auto_update_enabled_ = false;
+ switch_name = switches::kSimulateOutdatedNoAU;
+ } else {
+ switch_name = switches::kSimulateOutdated;
+ }
+ std::string build_date = command_line.GetSwitchValueASCII(switch_name);
base::Time maybe_build_time;
bool result = base::Time::FromString(build_date.c_str(), &maybe_build_time);
if (result && !maybe_build_time.is_null()) {
@@ -164,7 +196,9 @@ UpgradeDetectorImpl::UpgradeDetectorImpl()
StartTimerForUpgradeCheck();
} else {
// Without a valid date, we simulate that we are already outdated...
- UpgradeDetected(UPGRADE_NEEDED_OUTDATED_INSTALL);
+ UpgradeDetected(
+ is_auto_update_enabled_ ? UPGRADE_NEEDED_OUTDATED_INSTALL
+ : UPGRADE_NEEDED_OUTDATED_INSTALL_NO_AU);
}
return;
}
@@ -177,18 +211,27 @@ UpgradeDetectorImpl::UpgradeDetectorImpl()
// Only enable upgrade notifications for official builds. Chromium has no
// upgrade channel.
#if defined(GOOGLE_CHROME_BUILD)
- // On Windows, there might be a policy preventing updates, so validate
- // updatability, and then call StartTimerForUpgradeCheck appropriately.
+ // On Windows, there might be a policy/enterprise environment preventing
+ // updates, so validate updatability, and then call StartTimerForUpgradeCheck
+ // appropriately. And don't check for autoupdate if we already attempted to
+ // enable it in the past.
+ bool attempted_enabling_autoupdate = g_browser_process->local_state() &&
+ g_browser_process->local_state()->GetBoolean(
+ prefs::kAttemptedToEnableAutoupdate);
BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
base::Bind(&DetectUpdatability,
start_upgrade_check_timer_task,
- &is_unstable_channel_));
+ &is_unstable_channel_,
+ attempted_enabling_autoupdate ?
+ NULL : &is_auto_update_enabled_));
#endif
#else
#if defined(OS_MACOSX)
// Only enable upgrade notifications if the updater (Keystone) is present.
- if (!keystone_glue::KeystoneEnabled())
+ if (!keystone_glue::KeystoneEnabled()) {
+ is_auto_update_enabled_ = false;
return;
+ }
#elif defined(OS_POSIX)
// Always enable upgrade notifications regardless of branding.
#else
@@ -199,10 +242,9 @@ UpgradeDetectorImpl::UpgradeDetectorImpl()
base::Bind(&CheckForUnstableChannel,
start_upgrade_check_timer_task,
&is_unstable_channel_));
-
+#endif
// Start tracking network time updates.
network_time_tracker_.Start();
-#endif
}
UpgradeDetectorImpl::~UpgradeDetectorImpl() {
@@ -311,12 +353,10 @@ void UpgradeDetectorImpl::CheckForUpgrade() {
}
bool UpgradeDetectorImpl::DetectOutdatedInstall() {
- // Only enable the outdated install check if we are running the trial for it,
- // unless we are simulating an outdated isntall.
- static bool simulate_outdated = CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kSimulateOutdated);
+ // Don't show the bubble if we have a brand code that is NOT organic, unless
+ // an outdated build is being simulated by command line switches.
+ static bool simulate_outdated = SimulatingOutdated();
if (!simulate_outdated) {
- // Also don't show the bubble if we have a brand code that is NOT organic.
std::string brand;
if (google_util::GetBrand(&brand) && !google_util::IsOrganic(brand))
return false;
@@ -327,7 +367,9 @@ bool UpgradeDetectorImpl::DetectOutdatedInstall() {
if (!network_time_tracker_.GetNetworkTime(base::TimeTicks::Now(),
&network_time,
&uncertainty)) {
- return false;
+ // When network time has not been initialized yet, simply rely on the
+ // machine's current time.
+ network_time = base::Time::Now();
}
if (network_time.is_null() || build_date_.is_null() ||
@@ -338,7 +380,9 @@ bool UpgradeDetectorImpl::DetectOutdatedInstall() {
if (network_time - build_date_ >
base::TimeDelta::FromDays(kOutdatedBuildAgeInDays)) {
- UpgradeDetected(UPGRADE_NEEDED_OUTDATED_INSTALL);
+ UpgradeDetected(is_auto_update_enabled_ ?
+ UPGRADE_NEEDED_OUTDATED_INSTALL :
+ UPGRADE_NEEDED_OUTDATED_INSTALL_NO_AU);
return true;
}
// If we simlated an outdated install with a date, we don't want to keep
diff --git a/chrome/browser/upgrade_detector_impl.h b/chrome/browser/upgrade_detector_impl.h
index d0eef53..30bf7b0 100644
--- a/chrome/browser/upgrade_detector_impl.h
+++ b/chrome/browser/upgrade_detector_impl.h
@@ -66,6 +66,9 @@ class UpgradeDetectorImpl : public UpgradeDetector {
// True if this build is a dev or canary channel build.
bool is_unstable_channel_;
+ // True if auto update is turned on.
+ bool is_auto_update_enabled_;
+
// The date the binaries were built.
base::Time build_date_;
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 81485a0..2d6ec19 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -1223,6 +1223,9 @@ const char kSimulateCriticalUpdate[] = "simulate-critical-update";
// Simulates that current version is outdated.
const char kSimulateOutdated[] = "simulate-outdated";
+// Simulates that current version is outdated and auto-update is off.
+const char kSimulateOutdatedNoAU[] = "simulate-outdated-no-au";
+
// Replaces the buffered data source for <audio> and <video> with a simplified
// resource loader that downloads the entire resource into memory.
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index bf9de46..8f4001b 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -332,6 +332,7 @@ extern const char kSilentDumpOnDCHECK[];
extern const char kSimulateUpgrade[];
extern const char kSimulateCriticalUpdate[];
extern const char kSimulateOutdated[];
+extern const char kSimulateOutdatedNoAU[];
extern const char kSpdyProxyAuthFallback[];
extern const char kSpdyProxyAuthOrigin[];
extern const char kSpdyProxyAuthValue[];
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index dd8b47a..610d5d0 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -2357,6 +2357,13 @@ const char kRecoveryComponentVersion[] = "recovery_component.version";
// troubleshooting.
const char kComponentUpdaterState[] = "component_updater.state";
+// A boolean where true means that the browser has previously attempted to
+// enable autoupdate and failed, so the next out-of-date browser start should
+// not prompt the user to enable autoupdate, it should offer to reinstall Chrome
+// instead.
+const char kAttemptedToEnableAutoupdate[] =
+ "browser.attempted_to_enable_autoupdate";
+
// The next media gallery ID to assign.
const char kMediaGalleriesUniqueId[] = "media_galleries.gallery_id";
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 7c8646f..aad3239 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -799,6 +799,7 @@ extern const char kMessageCenterShowedFirstRunBalloon[];
extern const char kRecoveryComponentVersion[];
extern const char kComponentUpdaterState[];
+extern const char kAttemptedToEnableAutoupdate[];
extern const char kMediaGalleriesUniqueId[];
extern const char kMediaGalleriesRememberedGalleries[];
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index b9e202e..b424cfa 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -8676,19 +8676,40 @@ should be able to be added at any place in this file.
<description>Please enter the description of this user action.</description>
</action>
+<action name="OutdatedUpgradeBubble.EnableAU">
+ <owner>mad@chromium.org</owner>
+ <description>
+ When the user clicks on the Enable updates button of the outdated upgrade
+ bubble.
+ </description>
+</action>
+
<action name="OutdatedUpgradeBubble.Later">
- <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
- <description>Please enter the description of this user action.</description>
+ <owner>mad@chromium.org</owner>
+ <description>
+ When the user clicks on the Later button of the outdated upgrade bubble.
+ </description>
</action>
<action name="OutdatedUpgradeBubble.Reinstall">
- <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
- <description>Please enter the description of this user action.</description>
+ <owner>mad@chromium.org</owner>
+ <description>
+ When the user clicks on the Reinstall button of the outdated upgrade bubble.
+ </description>
</action>
<action name="OutdatedUpgradeBubble.Show">
- <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
- <description>Please enter the description of this user action.</description>
+ <owner>mad@chromium.org</owner>
+ <description>
+ When the outdated upgrade bubble is shown for a user with auto-update on.
+ </description>
+</action>
+
+<action name="OutdatedUpgradeBubble.ShowNoAU">
+ <owner>mad@chromium.org</owner>
+ <description>
+ When the outdated upgrade bubble is shown for a user with auto-update off.
+ </description>
</action>
<action name="Outdent">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 8201625..90a30e2 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -16073,6 +16073,15 @@ other types of suffix sets.
<summary>Events seen by the OSX NSException swizzle.</summary>
</histogram>
+<histogram name="OutdatedUpgradeBubble.NumLaterPerEnableAU">
+ <owner>mad@chromium.org</owner>
+ <summary>
+ Counts the number of times the user clicked on the later button of the
+ outdated upgrade bubble, before clicking on the enable updates button in the
+ same Chrome session.
+ </summary>
+</histogram>
+
<histogram name="OutdatedUpgradeBubble.NumLaterPerReinstall">
<owner>mad@chromium.org</owner>
<summary>