| Index: chrome/browser/policy/cloud/cloud_policy_refresh_scheduler.cc
|
| diff --git a/chrome/browser/policy/cloud/cloud_policy_refresh_scheduler.cc b/chrome/browser/policy/cloud/cloud_policy_refresh_scheduler.cc
|
| deleted file mode 100644
|
| index aaf1c2964cedccb87ee6c9ad13f3124f0d6a44cf..0000000000000000000000000000000000000000
|
| --- a/chrome/browser/policy/cloud/cloud_policy_refresh_scheduler.cc
|
| +++ /dev/null
|
| @@ -1,375 +0,0 @@
|
| -// Copyright (c) 2012 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/policy/cloud/cloud_policy_refresh_scheduler.h"
|
| -
|
| -#include <algorithm>
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/bind_helpers.h"
|
| -#include "base/command_line.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 "chrome/browser/policy/cloud/cloud_policy_constants.h"
|
| -#include "components/policy/core/common/policy_switches.h"
|
| -
|
| -namespace policy {
|
| -
|
| -namespace {
|
| -
|
| -// The maximum rate at which to refresh policies.
|
| -const size_t kMaxRefreshesPerHour = 5;
|
| -
|
| -// The maximum time to wait for the invalidations service to become available
|
| -// before starting to issue requests.
|
| -const int kWaitForInvalidationsTimeoutSeconds = 5;
|
| -
|
| -} // namespace
|
| -
|
| -#if defined(OS_ANDROID)
|
| -
|
| -const int64 CloudPolicyRefreshScheduler::kDefaultRefreshDelayMs =
|
| - 24 * 60 * 60 * 1000; // 1 day.
|
| -const int64 CloudPolicyRefreshScheduler::kUnmanagedRefreshDelayMs =
|
| - 24 * 60 * 60 * 1000; // 1 day.
|
| -// Delay for periodic refreshes when the invalidations service is available,
|
| -// in milliseconds.
|
| -// TODO(joaodasilva): increase this value once we're confident that the
|
| -// invalidations channel works as expected.
|
| -const int64 CloudPolicyRefreshScheduler::kWithInvalidationsRefreshDelayMs =
|
| - 24 * 60 * 60 * 1000; // 1 day.
|
| -const int64 CloudPolicyRefreshScheduler::kInitialErrorRetryDelayMs =
|
| - 5 * 60 * 1000; // 5 minutes.
|
| -const int64 CloudPolicyRefreshScheduler::kRefreshDelayMinMs =
|
| - 30 * 60 * 1000; // 30 minutes.
|
| -const int64 CloudPolicyRefreshScheduler::kRefreshDelayMaxMs =
|
| - 7 * 24 * 60 * 60 * 1000; // 1 week.
|
| -
|
| -#else
|
| -
|
| -const int64 CloudPolicyRefreshScheduler::kDefaultRefreshDelayMs =
|
| - 3 * 60 * 60 * 1000; // 3 hours.
|
| -const int64 CloudPolicyRefreshScheduler::kUnmanagedRefreshDelayMs =
|
| - 24 * 60 * 60 * 1000; // 1 day.
|
| -// Delay for periodic refreshes when the invalidations service is available,
|
| -// in milliseconds.
|
| -// TODO(joaodasilva): increase this value once we're confident that the
|
| -// invalidations channel works as expected.
|
| -const int64 CloudPolicyRefreshScheduler::kWithInvalidationsRefreshDelayMs =
|
| - 3 * 60 * 60 * 1000; // 3 hours.
|
| -const int64 CloudPolicyRefreshScheduler::kInitialErrorRetryDelayMs =
|
| - 5 * 60 * 1000; // 5 minutes.
|
| -const int64 CloudPolicyRefreshScheduler::kRefreshDelayMinMs =
|
| - 30 * 60 * 1000; // 30 minutes.
|
| -const int64 CloudPolicyRefreshScheduler::kRefreshDelayMaxMs =
|
| - 24 * 60 * 60 * 1000; // 1 day.
|
| -
|
| -#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();
|
| -
|
| - // Give some time for the invalidation service to become available before the
|
| - // first refresh if there is already policy present.
|
| - if (store->has_policy())
|
| - WaitForInvalidationService();
|
| - else
|
| - 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() {
|
| - // An external consumer needs a policy update now (e.g. a new extension, or
|
| - // the InvalidationService received a policy invalidation), so don't wait
|
| - // before fetching anymore.
|
| - wait_for_invalidations_timeout_callback_.Cancel();
|
| - 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_) {
|
| - // No change in state. If we're currently WaitingForInvalidationService
|
| - // then the timeout task will eventually execute and trigger a reschedule;
|
| - // let the InvalidationService keep retrying until that happens.
|
| - return;
|
| - }
|
| -
|
| - wait_for_invalidations_timeout_callback_.Cancel();
|
| - invalidations_available_ = is_available;
|
| -
|
| - // Schedule a refresh since the refresh delay has been updated; however, allow
|
| - // some time for the invalidation service to update. If it is now online, the
|
| - // wait allows pending invalidations to be delivered. If it is now offline,
|
| - // then the wait allows for the service to recover from transient failure
|
| - // before falling back on the polling behavior.
|
| - WaitForInvalidationService();
|
| -}
|
| -
|
| -void CloudPolicyRefreshScheduler::OnPolicyFetched(CloudPolicyClient* client) {
|
| - error_retry_delay_ms_ = kInitialErrorRetryDelayMs;
|
| -
|
| - // Schedule the next refresh.
|
| - last_refresh_ = base::Time::NowFromSystemTime();
|
| - ScheduleRefresh();
|
| -}
|
| -
|
| -void CloudPolicyRefreshScheduler::OnRegistrationStateChanged(
|
| - CloudPolicyClient* client) {
|
| - error_retry_delay_ms_ = kInitialErrorRetryDelayMs;
|
| -
|
| - // The client might have registered, so trigger an immediate refresh.
|
| - RefreshNow();
|
| -}
|
| -
|
| -void CloudPolicyRefreshScheduler::OnClientError(CloudPolicyClient* client) {
|
| - // Save the status for below.
|
| - DeviceManagementStatus status = client_->status();
|
| -
|
| - // Schedule an error retry if applicable.
|
| - last_refresh_ = base::Time::NowFromSystemTime();
|
| - ScheduleRefresh();
|
| -
|
| - // Update the retry delay.
|
| - 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();
|
| -
|
| - // Re-schedule the next refresh in case the is_managed bit changed.
|
| - ScheduleRefresh();
|
| -}
|
| -
|
| -void CloudPolicyRefreshScheduler::OnStoreError(CloudPolicyStore* store) {
|
| - // If |store_| fails, the is_managed bit that it provides may become stale.
|
| - // The best guess in that situation is to assume is_managed didn't change and
|
| - // continue using the stale information. Thus, no specific response to a store
|
| - // error is required. NB: Changes to is_managed fire OnStoreLoaded().
|
| -}
|
| -
|
| -void CloudPolicyRefreshScheduler::OnIPAddressChanged() {
|
| - if (client_->status() == DM_STATUS_REQUEST_FAILED)
|
| - RefreshSoon();
|
| -}
|
| -
|
| -void CloudPolicyRefreshScheduler::UpdateLastRefreshFromPolicy() {
|
| - if (!last_refresh_.is_null())
|
| - return;
|
| -
|
| - // If the client has already fetched policy, assume that happened recently. If
|
| - // that assumption ever breaks, the proper thing to do probably is to move the
|
| - // |last_refresh_| bookkeeping to CloudPolicyClient.
|
| - if (!client_->responses().empty()) {
|
| - last_refresh_ = base::Time::NowFromSystemTime();
|
| - return;
|
| - }
|
| -
|
| -#if defined(OS_ANDROID)
|
| - // Refreshing on Android:
|
| - // - if no user is signed-in then the |client_| is never registered and
|
| - // nothing happens here.
|
| - // - if the user is signed-in but isn't enterprise then the |client_| is
|
| - // never registered and nothing happens here.
|
| - // - if the user is signed-in but isn't registered for policy yet then the
|
| - // |client_| isn't registered either; the UserPolicySigninService will try
|
| - // to register, and OnRegistrationStateChanged() will be invoked later.
|
| - // - if the client is signed-in and has policy then its timestamp is used to
|
| - // determine when to perform the next fetch, which will be once the cached
|
| - // version is considered "old enough".
|
| - //
|
| - // If there is an old policy cache then a fetch will be performed "soon"; if
|
| - // that fetch fails then a retry is attempted after a delay, with exponential
|
| - // backoff. If those fetches keep failing then the cached timestamp is *not*
|
| - // updated, and another fetch (and subsequent retries) will be attempted
|
| - // again on the next startup.
|
| - //
|
| - // But if the cached policy is considered fresh enough then we try to avoid
|
| - // fetching again on startup; the Android logic differs from the desktop in
|
| - // this aspect.
|
| - if (store_->has_policy() && store_->policy()->has_timestamp()) {
|
| - last_refresh_ =
|
| - base::Time::UnixEpoch() +
|
| - base::TimeDelta::FromMilliseconds(store_->policy()->timestamp());
|
| - }
|
| -#else
|
| - // If there is a cached non-managed response, make sure to only re-query the
|
| - // server after kUnmanagedRefreshDelayMs. NB: For existing policy, an
|
| - // immediate refresh is intentional.
|
| - 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 the client isn't registered, there is nothing to do.
|
| - if (!client_->is_registered()) {
|
| - refresh_callback_.Cancel();
|
| - return;
|
| - }
|
| -
|
| - // Don't schedule anything yet if we're still waiting for the invalidations
|
| - // service.
|
| - if (WaitingForInvalidationService())
|
| - return;
|
| -
|
| - // If policy invalidations are available then periodic updates are done at
|
| - // a much lower rate; otherwise use the |refresh_delay_ms_| value.
|
| - int64 refresh_delay_ms =
|
| - invalidations_available_ ? kWithInvalidationsRefreshDelayMs
|
| - : refresh_delay_ms_;
|
| -
|
| - // If there is a registration, go by the client's status. That will tell us
|
| - // what the appropriate refresh delay should be.
|
| - 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:
|
| - // Need a re-registration, no use in retrying.
|
| - refresh_callback_.Cancel();
|
| - return;
|
| - }
|
| -
|
| - NOTREACHED() << "Invalid client status " << client_->status();
|
| - RefreshAfter(kUnmanagedRefreshDelayMs);
|
| -}
|
| -
|
| -void CloudPolicyRefreshScheduler::PerformRefresh() {
|
| - if (client_->is_registered()) {
|
| - // Update |last_refresh_| so another fetch isn't triggered inadvertently.
|
| - last_refresh_ = base::Time::NowFromSystemTime();
|
| -
|
| - // The result of this operation will be reported through a callback, at
|
| - // which point the next refresh will be scheduled.
|
| - client_->FetchPolicy();
|
| - return;
|
| - }
|
| -
|
| - // This should never happen, as the registration change should have been
|
| - // handled via OnRegistrationStateChanged().
|
| - NOTREACHED();
|
| -}
|
| -
|
| -void CloudPolicyRefreshScheduler::RefreshAfter(int delta_ms) {
|
| - base::TimeDelta delta(base::TimeDelta::FromMilliseconds(delta_ms));
|
| - refresh_callback_.Cancel();
|
| -
|
| - // Schedule the callback.
|
| - 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);
|
| -}
|
| -
|
| -void CloudPolicyRefreshScheduler::WaitForInvalidationService() {
|
| - DCHECK(!WaitingForInvalidationService());
|
| - wait_for_invalidations_timeout_callback_.Reset(
|
| - base::Bind(
|
| - &CloudPolicyRefreshScheduler::OnWaitForInvalidationServiceTimeout,
|
| - base::Unretained(this)));
|
| - base::TimeDelta delay =
|
| - base::TimeDelta::FromSeconds(kWaitForInvalidationsTimeoutSeconds);
|
| - // Do not wait for the invalidation service if the feature is disabled.
|
| - if (CommandLine::ForCurrentProcess()->HasSwitch(
|
| - switches::kDisableCloudPolicyPush)) {
|
| - delay = base::TimeDelta();
|
| - }
|
| - task_runner_->PostDelayedTask(
|
| - FROM_HERE,
|
| - wait_for_invalidations_timeout_callback_.callback(),
|
| - delay);
|
| -}
|
| -
|
| -void CloudPolicyRefreshScheduler::OnWaitForInvalidationServiceTimeout() {
|
| - wait_for_invalidations_timeout_callback_.Cancel();
|
| - ScheduleRefresh();
|
| -}
|
| -
|
| -bool CloudPolicyRefreshScheduler::WaitingForInvalidationService() const {
|
| - return !wait_for_invalidations_timeout_callback_.IsCancelled();
|
| -}
|
| -
|
| -} // namespace policy
|
|
|