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 627db0cdbbbce8bf62d39a22ddc8f10136083c5e..84834e248e638d710c5c2972bc33198fd09d81d6 100644 |
| --- a/chrome/browser/policy/device_management_policy_provider.cc |
| +++ b/chrome/browser/policy/device_management_policy_provider.cc |
| @@ -13,6 +13,7 @@ |
| #include "chrome/browser/policy/device_management_backend.h" |
| #include "chrome/browser/policy/device_management_policy_cache.h" |
| #include "chrome/browser/policy/proto/device_management_constants.h" |
| +#include "chrome/browser/policy/proto/device_management_local.pb.h" |
| #include "chrome/common/chrome_paths.h" |
| #include "chrome/common/chrome_switches.h" |
| #include "chrome/common/notification_service.h" |
| @@ -20,12 +21,20 @@ |
| namespace policy { |
| +namespace em = enterprise_management; |
| + |
| 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; |
| +// For unmanaged devices, check once per day whether they're still unmanaged. |
| +const int64 kPolicyRefreshUnmanagedDeviceInMilliseconds = 24 * 60 * 60 * 1000; |
| + |
| +const char* kDeviceTokenFilename = "Token"; |
| +const char* kPolicyFilename = "Policy"; |
| +const char* kUnmanagedDeviceMarkerFilename = "UnmanagedDevice"; |
|
danno
2010/11/25 16:35:01
It occurs to me that the information in this file
Jakob Kummerow
2010/11/26 09:17:23
Done.
|
| // Ensures that the portion of the policy provider implementation that requires |
| // the IOThread is deferred until the IOThread is fully initialized. The policy |
| @@ -78,10 +87,13 @@ DeviceManagementPolicyProvider::DeviceManagementPolicyProvider( |
| storage_dir_(GetOrCreateDeviceManagementDir(storage_dir)), |
| policy_request_pending_(false), |
| refresh_task_pending_(false), |
| + waiting_for_initial_policies_(true), |
| policy_refresh_rate_ms_(kPolicyRefreshRateInMilliseconds), |
| policy_refresh_max_earlier_ms_(kPolicyRefreshMaxEarlierInMilliseconds), |
| policy_refresh_error_delay_ms_(kPolicyRefreshErrorDelayInMilliseconds), |
| - token_fetch_error_delay_ms_(kDeviceTokenRefreshErrorDelayInMilliseconds) { |
| + token_fetch_error_delay_ms_(kDeviceTokenRefreshErrorDelayInMilliseconds), |
| + unmanaged_device_refresh_rate_ms_( |
| + kPolicyRefreshUnmanagedDeviceInMilliseconds) { |
| Initialize(); |
| } |
| @@ -102,6 +114,9 @@ void DeviceManagementPolicyProvider::HandlePolicyResponse( |
| // Reset the error delay since policy fetching succeeded this time. |
| policy_refresh_error_delay_ms_ = kPolicyRefreshErrorDelayInMilliseconds; |
| ScheduleRefreshTask(GetRefreshTaskDelay()); |
| + // Update this provider's internal waiting state, but don't notify anyone |
| + // else yet (that's done by the PrefValueStore that receives the policy). |
| + waiting_for_initial_policies_ = false; |
| } |
| void DeviceManagementPolicyProvider::OnError( |
| @@ -116,25 +131,16 @@ void DeviceManagementPolicyProvider::OnError( |
| policy_refresh_rate_ms_ < policy_refresh_error_delay_ms_) { |
| policy_refresh_error_delay_ms_ = policy_refresh_rate_ms_; |
| } |
| -#if defined(OS_CHROMEOS) |
| - // Send a CLOUD_POLICY_UPDATE notification to unblock ChromeOS logins that |
| - // are waiting for an initial policy fetch to complete. |
| - NotifyCloudPolicyUpdate(); |
| -#endif |
| -} |
| - |
| -#if defined(OS_CHROMEOS) |
| -void DeviceManagementPolicyProvider::NotifyCloudPolicyUpdate() const { |
| - NotificationService::current()->Notify( |
| - NotificationType::CLOUD_POLICY_UPDATE, |
| - Source<DeviceManagementPolicyProvider>(this), |
| - NotificationService::NoDetails()); |
| + StopWaitingForInitialPolicies(); |
| } |
| -#endif |
| void DeviceManagementPolicyProvider::OnTokenSuccess() { |
| - if (policy_request_pending_) |
| - return; |
| + BrowserThread::PostTask( |
| + BrowserThread::FILE, |
| + FROM_HERE, |
| + NewRunnableFunction( |
| + &DeviceManagementPolicyProvider::DeleteUnmanagedDeviceMarker, |
| + storage_dir_)); |
| SendPolicyRequest(); |
| } |
| @@ -144,10 +150,20 @@ void DeviceManagementPolicyProvider::OnTokenError() { |
| 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_; |
| + StopWaitingForInitialPolicies(); |
| } |
| void DeviceManagementPolicyProvider::OnNotManaged() { |
| VLOG(1) << "This device is not managed."; |
| + BrowserThread::PostTask( |
| + BrowserThread::FILE, |
| + FROM_HERE, |
| + NewRunnableFunction( |
| + &DeviceManagementPolicyProvider::CreateUnmanagedDeviceMarker, |
| + storage_dir_, |
| + base::Time::NowFromSystemTime())); |
| + ScheduleRefreshTask(unmanaged_device_refresh_rate_ms_); |
| + StopWaitingForInitialPolicies(); |
| } |
| void DeviceManagementPolicyProvider::Shutdown() { |
| @@ -158,19 +174,40 @@ void DeviceManagementPolicyProvider::Shutdown() { |
| void DeviceManagementPolicyProvider::Initialize() { |
| const FilePath policy_path = storage_dir_.Append( |
| - FILE_PATH_LITERAL("Policy")); |
| + FILE_PATH_LITERAL(kPolicyFilename)); |
| + if (UnmanagedDeviceMarkerExists()) { |
| + // This is a non-first login on an unmanaged device. |
| + waiting_for_initial_policies_ = false; |
| + // Defer token_fetcher_ initialization until this device should ask for |
| + // a device token again. |
| + base::Time unmanaged_timestamp = GetUnmanagedDeviceTimestamp(); |
| + int64 delay = unmanaged_device_refresh_rate_ms_ - |
| + (base::Time::NowFromSystemTime().ToInternalValue() - |
| + unmanaged_timestamp.ToInternalValue()); |
| + if (delay < 0) |
| + delay = 0; |
| + BrowserThread::PostDelayedTask( |
| + BrowserThread::UI, FROM_HERE, |
| + new InitializeAfterIOThreadExistsTask(AsWeakPtr()), |
| + delay); |
| + } else { |
| + if (file_util::PathExists( |
| + storage_dir_.Append(FILE_PATH_LITERAL(kDeviceTokenFilename)))) { |
| + // This is a non-first login on a managed device. |
| + waiting_for_initial_policies_ = false; |
| + } |
| + // Defer initialization that requires the IOThread until after the IOThread |
| + // has been initialized. |
| + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| + new InitializeAfterIOThreadExistsTask(AsWeakPtr())); |
| + } |
| cache_.reset(new DeviceManagementPolicyCache(policy_path)); |
| cache_->LoadPolicyFromFile(); |
| - |
| - // Defer initialization that requires the IOThread until after the IOThread |
| - // has been initialized. |
| - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| - new InitializeAfterIOThreadExistsTask(AsWeakPtr())); |
| } |
| void DeviceManagementPolicyProvider::InitializeAfterIOThreadExists() { |
| const FilePath token_path = storage_dir_.Append( |
| - FILE_PATH_LITERAL("Token")); |
| + FILE_PATH_LITERAL(kDeviceTokenFilename)); |
| if (token_service_) { |
| token_fetcher_ = |
| new DeviceTokenFetcher(backend_.get(), token_service_, token_path); |
| @@ -181,17 +218,17 @@ void DeviceManagementPolicyProvider::InitializeAfterIOThreadExists() { |
| } |
| void DeviceManagementPolicyProvider::SendPolicyRequest() { |
| - if (!policy_request_pending_) { |
| - policy_request_pending_ = true; |
| - em::DevicePolicyRequest policy_request; |
| - policy_request.set_policy_scope(kChromePolicyScope); |
| - em::DevicePolicySettingRequest* setting = |
| - policy_request.add_setting_request(); |
| - setting->set_key(kChromeDevicePolicySettingKey); |
| - backend_->ProcessPolicyRequest(token_fetcher_->GetDeviceToken(), |
| - token_fetcher_->GetDeviceID(), |
| - policy_request, this); |
| - } |
| + if (policy_request_pending_) |
|
danno
2010/11/25 16:35:01
Why reverse this? Seems like an unrelated change.
Jakob Kummerow
2010/11/25 16:54:24
It is indeed unrelated and merely a formatting cha
|
| + return; |
| + policy_request_pending_ = true; |
| + em::DevicePolicyRequest policy_request; |
| + policy_request.set_policy_scope(kChromePolicyScope); |
| + em::DevicePolicySettingRequest* setting = |
| + policy_request.add_setting_request(); |
| + setting->set_key(kChromeDevicePolicySettingKey); |
| + backend_->ProcessPolicyRequest(token_fetcher_->GetDeviceToken(), |
| + token_fetcher_->GetDeviceID(), |
| + policy_request, this); |
| } |
| void DeviceManagementPolicyProvider::RefreshTaskExecute() { |
| @@ -231,6 +268,80 @@ int64 DeviceManagementPolicyProvider::GetRefreshTaskDelay() { |
| return delay; |
| } |
| +void DeviceManagementPolicyProvider::StopWaitingForInitialPolicies() { |
| + waiting_for_initial_policies_ = false; |
| +#if defined(OS_CHROMEOS) |
|
danno
2010/11/25 16:35:01
Do you need this #define here? sending the notific
Jakob Kummerow
2010/11/25 16:54:24
This is Markus' code, I only moved it. Battle it o
|
| + // Send a CLOUD_POLICY_UPDATE notification to unblock ChromeOS logins that |
| + // are waiting for an initial policy fetch to complete. |
| + NotifyCloudPolicyUpdate(); |
|
danno
2010/11/25 16:35:01
Would it be possible to create a specific observer
Jakob Kummerow
2010/11/25 16:54:24
Same as above -- not my code. I'm just keeping the
|
| +#endif |
| +} |
| + |
| +#if defined(OS_CHROMEOS) |
| +void DeviceManagementPolicyProvider::NotifyCloudPolicyUpdate() const { |
| + NotificationService::current()->Notify( |
| + NotificationType::CLOUD_POLICY_UPDATE, |
| + Source<DeviceManagementPolicyProvider>(this), |
| + NotificationService::NoDetails()); |
| +} |
| +#endif |
| + |
| +// static |
| +FilePath DeviceManagementPolicyProvider::GetUnmanagedDeviceMarkerPath( |
| + const FilePath& storage_dir) { |
| + return storage_dir.Append(FILE_PATH_LITERAL(kUnmanagedDeviceMarkerFilename)); |
| +} |
| + |
| +// static |
| +void DeviceManagementPolicyProvider::CreateUnmanagedDeviceMarker( |
| + const FilePath& storage_dir, const base::Time& timestamp) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| + std::string data; |
| + em::UnmanagedDevice unmanaged_device; |
| + unmanaged_device.set_timestamp(timestamp.ToInternalValue()); |
| + if (!unmanaged_device.SerializeToString(&data)) { |
| + LOG(WARNING) << "Failed to serialize UnmanagedDevice timestamp."; |
| + return; |
| + } |
| + int size = data.size(); |
| + FilePath path(GetUnmanagedDeviceMarkerPath(storage_dir)); |
| + if (file_util::WriteFile(path, data.c_str(), size) != size) { |
| + LOG(WARNING) << "Failed to write "<< path.value(); |
| + } |
| +} |
| + |
| +// static |
| +void DeviceManagementPolicyProvider::DeleteUnmanagedDeviceMarker( |
| + const FilePath& storage_dir) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| + FilePath marker_file = GetUnmanagedDeviceMarkerPath(storage_dir); |
| + if (file_util::PathExists(marker_file)) { |
| + if (!file_util::Delete(marker_file, false)) { |
| + LOG(WARNING) << "Failed to delete UnmanagedDevice marker from " |
| + << marker_file.value(); |
| + } |
| + } |
| +} |
| + |
| +bool DeviceManagementPolicyProvider::UnmanagedDeviceMarkerExists() { |
| + return file_util::PathExists(GetUnmanagedDeviceMarkerPath(storage_dir_)); |
| +} |
| + |
| +base::Time DeviceManagementPolicyProvider::GetUnmanagedDeviceTimestamp() { |
| + FilePath file_path(GetUnmanagedDeviceMarkerPath(storage_dir_)); |
| + DCHECK(file_util::PathExists(file_path)); |
| + std::string data; |
| + if (!file_util::ReadFileToString(file_path, &data)) { |
| + LOG(WARNING) << "Failed to read UnmanagedDevice timestamp from " |
| + << file_path.value(); |
| + } |
| + em::UnmanagedDevice unmanaged_device; |
| + if (!unmanaged_device.ParseFromArray(data.c_str(), data.size())) { |
| + LOG(WARNING) << "Failed to parse UnmanagedDevice timestamp."; |
| + } |
| + return base::Time::FromInternalValue(unmanaged_device.timestamp()); |
| +} |
| + |
| // static |
| std::string DeviceManagementPolicyProvider::GetDeviceManagementURL() { |
| return CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
| @@ -249,12 +360,8 @@ FilePath DeviceManagementPolicyProvider::GetOrCreateDeviceManagementDir( |
| return device_management_dir; |
| } |
| -bool DeviceManagementPolicyProvider::IsPolicyCacheEmpty() const { |
| - return cache_->last_policy_refresh_time().is_null(); |
| -} |
| - |
| bool DeviceManagementPolicyProvider::WaitingForInitialPolicies() const { |
| - return (IsPolicyCacheEmpty() && IsPolicyRequestPending()); |
| + return waiting_for_initial_policies_; |
| } |
| } // namespace policy |