diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd
index 9f6f4555d2263b..736ea9d1c81029 100644
--- a/ash/ash_strings.grd
+++ b/ash/ash_strings.grd
@@ -366,15 +366,24 @@ This file contains the strings for ash.
Adobe Flash Player update available
+
+ Device will be rolled back
+
Learn more about the latest $1Chromium OS update
Restart to update
+
+ Restart and reset
+
This update requires powerwashing your device. Learn more about the latest $1Chromium OS update.
+
+ Your administrator is rolling back your device. All data will be deleted when the device is restarted.
+
Volume
diff --git a/ash/public/interfaces/system_tray.mojom b/ash/public/interfaces/system_tray.mojom
index c90c3e294f415e..7ef30f39dad3b2 100644
--- a/ash/public/interfaces/system_tray.mojom
+++ b/ash/public/interfaces/system_tray.mojom
@@ -33,11 +33,21 @@ interface SystemTray {
// tracing is running.
SetPerformanceTracingIconVisible(bool visible);
- // Shows an icon in the system tray indicating that a software update is
- // available. Once shown the icon persists until reboot. |severity| and
- // |factory_reset_required| are used to set the icon, color, and tooltip.
+ // Shows an icon in the system tray or a notification on the unified system
+ // menu indicating that a software update is available. Once shown, the icon
+ // or the notification persists until reboot.
+ // |severity| specifies how critical is the update.
+ // |factory_reset_required| is true if during the update the device will
+ // be wiped.
+ // |rollback| specifies whether the update is actually an admin-initiated
+ // rollback. This implies that a the device will be wiped.
+ // |update_type| specifies the component which has been updated.
+ //
+ // These values are used to control the icon, color and the text of the
+ // tooltip or the notification.
ShowUpdateIcon(UpdateSeverity severity,
bool factory_reset_required,
+ bool rollback,
UpdateType update_type);
// If |visible| is true, shows an icon in the system tray which indicates that
diff --git a/ash/system/model/system_tray_model.cc b/ash/system/model/system_tray_model.cc
index 0ec2691176bdc0..bf9bc4a15777be 100644
--- a/ash/system/model/system_tray_model.cc
+++ b/ash/system/model/system_tray_model.cc
@@ -78,8 +78,9 @@ void SystemTrayModel::SetPerformanceTracingIconVisible(bool visible) {
void SystemTrayModel::ShowUpdateIcon(mojom::UpdateSeverity severity,
bool factory_reset_required,
+ bool rollback,
mojom::UpdateType update_type) {
- update_model()->SetUpdateAvailable(severity, factory_reset_required,
+ update_model()->SetUpdateAvailable(severity, factory_reset_required, rollback,
update_type);
}
diff --git a/ash/system/model/system_tray_model.h b/ash/system/model/system_tray_model.h
index ba14516cc18ed7..e0acc3bc8dae42 100644
--- a/ash/system/model/system_tray_model.h
+++ b/ash/system/model/system_tray_model.h
@@ -38,6 +38,7 @@ class SystemTrayModel : public mojom::SystemTray {
void SetPerformanceTracingIconVisible(bool visible) override;
void ShowUpdateIcon(mojom::UpdateSeverity severity,
bool factory_reset_required,
+ bool rollback,
mojom::UpdateType update_type) override;
void SetUpdateOverCellularAvailableIconVisible(bool visible) override;
void ShowVolumeSliderBubble() override;
diff --git a/ash/system/model/update_model.cc b/ash/system/model/update_model.cc
index caf6c3336ba81d..2f30e6dc6ee775 100644
--- a/ash/system/model/update_model.cc
+++ b/ash/system/model/update_model.cc
@@ -19,10 +19,12 @@ void UpdateModel::RemoveObserver(UpdateObserver* observer) {
void UpdateModel::SetUpdateAvailable(mojom::UpdateSeverity severity,
bool factory_reset_required,
+ bool rollback,
mojom::UpdateType update_type) {
update_required_ = true;
severity_ = severity;
factory_reset_required_ = factory_reset_required;
+ rollback_ = rollback;
update_type_ = update_type;
NotifyUpdateAvailable();
}
diff --git a/ash/system/model/update_model.h b/ash/system/model/update_model.h
index b7255446e77e37..b8557e508911d7 100644
--- a/ash/system/model/update_model.h
+++ b/ash/system/model/update_model.h
@@ -28,11 +28,12 @@ class UpdateModel {
void RemoveObserver(UpdateObserver* observer);
// Store the state that a software update is available. The state persists
- // until reboot. Based on |severity| and |factory_reset_required|, the
- // observer views can indicate the severity of the update to users by changing
- // the icon, color, and tooltip.
+ // until reboot. Based on |severity|, |factory_reset_required| and |rollback|,
+ // the observer views can indicate the severity of the update to users by
+ // changing the icon, color, and tooltip.
void SetUpdateAvailable(mojom::UpdateSeverity severity,
bool factory_reset_required,
+ bool rollback,
mojom::UpdateType update_type);
// If |available| is true, a software update is available but user's agreement
@@ -45,6 +46,7 @@ class UpdateModel {
bool update_required() const { return update_required_; }
bool factory_reset_required() const { return factory_reset_required_; }
+ bool rollback() const { return rollback_; }
mojom::UpdateType update_type() const { return update_type_; }
bool update_over_cellular_available() const {
return update_over_cellular_available_;
@@ -56,6 +58,7 @@ class UpdateModel {
bool update_required_ = false;
mojom::UpdateSeverity severity_ = mojom::UpdateSeverity::NONE;
bool factory_reset_required_ = false;
+ bool rollback_ = false;
mojom::UpdateType update_type_ = mojom::UpdateType::SYSTEM;
bool update_over_cellular_available_ = false;
diff --git a/ash/system/update/tray_update_unittest.cc b/ash/system/update/tray_update_unittest.cc
index 742bc135bb05f0..99ed20c9cfe6bd 100644
--- a/ash/system/update/tray_update_unittest.cc
+++ b/ash/system/update/tray_update_unittest.cc
@@ -34,7 +34,7 @@ TEST_F(TrayUpdateTest, VisibilityAfterUpdate) {
// Simulate an update.
Shell::Get()->system_tray_model()->ShowUpdateIcon(
- mojom::UpdateSeverity::LOW, false, mojom::UpdateType::SYSTEM);
+ mojom::UpdateSeverity::LOW, false, false, mojom::UpdateType::SYSTEM);
// Tray item is now visible.
EXPECT_TRUE(tray_update->tray_view()->visible());
@@ -58,7 +58,7 @@ TEST_F(TrayUpdateTest, VisibilityAfterFlashUpdate) {
// Simulate an update.
Shell::Get()->system_tray_model()->ShowUpdateIcon(
- mojom::UpdateSeverity::LOW, false, mojom::UpdateType::FLASH);
+ mojom::UpdateSeverity::LOW, false, false, mojom::UpdateType::FLASH);
// Tray item is now visible.
EXPECT_TRUE(tray_update->tray_view()->visible());
diff --git a/ash/system/update/update_notification_controller.cc b/ash/system/update/update_notification_controller.cc
index 00d5e4ea41cf96..c0c4ac4e069662 100644
--- a/ash/system/update/update_notification_controller.cc
+++ b/ash/system/update/update_notification_controller.cc
@@ -45,6 +45,10 @@ void UpdateNotificationController::OnUpdateAvailable() {
return;
}
+ message_center::SystemNotificationWarningLevel warning_level =
+ model_->rollback()
+ ? message_center::SystemNotificationWarningLevel::WARNING
+ : message_center::SystemNotificationWarningLevel::NORMAL;
std::unique_ptr notification =
Notification::CreateSystemNotification(
message_center::NOTIFICATION_TYPE_SIMPLE, kNotificationId,
@@ -57,15 +61,18 @@ void UpdateNotificationController::OnUpdateAvailable() {
base::BindRepeating(
&UpdateNotificationController::HandleNotificationClick,
weak_ptr_factory_.GetWeakPtr())),
- kSystemMenuUpdateIcon,
- message_center::SystemNotificationWarningLevel::NORMAL);
+ kSystemMenuUpdateIcon, warning_level);
notification->set_pinned(true);
if (model_->update_required()) {
std::vector notification_actions;
- message_center::ButtonInfo button_info = message_center::ButtonInfo(
- l10n_util::GetStringUTF16(IDS_UPDATE_NOTIFICATION_RESTART_BUTTON));
- notification_actions.push_back(button_info);
+ if (model_->rollback()) {
+ notification_actions.push_back(message_center::ButtonInfo(
+ l10n_util::GetStringUTF16(IDS_ROLLBACK_NOTIFICATION_RESTART_BUTTON)));
+ } else {
+ notification_actions.push_back(message_center::ButtonInfo(
+ l10n_util::GetStringUTF16(IDS_UPDATE_NOTIFICATION_RESTART_BUTTON)));
+ }
notification->set_buttons(notification_actions);
}
@@ -79,6 +86,9 @@ bool UpdateNotificationController::ShouldShowUpdate() const {
base::string16 UpdateNotificationController::GetNotificationMessage() const {
base::string16 system_app_name =
l10n_util::GetStringUTF16(IDS_ASH_MESSAGE_CENTER_SYSTEM_APP_NAME);
+ if (model_->rollback()) {
+ return l10n_util::GetStringUTF16(IDS_UPDATE_NOTIFICATION_MESSAGE_ROLLBACK);
+ }
if (model_->factory_reset_required()) {
return l10n_util::GetStringFUTF16(IDS_UPDATE_NOTIFICATION_MESSAGE_POWERWASH,
system_app_name);
@@ -94,8 +104,9 @@ base::string16 UpdateNotificationController::GetNotificationTitle() const {
IDS_UPDATE_NOTIFICATION_TITLE_FLASH_PLAYER);
}
#endif
-
- return l10n_util::GetStringUTF16(IDS_UPDATE_NOTIFICATION_TITLE);
+ return model_->rollback()
+ ? l10n_util::GetStringUTF16(IDS_ROLLBACK_NOTIFICATION_TITLE)
+ : l10n_util::GetStringUTF16(IDS_UPDATE_NOTIFICATION_TITLE);
}
void UpdateNotificationController::HandleNotificationClick(
diff --git a/ash/system/update/update_notification_controller_unittest.cc b/ash/system/update/update_notification_controller_unittest.cc
index 25d6cde6e6c15a..2ae8427a8ee6cb 100644
--- a/ash/system/update/update_notification_controller_unittest.cc
+++ b/ash/system/update/update_notification_controller_unittest.cc
@@ -85,7 +85,7 @@ TEST_F(UpdateNotificationControllerTest, VisibilityAfterUpdate) {
// Simulate an update.
Shell::Get()->system_tray_model()->ShowUpdateIcon(
- mojom::UpdateSeverity::LOW, false, mojom::UpdateType::SYSTEM);
+ mojom::UpdateSeverity::LOW, false, false, mojom::UpdateType::SYSTEM);
// The notification is now visible.
ASSERT_TRUE(HasNotification());
@@ -103,7 +103,7 @@ TEST_F(UpdateNotificationControllerTest, VisibilityAfterFlashUpdate) {
// Simulate an update.
Shell::Get()->system_tray_model()->ShowUpdateIcon(
- mojom::UpdateSeverity::LOW, false, mojom::UpdateType::FLASH);
+ mojom::UpdateSeverity::LOW, false, false, mojom::UpdateType::FLASH);
// The notification is now visible.
ASSERT_TRUE(HasNotification());
@@ -150,7 +150,7 @@ TEST_F(UpdateNotificationControllerTest,
// Simulate an update that requires factory reset.
Shell::Get()->system_tray_model()->ShowUpdateIcon(
- mojom::UpdateSeverity::LOW, true, mojom::UpdateType::SYSTEM);
+ mojom::UpdateSeverity::LOW, true, false, mojom::UpdateType::SYSTEM);
// The notification is now visible.
ASSERT_TRUE(HasNotification());
@@ -162,4 +162,23 @@ TEST_F(UpdateNotificationControllerTest,
EXPECT_EQ("Restart to update", GetNotificationButton(0));
}
+TEST_F(UpdateNotificationControllerTest, VisibilityAfterRollback) {
+ // The system starts with no update pending, so the notification isn't
+ // visible.
+ EXPECT_FALSE(HasNotification());
+
+ // Simulate a rollback.
+ Shell::Get()->system_tray_model()->ShowUpdateIcon(
+ mojom::UpdateSeverity::LOW, false, true, mojom::UpdateType::SYSTEM);
+
+ // The notification is now visible.
+ ASSERT_TRUE(HasNotification());
+ EXPECT_EQ("Device will be rolled back", GetNotificationTitle());
+ EXPECT_EQ(
+ "Your administrator is rolling back your device. All data will"
+ " be deleted when the device is restarted.",
+ GetNotificationMessage());
+ EXPECT_EQ("Restart and reset", GetNotificationButton(0));
+}
+
} // namespace ash
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index 7d0ad7767161c2..2bc240e543fb82 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -59,8 +59,8 @@
Restart
-
- Relaunch and Powerwash
+
+ Restart and reset
Powerwash for added security
@@ -83,6 +83,12 @@
Channel changed. Restart your device to apply changes.
+
+ Your administrator is rolling back this device ($190%)
+
+
+ Your administrator rolled back this device. Please save important files, then restart. All data on the device will be deleted.
+
Your $1Chromebook is up to date
diff --git a/chrome/browser/chromeos/upgrade_detector_chromeos.cc b/chrome/browser/chromeos/upgrade_detector_chromeos.cc
index fc1a76f162aca8..efd87ae784684e 100644
--- a/chrome/browser/chromeos/upgrade_detector_chromeos.cc
+++ b/chrome/browser/chromeos/upgrade_detector_chromeos.cc
@@ -146,7 +146,7 @@ void UpgradeDetectorChromeos::UpdateStatusChanged(
set_upgrade_detected_time(tick_clock()->NowTicks());
if (status.is_rollback) {
- set_is_factory_reset_required(true);
+ set_is_rollback(true);
NotifyOnUpgrade();
} else {
// Determine whether powerwash is required based on the channel.
diff --git a/chrome/browser/resources/settings/about_page/about_page.js b/chrome/browser/resources/settings/about_page/about_page.js
index 1ddbddc6f6084f..9fcdad3314a4e5 100644
--- a/chrome/browser/resources/settings/about_page/about_page.js
+++ b/chrome/browser/resources/settings/about_page/about_page.js
@@ -16,7 +16,12 @@ Polymer({
/** @private {?UpdateStatusChangedEvent} */
currentUpdateStatusEvent_: {
type: Object,
- value: {message: '', progress: 0, status: UpdateStatus.DISABLED},
+ value: {
+ message: '',
+ progress: 0,
+ rollback: false,
+ status: UpdateStatus.DISABLED
+ },
},
//
@@ -298,8 +303,8 @@ Polymer({
this.showRelaunch_ = this.checkStatus_(UpdateStatus.NEARLY_UPDATED);
//
//
- this.showRelaunch_ = this.checkStatus_(UpdateStatus.NEARLY_UPDATED) &&
- !this.isTargetChannelMoreStable_();
+ this.showRelaunch_ =
+ this.checkStatus_(UpdateStatus.NEARLY_UPDATED) && !this.isRollback_();
//
},
@@ -324,6 +329,8 @@ Polymer({
//
if (this.currentChannel_ != this.targetChannel_)
return this.i18nAdvanced('aboutUpgradeSuccessChannelSwitch');
+ if (this.currentUpdateStatusEvent_.rollback)
+ return this.i18nAdvanced('aboutRollbackSuccess');
//
return this.i18nAdvanced('aboutUpgradeRelaunch');
case UpdateStatus.UPDATED:
@@ -342,6 +349,11 @@ Polymer({
]
});
}
+ if (this.currentUpdateStatusEvent_.rollback) {
+ return this.i18nAdvanced('aboutRollbackInProgress', {
+ substitutions: [progressPercent],
+ });
+ }
//
if (this.currentUpdateStatusEvent_.progress > 0) {
// NOTE(dbeam): some platforms (i.e. Mac) always send 0% while
@@ -442,9 +454,13 @@ Polymer({
* @return {boolean}
* @private
*/
- isTargetChannelMoreStable_: function() {
+ isRollback_: function() {
assert(this.currentChannel_.length > 0);
assert(this.targetChannel_.length > 0);
+ if (this.currentUpdateStatusEvent_.rollback) {
+ return true;
+ }
+ // Channel switch to a more stable channel is also a rollback
return settings.isTargetChannelMoreStable(
this.currentChannel_, this.targetChannel_);
},
@@ -464,8 +480,7 @@ Polymer({
* @private
*/
computeShowRelaunchAndPowerwash_: function() {
- return this.checkStatus_(UpdateStatus.NEARLY_UPDATED) &&
- this.isTargetChannelMoreStable_();
+ return this.checkStatus_(UpdateStatus.NEARLY_UPDATED) && this.isRollback_();
},
/** @private */
diff --git a/chrome/browser/ui/ash/system_tray_client.cc b/chrome/browser/ui/ash/system_tray_client.cc
index a89af16d816988..9327ba76717d92 100644
--- a/chrome/browser/ui/ash/system_tray_client.cc
+++ b/chrome/browser/ui/ash/system_tray_client.cc
@@ -453,7 +453,7 @@ void SystemTrayClient::HandleUpdateAvailable() {
: ash::mojom::UpdateType::FLASH;
system_tray_->ShowUpdateIcon(severity, detector->is_factory_reset_required(),
- update_type);
+ detector->is_rollback(), update_type);
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/ui/webui/help/version_updater.h b/chrome/browser/ui/webui/help/version_updater.h
index 2bfc0d51f94ee5..ad34cb0c53f614 100644
--- a/chrome/browser/ui/webui/help/version_updater.h
+++ b/chrome/browser/ui/webui/help/version_updater.h
@@ -52,15 +52,22 @@ class VersionUpdater {
EolStatusCallback;
#endif
- // Used to update the client of status changes. int parameter is the progress
- // and should only be non-zero for the UPDATING state.
- // std::string parameter is the version of the available update and should be
- // empty string when update is not available.
- // int64_t parameter is the size in bytes of the available update and should
- // be 0 when update is not available.
- // base::string16 parameter is a message explaining a failure.
- typedef base::Callback<
- void(Status, int, const std::string&, int64_t, const base::string16&)>
+ // Used to update the client of status changes.
+ // |status| is the current state of the update.
+ // |progress| should only be non-zero for the UPDATING state.
+ // |rollback| indicates whether the update is actually a rollback, which
+ // requires wiping the device upon reboot.
+ // |version| is the version of the available update and should be empty string
+ // when update is not available.
+ // |update_size| is the size of the available update in bytes and should be 0
+ // when update is not available.
+ // |message| is a message explaining a failure.
+ typedef base::Callback
StatusCallback;
// Used to show or hide the promote UI elements. Mac-only.
diff --git a/chrome/browser/ui/webui/help/version_updater_basic.cc b/chrome/browser/ui/webui/help/version_updater_basic.cc
index 8cb85a35079989..796d0a5a9f4a26 100644
--- a/chrome/browser/ui/webui/help/version_updater_basic.cc
+++ b/chrome/browser/ui/webui/help/version_updater_basic.cc
@@ -11,9 +11,10 @@ void VersionUpdaterBasic::CheckForUpdate(
const StatusCallback& status_callback,
const PromoteCallback&) {
if (UpgradeDetector::GetInstance()->notify_upgrade())
- status_callback.Run(NEARLY_UPDATED, 0, std::string(), 0, base::string16());
+ status_callback.Run(NEARLY_UPDATED, 0, false, std::string(), 0,
+ base::string16());
else
- status_callback.Run(DISABLED, 0, std::string(), 0, base::string16());
+ status_callback.Run(DISABLED, 0, false, std::string(), 0, base::string16());
}
VersionUpdater* VersionUpdater::Create(content::WebContents* web_contents) {
diff --git a/chrome/browser/ui/webui/help/version_updater_chromeos.cc b/chrome/browser/ui/webui/help/version_updater_chromeos.cc
index 815a49eb16d2e5..66060e64fa7a92 100644
--- a/chrome/browser/ui/webui/help/version_updater_chromeos.cc
+++ b/chrome/browser/ui/webui/help/version_updater_chromeos.cc
@@ -106,7 +106,7 @@ base::string16 GetConnectionTypeAsUTF16(const chromeos::NetworkState* network) {
bool EnsureCanUpdate(bool interactive,
const VersionUpdater::StatusCallback& callback) {
if (IsAutoUpdateDisabled()) {
- callback.Run(VersionUpdater::DISABLED_BY_ADMIN, 0, std::string(), 0,
+ callback.Run(VersionUpdater::DISABLED_BY_ADMIN, 0, false, std::string(), 0,
l10n_util::GetStringUTF16(IDS_UPGRADE_DISABLED_BY_POLICY));
return false;
}
@@ -120,13 +120,13 @@ bool EnsureCanUpdate(bool interactive,
// to a network for which updates are disallowed.
NetworkStatus status = GetNetworkStatus(interactive, network);
if (status == NETWORK_STATUS_OFFLINE) {
- callback.Run(VersionUpdater::FAILED_OFFLINE, 0, std::string(), 0,
+ callback.Run(VersionUpdater::FAILED_OFFLINE, 0, false, std::string(), 0,
l10n_util::GetStringUTF16(IDS_UPGRADE_OFFLINE));
return false;
} else if (status == NETWORK_STATUS_DISALLOWED) {
base::string16 message = l10n_util::GetStringFUTF16(
IDS_UPGRADE_DISALLOWED, GetConnectionTypeAsUTF16(network));
- callback.Run(VersionUpdater::FAILED_CONNECTION_TYPE_DISALLOWED, 0,
+ callback.Run(VersionUpdater::FAILED_CONNECTION_TYPE_DISALLOWED, 0, false,
std::string(), 0, message);
return false;
}
@@ -221,7 +221,7 @@ void VersionUpdaterCros::OnSetUpdateOverCellularOneTimePermission(
// TODO(weidongg/691108): invoke callback to signal about page to show
// appropriate error message.
LOG(ERROR) << "Error setting update over cellular one time permission.";
- callback_.Run(VersionUpdater::FAILED, 0, std::string(), 0,
+ callback_.Run(VersionUpdater::FAILED, 0, false, std::string(), 0,
base::string16());
}
}
@@ -325,7 +325,8 @@ void VersionUpdaterCros::UpdateStatusChanged(
break;
}
- callback_.Run(my_status, progress, version, size, message);
+ callback_.Run(my_status, progress, status.is_rollback, version, size,
+ message);
last_operation_ = status.status;
if (check_for_update_when_idle_ &&
@@ -339,5 +340,5 @@ void VersionUpdaterCros::OnUpdateCheck(
// If version updating is not implemented, this binary is the most up-to-date
// possible with respect to automatic updating.
if (result == UpdateEngineClient::UPDATE_RESULT_NOTIMPLEMENTED)
- callback_.Run(UPDATED, 0, std::string(), 0, base::string16());
+ callback_.Run(UPDATED, 0, false, std::string(), 0, base::string16());
}
diff --git a/chrome/browser/ui/webui/help/version_updater_chromeos_unittest.cc b/chrome/browser/ui/webui/help/version_updater_chromeos_unittest.cc
index 2e47406c229865..587ec32394c1f1 100644
--- a/chrome/browser/ui/webui/help/version_updater_chromeos_unittest.cc
+++ b/chrome/browser/ui/webui/help/version_updater_chromeos_unittest.cc
@@ -33,6 +33,7 @@ namespace {
void CheckNotification(VersionUpdater::Status /* status */,
int /* progress */,
+ bool /* rollback */,
const std::string& /* version */,
int64_t /* size */,
const base::string16& /* message */) {}
diff --git a/chrome/browser/ui/webui/help/version_updater_mac.mm b/chrome/browser/ui/webui/help/version_updater_mac.mm
index 243d56245425d8..e339760732f7d3 100644
--- a/chrome/browser/ui/webui/help/version_updater_mac.mm
+++ b/chrome/browser/ui/webui/help/version_updater_mac.mm
@@ -108,7 +108,8 @@ - (void)handleStatusNotification:(NSNotification*)notification {
} else {
// There is no glue, or the application is on a read-only filesystem.
// Updates and promotions are impossible.
- status_callback_.Run(DISABLED, 0, std::string(), 0, base::string16());
+ status_callback_.Run(DISABLED, 0, false, std::string(), 0,
+ base::string16());
}
}
@@ -235,7 +236,7 @@ - (void)handleStatusNotification:(NSNotification*)notification {
}
if (!status_callback_.is_null())
- status_callback_.Run(status, 0, std::string(), 0, message);
+ status_callback_.Run(status, 0, false, std::string(), 0, message);
PromotionState promotion_state;
if (!promote_callback_.is_null()) {
diff --git a/chrome/browser/ui/webui/help/version_updater_win.cc b/chrome/browser/ui/webui/help/version_updater_win.cc
index 861526eea8a14e..a09e57511764f0 100644
--- a/chrome/browser/ui/webui/help/version_updater_win.cc
+++ b/chrome/browser/ui/webui/help/version_updater_win.cc
@@ -29,7 +29,7 @@ void VersionUpdaterWin::CheckForUpdate(const StatusCallback& callback,
// There is no supported integration with Google Update for Chromium.
callback_ = callback;
- callback_.Run(CHECKING, 0, std::string(), 0, base::string16());
+ callback_.Run(CHECKING, 0, false, std::string(), 0, base::string16());
DoBeginUpdateCheck(false /* !install_update_if_possible */);
}
@@ -50,18 +50,18 @@ void VersionUpdaterWin::OnUpdateCheckComplete(
// Notify the caller that the update is now beginning and initiate it.
DoBeginUpdateCheck(true /* install_update_if_possible */);
- callback_.Run(UPDATING, 0, std::string(), 0, base::string16());
+ callback_.Run(UPDATING, 0, false, std::string(), 0, base::string16());
}
void VersionUpdaterWin::OnUpgradeProgress(int progress,
const base::string16& new_version) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- callback_.Run(UPDATING, progress, std::string(), 0, base::string16());
+ callback_.Run(UPDATING, progress, false, std::string(), 0, base::string16());
}
void VersionUpdaterWin::OnUpgradeComplete(const base::string16& new_version) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- callback_.Run(NEARLY_UPDATED, 0, std::string(), 0, base::string16());
+ callback_.Run(NEARLY_UPDATED, 0, false, std::string(), 0, base::string16());
}
void VersionUpdaterWin::OnError(GoogleUpdateErrorCode error_code,
@@ -92,7 +92,7 @@ void VersionUpdaterWin::OnError(GoogleUpdateErrorCode error_code,
}
break;
}
- callback_.Run(status, 0, std::string(), 0, message);
+ callback_.Run(status, 0, false, std::string(), 0, message);
}
void VersionUpdaterWin::DoBeginUpdateCheck(bool install_update_if_possible) {
@@ -104,7 +104,7 @@ void VersionUpdaterWin::DoBeginUpdateCheck(bool install_update_if_possible) {
}
void VersionUpdaterWin::OnPendingRestartCheck(bool is_update_pending_restart) {
- callback_.Run(is_update_pending_restart ? NEARLY_UPDATED : UPDATED, 0,
+ callback_.Run(is_update_pending_restart ? NEARLY_UPDATED : UPDATED, 0, false,
std::string(), 0, base::string16());
}
diff --git a/chrome/browser/ui/webui/settings/about_handler.cc b/chrome/browser/ui/webui/settings/about_handler.cc
index e72196562df1bc..6683c9e776744e 100644
--- a/chrome/browser/ui/webui/settings/about_handler.cc
+++ b/chrome/browser/ui/webui/settings/about_handler.cc
@@ -647,6 +647,7 @@ void AboutHandler::RequestUpdate() {
void AboutHandler::SetUpdateStatus(VersionUpdater::Status status,
int progress,
+ bool rollback,
const std::string& version,
int64_t size,
const base::string16& message) {
@@ -657,6 +658,7 @@ void AboutHandler::SetUpdateStatus(VersionUpdater::Status status,
event->SetString("status", UpdateStatusToString(status));
event->SetString("message", message);
event->SetInteger("progress", progress);
+ event->SetBoolean("rollback", rollback);
event->SetString("version", version);
// DictionaryValue does not support int64_t, so convert to string.
event->SetString("size", base::Int64ToString(size));
diff --git a/chrome/browser/ui/webui/settings/about_handler.h b/chrome/browser/ui/webui/settings/about_handler.h
index 4363cda035708a..4c8ae08a2928dd 100644
--- a/chrome/browser/ui/webui/settings/about_handler.h
+++ b/chrome/browser/ui/webui/settings/about_handler.h
@@ -127,6 +127,7 @@ class AboutHandler : public settings::SettingsPageUIHandler,
// Callback method which forwards status updates to the page.
void SetUpdateStatus(VersionUpdater::Status status,
int progress,
+ bool rollback,
const std::string& version,
int64_t size,
const base::string16& fail_message);
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
index 59189009c128db..745ab481524fda 100644
--- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -335,6 +335,8 @@ void AddAboutStrings(content::WebUIDataSource* html_source) {
{"aboutPlatformLabel", IDS_SETTINGS_ABOUT_PAGE_PLATFORM},
{"aboutRelaunchAndPowerwash",
IDS_SETTINGS_ABOUT_PAGE_RELAUNCH_AND_POWERWASH},
+ {"aboutRollbackInProgress", IDS_SETTINGS_UPGRADE_ROLLBACK_IN_PROGRESS},
+ {"aboutRollbackSuccess", IDS_SETTINGS_UPGRADE_ROLLBACK_SUCCESS},
{"aboutUpgradeUpdatingChannelSwitch",
IDS_SETTINGS_UPGRADE_UPDATING_CHANNEL_SWITCH},
{"aboutUpgradeSuccessChannelSwitch",
diff --git a/chrome/browser/upgrade_detector.h b/chrome/browser/upgrade_detector.h
index 140d3999701066..084b331828485a 100644
--- a/chrome/browser/upgrade_detector.h
+++ b/chrome/browser/upgrade_detector.h
@@ -93,6 +93,10 @@ class UpgradeDetector {
bool is_factory_reset_required() const { return is_factory_reset_required_; }
+#if defined(OS_CHROMEOS)
+ bool is_rollback() const { return is_rollback_; }
+#endif // defined(OS_CHROMEOS)
+
// Retrieves the right icon based on the degree of severity (see
// UpgradeNotificationAnnoyanceLevel, each level has an an accompanying icon
// to go with it) to display within the app menu.
@@ -202,6 +206,10 @@ class UpgradeDetector {
is_factory_reset_required_ = is_factory_reset_required;
}
+#if defined(OS_CHROMEOS)
+ void set_is_rollback(bool is_rollback) { is_rollback_ = is_rollback; }
+#endif // defined(OS_CHROMEOS)
+
private:
FRIEND_TEST_ALL_PREFIXES(AppMenuModelTest, Basics);
FRIEND_TEST_ALL_PREFIXES(SystemTrayClientTest, UpdateTrayIcon);
@@ -245,6 +253,13 @@ class UpgradeDetector {
// Whether a factory reset is needed to complete an update.
bool is_factory_reset_required_;
+#if defined(OS_CHROMEOS)
+ // Whether the update is actually an admin-initiated rollback of the device
+ // to an earlier version of Chrome OS, which results in the device being
+ // wiped when it's rebooted.
+ bool is_rollback_ = false;
+#endif // defined(OS_CHROMEOS)
+
// A timer to check to see if we've been idle for long enough to show the
// critical warning. Should only be set if |upgrade_available_| is
// UPGRADE_AVAILABLE_CRITICAL.