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..f19156441e51dd1690269ed6149dae4f892b88f6 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() { |
+ VLOG(1) << "This device is not managed."; |
} |
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_.Init(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 |