[New Deal] Show deferred update notification
Send a notification on the system tray when there is a deferred update. Update button click on the notification will apply the deferred update. Automatic updates button will take users to the settings page with automatic update toggle. BUG=1293120 TEST=ash_unittests --gtest_filter=UpdateNotificationControllerTest* Change-Id: Idd8cf6d2a9a3441ff627ccfec180105dde8d4bae Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3766223 Commit-Queue: Yuanpeng Ni <yuanpengni@chromium.org> Reviewed-by: Xiaohui Chen <xiaohuic@chromium.org> Reviewed-by: Xiyuan Xia <xiyuan@chromium.org> Cr-Commit-Position: refs/heads/main@{#1027979}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
30a149d9f9
commit
20f85f6f3d
ash
BUILD.gnash_strings.grd
ash_strings_grd
IDS_UPDATE_NOTIFICATION_APPLY_UPDATE_BUTTON.png.sha1IDS_UPDATE_NOTIFICATION_AUTOMATIC_UPDATE_BUTTON.png.sha1IDS_UPDATE_NOTIFICATION_MESSAGE_DEFERRED_UPDATE.png.sha1
public
system
chrome/browser
ui
upgrade_detector
chromeos/ash/components/dbus/update_engine
@ -2261,6 +2261,7 @@ component("ash") {
|
||||
"//chromeos/ash/components/dbus/rmad:rmad_proto",
|
||||
"//chromeos/ash/components/dbus/services",
|
||||
"//chromeos/ash/components/dbus/system_clock",
|
||||
"//chromeos/ash/components/dbus/update_engine",
|
||||
"//chromeos/ash/components/dbus/usb",
|
||||
"//chromeos/ash/components/feature_usage",
|
||||
"//chromeos/ash/components/human_presence",
|
||||
|
@ -773,9 +773,18 @@ This file contains the strings for ash.
|
||||
<message name="IDS_UPDATE_NOTIFICATION_RESTART_BUTTON" meaning="button label" desc="The label used as the button to restart system and update. Displayed as the action button of the notification for system update.">
|
||||
Restart to update
|
||||
</message>
|
||||
<message name="IDS_UPDATE_NOTIFICATION_APPLY_UPDATE_BUTTON" meaning="button label" desc="The label used as the button to apply deferred update. Displayed as the action button of the notification for deferred system update.">
|
||||
Update
|
||||
</message>
|
||||
<message name="IDS_UPDATE_NOTIFICATION_AUTOMATIC_UPDATE_BUTTON" meaning="button label" desc="The label used as the button to take users to the settings page with the automatic update toggle. Displayed as the action button of the notification for deferred system update.">
|
||||
Automatic updates
|
||||
</message>
|
||||
<message name="IDS_ROLLBACK_NOTIFICATION_RESTART_BUTTON" meaning="button label" desc="The label used as the button to restart system to rollback. Displayed as the action button of the notification for system rollback.">
|
||||
Reset
|
||||
</message>
|
||||
<message name="IDS_UPDATE_NOTIFICATION_MESSAGE_DEFERRED_UPDATE" desc="The notification message used in the system notification update when update is downloaded but deferred.">
|
||||
Get the latest features and security improvements. Updates happen in the background.
|
||||
</message>
|
||||
<message name="IDS_UPDATE_NOTIFICATION_MESSAGE_POWERWASH" desc="The notification message used in the system notification update when user need to powerwash the device in order to update the system.">
|
||||
This update requires powerwashing your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>. All data will be deleted. Learn more about the latest <ph name="SYSTEM_APP_NAME">$2<ex>ChromiumOS</ex></ph> update.
|
||||
</message>
|
||||
|
@ -0,0 +1 @@
|
||||
066986453af2cd1dee319ee0128a03aa1faec13c
|
@ -0,0 +1 @@
|
||||
066986453af2cd1dee319ee0128a03aa1faec13c
|
@ -0,0 +1 @@
|
||||
066986453af2cd1dee319ee0128a03aa1faec13c
|
@ -94,6 +94,10 @@ class ASH_PUBLIC_EXPORT SystemTray {
|
||||
// when a new update starts before the current update is applied.
|
||||
virtual void ResetUpdateState() = 0;
|
||||
|
||||
// Shows an icon in the system tray which indicates that a update is
|
||||
// downloaded but deferred.
|
||||
virtual void SetUpdateDeferred(bool deferred) = 0;
|
||||
|
||||
// If |visible| is true, shows an icon in the system tray which indicates that
|
||||
// a software update is available but user's agreement is required as current
|
||||
// connection is cellular. If |visible| is false, hides the icon because the
|
||||
|
@ -80,6 +80,9 @@ class ASH_PUBLIC_EXPORT SystemTrayClient {
|
||||
// loaded.
|
||||
virtual void ShowAboutChromeOS() = 0;
|
||||
|
||||
// Shows the about chrome OS additional details page.
|
||||
virtual void ShowAboutChromeOSDetails() = 0;
|
||||
|
||||
// Shows accessibility help.
|
||||
virtual void ShowAccessibilityHelp() = 0;
|
||||
|
||||
|
@ -54,6 +54,8 @@ void TestSystemTrayClient::ShowWifiSyncSettings() {
|
||||
|
||||
void TestSystemTrayClient::ShowAboutChromeOS() {}
|
||||
|
||||
void TestSystemTrayClient::ShowAboutChromeOSDetails() {}
|
||||
|
||||
void TestSystemTrayClient::ShowAccessibilityHelp() {}
|
||||
|
||||
void TestSystemTrayClient::ShowAccessibilitySettings() {}
|
||||
|
@ -41,6 +41,7 @@ class ASH_PUBLIC_EXPORT TestSystemTrayClient : public SystemTrayClient {
|
||||
void ShowTetherNetworkSettings() override;
|
||||
void ShowWifiSyncSettings() override;
|
||||
void ShowAboutChromeOS() override;
|
||||
void ShowAboutChromeOSDetails() override;
|
||||
void ShowAccessibilityHelp() override;
|
||||
void ShowAccessibilitySettings() override;
|
||||
void ShowGestureEducationHelp() override;
|
||||
|
@ -105,6 +105,10 @@ void SystemTrayModel::ResetUpdateState() {
|
||||
update_model()->ResetUpdateAvailable();
|
||||
}
|
||||
|
||||
void SystemTrayModel::SetUpdateDeferred(bool deferred) {
|
||||
update_model()->SetUpdateDeferred(deferred);
|
||||
}
|
||||
|
||||
void SystemTrayModel::SetUpdateOverCellularAvailableIconVisible(bool visible) {
|
||||
update_model()->SetUpdateOverCellularAvailable(visible);
|
||||
}
|
||||
|
@ -54,6 +54,7 @@ class SystemTrayModel : public SystemTray {
|
||||
void SetRelaunchNotificationState(
|
||||
const RelaunchNotificationState& relaunch_notification_state) override;
|
||||
void ResetUpdateState() override;
|
||||
void SetUpdateDeferred(bool deferred) override;
|
||||
void SetUpdateOverCellularAvailableIconVisible(bool visible) override;
|
||||
void ShowVolumeSliderBubble() override;
|
||||
void ShowNetworkDetailedViewBubble() override;
|
||||
|
@ -22,6 +22,7 @@ void UpdateModel::SetUpdateAvailable(UpdateSeverity severity,
|
||||
bool rollback,
|
||||
UpdateType update_type) {
|
||||
update_required_ = true;
|
||||
update_deferred_ = false;
|
||||
severity_ = severity;
|
||||
factory_reset_required_ = factory_reset_required;
|
||||
rollback_ = rollback;
|
||||
@ -41,6 +42,11 @@ void UpdateModel::SetUpdateOverCellularAvailable(bool available) {
|
||||
NotifyUpdateAvailable();
|
||||
}
|
||||
|
||||
void UpdateModel::SetUpdateDeferred(bool deferred) {
|
||||
update_deferred_ = deferred;
|
||||
NotifyUpdateAvailable();
|
||||
}
|
||||
|
||||
UpdateSeverity UpdateModel::GetSeverity() const {
|
||||
// TODO(https://crbug.com/927010): adjust severity according the amount of
|
||||
// time passing after update is available over cellular connection. Use low
|
||||
@ -50,6 +56,7 @@ UpdateSeverity UpdateModel::GetSeverity() const {
|
||||
|
||||
void UpdateModel::ResetUpdateAvailable() {
|
||||
update_required_ = false;
|
||||
update_deferred_ = false;
|
||||
NotifyUpdateAvailable();
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,9 @@ class UpdateModel {
|
||||
// granted.
|
||||
void SetUpdateOverCellularAvailable(bool available);
|
||||
|
||||
// If `deferred` is true, an update is downloaded but deferred.
|
||||
void SetUpdateDeferred(bool deferred);
|
||||
|
||||
UpdateSeverity GetSeverity() const;
|
||||
|
||||
// Sets |update_required_| back to false.
|
||||
@ -65,6 +68,7 @@ class UpdateModel {
|
||||
bool update_over_cellular_available() const {
|
||||
return update_over_cellular_available_;
|
||||
}
|
||||
bool update_deferred() const { return update_deferred_; }
|
||||
|
||||
private:
|
||||
void NotifyUpdateAvailable();
|
||||
@ -76,6 +80,7 @@ class UpdateModel {
|
||||
UpdateType update_type_ = UpdateType::kSystem;
|
||||
RelaunchNotificationState relaunch_notification_state_;
|
||||
bool update_over_cellular_available_ = false;
|
||||
bool update_deferred_ = false;
|
||||
|
||||
base::ObserverList<UpdateObserver>::Unchecked observers_;
|
||||
};
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "base/metrics/user_metrics.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/task/thread_pool.h"
|
||||
#include "chromeos/ash/components/dbus/update_engine/update_engine_client.h"
|
||||
#include "components/vector_icons/vector_icons.h"
|
||||
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
@ -105,7 +106,14 @@ void UpdateNotificationController::GenerateUpdateNotification(
|
||||
RelaunchNotificationState::kRequired)
|
||||
notification->SetSystemPriority();
|
||||
|
||||
if (model_->update_required()) {
|
||||
if (model_->update_deferred()) {
|
||||
notification->set_buttons({
|
||||
message_center::ButtonInfo(l10n_util::GetStringUTF16(
|
||||
IDS_UPDATE_NOTIFICATION_APPLY_UPDATE_BUTTON)),
|
||||
message_center::ButtonInfo(l10n_util::GetStringUTF16(
|
||||
IDS_UPDATE_NOTIFICATION_AUTOMATIC_UPDATE_BUTTON)),
|
||||
});
|
||||
} else if (model_->update_required()) {
|
||||
std::vector<message_center::ButtonInfo> notification_actions;
|
||||
if (model_->rollback()) {
|
||||
notification_actions.push_back(message_center::ButtonInfo(
|
||||
@ -132,7 +140,8 @@ void UpdateNotificationController::OnUpdateAvailable() {
|
||||
}
|
||||
|
||||
bool UpdateNotificationController::ShouldShowUpdate() const {
|
||||
return model_->update_required() || model_->update_over_cellular_available();
|
||||
return model_->update_required() ||
|
||||
model_->update_over_cellular_available() || model_->update_deferred();
|
||||
}
|
||||
|
||||
std::u16string UpdateNotificationController::GetTitle() const {
|
||||
@ -189,6 +198,11 @@ std::u16string UpdateNotificationController::GetMessage() const {
|
||||
if (model_->update_type() == UpdateType::kLacros)
|
||||
return l10n_util::GetStringUTF16(IDS_UPDATE_NOTIFICATION_MESSAGE_LACROS);
|
||||
|
||||
if (model_->update_deferred()) {
|
||||
return l10n_util::GetStringUTF16(
|
||||
IDS_UPDATE_NOTIFICATION_MESSAGE_DEFERRED_UPDATE);
|
||||
}
|
||||
|
||||
const std::u16string system_app_name =
|
||||
l10n_util::GetStringUTF16(IDS_ASH_MESSAGE_CENTER_SYSTEM_APP_NAME);
|
||||
if (model_->factory_reset_required() && !model_->rollback()) {
|
||||
@ -295,30 +309,38 @@ void UpdateNotificationController::HandleNotificationClick(
|
||||
return;
|
||||
}
|
||||
|
||||
// Restart
|
||||
DCHECK(button_index.value() == 0);
|
||||
message_center::MessageCenter::Get()->RemoveNotification(kNotificationId,
|
||||
false /* by_user */);
|
||||
if (button_index.value() == 0) {
|
||||
message_center::MessageCenter::Get()->RemoveNotification(
|
||||
kNotificationId, false /* by_user */);
|
||||
|
||||
if (model_->update_required()) {
|
||||
if (slow_boot_file_path_exists_) {
|
||||
// An active dialog exists already.
|
||||
if (confirmation_dialog_)
|
||||
return;
|
||||
if (model_->update_deferred()) {
|
||||
// When the "update" button is clicked, apply the deferred update.
|
||||
ash::UpdateEngineClient::Get()->ApplyDeferredUpdate(base::DoNothing());
|
||||
} else if (model_->update_required()) {
|
||||
// Restart
|
||||
if (slow_boot_file_path_exists_) {
|
||||
// An active dialog exists already.
|
||||
if (confirmation_dialog_)
|
||||
return;
|
||||
|
||||
confirmation_dialog_ = new ShutdownConfirmationDialog(
|
||||
IDS_DIALOG_TITLE_SLOW_BOOT, IDS_DIALOG_MESSAGE_SLOW_BOOT,
|
||||
base::BindOnce(&UpdateNotificationController::RestartForUpdate,
|
||||
weak_ptr_factory_.GetWeakPtr()),
|
||||
base::BindOnce(&UpdateNotificationController::RestartCancelled,
|
||||
weak_ptr_factory_.GetWeakPtr()));
|
||||
confirmation_dialog_ = new ShutdownConfirmationDialog(
|
||||
IDS_DIALOG_TITLE_SLOW_BOOT, IDS_DIALOG_MESSAGE_SLOW_BOOT,
|
||||
base::BindOnce(&UpdateNotificationController::RestartForUpdate,
|
||||
weak_ptr_factory_.GetWeakPtr()),
|
||||
base::BindOnce(&UpdateNotificationController::RestartCancelled,
|
||||
weak_ptr_factory_.GetWeakPtr()));
|
||||
} else {
|
||||
RestartForUpdate();
|
||||
}
|
||||
} else {
|
||||
RestartForUpdate();
|
||||
// Shows the about chrome OS page and checks for update after the page is
|
||||
// loaded.
|
||||
Shell::Get()->system_tray_model()->client()->ShowAboutChromeOS();
|
||||
}
|
||||
} else {
|
||||
// Shows the about chrome OS page and checks for update after the page is
|
||||
// loaded.
|
||||
Shell::Get()->system_tray_model()->client()->ShowAboutChromeOS();
|
||||
// When the "automatic update" button is clicked, take user to the ChromeOS
|
||||
// additional details page that has the automatic update toggle.
|
||||
Shell::Get()->system_tray_model()->client()->ShowAboutChromeOSDetails();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -685,4 +685,26 @@ TEST_F(UpdateNotificationControllerTest, VisibilityAfterLacrosUpdate) {
|
||||
EXPECT_EQ(1, GetSessionControllerClient()->attempt_restart_chrome_count());
|
||||
}
|
||||
|
||||
TEST_F(UpdateNotificationControllerTest, VisibilityAfterDeferredUpdate) {
|
||||
// Simulate a deferred update.
|
||||
Shell::Get()->system_tray_model()->SetUpdateDeferred(true);
|
||||
|
||||
// Wait until everything is complete and then check if the notification is
|
||||
// visible.
|
||||
task_environment()->RunUntilIdle();
|
||||
|
||||
// The notification is now visible.
|
||||
ASSERT_TRUE(HasNotification());
|
||||
EXPECT_EQ(kSystemNotificationColorNormal, *GetNotificationColor());
|
||||
EXPECT_TRUE(strcmp(kSystemMenuUpdateIcon.name, GetNotificationIcon().name) ==
|
||||
0);
|
||||
EXPECT_EQ("Update available", GetNotificationTitle());
|
||||
EXPECT_EQ(
|
||||
"Get the latest features and security improvements. Updates happen in "
|
||||
"the background.",
|
||||
GetNotificationMessage());
|
||||
EXPECT_EQ("Update", GetNotificationButton(0));
|
||||
EXPECT_EQ("Automatic updates", GetNotificationButton(1));
|
||||
}
|
||||
|
||||
} // namespace ash
|
||||
|
@ -491,6 +491,11 @@ void SystemTrayClientImpl::ShowAboutChromeOS() {
|
||||
"?checkForUpdate=true");
|
||||
}
|
||||
|
||||
void SystemTrayClientImpl::ShowAboutChromeOSDetails() {
|
||||
ShowSettingsSubPageForActiveUser(
|
||||
chromeos::settings::mojom::kDetailedBuildInfoSubpagePath);
|
||||
}
|
||||
|
||||
void SystemTrayClientImpl::ShowAccessibilityHelp() {
|
||||
ash::AccessibilityManager::ShowAccessibilityHelp();
|
||||
}
|
||||
@ -806,6 +811,10 @@ void SystemTrayClientImpl::OnSystemClockChanged(
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// UpgradeDetector::UpgradeObserver:
|
||||
void SystemTrayClientImpl::OnUpdateDeferred() {
|
||||
system_tray_->SetUpdateDeferred(true);
|
||||
}
|
||||
|
||||
void SystemTrayClientImpl::OnUpdateOverCellularAvailable() {
|
||||
// Requests that ash show the update over cellular available icon.
|
||||
system_tray_->SetUpdateOverCellularAvailableIconVisible(true);
|
||||
|
@ -81,6 +81,7 @@ class SystemTrayClientImpl : public ash::SystemTrayClient,
|
||||
void ShowTetherNetworkSettings() override;
|
||||
void ShowWifiSyncSettings() override;
|
||||
void ShowAboutChromeOS() override;
|
||||
void ShowAboutChromeOSDetails() override;
|
||||
void ShowAccessibilityHelp() override;
|
||||
void ShowAccessibilitySettings() override;
|
||||
void ShowGestureEducationHelp() override;
|
||||
@ -126,6 +127,7 @@ class SystemTrayClientImpl : public ash::SystemTrayClient,
|
||||
void OnSystemClockChanged(ash::system::SystemClock* clock) override;
|
||||
|
||||
// UpgradeObserver implementation.
|
||||
void OnUpdateDeferred() override;
|
||||
void OnUpdateOverCellularAvailable() override;
|
||||
void OnUpdateOverCellularOneTimePermissionGranted() override;
|
||||
void OnUpgradeRecommended() override;
|
||||
|
@ -347,6 +347,15 @@ void UpgradeDetector::NotifyCriticalUpgradeInstalled() {
|
||||
observer.OnCriticalUpgradeInstalled();
|
||||
}
|
||||
|
||||
void UpgradeDetector::NotifyUpdateDeferred() {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
if (observer_list_.empty())
|
||||
return;
|
||||
|
||||
for (auto& observer : observer_list_)
|
||||
observer.OnUpdateDeferred();
|
||||
}
|
||||
|
||||
void UpgradeDetector::NotifyUpdateOverCellularAvailable() {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
if (observer_list_.empty())
|
||||
|
@ -254,6 +254,9 @@ class UpgradeDetector {
|
||||
// expected.
|
||||
void NotifyCriticalUpgradeInstalled();
|
||||
|
||||
// Notifies that an update is downloaded but deferred.
|
||||
void NotifyUpdateDeferred();
|
||||
|
||||
// The function that sends out a notification that lets the rest of the UI
|
||||
// know we should notify the user that a new update is available to download
|
||||
// over cellular connection.
|
||||
|
@ -208,6 +208,11 @@ void UpgradeDetectorChromeos::UpdateStatusChanged(
|
||||
// Update engine broadcasts this state only when update is available but
|
||||
// downloading over cellular connection requires user's agreement.
|
||||
NotifyUpdateOverCellularAvailable();
|
||||
} else if (status.current_operation() ==
|
||||
update_engine::Operation::UPDATED_BUT_DEFERRED) {
|
||||
// Update engine broadcasts this state when update is downloaded but
|
||||
// deferred.
|
||||
NotifyUpdateDeferred();
|
||||
} else if (!update_in_progress_ &&
|
||||
status.current_operation() ==
|
||||
update_engine::Operation::DOWNLOADING) {
|
||||
|
@ -7,6 +7,9 @@
|
||||
|
||||
class UpgradeObserver {
|
||||
public:
|
||||
// Triggered when a software update is downloaded but deferred.
|
||||
virtual void OnUpdateDeferred() {}
|
||||
|
||||
// Triggered when a software update is available, but downloading requires
|
||||
// user's agreement as current connection is cellular.
|
||||
virtual void OnUpdateOverCellularAvailable() {}
|
||||
|
@ -121,6 +121,9 @@ void FakeUpdateEngineClient::IsFeatureEnabled(
|
||||
: absl::nullopt);
|
||||
}
|
||||
|
||||
void FakeUpdateEngineClient::ApplyDeferredUpdate(
|
||||
base::OnceClosure failure_callback) {}
|
||||
|
||||
void FakeUpdateEngineClient::set_default_status(
|
||||
const update_engine::StatusResult& status) {
|
||||
default_status_ = status;
|
||||
|
@ -57,6 +57,7 @@ class COMPONENT_EXPORT(ASH_DBUS_UPDATE_ENGINE) FakeUpdateEngineClient
|
||||
void ToggleFeature(const std::string& feature, bool enable) override;
|
||||
void IsFeatureEnabled(const std::string& feature,
|
||||
IsFeatureEnabledCallback callback) override;
|
||||
void ApplyDeferredUpdate(base::OnceClosure failure_callback) override;
|
||||
// Pushes update_engine::StatusResult in the queue to test changing status.
|
||||
// GetLastStatus() returns the status set by this method in FIFO order.
|
||||
// See set_default_status().
|
||||
|
@ -264,6 +264,22 @@ class UpdateEngineClientImpl : public UpdateEngineClient {
|
||||
std::move(callback)));
|
||||
}
|
||||
|
||||
void ApplyDeferredUpdate(base::OnceClosure failure_callback) override {
|
||||
dbus::MethodCall method_call(update_engine::kUpdateEngineInterface,
|
||||
update_engine::kApplyDeferredUpdate);
|
||||
dbus::MessageWriter writer(&method_call);
|
||||
|
||||
VLOG(1) << "Requesting UpdateEngine to apply deferred update.";
|
||||
|
||||
// TODO(yuanpengni): Add an option to shutdown after applied deferred
|
||||
// update.
|
||||
update_engine_proxy_->CallMethod(
|
||||
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
|
||||
base::BindOnce(&UpdateEngineClientImpl::OnApplyDeferredUpdate,
|
||||
weak_ptr_factory_.GetWeakPtr(),
|
||||
std::move(failure_callback)));
|
||||
}
|
||||
|
||||
void Init(dbus::Bus* bus) override {
|
||||
update_engine_proxy_ = bus->GetObjectProxy(
|
||||
update_engine::kUpdateEngineServiceName,
|
||||
@ -532,6 +548,18 @@ class UpdateEngineClientImpl : public UpdateEngineClient {
|
||||
std::move(callback).Run(success);
|
||||
}
|
||||
|
||||
// Called when a response for `ApplyDeferredUpdate()` is received.
|
||||
void OnApplyDeferredUpdate(base::OnceClosure failure_callback,
|
||||
dbus::Response* response) {
|
||||
if (!response) {
|
||||
LOG(ERROR) << update_engine::kApplyDeferredUpdate << " call failed.";
|
||||
std::move(failure_callback).Run();
|
||||
return;
|
||||
}
|
||||
|
||||
VLOG(1) << "Update is applied.";
|
||||
}
|
||||
|
||||
// Called when a status update signal is received.
|
||||
void StatusUpdateReceived(dbus::Signal* signal) {
|
||||
VLOG(1) << "Status update signal received: " << signal->ToString();
|
||||
@ -679,6 +707,10 @@ class UpdateEngineClientDesktopFake : public UpdateEngineClient {
|
||||
std::move(callback).Run(absl::nullopt);
|
||||
}
|
||||
|
||||
void ApplyDeferredUpdate(base::OnceClosure failure_callback) override {
|
||||
VLOG(1) << "Applying deferred update.";
|
||||
}
|
||||
|
||||
private:
|
||||
void StateTransition(bool apply_update) {
|
||||
update_engine::Operation next_operation = update_engine::Operation::ERROR;
|
||||
|
@ -189,6 +189,9 @@ class COMPONENT_EXPORT(ASH_DBUS_UPDATE_ENGINE) UpdateEngineClient
|
||||
virtual void IsFeatureEnabled(const std::string& feature,
|
||||
IsFeatureEnabledCallback callback) = 0;
|
||||
|
||||
// Apply a downloaded but deferred update. Runs callback on failure.
|
||||
virtual void ApplyDeferredUpdate(base::OnceClosure failure_callback) = 0;
|
||||
|
||||
protected:
|
||||
// Initialize() should be used instead.
|
||||
UpdateEngineClient();
|
||||
|
Reference in New Issue
Block a user