Commit 28230407 authored by Abhishek Bhardwaj's avatar Abhishek Bhardwaj Committed by Commit Bot

DeviceScheduledUpdateChecker: Perform update check on timer expiration

This change performs an update check when the update checker timer
expires.

BUG=924762
TEST=Unit tests.

Change-Id: Idc4dcfb3a0d9eff6f0a24b6a8f9f2fa4080710cd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1663590
Commit-Queue: Abhishek Bhardwaj <abhishekbh@chromium.org>
Reviewed-by: default avatarPavol Marko <pmarko@chromium.org>
Cr-Commit-Position: refs/heads/master@{#675804}
parent e0e1b344
...@@ -1661,6 +1661,8 @@ source_set("chromeos") { ...@@ -1661,6 +1661,8 @@ source_set("chromeos") {
"policy/off_hours/off_hours_policy_applier.h", "policy/off_hours/off_hours_policy_applier.h",
"policy/off_hours/off_hours_proto_parser.cc", "policy/off_hours/off_hours_proto_parser.cc",
"policy/off_hours/off_hours_proto_parser.h", "policy/off_hours/off_hours_proto_parser.h",
"policy/os_and_policies_update_checker.cc",
"policy/os_and_policies_update_checker.h",
"policy/policy_cert_service.cc", "policy/policy_cert_service.cc",
"policy/policy_cert_service.h", "policy/policy_cert_service.h",
"policy/policy_cert_service_factory.cc", "policy/policy_cert_service_factory.cc",
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/optional.h" #include "base/optional.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "chrome/browser/chromeos/policy/os_and_policies_update_checker.h"
#include "chrome/browser/chromeos/policy/task_executor_with_retries.h" #include "chrome/browser/chromeos/policy/task_executor_with_retries.h"
#include "chrome/browser/chromeos/settings/cros_settings.h" #include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chromeos/dbus/power/native_timer.h" #include "chromeos/dbus/power/native_timer.h"
...@@ -29,12 +30,15 @@ base::Optional<base::Time> IncrementMonthAndSetDayOfMonth( ...@@ -29,12 +30,15 @@ base::Optional<base::Time> IncrementMonthAndSetDayOfMonth(
// The maximum iterations allowed to start an update check timer if the // The maximum iterations allowed to start an update check timer if the
// operation fails. // operation fails.
constexpr int kMaxRetryUpdateCheckIterations = 5; constexpr int kMaxStartUpdateCheckTimerRetryIterations = 5;
// Time to call |StartUpdateCheckTimer| again in case it failed. // Time to call |StartUpdateCheckTimer| again in case it failed.
constexpr base::TimeDelta kStartUpdateCheckTimerRetryTime = constexpr base::TimeDelta kStartUpdateCheckTimerRetryTime =
base::TimeDelta::FromMinutes(5); base::TimeDelta::FromMinutes(5);
// Number of days in a week.
constexpr int kDaysInAWeek = 7;
} // namespace update_checker_internal } // namespace update_checker_internal
// This class listens for changes in the scheduled update check policy and then // This class listens for changes in the scheduled update check policy and then
...@@ -44,18 +48,19 @@ class DeviceScheduledUpdateChecker { ...@@ -44,18 +48,19 @@ class DeviceScheduledUpdateChecker {
explicit DeviceScheduledUpdateChecker(chromeos::CrosSettings* cros_settings); explicit DeviceScheduledUpdateChecker(chromeos::CrosSettings* cros_settings);
virtual ~DeviceScheduledUpdateChecker(); virtual ~DeviceScheduledUpdateChecker();
// Frequency at which the update check should occur.
enum class Frequency {
kDaily,
kWeekly,
kMonthly,
};
// Holds the data associated with the current scheduled update check policy. // Holds the data associated with the current scheduled update check policy.
struct ScheduledUpdateCheckData { struct ScheduledUpdateCheckData {
ScheduledUpdateCheckData(); ScheduledUpdateCheckData();
ScheduledUpdateCheckData(const ScheduledUpdateCheckData&); ScheduledUpdateCheckData(const ScheduledUpdateCheckData&);
~ScheduledUpdateCheckData(); ~ScheduledUpdateCheckData();
enum class Frequency {
kDaily,
kWeekly,
kMonthly,
};
int hour; int hour;
int minute; int minute;
...@@ -78,7 +83,7 @@ class DeviceScheduledUpdateChecker { ...@@ -78,7 +83,7 @@ class DeviceScheduledUpdateChecker {
protected: protected:
// Called when |update_check_timer_| fires. Triggers an update check and // Called when |update_check_timer_| fires. Triggers an update check and
// schedules the next update check based on |scheduled_update_check_data_|. // schedules the next update check based on |scheduled_update_check_data_|.
virtual void UpdateCheck(); virtual void OnUpdateCheckTimerExpired();
// Calculates next update check time based on |scheduled_update_check_data_| // Calculates next update check time based on |scheduled_update_check_data_|
// and |cur_local_time|. Returns |base::nullopt| if calculation failed due to // and |cur_local_time|. Returns |base::nullopt| if calculation failed due to
...@@ -87,6 +92,10 @@ class DeviceScheduledUpdateChecker { ...@@ -87,6 +92,10 @@ class DeviceScheduledUpdateChecker {
virtual base::Optional<base::Time> CalculateNextUpdateCheckTime( virtual base::Optional<base::Time> CalculateNextUpdateCheckTime(
base::Time cur_local_time); base::Time cur_local_time);
// Called when |os_and_policies_update_checker_| has finished successfully or
// unsuccessfully after retrying.
virtual void OnUpdateCheckCompletion(bool result);
private: private:
// Callback triggered when scheduled update check setting has changed. // Callback triggered when scheduled update check setting has changed.
void OnScheduledUpdateCheckDataChanged(); void OnScheduledUpdateCheckDataChanged();
...@@ -107,7 +116,12 @@ class DeviceScheduledUpdateChecker { ...@@ -107,7 +116,12 @@ class DeviceScheduledUpdateChecker {
// been reached. // been reached.
void OnStartUpdateCheckTimerRetryFailure(); void OnStartUpdateCheckTimerRetryFailure();
// Reset all state and cancel all pending tasks. // Starts |start_update_check_timer_task_executor_| to run the next update
// check timer, via |StartUpdateCheckTimer|, only if a policy i.e.
// |scheduled_update_check_data_| is set.
void MaybeStartUpdateCheckTimer();
// Reset all state and cancel all pending tasks
void ResetState(); void ResetState();
// Returns current time. // Returns current time.
...@@ -129,6 +143,9 @@ class DeviceScheduledUpdateChecker { ...@@ -129,6 +143,9 @@ class DeviceScheduledUpdateChecker {
// Used to run and retry |StartUpdateCheckTimer| if it fails. // Used to run and retry |StartUpdateCheckTimer| if it fails.
TaskExecutorWithRetries start_update_check_timer_task_executor_; TaskExecutorWithRetries start_update_check_timer_task_executor_;
// Used to initiate update checks when |update_check_timer_| fires.
OsAndPoliciesUpdateChecker os_and_policies_update_checker_;
// Timer that is scheduled to check for updates. // Timer that is scheduled to check for updates.
std::unique_ptr<chromeos::NativeTimer> update_check_timer_; std::unique_ptr<chromeos::NativeTimer> update_check_timer_;
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chromeos/policy/os_and_policies_update_checker.h"
#include <utility>
#include "chrome/browser/chromeos/policy/task_executor_with_retries.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/update_engine_client.h"
namespace policy {
namespace {
// The tag associated to register |update_check_task_executor_|.
constexpr char kUpdateCheckTaskExecutorTag[] = "UpdateCheckTaskExecutor";
} // namespace
OsAndPoliciesUpdateChecker::OsAndPoliciesUpdateChecker(
TaskExecutorWithRetries::GetTicksSinceBootFn get_ticks_since_boot_fn)
: update_check_task_executor_(
kUpdateCheckTaskExecutorTag,
std::move(get_ticks_since_boot_fn),
update_checker_internal::
kMaxOsAndPoliciesUpdateCheckerRetryIterations,
update_checker_internal::kOsAndPoliciesUpdateCheckerRetryTime) {}
OsAndPoliciesUpdateChecker::~OsAndPoliciesUpdateChecker() = default;
void OsAndPoliciesUpdateChecker::Start(UpdateCheckCompletionCallback cb) {
// Override any previous calls by resetting state.
ResetState();
// Must be set before starting the task runner, as callbacks may be called
// synchronously.
update_check_completion_cb_ = std::move(cb);
// Safe to use "this" as |update_check_task_executor_| is a member of this
// class.
update_check_task_executor_.Start(
base::BindRepeating(&OsAndPoliciesUpdateChecker::StartUpdateCheck,
base::Unretained(this)),
base::BindOnce(&OsAndPoliciesUpdateChecker::OnUpdateCheckFailure,
base::Unretained(this)));
}
void OsAndPoliciesUpdateChecker::Stop() {
ResetState();
}
void OsAndPoliciesUpdateChecker::OnUpdateCheckFailure() {
RunCompletionCallbackAndResetState(false);
}
void OsAndPoliciesUpdateChecker::RunCompletionCallbackAndResetState(
bool result) {
if (update_check_completion_cb_)
std::move(update_check_completion_cb_).Run(result);
ResetState();
}
void OsAndPoliciesUpdateChecker::StartUpdateCheck() {
// Only one update check can be pending at any time.
weak_factory_.InvalidateWeakPtrs();
// This could be a retry, reset observer state as adding observers is not
// idempotent.
chromeos::DBusThreadManager::Get()->GetUpdateEngineClient()->RemoveObserver(
this);
// Register observer to keep track of different stages of the update check.
chromeos::DBusThreadManager::Get()->GetUpdateEngineClient()->AddObserver(
this);
chromeos::DBusThreadManager::Get()
->GetUpdateEngineClient()
->RequestUpdateCheck(
base::BindRepeating(&OsAndPoliciesUpdateChecker::OnUpdateCheckStarted,
weak_factory_.GetWeakPtr()));
// Do nothing for the initial idle stage when the update check state machine
// has just started.
ignore_idle_status_ = true;
}
void OsAndPoliciesUpdateChecker::UpdateStatusChanged(
const chromeos::UpdateEngineClient::Status& status) {
// Only ignore idle state if it is the first and only non-error state in the
// state machine.
if (ignore_idle_status_ &&
status.status > chromeos::UpdateEngineClient::UPDATE_STATUS_IDLE) {
ignore_idle_status_ = false;
}
switch (status.status) {
case chromeos::UpdateEngineClient::UpdateStatusOperation::
UPDATE_STATUS_IDLE:
// Exit update only if update engine was in non-idle status before i.e.
// no update to download. Otherwise, it's possible that the update request
// has not yet been started.
if (!ignore_idle_status_)
RunCompletionCallbackAndResetState(true);
break;
case chromeos::UpdateEngineClient::UpdateStatusOperation::
UPDATE_STATUS_UPDATED_NEED_REBOOT:
RunCompletionCallbackAndResetState(true);
break;
case chromeos::UpdateEngineClient::UpdateStatusOperation::
UPDATE_STATUS_ERROR:
case chromeos::UpdateEngineClient::UpdateStatusOperation::
UPDATE_STATUS_NEED_PERMISSION_TO_UPDATE:
case chromeos::UpdateEngineClient::UpdateStatusOperation::
UPDATE_STATUS_REPORTING_ERROR_EVENT:
update_check_task_executor_.ScheduleRetry();
break;
case chromeos::UpdateEngineClient::UpdateStatusOperation::
UPDATE_STATUS_FINALIZING:
case chromeos::UpdateEngineClient::UpdateStatusOperation::
UPDATE_STATUS_VERIFYING:
case chromeos::UpdateEngineClient::UpdateStatusOperation::
UPDATE_STATUS_DOWNLOADING:
case chromeos::UpdateEngineClient::UpdateStatusOperation::
UPDATE_STATUS_UPDATE_AVAILABLE:
case chromeos::UpdateEngineClient::UpdateStatusOperation::
UPDATE_STATUS_CHECKING_FOR_UPDATE:
case chromeos::UpdateEngineClient::UpdateStatusOperation::
UPDATE_STATUS_ATTEMPTING_ROLLBACK:
// Do nothing on intermediate states.
break;
}
}
void OsAndPoliciesUpdateChecker::OnUpdateCheckStarted(
chromeos::UpdateEngineClient::UpdateCheckResult result) {
switch (result) {
case chromeos::UpdateEngineClient::UPDATE_RESULT_SUCCESS:
// Nothing to do if the update check started successfully.
break;
case chromeos::UpdateEngineClient::UPDATE_RESULT_FAILED:
update_check_task_executor_.ScheduleRetry();
break;
case chromeos::UpdateEngineClient::UPDATE_RESULT_NOTIMPLEMENTED:
// No point retrying if the operation is not implemented. This should
// never happen.
LOG(ERROR) << "Operation not implemented";
RunCompletionCallbackAndResetState(false);
break;
}
}
void OsAndPoliciesUpdateChecker::ResetState() {
weak_factory_.InvalidateWeakPtrs();
chromeos::DBusThreadManager::Get()->GetUpdateEngineClient()->RemoveObserver(
this);
update_check_task_executor_.Stop();
ignore_idle_status_ = true;
}
} // namespace policy
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_CHROMEOS_POLICY_OS_AND_POLICIES_UPDATE_CHECKER_H_
#define CHROME_BROWSER_CHROMEOS_POLICY_OS_AND_POLICIES_UPDATE_CHECKER_H_
#include <memory>
#include <string>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "chrome/browser/chromeos/policy/task_executor_with_retries.h"
#include "chromeos/dbus/power/native_timer.h"
#include "chromeos/dbus/update_engine_client.h"
namespace policy {
namespace update_checker_internal {
// The maximum iterations allowed to check for and download an update if the
// operation fails. Used with |os_and_policies_update_checker_|.
constexpr int kMaxOsAndPoliciesUpdateCheckerRetryIterations = 2;
// Interval at which |os_and_policies_update_checker_| retries checking for and
// downloading updates.
constexpr base::TimeDelta kOsAndPoliciesUpdateCheckerRetryTime =
base::TimeDelta::FromMinutes(30);
} // namespace update_checker_internal
// This class is used by the scheduled update check policy to perform the actual
// device update check.
class OsAndPoliciesUpdateChecker
: public chromeos::UpdateEngineClient::Observer {
public:
OsAndPoliciesUpdateChecker(
TaskExecutorWithRetries::GetTicksSinceBootFn get_ticks_since_boot_fn);
~OsAndPoliciesUpdateChecker() override;
using UpdateCheckCompletionCallback = base::OnceCallback<void(bool result)>;
// Starts an update check and possible download and calls |cb| to indicate
// success or failure when the process is complete. Overrides any previous
// calls to |Start|.
void Start(UpdateCheckCompletionCallback cb);
// Stops any pending update checks. Calls |update_check_completion_cb_| with
// false. It is safe to call |Start| after this.
void Stop();
private:
// Runs |update_check_completion_cb_| with |result| and runs |ResetState|.
void RunCompletionCallbackAndResetState(bool result);
// Runs when |update_check_task_executor_::Start| has failed after retries.
void OnUpdateCheckFailure();
// Requests update engine to do an update check.
void StartUpdateCheck();
// UpdateEngineClient::Observer overrides.
void UpdateStatusChanged(
const chromeos::UpdateEngineClient::Status& status) override;
// Tells whether starting an update check succeeded or not.
void OnUpdateCheckStarted(
chromeos::UpdateEngineClient::UpdateCheckResult result);
// Resets all state and cancels any pending update checks.
void ResetState();
// Ignore fist IDLE status that is sent when the update check is initiated.
bool ignore_idle_status_ = true;
// Callback passed to |Start|. Called if |StartUpdateCheck| is unsuccessful
// after retries or when an update check finishes successfully.
UpdateCheckCompletionCallback update_check_completion_cb_;
// Scheduled and retries |StartUpdateCheck|.
TaskExecutorWithRetries update_check_task_executor_;
base::WeakPtrFactory<OsAndPoliciesUpdateChecker> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(OsAndPoliciesUpdateChecker);
};
} // namespace policy
#endif // CHROME_BROWSER_CHROMEOS_POLICY_OS_AND_POLICIES_UPDATE_CHECKER_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment