This source file includes following definitions.
- creation_time_
- SetRefreshDelay
- RefreshSoon
- SetInvalidationServiceAvailability
- OnPolicyFetched
- OnRegistrationStateChanged
- OnClientError
- OnStoreLoaded
- OnStoreError
- OnIPAddressChanged
- UpdateLastRefreshFromPolicy
- RefreshNow
- ScheduleRefresh
- PerformRefresh
- RefreshAfter
#include "components/policy/core/common/cloud/cloud_policy_refresh_scheduler.h"
#include <algorithm>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/memory/scoped_ptr.h"
#include "base/metrics/histogram.h"
#include "base/sequenced_task_runner.h"
#include "base/time/default_tick_clock.h"
#include "base/time/tick_clock.h"
#include "components/policy/core/common/cloud/cloud_policy_constants.h"
namespace policy {
namespace {
const size_t kMaxRefreshesPerHour = 5;
}
#if defined(OS_ANDROID) || defined(OS_IOS)
const int64 CloudPolicyRefreshScheduler::kDefaultRefreshDelayMs =
24 * 60 * 60 * 1000;
const int64 CloudPolicyRefreshScheduler::kUnmanagedRefreshDelayMs =
24 * 60 * 60 * 1000;
const int64 CloudPolicyRefreshScheduler::kWithInvalidationsRefreshDelayMs =
24 * 60 * 60 * 1000;
const int64 CloudPolicyRefreshScheduler::kInitialErrorRetryDelayMs =
5 * 60 * 1000;
const int64 CloudPolicyRefreshScheduler::kRefreshDelayMinMs =
30 * 60 * 1000;
const int64 CloudPolicyRefreshScheduler::kRefreshDelayMaxMs =
7 * 24 * 60 * 60 * 1000;
#else
const int64 CloudPolicyRefreshScheduler::kDefaultRefreshDelayMs =
3 * 60 * 60 * 1000;
const int64 CloudPolicyRefreshScheduler::kUnmanagedRefreshDelayMs =
24 * 60 * 60 * 1000;
const int64 CloudPolicyRefreshScheduler::kWithInvalidationsRefreshDelayMs =
3 * 60 * 60 * 1000;
const int64 CloudPolicyRefreshScheduler::kInitialErrorRetryDelayMs =
5 * 60 * 1000;
const int64 CloudPolicyRefreshScheduler::kRefreshDelayMinMs =
30 * 60 * 1000;
const int64 CloudPolicyRefreshScheduler::kRefreshDelayMaxMs =
24 * 60 * 60 * 1000;
#endif
CloudPolicyRefreshScheduler::CloudPolicyRefreshScheduler(
CloudPolicyClient* client,
CloudPolicyStore* store,
const scoped_refptr<base::SequencedTaskRunner>& task_runner)
: client_(client),
store_(store),
task_runner_(task_runner),
error_retry_delay_ms_(kInitialErrorRetryDelayMs),
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())),
invalidations_available_(false),
creation_time_(base::Time::NowFromSystemTime()) {
client_->AddObserver(this);
store_->AddObserver(this);
net::NetworkChangeNotifier::AddIPAddressObserver(this);
UpdateLastRefreshFromPolicy();
ScheduleRefresh();
}
CloudPolicyRefreshScheduler::~CloudPolicyRefreshScheduler() {
store_->RemoveObserver(this);
client_->RemoveObserver(this);
net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
}
void CloudPolicyRefreshScheduler::SetRefreshDelay(int64 refresh_delay) {
refresh_delay_ms_ = std::min(std::max(refresh_delay, kRefreshDelayMinMs),
kRefreshDelayMaxMs);
ScheduleRefresh();
}
void CloudPolicyRefreshScheduler::RefreshSoon() {
rate_limiter_.PostRequest();
}
void CloudPolicyRefreshScheduler::SetInvalidationServiceAvailability(
bool is_available) {
if (!creation_time_.is_null()) {
base::TimeDelta elapsed = base::Time::NowFromSystemTime() - creation_time_;
UMA_HISTOGRAM_MEDIUM_TIMES("Enterprise.PolicyInvalidationsStartupTime",
elapsed);
creation_time_ = base::Time();
}
if (is_available == invalidations_available_) {
return;
}
invalidations_available_ = is_available;
ScheduleRefresh();
}
void CloudPolicyRefreshScheduler::OnPolicyFetched(CloudPolicyClient* client) {
error_retry_delay_ms_ = kInitialErrorRetryDelayMs;
last_refresh_ = base::Time::NowFromSystemTime();
ScheduleRefresh();
}
void CloudPolicyRefreshScheduler::OnRegistrationStateChanged(
CloudPolicyClient* client) {
error_retry_delay_ms_ = kInitialErrorRetryDelayMs;
RefreshNow();
}
void CloudPolicyRefreshScheduler::OnClientError(CloudPolicyClient* client) {
DeviceManagementStatus status = client_->status();
last_refresh_ = base::Time::NowFromSystemTime();
ScheduleRefresh();
if (client->is_registered() &&
(status == DM_STATUS_REQUEST_FAILED ||
status == DM_STATUS_TEMPORARY_UNAVAILABLE)) {
error_retry_delay_ms_ = std::min(error_retry_delay_ms_ * 2,
refresh_delay_ms_);
} else {
error_retry_delay_ms_ = kInitialErrorRetryDelayMs;
}
}
void CloudPolicyRefreshScheduler::OnStoreLoaded(CloudPolicyStore* store) {
UpdateLastRefreshFromPolicy();
ScheduleRefresh();
}
void CloudPolicyRefreshScheduler::OnStoreError(CloudPolicyStore* store) {
}
void CloudPolicyRefreshScheduler::OnIPAddressChanged() {
if (client_->status() == DM_STATUS_REQUEST_FAILED)
RefreshSoon();
}
void CloudPolicyRefreshScheduler::UpdateLastRefreshFromPolicy() {
if (!last_refresh_.is_null())
return;
if (!client_->responses().empty()) {
last_refresh_ = base::Time::NowFromSystemTime();
return;
}
#if defined(OS_ANDROID) || defined(OS_IOS)
if (store_->has_policy() && store_->policy()->has_timestamp()) {
last_refresh_ =
base::Time::UnixEpoch() +
base::TimeDelta::FromMilliseconds(store_->policy()->timestamp());
}
#else
if (store_->has_policy() && store_->policy()->has_timestamp() &&
!store_->is_managed()) {
last_refresh_ =
base::Time::UnixEpoch() +
base::TimeDelta::FromMilliseconds(store_->policy()->timestamp());
}
#endif
}
void CloudPolicyRefreshScheduler::RefreshNow() {
last_refresh_ = base::Time();
ScheduleRefresh();
}
void CloudPolicyRefreshScheduler::ScheduleRefresh() {
if (!client_->is_registered()) {
refresh_callback_.Cancel();
return;
}
int64 refresh_delay_ms =
invalidations_available_ ? kWithInvalidationsRefreshDelayMs
: refresh_delay_ms_;
switch (client_->status()) {
case DM_STATUS_SUCCESS:
if (store_->is_managed())
RefreshAfter(refresh_delay_ms);
else
RefreshAfter(kUnmanagedRefreshDelayMs);
return;
case DM_STATUS_SERVICE_ACTIVATION_PENDING:
case DM_STATUS_SERVICE_POLICY_NOT_FOUND:
RefreshAfter(refresh_delay_ms);
return;
case DM_STATUS_REQUEST_FAILED:
case DM_STATUS_TEMPORARY_UNAVAILABLE:
RefreshAfter(error_retry_delay_ms_);
return;
case DM_STATUS_REQUEST_INVALID:
case DM_STATUS_HTTP_STATUS_ERROR:
case DM_STATUS_RESPONSE_DECODING_ERROR:
case DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED:
RefreshAfter(kUnmanagedRefreshDelayMs);
return;
case DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID:
case DM_STATUS_SERVICE_DEVICE_NOT_FOUND:
case DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER:
case DM_STATUS_SERVICE_DEVICE_ID_CONFLICT:
case DM_STATUS_SERVICE_MISSING_LICENSES:
case DM_STATUS_SERVICE_DEPROVISIONED:
case DM_STATUS_SERVICE_DOMAIN_MISMATCH:
refresh_callback_.Cancel();
return;
}
NOTREACHED() << "Invalid client status " << client_->status();
RefreshAfter(kUnmanagedRefreshDelayMs);
}
void CloudPolicyRefreshScheduler::PerformRefresh() {
if (client_->is_registered()) {
last_refresh_ = base::Time::NowFromSystemTime();
client_->FetchPolicy();
return;
}
NOTREACHED();
}
void CloudPolicyRefreshScheduler::RefreshAfter(int delta_ms) {
base::TimeDelta delta(base::TimeDelta::FromMilliseconds(delta_ms));
refresh_callback_.Cancel();
base::TimeDelta delay =
std::max((last_refresh_ + delta) - base::Time::NowFromSystemTime(),
base::TimeDelta());
refresh_callback_.Reset(
base::Bind(&CloudPolicyRefreshScheduler::PerformRefresh,
base::Unretained(this)));
task_runner_->PostDelayedTask(FROM_HERE, refresh_callback_.callback(), delay);
}
}