Refactor ChromeOSPolicy into policy and utilities
Building on the policy fragments that have been previously extracted
from ChromeOSPolicy, this extracts a few more pieces of logic and
replaces sections of ChromeOSPolicy with calls to the extracted
methods.
Bug: 66016687
Test: unit tests, manually triggered OTA updates
Change-Id: I3bc608065f8ab89982f71b8490ebd66ed2266aa3
diff --git a/Android.mk b/Android.mk
index d79d89b..d2a83bc 100644
--- a/Android.mk
+++ b/Android.mk
@@ -978,9 +978,11 @@
update_manager/boxed_value_unittest.cc \
update_manager/chromeos_policy.cc \
update_manager/chromeos_policy_unittest.cc \
+ update_manager/enterprise_device_policy_impl.cc \
update_manager/evaluation_context_unittest.cc \
update_manager/generic_variables_unittest.cc \
update_manager/next_update_check_policy_impl_unittest.cc \
+ update_manager/out_of_box_experience_policy_impl.cc \
update_manager/policy_test_utils.cc \
update_manager/prng_unittest.cc \
update_manager/real_device_policy_provider_unittest.cc \
diff --git a/update_engine.gyp b/update_engine.gyp
index f72ca14..8111100 100644
--- a/update_engine.gyp
+++ b/update_engine.gyp
@@ -274,8 +274,15 @@
'update_manager/boxed_value.cc',
'update_manager/chromeos_policy.cc',
'update_manager/default_policy.cc',
+ 'update_manager/enough_slots_ab_updates_policy_impl.cc',
+ 'update_manager/enterprise_device_policy_impl.cc',
'update_manager/evaluation_context.cc',
+ 'update_manager/interactive_update_policy_impl.cc',
+ 'update_manager/next_update_check_policy_impl.cc',
+ 'update_manager/official_build_check_policy_impl.cc',
+ 'update_manager/out_of_box_experience_policy_impl.cc',
'update_manager/policy.cc',
+ 'update_manager/policy_test_utils.cc',
'update_manager/real_config_provider.cc',
'update_manager/real_device_policy_provider.cc',
'update_manager/real_random_provider.cc',
diff --git a/update_manager/chromeos_policy.cc b/update_manager/chromeos_policy.cc
index 12f417c..842839a 100644
--- a/update_manager/chromeos_policy.cc
+++ b/update_manager/chromeos_policy.cc
@@ -19,6 +19,7 @@
#include <algorithm>
#include <set>
#include <string>
+#include <vector>
#include <base/logging.h>
#include <base/strings/string_util.h>
@@ -28,6 +29,11 @@
#include "update_engine/common/error_code_utils.h"
#include "update_engine/common/utils.h"
#include "update_engine/update_manager/device_policy_provider.h"
+#include "update_engine/update_manager/enough_slots_ab_updates_policy_impl.h"
+#include "update_engine/update_manager/enterprise_device_policy_impl.h"
+#include "update_engine/update_manager/interactive_update_policy_impl.h"
+#include "update_engine/update_manager/official_build_check_policy_impl.h"
+#include "update_engine/update_manager/out_of_box_experience_policy_impl.h"
#include "update_engine/update_manager/policy_utils.h"
#include "update_engine/update_manager/shill_provider.h"
@@ -38,10 +44,10 @@
using chromeos_update_engine::ErrorCode;
using chromeos_update_engine::InstallPlan;
using std::get;
-using std::max;
using std::min;
using std::set;
using std::string;
+using std::vector;
namespace {
@@ -172,21 +178,16 @@
namespace chromeos_update_manager {
-const int ChromeOSPolicy::kTimeoutInitialInterval = 7 * 60;
+const NextUpdateCheckPolicyConstants
+ ChromeOSPolicy::kNextUpdateCheckPolicyConstants = {
+ .timeout_initial_interval = 7 * 60,
+ .timeout_periodic_interval = 45 * 60,
+ .timeout_max_backoff_interval = 4 * 60 * 60,
+ .timeout_regular_fuzz = 10 * 60,
+ .attempt_backoff_max_interval_in_days = 16,
+ .attempt_backoff_fuzz_in_hours = 12,
+};
-// TODO(deymo): Split the update_manager policies for Brillo and ChromeOS and
-// make the update check periodic interval configurable.
-#ifdef __ANDROID__
-const int ChromeOSPolicy::kTimeoutPeriodicInterval = 5 * 60 * 60;
-const int ChromeOSPolicy::kTimeoutMaxBackoffInterval = 26 * 60 * 60;
-#else
-const int ChromeOSPolicy::kTimeoutPeriodicInterval = 45 * 60;
-const int ChromeOSPolicy::kTimeoutMaxBackoffInterval = 4 * 60 * 60;
-#endif // __ANDROID__
-
-const int ChromeOSPolicy::kTimeoutRegularFuzz = 10 * 60;
-const int ChromeOSPolicy::kAttemptBackoffMaxIntervalInDays = 16;
-const int ChromeOSPolicy::kAttemptBackoffFuzzInHours = 12;
const int ChromeOSPolicy::kMaxP2PAttempts = 10;
const int ChromeOSPolicy::kMaxP2PAttemptsPeriodInSeconds = 5 * 24 * 60 * 60;
@@ -199,130 +200,53 @@
result->target_version_prefix.clear();
result->is_interactive = false;
- DevicePolicyProvider* const dp_provider = state->device_policy_provider();
- UpdaterProvider* const updater_provider = state->updater_provider();
- SystemProvider* const system_provider = state->system_provider();
+ EnoughSlotsAbUpdatesPolicyImpl enough_slots_ab_updates_policy;
+ EnterpriseDevicePolicyImpl enterprise_device_policy;
+ OnlyUpdateOfficialBuildsPolicyImpl only_update_official_builds_policy;
+ InteractiveUpdatePolicyImpl interactive_update_policy;
+ OobePolicyImpl oobe_policy;
+ NextUpdateCheckTimePolicyImpl next_update_check_time_policy(
+ kNextUpdateCheckPolicyConstants);
- // Do not perform any updates if booted from removable device. This decision
- // is final.
- const unsigned int* num_slots_p = ec->GetValue(
- system_provider->var_num_slots());
- if (!num_slots_p || *num_slots_p < 2) {
- LOG(INFO) << "Not enough slots for A/B updates, disabling update checks.";
- result->updates_enabled = false;
+ vector<Policy const*> policies_to_consult = {
+ // Do not perform any updates if there are not enough slots to do A/B
+ // updates.
+ &enough_slots_ab_updates_policy,
+
+ // Check to see if Enterprise-managed (has DevicePolicy) and/or
+ // Kiosk-mode. If so, then defer to those settings.
+ &enterprise_device_policy,
+
+ // Check to see if an interactive update was requested.
+ &interactive_update_policy,
+
+ // Unofficial builds should not perform periodic update checks.
+ &only_update_official_builds_policy,
+
+ // If OOBE is enabled, wait until it is completed.
+ &oobe_policy,
+
+ // Ensure that periodic update checks are timed properly.
+ &next_update_check_time_policy,
+ };
+
+ // Now that the list of policy implementations, and the order to consult them,
+ // has been setup, consult the policies. If none of the policies make a
+ // definitive decisions about whether or not to check for updates, then allow
+ // the update check to happen.
+ EvalStatus status = ConsultPolicies(policies_to_consult,
+ &Policy::UpdateCheckAllowed,
+ ec,
+ state,
+ error,
+ result);
+ if (EvalStatus::kContinue != status) {
+ return status;
+ } else {
+ // It is time to check for an update.
+ LOG(INFO) << "Allowing update check.";
return EvalStatus::kSucceeded;
}
-
- const bool* device_policy_is_loaded_p = ec->GetValue(
- dp_provider->var_device_policy_is_loaded());
- if (device_policy_is_loaded_p && *device_policy_is_loaded_p) {
- bool kiosk_app_control_chrome_version = false;
-
- // Check whether updates are disabled by policy.
- const bool* update_disabled_p = ec->GetValue(
- dp_provider->var_update_disabled());
- if (update_disabled_p && *update_disabled_p) {
- // Check whether allow kiosk app to control chrome version policy. This
- // policy is only effective when AU is disabled by admin.
- const bool* allow_kiosk_app_control_chrome_version_p = ec->GetValue(
- dp_provider->var_allow_kiosk_app_control_chrome_version());
- kiosk_app_control_chrome_version =
- allow_kiosk_app_control_chrome_version_p &&
- *allow_kiosk_app_control_chrome_version_p;
- if (!kiosk_app_control_chrome_version) {
- // No kiosk pin chrome version policy. AU is really disabled.
- LOG(INFO) << "Updates disabled by policy, blocking update checks.";
- return EvalStatus::kAskMeAgainLater;
- }
- }
-
- if (kiosk_app_control_chrome_version) {
- // Get the required platform version from Chrome.
- const string* kiosk_required_platform_version_p =
- ec->GetValue(system_provider->var_kiosk_required_platform_version());
- if (!kiosk_required_platform_version_p) {
- LOG(INFO) << "Kiosk app required platform version is not fetched, "
- "blocking update checks";
- return EvalStatus::kAskMeAgainLater;
- }
-
- result->target_version_prefix = *kiosk_required_platform_version_p;
- LOG(INFO) << "Allow kiosk app to control Chrome version policy is set, "
- << "target version is "
- << (!kiosk_required_platform_version_p->empty()
- ? *kiosk_required_platform_version_p
- : std::string("latest"));
- } else {
- // Determine whether a target version prefix is dictated by policy.
- const string* target_version_prefix_p = ec->GetValue(
- dp_provider->var_target_version_prefix());
- if (target_version_prefix_p)
- result->target_version_prefix = *target_version_prefix_p;
- }
-
- // Determine whether a target channel is dictated by policy.
- const bool* release_channel_delegated_p = ec->GetValue(
- dp_provider->var_release_channel_delegated());
- if (release_channel_delegated_p && !(*release_channel_delegated_p)) {
- const string* release_channel_p = ec->GetValue(
- dp_provider->var_release_channel());
- if (release_channel_p)
- result->target_channel = *release_channel_p;
- }
- }
-
- // First, check to see if an interactive update was requested.
- const UpdateRequestStatus* forced_update_requested_p = ec->GetValue(
- updater_provider->var_forced_update_requested());
- if (forced_update_requested_p &&
- *forced_update_requested_p != UpdateRequestStatus::kNone) {
- result->is_interactive =
- (*forced_update_requested_p == UpdateRequestStatus::kInteractive);
- LOG(INFO) << "Forced update signaled ("
- << (result->is_interactive ? "interactive" : "periodic")
- << "), allowing update check.";
- return EvalStatus::kSucceeded;
- }
-
- // The logic thereafter applies to periodic updates. Bear in mind that we
- // should not return a final "no" if any of these criteria are not satisfied,
- // because the system may still update due to an interactive update request.
-
- // Unofficial builds should not perform periodic update checks.
- const bool* is_official_build_p = ec->GetValue(
- system_provider->var_is_official_build());
- if (is_official_build_p && !(*is_official_build_p)) {
- LOG(INFO) << "Unofficial build, blocking periodic update checks.";
- return EvalStatus::kAskMeAgainLater;
- }
-
- // If OOBE is enabled, wait until it is completed.
- const bool* is_oobe_enabled_p = ec->GetValue(
- state->config_provider()->var_is_oobe_enabled());
- if (is_oobe_enabled_p && *is_oobe_enabled_p) {
- const bool* is_oobe_complete_p = ec->GetValue(
- system_provider->var_is_oobe_complete());
- if (is_oobe_complete_p && !(*is_oobe_complete_p)) {
- LOG(INFO) << "OOBE not completed, blocking update checks.";
- return EvalStatus::kAskMeAgainLater;
- }
- }
-
- // Ensure that periodic update checks are timed properly.
- Time next_update_check;
- if (NextUpdateCheckTime(ec, state, error, &next_update_check) !=
- EvalStatus::kSucceeded) {
- return EvalStatus::kFailed;
- }
- if (!ec->IsWallclockTimeGreaterThan(next_update_check)) {
- LOG(INFO) << "Periodic check interval not satisfied, blocking until "
- << chromeos_update_engine::utils::ToString(next_update_check);
- return EvalStatus::kAskMeAgainLater;
- }
-
- // It is time to check for an update.
- LOG(INFO) << "Allowing update check.";
- return EvalStatus::kSucceeded;
}
EvalStatus ChromeOSPolicy::UpdateCanBeApplied(EvaluationContext* ec,
@@ -626,92 +550,6 @@
return status;
}
-EvalStatus ChromeOSPolicy::NextUpdateCheckTime(EvaluationContext* ec,
- State* state, string* error,
- Time* next_update_check) const {
- UpdaterProvider* const updater_provider = state->updater_provider();
-
- // Don't check for updates too often. We limit the update checks to once every
- // some interval. The interval is kTimeoutInitialInterval the first time and
- // kTimeoutPeriodicInterval for the subsequent update checks. If the update
- // check fails, we increase the interval between the update checks
- // exponentially until kTimeoutMaxBackoffInterval. Finally, to avoid having
- // many chromebooks running update checks at the exact same time, we add some
- // fuzz to the interval.
- const Time* updater_started_time =
- ec->GetValue(updater_provider->var_updater_started_time());
- POLICY_CHECK_VALUE_AND_FAIL(updater_started_time, error);
-
- const Time* last_checked_time =
- ec->GetValue(updater_provider->var_last_checked_time());
-
- const uint64_t* seed = ec->GetValue(state->random_provider()->var_seed());
- POLICY_CHECK_VALUE_AND_FAIL(seed, error);
-
- PRNG prng(*seed);
-
- // If this is the first attempt, compute and return an initial value.
- if (!last_checked_time || *last_checked_time < *updater_started_time) {
- *next_update_check = *updater_started_time + FuzzedInterval(
- &prng, kTimeoutInitialInterval, kTimeoutRegularFuzz);
- return EvalStatus::kSucceeded;
- }
-
- // Check whether the server is enforcing a poll interval; if not, this value
- // will be zero.
- const unsigned int* server_dictated_poll_interval = ec->GetValue(
- updater_provider->var_server_dictated_poll_interval());
- POLICY_CHECK_VALUE_AND_FAIL(server_dictated_poll_interval, error);
-
- int interval = *server_dictated_poll_interval;
- int fuzz = 0;
-
- // If no poll interval was dictated by server compute a back-off period,
- // starting from a predetermined base periodic interval and increasing
- // exponentially by the number of consecutive failed attempts.
- if (interval == 0) {
- const unsigned int* consecutive_failed_update_checks = ec->GetValue(
- updater_provider->var_consecutive_failed_update_checks());
- POLICY_CHECK_VALUE_AND_FAIL(consecutive_failed_update_checks, error);
-
- interval = kTimeoutPeriodicInterval;
- unsigned int num_failures = *consecutive_failed_update_checks;
- while (interval < kTimeoutMaxBackoffInterval && num_failures) {
- interval *= 2;
- num_failures--;
- }
- }
-
- // We cannot back off longer than the predetermined maximum interval.
- if (interval > kTimeoutMaxBackoffInterval)
- interval = kTimeoutMaxBackoffInterval;
-
- // We cannot back off shorter than the predetermined periodic interval. Also,
- // in this case set the fuzz to a predetermined regular value.
- if (interval <= kTimeoutPeriodicInterval) {
- interval = kTimeoutPeriodicInterval;
- fuzz = kTimeoutRegularFuzz;
- }
-
- // If not otherwise determined, defer to a fuzz of +/-(interval / 2).
- if (fuzz == 0)
- fuzz = interval;
-
- *next_update_check = *last_checked_time + FuzzedInterval(
- &prng, interval, fuzz);
- return EvalStatus::kSucceeded;
-}
-
-TimeDelta ChromeOSPolicy::FuzzedInterval(PRNG* prng, int interval, int fuzz) {
- DCHECK_GE(interval, 0);
- DCHECK_GE(fuzz, 0);
- int half_fuzz = fuzz / 2;
- // This guarantees the output interval is non negative.
- int interval_min = max(interval - half_fuzz, 0);
- int interval_max = interval + half_fuzz;
- return TimeDelta::FromSeconds(prng->RandMinMax(interval_min, interval_max));
-}
-
EvalStatus ChromeOSPolicy::UpdateBackoffAndDownloadUrl(
EvaluationContext* ec, State* state, string* error,
UpdateBackoffAndDownloadUrlResult* result,
@@ -883,11 +721,13 @@
PRNG prng(*seed);
int exp = min(update_state.num_failures,
static_cast<int>(sizeof(int)) * 8 - 2);
- TimeDelta backoff_interval = TimeDelta::FromDays(
- min(1 << exp, kAttemptBackoffMaxIntervalInDays));
- TimeDelta backoff_fuzz = TimeDelta::FromHours(kAttemptBackoffFuzzInHours);
- TimeDelta wait_period = FuzzedInterval(&prng, backoff_interval.InSeconds(),
- backoff_fuzz.InSeconds());
+ TimeDelta backoff_interval = TimeDelta::FromDays(min(
+ 1 << exp,
+ kNextUpdateCheckPolicyConstants.attempt_backoff_max_interval_in_days));
+ TimeDelta backoff_fuzz = TimeDelta::FromHours(
+ kNextUpdateCheckPolicyConstants.attempt_backoff_fuzz_in_hours);
+ TimeDelta wait_period = NextUpdateCheckTimePolicyImpl::FuzzedInterval(
+ &prng, backoff_interval.InSeconds(), backoff_fuzz.InSeconds());
backoff_expiry = err_time + wait_period;
// If the newly computed backoff already expired, nullify it.
diff --git a/update_manager/chromeos_policy.h b/update_manager/chromeos_policy.h
index 283bedc..67c0d15 100644
--- a/update_manager/chromeos_policy.h
+++ b/update_manager/chromeos_policy.h
@@ -20,10 +20,9 @@
#include <string>
#include <base/time/time.h>
-#include <gtest/gtest_prod.h> // for FRIEND_TEST
-#include "update_engine/update_manager/policy.h"
-#include "update_engine/update_manager/prng.h"
+#include "update_engine/update_manager/next_update_check_policy_impl.h"
+#include "update_engine/update_manager/policy_utils.h"
namespace chromeos_update_manager {
@@ -98,12 +97,6 @@
private:
friend class UmChromeOSPolicyTest;
- FRIEND_TEST(UmChromeOSPolicyTest,
- FirstCheckIsAtMostInitialIntervalAfterStart);
- FRIEND_TEST(UmChromeOSPolicyTest, RecurringCheckBaseIntervalAndFuzz);
- FRIEND_TEST(UmChromeOSPolicyTest, RecurringCheckBackoffIntervalAndFuzz);
- FRIEND_TEST(UmChromeOSPolicyTest, RecurringCheckServerDictatedPollInterval);
- FRIEND_TEST(UmChromeOSPolicyTest, ExponentialBackoffIsCapped);
FRIEND_TEST(UmChromeOSPolicyTest, UpdateCheckAllowedWaitsForTheTimeout);
FRIEND_TEST(UmChromeOSPolicyTest, UpdateCheckAllowedWaitsForOOBE);
FRIEND_TEST(UmChromeOSPolicyTest,
@@ -125,38 +118,13 @@
// Auxiliary constant (zero by default).
const base::TimeDelta kZeroInterval;
- // Default update check timeout interval/fuzz values used to compute the
- // NextUpdateCheckTime(), in seconds. Actual fuzz is within +/- half of the
- // indicated value.
- static const int kTimeoutInitialInterval;
- static const int kTimeoutPeriodicInterval;
- static const int kTimeoutMaxBackoffInterval;
- static const int kTimeoutRegularFuzz;
-
- // Maximum update attempt backoff interval and fuzz.
- static const int kAttemptBackoffMaxIntervalInDays;
- static const int kAttemptBackoffFuzzInHours;
+ static const NextUpdateCheckPolicyConstants kNextUpdateCheckPolicyConstants;
// Maximum number of times we'll allow using P2P for the same update payload.
static const int kMaxP2PAttempts;
// Maximum period of time allowed for download a payload via P2P, in seconds.
static const int kMaxP2PAttemptsPeriodInSeconds;
- // A private policy implementation returning the wallclock timestamp when
- // the next update check should happen.
- // TODO(garnold) We should probably change that to infer a monotonic
- // timestamp, which will make the update check intervals more resilient to
- // clock skews. Might require switching some of the variables exported by the
- // UpdaterProvider to report monotonic time, as well.
- EvalStatus NextUpdateCheckTime(EvaluationContext* ec, State* state,
- std::string* error,
- base::Time* next_update_check) const;
-
- // Returns a TimeDelta based on the provided |interval| seconds +/- half
- // |fuzz| seconds. The return value is guaranteed to be a non-negative
- // TimeDelta.
- static base::TimeDelta FuzzedInterval(PRNG* prng, int interval, int fuzz);
-
// A private policy for determining backoff and the download URL to use.
// Within |update_state|, |backoff_expiry| and |is_backoff_disabled| are used
// for determining whether backoff is still in effect; if not,
diff --git a/update_manager/chromeos_policy_unittest.cc b/update_manager/chromeos_policy_unittest.cc
index 63fa0f7..df29e8c 100644
--- a/update_manager/chromeos_policy_unittest.cc
+++ b/update_manager/chromeos_policy_unittest.cc
@@ -16,72 +16,35 @@
#include "update_engine/update_manager/chromeos_policy.h"
+#include <memory>
#include <set>
-#include <string>
-#include <tuple>
-#include <vector>
-#include <base/time/time.h>
-#include <brillo/message_loops/fake_message_loop.h>
-#include <gtest/gtest.h>
-
-#include "update_engine/common/fake_clock.h"
-#include "update_engine/update_manager/evaluation_context.h"
-#include "update_engine/update_manager/fake_state.h"
-#include "update_engine/update_manager/umtest_utils.h"
+#include "update_engine/update_manager/next_update_check_policy_impl.h"
+#include "update_engine/update_manager/policy_test_utils.h"
using base::Time;
using base::TimeDelta;
using chromeos_update_engine::ConnectionTethering;
using chromeos_update_engine::ConnectionType;
using chromeos_update_engine::ErrorCode;
-using chromeos_update_engine::FakeClock;
using std::set;
using std::string;
-using std::tuple;
-using std::vector;
namespace chromeos_update_manager {
-class UmChromeOSPolicyTest : public ::testing::Test {
+class UmChromeOSPolicyTest : public UmPolicyTestBase {
protected:
+ UmChromeOSPolicyTest() : UmPolicyTestBase() {
+ policy_ = std::make_unique<ChromeOSPolicy>();
+ }
+
void SetUp() override {
- loop_.SetAsCurrent();
- SetUpDefaultClock();
- eval_ctx_ = new EvaluationContext(&fake_clock_, TimeDelta::FromSeconds(5));
- SetUpDefaultState();
+ UmPolicyTestBase::SetUp();
SetUpDefaultDevicePolicy();
}
- void TearDown() override {
- EXPECT_FALSE(loop_.PendingTasks());
- }
-
- // Sets the clock to fixed values.
- void SetUpDefaultClock() {
- fake_clock_.SetMonotonicTime(Time::FromInternalValue(12345678L));
- fake_clock_.SetWallclockTime(Time::FromInternalValue(12345678901234L));
- }
-
- void SetUpDefaultState() {
- fake_state_.updater_provider()->var_updater_started_time()->reset(
- new Time(fake_clock_.GetWallclockTime()));
- fake_state_.updater_provider()->var_last_checked_time()->reset(
- new Time(fake_clock_.GetWallclockTime()));
- fake_state_.updater_provider()->var_consecutive_failed_update_checks()->
- reset(new unsigned int{0});
- fake_state_.updater_provider()->var_server_dictated_poll_interval()->
- reset(new unsigned int{0});
- fake_state_.updater_provider()->var_forced_update_requested()->
- reset(new UpdateRequestStatus{UpdateRequestStatus::kNone});
-
- fake_state_.random_provider()->var_seed()->reset(
- new uint64_t(4)); // chosen by fair dice roll.
- // guaranteed to be random.
-
- // No device policy loaded by default.
- fake_state_.device_policy_provider()->var_device_policy_is_loaded()->reset(
- new bool(false));
+ void SetUpDefaultState() override {
+ UmPolicyTestBase::SetUpDefaultState();
// OOBE is enabled by default.
fake_state_.config_provider()->var_is_oobe_enabled()->reset(
@@ -122,14 +85,17 @@
reset(new bool(true));
}
- // Configures the UpdateCheckAllowed policy to return a desired value by
+ // Configures the policy to return a desired value from UpdateCheckAllowed by
// faking the current wall clock time as needed. Restores the default state.
// This is used when testing policies that depend on this one.
- void SetUpdateCheckAllowed(bool allow_check) {
+ //
+ // Note that the default implementation relies on NextUpdateCheckPolicyImpl to
+ // set the FakeClock to the appropriate time.
+ virtual void SetUpdateCheckAllowed(bool allow_check) {
Time next_update_check;
- ExpectPolicyStatus(EvalStatus::kSucceeded,
- &ChromeOSPolicy::NextUpdateCheckTime,
- &next_update_check);
+ CallMethodWithContext(&NextUpdateCheckTimePolicyImpl::NextUpdateCheckTime,
+ &next_update_check,
+ ChromeOSPolicy::kNextUpdateCheckPolicyConstants);
SetUpDefaultState();
SetUpDefaultDevicePolicy();
Time curr_time = next_update_check;
@@ -139,178 +105,8 @@
curr_time -= TimeDelta::FromSeconds(1);
fake_clock_.SetWallclockTime(curr_time);
}
-
- // Returns a default UpdateState structure:
- UpdateState GetDefaultUpdateState(TimeDelta first_seen_period) {
- Time first_seen_time = fake_clock_.GetWallclockTime() - first_seen_period;
- UpdateState update_state = UpdateState();
-
- // This is a non-interactive check returning a delta payload, seen for the
- // first time (|first_seen_period| ago). Clearly, there were no failed
- // attempts so far.
- update_state.is_interactive = false;
- update_state.is_delta_payload = false;
- update_state.first_seen = first_seen_time;
- update_state.num_checks = 1;
- update_state.num_failures = 0;
- update_state.failures_last_updated = Time(); // Needs to be zero.
- // There's a single HTTP download URL with a maximum of 10 retries.
- update_state.download_urls = vector<string>{"http://fake/url/"};
- update_state.download_errors_max = 10;
- // Download was never attempted.
- update_state.last_download_url_idx = -1;
- update_state.last_download_url_num_errors = 0;
- // There were no download errors.
- update_state.download_errors = vector<tuple<int, ErrorCode, Time>>();
- // P2P is not disabled by Omaha.
- update_state.p2p_downloading_disabled = false;
- update_state.p2p_sharing_disabled = false;
- // P2P was not attempted.
- update_state.p2p_num_attempts = 0;
- update_state.p2p_first_attempted = Time();
- // No active backoff period, backoff is not disabled by Omaha.
- update_state.backoff_expiry = Time();
- update_state.is_backoff_disabled = false;
- // There is no active scattering wait period (max 7 days allowed) nor check
- // threshold (none allowed).
- update_state.scatter_wait_period = TimeDelta();
- update_state.scatter_check_threshold = 0;
- update_state.scatter_wait_period_max = TimeDelta::FromDays(7);
- update_state.scatter_check_threshold_min = 0;
- update_state.scatter_check_threshold_max = 0;
-
- return update_state;
- }
-
- // Runs the passed |policy_method| policy and expects it to return the
- // |expected| return value.
- template<typename T, typename R, typename... Args>
- void ExpectPolicyStatus(
- EvalStatus expected,
- T policy_method,
- R* result, Args... args) {
- string error = "<None>";
- eval_ctx_->ResetEvaluation();
- EXPECT_EQ(expected,
- (policy_.*policy_method)(eval_ctx_.get(), &fake_state_, &error,
- result, args...))
- << "Returned error: " << error
- << "\nEvaluation context: " << eval_ctx_->DumpContext();
- }
-
- brillo::FakeMessageLoop loop_{nullptr};
- FakeClock fake_clock_;
- FakeState fake_state_;
- scoped_refptr<EvaluationContext> eval_ctx_;
- ChromeOSPolicy policy_; // ChromeOSPolicy under test.
};
-TEST_F(UmChromeOSPolicyTest, FirstCheckIsAtMostInitialIntervalAfterStart) {
- Time next_update_check;
-
- // Set the last update time so it'll appear as if this is a first update check
- // in the lifetime of the current updater.
- fake_state_.updater_provider()->var_last_checked_time()->reset(
- new Time(fake_clock_.GetWallclockTime() - TimeDelta::FromMinutes(10)));
-
- ExpectPolicyStatus(EvalStatus::kSucceeded,
- &ChromeOSPolicy::NextUpdateCheckTime, &next_update_check);
-
- EXPECT_LE(fake_clock_.GetWallclockTime(), next_update_check);
- EXPECT_GE(
- fake_clock_.GetWallclockTime() + TimeDelta::FromSeconds(
- ChromeOSPolicy::kTimeoutInitialInterval +
- ChromeOSPolicy::kTimeoutRegularFuzz / 2),
- next_update_check);
-}
-
-TEST_F(UmChromeOSPolicyTest, RecurringCheckBaseIntervalAndFuzz) {
- // Ensure that we're using the correct interval (kPeriodicInterval) and fuzz
- // (kTimeoutRegularFuzz) as base values for period updates.
- Time next_update_check;
-
- ExpectPolicyStatus(EvalStatus::kSucceeded,
- &ChromeOSPolicy::NextUpdateCheckTime, &next_update_check);
-
- EXPECT_LE(
- fake_clock_.GetWallclockTime() + TimeDelta::FromSeconds(
- ChromeOSPolicy::kTimeoutPeriodicInterval -
- ChromeOSPolicy::kTimeoutRegularFuzz / 2),
- next_update_check);
- EXPECT_GE(
- fake_clock_.GetWallclockTime() + TimeDelta::FromSeconds(
- ChromeOSPolicy::kTimeoutPeriodicInterval +
- ChromeOSPolicy::kTimeoutRegularFuzz / 2),
- next_update_check);
-}
-
-TEST_F(UmChromeOSPolicyTest, RecurringCheckBackoffIntervalAndFuzz) {
- // Ensure that we're properly backing off and fuzzing in the presence of
- // failed updates attempts.
- Time next_update_check;
-
- fake_state_.updater_provider()->var_consecutive_failed_update_checks()->
- reset(new unsigned int{2});
-
- ExpectPolicyStatus(EvalStatus::kSucceeded,
- &ChromeOSPolicy::NextUpdateCheckTime, &next_update_check);
-
- int expected_interval = ChromeOSPolicy::kTimeoutPeriodicInterval * 4;
- EXPECT_LE(
- fake_clock_.GetWallclockTime() + TimeDelta::FromSeconds(
- expected_interval - expected_interval / 2),
- next_update_check);
- EXPECT_GE(
- fake_clock_.GetWallclockTime() + TimeDelta::FromSeconds(
- expected_interval + expected_interval / 2),
- next_update_check);
-}
-
-TEST_F(UmChromeOSPolicyTest, RecurringCheckServerDictatedPollInterval) {
- // Policy honors the server provided check poll interval.
- Time next_update_check;
-
- const unsigned int kInterval = ChromeOSPolicy::kTimeoutPeriodicInterval * 4;
- fake_state_.updater_provider()->var_server_dictated_poll_interval()->
- reset(new unsigned int{kInterval});
- // We should not be backing off in this case.
- fake_state_.updater_provider()->var_consecutive_failed_update_checks()->
- reset(new unsigned int{2});
-
- ExpectPolicyStatus(EvalStatus::kSucceeded,
- &ChromeOSPolicy::NextUpdateCheckTime, &next_update_check);
-
- EXPECT_LE(
- fake_clock_.GetWallclockTime() + TimeDelta::FromSeconds(
- kInterval - kInterval / 2),
- next_update_check);
- EXPECT_GE(
- fake_clock_.GetWallclockTime() + TimeDelta::FromSeconds(
- kInterval + kInterval / 2),
- next_update_check);
-}
-
-TEST_F(UmChromeOSPolicyTest, ExponentialBackoffIsCapped) {
- Time next_update_check;
-
- fake_state_.updater_provider()->var_consecutive_failed_update_checks()->
- reset(new unsigned int{100});
-
- ExpectPolicyStatus(EvalStatus::kSucceeded,
- &ChromeOSPolicy::NextUpdateCheckTime, &next_update_check);
-
- EXPECT_LE(
- fake_clock_.GetWallclockTime() + TimeDelta::FromSeconds(
- ChromeOSPolicy::kTimeoutMaxBackoffInterval -
- ChromeOSPolicy::kTimeoutMaxBackoffInterval / 2),
- next_update_check);
- EXPECT_GE(
- fake_clock_.GetWallclockTime() + TimeDelta::FromSeconds(
- ChromeOSPolicy::kTimeoutMaxBackoffInterval +
- ChromeOSPolicy::kTimeoutMaxBackoffInterval /2),
- next_update_check);
-}
-
TEST_F(UmChromeOSPolicyTest, UpdateCheckAllowedWaitsForTheTimeout) {
// We get the next update_check timestamp from the policy's private method
// and then we check the public method respects that value on the normal
@@ -321,8 +117,9 @@
fake_state_.updater_provider()->var_last_checked_time()->reset(
new Time(last_checked_time));
- ExpectPolicyStatus(EvalStatus::kSucceeded,
- &ChromeOSPolicy::NextUpdateCheckTime, &next_update_check);
+ CallMethodWithContext(&NextUpdateCheckTimePolicyImpl::NextUpdateCheckTime,
+ &next_update_check,
+ ChromeOSPolicy::kNextUpdateCheckPolicyConstants);
UpdateCheckParams result;
@@ -356,8 +153,9 @@
fake_state_.updater_provider()->var_last_checked_time()->reset(
new Time(last_checked_time));
- ExpectPolicyStatus(EvalStatus::kSucceeded,
- &ChromeOSPolicy::NextUpdateCheckTime, &next_update_check);
+ CallMethodWithContext(&NextUpdateCheckTimePolicyImpl::NextUpdateCheckTime,
+ &next_update_check,
+ ChromeOSPolicy::kNextUpdateCheckPolicyConstants);
SetUpDefaultClock();
SetUpDefaultState();
diff --git a/update_manager/enterprise_device_policy_impl.cc b/update_manager/enterprise_device_policy_impl.cc
new file mode 100644
index 0000000..94518a1
--- /dev/null
+++ b/update_manager/enterprise_device_policy_impl.cc
@@ -0,0 +1,95 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "update_engine/update_manager/enterprise_device_policy_impl.h"
+
+#include "update_engine/common/utils.h"
+
+using std::string;
+
+namespace chromeos_update_manager {
+
+// Check to see if Enterprise-managed (has DevicePolicy) and/or Kiosk-mode. If
+// so, then defer to those settings.
+EvalStatus EnterpriseDevicePolicyImpl::UpdateCheckAllowed(
+ EvaluationContext* ec,
+ State* state,
+ std::string* error,
+ UpdateCheckParams* result) const {
+ DevicePolicyProvider* const dp_provider = state->device_policy_provider();
+ SystemProvider* const system_provider = state->system_provider();
+
+ const bool* device_policy_is_loaded_p =
+ ec->GetValue(dp_provider->var_device_policy_is_loaded());
+ if (device_policy_is_loaded_p && *device_policy_is_loaded_p) {
+ bool kiosk_app_control_chrome_version = false;
+
+ // Check whether updates are disabled by policy.
+ const bool* update_disabled_p =
+ ec->GetValue(dp_provider->var_update_disabled());
+ if (update_disabled_p && *update_disabled_p) {
+ // Check whether allow kiosk app to control chrome version policy. This
+ // policy is only effective when AU is disabled by admin.
+ const bool* allow_kiosk_app_control_chrome_version_p = ec->GetValue(
+ dp_provider->var_allow_kiosk_app_control_chrome_version());
+ kiosk_app_control_chrome_version =
+ allow_kiosk_app_control_chrome_version_p &&
+ *allow_kiosk_app_control_chrome_version_p;
+ if (!kiosk_app_control_chrome_version) {
+ // No kiosk pin chrome version policy. AU is really disabled.
+ LOG(INFO) << "Updates disabled by policy, blocking update checks.";
+ return EvalStatus::kAskMeAgainLater;
+ }
+ }
+
+ if (kiosk_app_control_chrome_version) {
+ // Get the required platform version from Chrome.
+ const string* kiosk_required_platform_version_p =
+ ec->GetValue(system_provider->var_kiosk_required_platform_version());
+ if (!kiosk_required_platform_version_p) {
+ LOG(INFO) << "Kiosk app required platform version is not fetched, "
+ "blocking update checks";
+ return EvalStatus::kAskMeAgainLater;
+ }
+
+ result->target_version_prefix = *kiosk_required_platform_version_p;
+ LOG(INFO) << "Allow kiosk app to control Chrome version policy is set,"
+ << ", target version is "
+ << (kiosk_required_platform_version_p
+ ? *kiosk_required_platform_version_p
+ : std::string("latest"));
+ } else {
+ // Determine whether a target version prefix is dictated by policy.
+ const string* target_version_prefix_p =
+ ec->GetValue(dp_provider->var_target_version_prefix());
+ if (target_version_prefix_p)
+ result->target_version_prefix = *target_version_prefix_p;
+ }
+
+ // Determine whether a target channel is dictated by policy.
+ const bool* release_channel_delegated_p =
+ ec->GetValue(dp_provider->var_release_channel_delegated());
+ if (release_channel_delegated_p && !(*release_channel_delegated_p)) {
+ const string* release_channel_p =
+ ec->GetValue(dp_provider->var_release_channel());
+ if (release_channel_p)
+ result->target_channel = *release_channel_p;
+ }
+ }
+ return EvalStatus::kContinue;
+}
+
+} // namespace chromeos_update_manager
diff --git a/update_manager/enterprise_device_policy_impl.h b/update_manager/enterprise_device_policy_impl.h
new file mode 100644
index 0000000..4b97fda
--- /dev/null
+++ b/update_manager/enterprise_device_policy_impl.h
@@ -0,0 +1,48 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef UPDATE_ENGINE_UPDATE_MANAGER_ENTERPRISE_DEVICE_POLICY_IMPL_H_
+#define UPDATE_ENGINE_UPDATE_MANAGER_ENTERPRISE_DEVICE_POLICY_IMPL_H_
+
+#include <string>
+
+#include "update_engine/update_manager/policy_utils.h"
+
+namespace chromeos_update_manager {
+
+// Check to see if Enterprise-managed (has DevicePolicy) and/or Kiosk-mode. If
+// so, then defer to those settings.
+class EnterpriseDevicePolicyImpl : public PolicyImplBase {
+ public:
+ EnterpriseDevicePolicyImpl() = default;
+ ~EnterpriseDevicePolicyImpl() override = default;
+
+ std::string PolicyName() const override {
+ return "EnterpriseDevicePolicyImpl";
+ }
+ // Policy overrides.
+ EvalStatus UpdateCheckAllowed(EvaluationContext* ec,
+ State* state,
+ std::string* error,
+ UpdateCheckParams* result) const override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(EnterpriseDevicePolicyImpl);
+};
+
+} // namespace chromeos_update_manager
+
+#endif // UPDATE_ENGINE_UPDATE_MANAGER_ENTERPRISE_DEVICE_POLICY_IMPL_H_
diff --git a/update_manager/out_of_box_experience_policy_impl.cc b/update_manager/out_of_box_experience_policy_impl.cc
new file mode 100644
index 0000000..8dcb560
--- /dev/null
+++ b/update_manager/out_of_box_experience_policy_impl.cc
@@ -0,0 +1,43 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "update_engine/update_manager/out_of_box_experience_policy_impl.h"
+
+#include "update_engine/common/utils.h"
+
+namespace chromeos_update_manager {
+
+EvalStatus OobePolicyImpl::UpdateCheckAllowed(EvaluationContext* ec,
+ State* state,
+ std::string* error,
+ UpdateCheckParams* result) const {
+ SystemProvider* const system_provider = state->system_provider();
+
+ // If OOBE is enabled, wait until it is completed.
+ const bool* is_oobe_enabled_p =
+ ec->GetValue(state->config_provider()->var_is_oobe_enabled());
+ if (is_oobe_enabled_p && *is_oobe_enabled_p) {
+ const bool* is_oobe_complete_p =
+ ec->GetValue(system_provider->var_is_oobe_complete());
+ if (is_oobe_complete_p && !(*is_oobe_complete_p)) {
+ LOG(INFO) << "OOBE not completed, blocking update checks.";
+ return EvalStatus::kAskMeAgainLater;
+ }
+ }
+ return EvalStatus::kContinue;
+}
+
+} // namespace chromeos_update_manager
diff --git a/update_manager/out_of_box_experience_policy_impl.h b/update_manager/out_of_box_experience_policy_impl.h
new file mode 100644
index 0000000..ec1997b
--- /dev/null
+++ b/update_manager/out_of_box_experience_policy_impl.h
@@ -0,0 +1,46 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef UPDATE_ENGINE_UPDATE_MANAGER_OUT_OF_BOX_EXPERIENCE_POLICY_IMPL_H_
+#define UPDATE_ENGINE_UPDATE_MANAGER_OUT_OF_BOX_EXPERIENCE_POLICY_IMPL_H_
+
+#include <string>
+
+#include "update_engine/update_manager/policy_utils.h"
+
+namespace chromeos_update_manager {
+
+// If OOBE is enabled, wait until it is completed.
+class OobePolicyImpl : public PolicyImplBase {
+ public:
+ OobePolicyImpl() = default;
+ ~OobePolicyImpl() override = default;
+
+ std::string PolicyName() const override { return "OobePolicyImpl"; }
+
+ // Policy overrides.
+ EvalStatus UpdateCheckAllowed(EvaluationContext* ec,
+ State* state,
+ std::string* error,
+ UpdateCheckParams* result) const override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(OobePolicyImpl);
+};
+
+} // namespace chromeos_update_manager
+
+#endif // UPDATE_ENGINE_UPDATE_MANAGER_OUT_OF_BOX_EXPERIENCE_POLICY_IMPL_H_