Chromium Code Reviews| Index: chrome/browser/policy/device_management_policy_provider.cc |
| diff --git a/chrome/browser/policy/device_management_policy_provider.cc b/chrome/browser/policy/device_management_policy_provider.cc |
| index 25cfc328ca29f2e028ac2395ec5fb8936d7a207d..8d75836f66190aa369b5e09b187c15766bd0ca25 100644 |
| --- a/chrome/browser/policy/device_management_policy_provider.cc |
| +++ b/chrome/browser/policy/device_management_policy_provider.cc |
| @@ -7,12 +7,11 @@ |
| #include "base/command_line.h" |
| #include "base/file_util.h" |
| #include "base/path_service.h" |
| +#include "base/rand_util.h" |
| #include "base/task.h" |
| -#include "base/time.h" |
| #include "chrome/browser/browser_thread.h" |
| #include "chrome/browser/policy/device_management_backend.h" |
| #include "chrome/browser/policy/device_management_policy_cache.h" |
| -#include "chrome/browser/policy/device_token_fetcher.h" |
| #include "chrome/common/chrome_paths.h" |
| #include "chrome/common/chrome_switches.h" |
| #include "chrome/common/notification_service.h" |
| @@ -22,7 +21,12 @@ namespace policy { |
| const char kChromePolicyScope[] = "chromeos/device"; |
| const char kChromeDevicePolicySettingKey[] = "chrome-policy"; |
| -const int64 kPolicyRefreshRateInMinutes = 3 * 60; // 3 hours |
| +const int64 kPolicyRefreshRateInMilliseconds = 3 * 60 * 60 * 1000; // 3 hours |
| +const int64 kPolicyRefreshMaxEarlierInMilliseconds = 20 * 60 * 1000; // 20 mins |
| +// These are the base values for delays before retrying after an error. They |
| +// will be doubled each time they are used. |
| +const int64 kPolicyRefreshErrorDelayInMilliseconds = 3 * 1000; // 3 seconds |
| +const int64 kDeviceTokenRefreshErrorDelayInMilliseconds = 3 * 1000; |
| // Ensures that the portion of the policy provider implementation that requires |
| // the IOThread is deferred until the IOThread is fully initialized. The policy |
| @@ -48,6 +52,22 @@ class DeviceManagementPolicyProvider::InitializeAfterIOThreadExistsTask |
| base::WeakPtr<DeviceManagementPolicyProvider> provider_; |
| }; |
| +class DeviceManagementPolicyProvider::RefreshTask : public Task { |
| + public: |
| + explicit RefreshTask(base::WeakPtr<DeviceManagementPolicyProvider> provider) |
| + : provider_(provider) {} |
| + |
| + // Task implementation: |
| + virtual void Run() { |
| + DeviceManagementPolicyProvider* provider = provider_.get(); |
| + if (provider) |
| + provider->RefreshTaskExecute(); |
| + } |
| + |
| + private: |
| + base::WeakPtr<DeviceManagementPolicyProvider> provider_; |
| +}; |
| + |
| DeviceManagementPolicyProvider::DeviceManagementPolicyProvider( |
| const ConfigurationPolicyProvider::PolicyDefinitionList* policy_list, |
| DeviceManagementBackend* backend, |
| @@ -57,7 +77,12 @@ DeviceManagementPolicyProvider::DeviceManagementPolicyProvider( |
| backend_(backend), |
| token_service_(token_service), |
| storage_dir_(GetOrCreateDeviceManagementDir(storage_dir)), |
| - policy_request_pending_(false) { |
| + policy_request_pending_(false), |
| + refresh_task_pending_(false), |
| + policy_refresh_rate_ms_(kPolicyRefreshRateInMilliseconds), |
| + policy_refresh_max_earlier_ms_(kPolicyRefreshMaxEarlierInMilliseconds), |
| + policy_refresh_error_delay_ms_(kPolicyRefreshErrorDelayInMilliseconds), |
| + token_fetch_error_delay_ms_(kDeviceTokenRefreshErrorDelayInMilliseconds) { |
| Initialize(); |
| } |
| @@ -70,34 +95,46 @@ bool DeviceManagementPolicyProvider::Provide( |
| return true; |
| } |
| -void DeviceManagementPolicyProvider::Observe( |
| - NotificationType type, |
| - const NotificationSource& source, |
| - const NotificationDetails& details) { |
| - if (type == NotificationType::DEVICE_TOKEN_AVAILABLE) { |
| - if (token_fetcher_.get() == Source<DeviceTokenFetcher>(source).ptr() && |
| - !policy_request_pending_ && |
| - IsPolicyStale()) { |
| - SendPolicyRequest(); |
| - } |
| - } else { |
| - NOTREACHED(); |
| - } |
| -} |
| - |
| void DeviceManagementPolicyProvider::HandlePolicyResponse( |
| const em::DevicePolicyResponse& response) { |
| - cache_->SetPolicy(response); |
| - NotifyStoreOfPolicyChange(); |
| + if (cache_->SetPolicy(response)) |
| + NotifyStoreOfPolicyChange(); |
| policy_request_pending_ = false; |
| + // Reset the error delay since policy fetching succeeded this time. |
| + policy_refresh_error_delay_ms_ = kPolicyRefreshErrorDelayInMilliseconds; |
| + ScheduleRefreshTask(GetRefreshTaskDelay()); |
| } |
| void DeviceManagementPolicyProvider::OnError( |
| DeviceManagementBackend::ErrorCode code) { |
| - LOG(WARNING) << "could not provide policy from the device manager (error = " |
| - << code << ")"; |
| policy_request_pending_ = false; |
| - // TODO(danno): do something sensible in the error case, perhaps retry later? |
| + LOG(WARNING) << "Could not provide policy from the device manager (error = " |
| + << code << "), will retry in " |
| + << (policy_refresh_error_delay_ms_/1000) << " seconds."; |
| + ScheduleRefreshTask(policy_refresh_error_delay_ms_); |
| + policy_refresh_error_delay_ms_ *= 2; |
| + if (policy_refresh_rate_ms_ && |
| + policy_refresh_rate_ms_ < policy_refresh_error_delay_ms_) { |
| + policy_refresh_error_delay_ms_ = policy_refresh_rate_ms_; |
| + } |
| +} |
| + |
| +void DeviceManagementPolicyProvider::OnTokenSuccess() { |
| + if (policy_request_pending_) |
| + return; |
| + SendPolicyRequest(); |
| +} |
| + |
| +void DeviceManagementPolicyProvider::OnTokenError() { |
| + LOG(WARNING) << "Could not retrieve device token."; |
| + ScheduleRefreshTask(token_fetch_error_delay_ms_); |
| + token_fetch_error_delay_ms_ *= 2; |
| + if (token_fetch_error_delay_ms_ > policy_refresh_rate_ms_) |
| + token_fetch_error_delay_ms_ = policy_refresh_rate_ms_; |
| +} |
| + |
| +void DeviceManagementPolicyProvider::OnNotManaged() { |
| + LOG(WARNING) << "This device is not managed."; |
|
danno
2010/11/23 12:10:14
Change to a INFO, or better yet VLOG.
Jakob Kummerow (corp)
2010/11/23 12:25:26
Done.
|
| } |
| void DeviceManagementPolicyProvider::Shutdown() { |
| @@ -107,10 +144,6 @@ void DeviceManagementPolicyProvider::Shutdown() { |
| } |
| void DeviceManagementPolicyProvider::Initialize() { |
| - registrar_.Add(this, |
| - NotificationType::DEVICE_TOKEN_AVAILABLE, |
| - NotificationService::AllSources()); |
| - |
| const FilePath policy_path = storage_dir_.Append( |
| FILE_PATH_LITERAL("Policy")); |
| cache_.reset(new DeviceManagementPolicyCache(policy_path)); |
| @@ -128,12 +161,15 @@ void DeviceManagementPolicyProvider::InitializeAfterIOThreadExists() { |
| if (token_service_) { |
| token_fetcher_ = |
| new DeviceTokenFetcher(backend_.get(), token_service_, token_path); |
| + registrar_.reset(new DeviceTokenFetcher::ObserverRegistrar(token_fetcher_)); |
| + registrar_->AddObserver(this); |
| token_fetcher_->StartFetching(); |
| } |
| } |
| void DeviceManagementPolicyProvider::SendPolicyRequest() { |
| if (!policy_request_pending_) { |
| + policy_request_pending_ = true; |
| em::DevicePolicyRequest policy_request; |
| policy_request.set_policy_scope(kChromePolicyScope); |
| em::DevicePolicySettingRequest* setting = |
| @@ -142,18 +178,44 @@ void DeviceManagementPolicyProvider::SendPolicyRequest() { |
| backend_->ProcessPolicyRequest(token_fetcher_->GetDeviceToken(), |
| token_fetcher_->GetDeviceID(), |
| policy_request, this); |
| - policy_request_pending_ = true; |
| } |
| } |
| -bool DeviceManagementPolicyProvider::IsPolicyStale() const { |
| - base::Time now(base::Time::NowFromSystemTime()); |
| - base::Time last_policy_refresh_time = |
| - cache_->last_policy_refresh_time(); |
| - base::Time policy_expiration_time = |
| - last_policy_refresh_time + base::TimeDelta::FromMinutes( |
| - kPolicyRefreshRateInMinutes); |
| - return (now > policy_expiration_time); |
| +void DeviceManagementPolicyProvider::RefreshTaskExecute() { |
| + DCHECK(refresh_task_pending_); |
| + refresh_task_pending_ = false; |
| + // If there is no valid device token, the token_fetcher_ apparently failed, |
| + // so it must be restarted. |
| + if (!token_fetcher_->IsTokenValid()) { |
| + if (token_fetcher_->IsTokenPending()) { |
| + NOTREACHED(); |
| + return; |
| + } |
| + token_fetcher_->Restart(); |
| + return; |
| + } |
| + // If there is a device token, just refresh policies. |
| + SendPolicyRequest(); |
| +} |
| + |
| +void DeviceManagementPolicyProvider::ScheduleRefreshTask( |
| + int64 delay_in_milliseconds) { |
| + // This check is simply a safeguard, the situation currently cannot happen. |
| + if (refresh_task_pending_) { |
| + NOTREACHED(); |
| + return; |
| + } |
| + refresh_task_pending_ = true; |
| + BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE, |
| + new RefreshTask(AsWeakPtr()), |
| + delay_in_milliseconds); |
| +} |
| + |
| +int64 DeviceManagementPolicyProvider::GetRefreshTaskDelay() { |
| + int64 delay = policy_refresh_rate_ms_; |
| + if (policy_refresh_max_earlier_ms_) |
| + delay -= base::RandGenerator(policy_refresh_max_earlier_ms_); |
| + return delay; |
| } |
| // static |