diff options
-rw-r--r-- | chrome/browser/chrome_notification_types.h | 4 | ||||
-rw-r--r-- | chrome/browser/ui/browser_commands.cc | 5 | ||||
-rw-r--r-- | chrome/browser/ui/toolbar/wrench_menu_model.cc | 7 | ||||
-rw-r--r-- | chrome/browser/ui/views/outdated_upgrade_bubble_view.cc | 138 | ||||
-rw-r--r-- | chrome/browser/ui/views/outdated_upgrade_bubble_view.h | 19 | ||||
-rw-r--r-- | chrome/browser/ui/views/toolbar/toolbar_view.cc | 15 | ||||
-rw-r--r-- | chrome/browser/ui/views/toolbar/toolbar_view.h | 3 | ||||
-rw-r--r-- | chrome/browser/upgrade_detector.cc | 8 | ||||
-rw-r--r-- | chrome/browser/upgrade_detector.h | 9 | ||||
-rw-r--r-- | chrome/browser/upgrade_detector_impl.cc | 92 | ||||
-rw-r--r-- | chrome/browser/upgrade_detector_impl.h | 3 | ||||
-rw-r--r-- | chrome/common/chrome_switches.cc | 3 | ||||
-rw-r--r-- | chrome/common/chrome_switches.h | 1 | ||||
-rw-r--r-- | chrome/common/pref_names.cc | 7 | ||||
-rw-r--r-- | chrome/common/pref_names.h | 1 | ||||
-rw-r--r-- | tools/metrics/actions/actions.xml | 33 | ||||
-rw-r--r-- | tools/metrics/histograms/histograms.xml | 9 |
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> |