summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--update_engine.gyp1
-rw-r--r--update_manager/default_policy.cc42
-rw-r--r--update_manager/default_policy.h44
-rw-r--r--update_manager/fake_update_manager.h2
-rw-r--r--update_manager/update_manager.cc3
5 files changed, 84 insertions, 8 deletions
diff --git a/update_engine.gyp b/update_engine.gyp
index 328ee692..3750673d 100644
--- a/update_engine.gyp
+++ b/update_engine.gyp
@@ -179,6 +179,7 @@
'update_check_scheduler.cc',
'update_manager/boxed_value.cc',
'update_manager/chromeos_policy.cc',
+ 'update_manager/default_policy.cc',
'update_manager/evaluation_context.cc',
'update_manager/event_loop.cc',
'update_manager/policy.cc',
diff --git a/update_manager/default_policy.cc b/update_manager/default_policy.cc
new file mode 100644
index 00000000..2c75d134
--- /dev/null
+++ b/update_manager/default_policy.cc
@@ -0,0 +1,42 @@
+// Copyright (c) 2014 The Chromium OS 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 "update_engine/update_manager/default_policy.h"
+
+namespace {
+
+// A fixed minimum interval between consecutive allowed update checks. This
+// needs to be long enough to prevent busywork and/or DDoS attacks on Omaha, but
+// at the same time short enough to allow the machine to update itself
+// reasonably soon.
+const int kCheckIntervalInSeconds = 15 * 60;
+
+} // namespace
+
+namespace chromeos_update_manager {
+
+DefaultPolicy::DefaultPolicy(chromeos_update_engine::ClockInterface* clock)
+ : clock_(clock), aux_state_(new DefaultPolicyState()) {}
+
+EvalStatus DefaultPolicy::UpdateCheckAllowed(
+ EvaluationContext* ec, State* state, std::string* error,
+ UpdateCheckParams* result) const {
+ result->updates_enabled = true;
+ result->target_channel.clear();
+
+ // Ensure that the minimum interval is set. If there's no clock, this defaults
+ // to always allowing the update.
+ if (!aux_state_->IsLastCheckAllowedTimeSet() ||
+ ec->IsMonotonicTimeGreaterThan(
+ aux_state_->last_check_allowed_time() +
+ base::TimeDelta::FromSeconds(kCheckIntervalInSeconds))) {
+ if (clock_)
+ aux_state_->set_last_check_allowed_time(clock_->GetMonotonicTime());
+ return EvalStatus::kSucceeded;
+ }
+
+ return EvalStatus::kAskMeAgainLater;
+}
+
+} // namespace chromeos_update_manager
diff --git a/update_manager/default_policy.h b/update_manager/default_policy.h
index ba787247..2fb1a06b 100644
--- a/update_manager/default_policy.h
+++ b/update_manager/default_policy.h
@@ -9,26 +9,52 @@
#include <base/time/time.h>
+#include "update_engine/clock_interface.h"
#include "update_engine/update_manager/policy.h"
namespace chromeos_update_manager {
+// Auxiliary state class for DefaultPolicy evaluations.
+//
+// IMPORTANT: The use of a state object in policies is generally forbidden, as
+// it was a design decision to keep policy calls side-effect free. We make an
+// exception here to ensure that DefaultPolicy indeed serves as a safe (and
+// secure) fallback option. This practice should be avoided when imlpementing
+// other policies.
+class DefaultPolicyState {
+ public:
+ DefaultPolicyState() {}
+
+ bool IsLastCheckAllowedTimeSet() const {
+ return last_check_allowed_time_ != base::Time::Max();
+ }
+
+ // Sets/returns the point time on the monotonic time scale when the latest
+ // check allowed was recorded.
+ void set_last_check_allowed_time(base::Time timestamp) {
+ last_check_allowed_time_ = timestamp;
+ }
+ base::Time last_check_allowed_time() const {
+ return last_check_allowed_time_;
+ }
+
+ private:
+ base::Time last_check_allowed_time_ = base::Time::Max();
+};
+
// The DefaultPolicy is a safe Policy implementation that doesn't fail. The
// values returned by this policy are safe default in case of failure of the
// actual policy being used by the UpdateManager.
class DefaultPolicy : public Policy {
public:
- DefaultPolicy() {}
+ explicit DefaultPolicy(chromeos_update_engine::ClockInterface* clock);
+ DefaultPolicy() : DefaultPolicy(nullptr) {}
virtual ~DefaultPolicy() {}
// Policy overrides.
virtual EvalStatus UpdateCheckAllowed(
EvaluationContext* ec, State* state, std::string* error,
- UpdateCheckParams* result) const override {
- result->updates_enabled = true;
- result->target_channel.clear();
- return EvalStatus::kSucceeded;
- }
+ UpdateCheckParams* result) const override;
virtual EvalStatus UpdateCanStart(
EvaluationContext* ec,
@@ -63,6 +89,12 @@ class DefaultPolicy : public Policy {
}
private:
+ // A clock interface.
+ chromeos_update_engine::ClockInterface* clock_;
+
+ // An auxiliary state object.
+ scoped_ptr<DefaultPolicyState> aux_state_;
+
DISALLOW_COPY_AND_ASSIGN(DefaultPolicy);
};
diff --git a/update_manager/fake_update_manager.h b/update_manager/fake_update_manager.h
index b246412f..b509454e 100644
--- a/update_manager/fake_update_manager.h
+++ b/update_manager/fake_update_manager.h
@@ -17,7 +17,7 @@ class FakeUpdateManager : public UpdateManager {
explicit FakeUpdateManager(chromeos_update_engine::ClockInterface* clock)
: UpdateManager(clock, base::TimeDelta::FromSeconds(5), new FakeState()) {
// The FakeUpdateManager uses a DefaultPolicy.
- set_policy(new DefaultPolicy());
+ set_policy(new DefaultPolicy(clock));
}
// UpdateManager overrides.
diff --git a/update_manager/update_manager.cc b/update_manager/update_manager.cc
index d6ffcee5..fdedc29f 100644
--- a/update_manager/update_manager.cc
+++ b/update_manager/update_manager.cc
@@ -11,7 +11,8 @@ namespace chromeos_update_manager {
UpdateManager::UpdateManager(chromeos_update_engine::ClockInterface* clock,
base::TimeDelta evaluation_timeout, State* state)
- : state_(state), clock_(clock), evaluation_timeout_(evaluation_timeout) {
+ : default_policy_(clock), state_(state), clock_(clock),
+ evaluation_timeout_(evaluation_timeout) {
// TODO(deymo): Make it possible to replace this policy with a different
// implementation with a build-time flag.
policy_.reset(new ChromeOSPolicy());