summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjoaodasilva@chromium.org <joaodasilva@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-06 20:08:38 +0000
committerjoaodasilva@chromium.org <joaodasilva@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-06 20:08:38 +0000
commitc74952cbf654a67c6a3b33719c82f81e72bffd30 (patch)
tree901302397f1c0e61526aa9bf2044a67dd239d1e9
parente438adb56453ff270750e37ba8ac2240b968bcea (diff)
downloadchromium_src-c74952cbf654a67c6a3b33719c82f81e72bffd30.zip
chromium_src-c74952cbf654a67c6a3b33719c82f81e72bffd30.tar.gz
chromium_src-c74952cbf654a67c6a3b33719c82f81e72bffd30.tar.bz2
Added a RefreshSoon() call to the cloud policy refresh scheduler.
This call can be used to request an automatic policy refresh outside the regular polling period. These refreshes have a rate limit, so that a misbehaving clients (or policy updates that trigger new fetches) don't flood the server. This is meant to be used by the component policy service, to request fetches when new components are found (e.g. a new extension is installed and needs policy). BUG=163318 Review URL: https://chromiumcodereview.appspot.com/12455003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@186487 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/policy/cloud_policy_core.cc13
-rw-r--r--chrome/browser/policy/cloud_policy_core.h4
-rw-r--r--chrome/browser/policy/cloud_policy_refresh_scheduler.cc36
-rw-r--r--chrome/browser/policy/cloud_policy_refresh_scheduler.h17
-rw-r--r--chrome/browser/policy/cloud_policy_refresh_scheduler_unittest.cc17
5 files changed, 75 insertions, 12 deletions
diff --git a/chrome/browser/policy/cloud_policy_core.cc b/chrome/browser/policy/cloud_policy_core.cc
index 2c56562..ba92b46 100644
--- a/chrome/browser/policy/cloud_policy_core.cc
+++ b/chrome/browser/policy/cloud_policy_core.cc
@@ -23,8 +23,8 @@ CloudPolicyCore::CloudPolicyCore(const PolicyNamespaceKey& key,
CloudPolicyCore::~CloudPolicyCore() {}
void CloudPolicyCore::Connect(scoped_ptr<CloudPolicyClient> client) {
- CHECK(!client_.get());
- CHECK(client.get());
+ CHECK(!client_);
+ CHECK(client);
client_ = client.Pass();
service_.reset(new CloudPolicyService(policy_ns_key_, client_.get(), store_));
}
@@ -36,8 +36,13 @@ void CloudPolicyCore::Disconnect() {
client_.reset();
}
+void CloudPolicyCore::RefreshSoon() {
+ if (refresh_scheduler_)
+ refresh_scheduler_->RefreshSoon();
+}
+
void CloudPolicyCore::StartRefreshScheduler() {
- if (!refresh_scheduler_.get()) {
+ if (!refresh_scheduler_) {
refresh_scheduler_.reset(
new CloudPolicyRefreshScheduler(
client_.get(), store_,
@@ -58,7 +63,7 @@ void CloudPolicyCore::TrackRefreshDelayPref(
}
void CloudPolicyCore::UpdateRefreshDelayFromPref() {
- if (refresh_scheduler_.get() && refresh_delay_.get())
+ if (refresh_scheduler_ && refresh_delay_)
refresh_scheduler_->SetRefreshDelay(refresh_delay_->GetValue());
}
diff --git a/chrome/browser/policy/cloud_policy_core.h b/chrome/browser/policy/cloud_policy_core.h
index 7e9c67a..37698d4 100644
--- a/chrome/browser/policy/cloud_policy_core.h
+++ b/chrome/browser/policy/cloud_policy_core.h
@@ -55,6 +55,10 @@ class CloudPolicyCore {
// Shuts down the cloud connection.
void Disconnect();
+ // Requests a policy refresh to be performed soon. This may apply throttling,
+ // and the request may not be immediately sent.
+ void RefreshSoon();
+
// Starts a refresh scheduler in case none is running yet.
void StartRefreshScheduler();
diff --git a/chrome/browser/policy/cloud_policy_refresh_scheduler.cc b/chrome/browser/policy/cloud_policy_refresh_scheduler.cc
index f24db4e..2ed0652 100644
--- a/chrome/browser/policy/cloud_policy_refresh_scheduler.cc
+++ b/chrome/browser/policy/cloud_policy_refresh_scheduler.cc
@@ -6,13 +6,25 @@
#include <algorithm>
-#include "base/task_runner.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/sequenced_task_runner.h"
+#include "base/time/default_tick_clock.h"
+#include "base/time/tick_clock.h"
#include "chrome/browser/policy/cloud_policy_constants.h"
#include "chrome/common/chrome_notification_types.h"
#include "content/public/browser/notification_details.h"
namespace policy {
+namespace {
+
+// The maximum rate at which to refresh policies.
+const size_t kMaxRefreshesPerHour = 5;
+
+} // namespace
+
const int64 CloudPolicyRefreshScheduler::kDefaultRefreshDelayMs =
3 * 60 * 60 * 1000; // 3 hours.
const int64 CloudPolicyRefreshScheduler::kUnmanagedRefreshDelayMs =
@@ -27,12 +39,18 @@ const int64 CloudPolicyRefreshScheduler::kRefreshDelayMaxMs =
CloudPolicyRefreshScheduler::CloudPolicyRefreshScheduler(
CloudPolicyClient* client,
CloudPolicyStore* store,
- const scoped_refptr<base::TaskRunner>& task_runner)
+ const scoped_refptr<base::SequencedTaskRunner>& task_runner)
: client_(client),
store_(store),
task_runner_(task_runner),
error_retry_delay_ms_(kInitialErrorRetryDelayMs),
- refresh_delay_ms_(kDefaultRefreshDelayMs) {
+ refresh_delay_ms_(kDefaultRefreshDelayMs),
+ rate_limiter_(kMaxRefreshesPerHour,
+ base::TimeDelta::FromHours(1),
+ base::Bind(&CloudPolicyRefreshScheduler::RefreshNow,
+ base::Unretained(this)),
+ task_runner_,
+ scoped_ptr<base::TickClock>(new base::DefaultTickClock())) {
client_->AddObserver(this);
store_->AddObserver(this);
net::NetworkChangeNotifier::AddIPAddressObserver(this);
@@ -53,6 +71,10 @@ void CloudPolicyRefreshScheduler::SetRefreshDelay(int64 refresh_delay) {
ScheduleRefresh();
}
+void CloudPolicyRefreshScheduler::RefreshSoon() {
+ rate_limiter_.PostRequest();
+}
+
void CloudPolicyRefreshScheduler::OnPolicyFetched(CloudPolicyClient* client) {
error_retry_delay_ms_ = kInitialErrorRetryDelayMs;
@@ -66,8 +88,7 @@ void CloudPolicyRefreshScheduler::OnRegistrationStateChanged(
error_retry_delay_ms_ = kInitialErrorRetryDelayMs;
// The client might have registered, so trigger an immediate refresh.
- last_refresh_ = base::Time();
- ScheduleRefresh();
+ RefreshNow();
}
void CloudPolicyRefreshScheduler::OnClientError(CloudPolicyClient* client) {
@@ -130,6 +151,11 @@ void CloudPolicyRefreshScheduler::UpdateLastRefreshFromPolicy() {
}
}
+void CloudPolicyRefreshScheduler::RefreshNow() {
+ last_refresh_ = base::Time();
+ ScheduleRefresh();
+}
+
void CloudPolicyRefreshScheduler::ScheduleRefresh() {
// If the client isn't registered, there is nothing to do.
if (!client_->is_registered()) {
diff --git a/chrome/browser/policy/cloud_policy_refresh_scheduler.h b/chrome/browser/policy/cloud_policy_refresh_scheduler.h
index 76b6dc8..f737559 100644
--- a/chrome/browser/policy/cloud_policy_refresh_scheduler.h
+++ b/chrome/browser/policy/cloud_policy_refresh_scheduler.h
@@ -11,10 +11,11 @@
#include "base/time.h"
#include "chrome/browser/policy/cloud_policy_client.h"
#include "chrome/browser/policy/cloud_policy_store.h"
+#include "chrome/browser/policy/rate_limiter.h"
#include "net/base/network_change_notifier.h"
namespace base {
-class TaskRunner;
+class SequencedTaskRunner;
}
namespace policy {
@@ -40,7 +41,7 @@ class CloudPolicyRefreshScheduler
CloudPolicyRefreshScheduler(
CloudPolicyClient* client,
CloudPolicyStore* store,
- const scoped_refptr<base::TaskRunner>& task_runner);
+ const scoped_refptr<base::SequencedTaskRunner>& task_runner);
virtual ~CloudPolicyRefreshScheduler();
base::Time last_refresh() const { return last_refresh_; }
@@ -49,6 +50,10 @@ class CloudPolicyRefreshScheduler
// Sets the refresh delay to |refresh_delay| (subject to min/max clamping).
void SetRefreshDelay(int64 refresh_delay);
+ // Requests a policy refresh to be performed soon. This may apply throttling,
+ // and the request may not be immediately sent.
+ void RefreshSoon();
+
// CloudPolicyClient::Observer:
virtual void OnPolicyFetched(CloudPolicyClient* client) OVERRIDE;
virtual void OnRegistrationStateChanged(CloudPolicyClient* client) OVERRIDE;
@@ -69,6 +74,9 @@ class CloudPolicyRefreshScheduler
// a refresh on every restart.
void UpdateLastRefreshFromPolicy();
+ // Schedules a refresh to be performed immediately.
+ void RefreshNow();
+
// Evaluates when the next refresh is pending and updates the callback to
// execute that refresh at the appropriate time.
void ScheduleRefresh();
@@ -84,7 +92,7 @@ class CloudPolicyRefreshScheduler
CloudPolicyStore* store_;
// For scheduling delayed tasks.
- const scoped_refptr<base::TaskRunner> task_runner_;
+ const scoped_refptr<base::SequencedTaskRunner> task_runner_;
// The delayed refresh callback.
base::CancelableClosure refresh_callback_;
@@ -98,6 +106,9 @@ class CloudPolicyRefreshScheduler
// The refresh delay.
int64 refresh_delay_ms_;
+ // Used to limit the rate at which refreshes are scheduled.
+ RateLimiter rate_limiter_;
+
DISALLOW_COPY_AND_ASSIGN(CloudPolicyRefreshScheduler);
};
diff --git a/chrome/browser/policy/cloud_policy_refresh_scheduler_unittest.cc b/chrome/browser/policy/cloud_policy_refresh_scheduler_unittest.cc
index 6e59c99..e887bfd 100644
--- a/chrome/browser/policy/cloud_policy_refresh_scheduler_unittest.cc
+++ b/chrome/browser/policy/cloud_policy_refresh_scheduler_unittest.cc
@@ -20,6 +20,7 @@
namespace em = enterprise_management;
using testing::DoAll;
+using testing::Mock;
using testing::Return;
using testing::SaveArg;
using testing::_;
@@ -137,6 +138,22 @@ TEST_F(CloudPolicyRefreshSchedulerTest, Unregistered) {
EXPECT_TRUE(task_runner_->GetPendingTasks().empty());
}
+TEST_F(CloudPolicyRefreshSchedulerTest, RefreshSoonRateLimit) {
+ scoped_ptr<CloudPolicyRefreshScheduler> scheduler(CreateRefreshScheduler());
+ // Max out the request rate.
+ for (int i = 0; i < 5; ++i) {
+ EXPECT_CALL(client_, FetchPolicy()).Times(1);
+ scheduler->RefreshSoon();
+ task_runner_->RunUntilIdle();
+ Mock::VerifyAndClearExpectations(&client_);
+ }
+ // The next refresh is throttled.
+ EXPECT_CALL(client_, FetchPolicy()).Times(0);
+ scheduler->RefreshSoon();
+ task_runner_->RunPendingTasks();
+ Mock::VerifyAndClearExpectations(&client_);
+}
+
class CloudPolicyRefreshSchedulerSteadyStateTest
: public CloudPolicyRefreshSchedulerTest {
protected: