OLD | NEW |
---|---|
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/policy/device_management_policy_provider.h" | 5 #include "chrome/browser/policy/device_management_policy_provider.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
9 #include "base/path_service.h" | 9 #include "base/path_service.h" |
10 #include "base/rand_util.h" | |
10 #include "base/task.h" | 11 #include "base/task.h" |
11 #include "base/time.h" | |
12 #include "chrome/browser/browser_thread.h" | 12 #include "chrome/browser/browser_thread.h" |
13 #include "chrome/browser/policy/device_management_backend.h" | 13 #include "chrome/browser/policy/device_management_backend.h" |
14 #include "chrome/browser/policy/device_management_backend_impl.h" | 14 #include "chrome/browser/policy/device_management_backend_impl.h" |
15 #include "chrome/browser/policy/device_management_policy_cache.h" | 15 #include "chrome/browser/policy/device_management_policy_cache.h" |
16 #include "chrome/browser/policy/device_token_fetcher.h" | |
17 #include "chrome/common/chrome_paths.h" | 16 #include "chrome/common/chrome_paths.h" |
18 #include "chrome/common/chrome_switches.h" | 17 #include "chrome/common/chrome_switches.h" |
19 #include "chrome/common/notification_service.h" | 18 #include "chrome/common/notification_service.h" |
20 #include "chrome/common/notification_type.h" | 19 #include "chrome/common/notification_type.h" |
21 | 20 |
22 namespace { | 21 namespace { |
23 | 22 |
24 const char kChromePolicyScope[] = "cros/device"; | 23 const char kChromePolicyScope[] = "cros/device"; |
25 const char kChromeDevicePolicySettingKey[] = "chrome-policy"; | 24 const char kChromeDevicePolicySettingKey[] = "chrome-policy"; |
26 const int64 kPolicyRefreshRateInMinutes = 3 * 60; // 3 hours | 25 const int64 kPolicyRefreshRateInMilliseconds = 3 * 60 * 60 * 1000; // 3 hours |
26 const int64 kPolicyRefreshMaxEarlierInMilliseconds = 20 * 60 * 1000; // 20 mins | |
27 // These are the base values for delays before retrying after an error. They | |
28 // will be doubled each time they are used. | |
29 const int64 kPolicyRefreshErrorDelayInMilliseconds = 3 * 1000; // 3 seconds | |
30 const int64 kDeviceTokenRefreshErrorDelayInMilliseconds = 3 * 1000; | |
27 | 31 |
28 } // namespace | 32 } // namespace |
29 | 33 |
30 namespace policy { | 34 namespace policy { |
31 | 35 |
32 // Ensures that the portion of the policy provider implementation that requires | 36 // Ensures that the portion of the policy provider implementation that requires |
33 // the IOThread is deferred until the IOThread is fully initialized. The policy | 37 // the IOThread is deferred until the IOThread is fully initialized. The policy |
34 // provider posts this task on the UI thread during its constructor, thereby | 38 // provider posts this task on the UI thread during its constructor, thereby |
35 // guaranteeing that the code won't get executed until after the UI and IO | 39 // guaranteeing that the code won't get executed until after the UI and IO |
36 // threads are fully constructed. | 40 // threads are fully constructed. |
37 class DeviceManagementPolicyProvider::InitializeAfterIOThreadExistsTask | 41 class DeviceManagementPolicyProvider::InitializeAfterIOThreadExistsTask |
38 : public Task { | 42 : public Task { |
39 public: | 43 public: |
40 explicit InitializeAfterIOThreadExistsTask( | 44 explicit InitializeAfterIOThreadExistsTask( |
41 base::WeakPtr<DeviceManagementPolicyProvider> provider) | 45 base::WeakPtr<DeviceManagementPolicyProvider> provider) |
42 : provider_(provider) { | 46 : provider_(provider) { |
43 } | 47 } |
44 | 48 |
45 // Task implementation: | 49 // Task implementation: |
46 virtual void Run() { | 50 virtual void Run() { |
47 DeviceManagementPolicyProvider* provider = provider_.get(); | 51 DeviceManagementPolicyProvider* provider = provider_.get(); |
48 if (provider) | 52 if (provider) |
49 provider->InitializeAfterIOThreadExists(); | 53 provider->InitializeAfterIOThreadExists(); |
50 } | 54 } |
51 | 55 |
52 private: | 56 private: |
53 base::WeakPtr<DeviceManagementPolicyProvider> provider_; | 57 base::WeakPtr<DeviceManagementPolicyProvider> provider_; |
54 }; | 58 }; |
55 | 59 |
60 class DeviceManagementPolicyProvider::RefreshTask : public Task { | |
61 public: | |
62 explicit RefreshTask(base::WeakPtr<DeviceManagementPolicyProvider> provider) | |
63 : provider_(provider) {} | |
64 | |
65 // Task implementation: | |
66 virtual void Run() { | |
67 DeviceManagementPolicyProvider* provider = provider_.get(); | |
68 if (provider) | |
69 provider->RefreshTaskExecute(); | |
70 } | |
71 | |
72 private: | |
73 base::WeakPtr<DeviceManagementPolicyProvider> provider_; | |
74 }; | |
75 | |
56 DeviceManagementPolicyProvider::DeviceManagementPolicyProvider( | 76 DeviceManagementPolicyProvider::DeviceManagementPolicyProvider( |
57 const ConfigurationPolicyProvider::PolicyDefinitionList* policy_list, | 77 const ConfigurationPolicyProvider::PolicyDefinitionList* policy_list, |
58 DeviceManagementBackend* backend, | 78 DeviceManagementBackend* backend, |
59 TokenService* token_service, | 79 TokenService* token_service, |
60 const FilePath& storage_dir) | 80 const FilePath& storage_dir) |
61 : ConfigurationPolicyProvider(policy_list), | 81 : ConfigurationPolicyProvider(policy_list), |
62 backend_(backend), | 82 backend_(backend), |
63 token_service_(token_service), | 83 token_service_(token_service), |
64 storage_dir_(GetOrCreateDeviceManagementDir(storage_dir)), | 84 storage_dir_(GetOrCreateDeviceManagementDir(storage_dir)), |
65 policy_request_pending_(false) { | 85 policy_request_pending_(false), |
86 refresh_task_pending_(false), | |
87 policy_refresh_rate_ms_(kPolicyRefreshRateInMilliseconds), | |
88 policy_refresh_max_earlier_ms_(kPolicyRefreshMaxEarlierInMilliseconds), | |
89 policy_refresh_error_delay_ms_(kPolicyRefreshErrorDelayInMilliseconds), | |
90 token_fetch_error_delay_ms_(kDeviceTokenRefreshErrorDelayInMilliseconds) { | |
66 Initialize(); | 91 Initialize(); |
67 } | 92 } |
68 | 93 |
69 DeviceManagementPolicyProvider::~DeviceManagementPolicyProvider() {} | 94 DeviceManagementPolicyProvider::~DeviceManagementPolicyProvider() {} |
70 | 95 |
71 bool DeviceManagementPolicyProvider::Provide( | 96 bool DeviceManagementPolicyProvider::Provide( |
72 ConfigurationPolicyStoreInterface* policy_store) { | 97 ConfigurationPolicyStoreInterface* policy_store) { |
73 scoped_ptr<DictionaryValue> policies(cache_->GetPolicy()); | 98 scoped_ptr<DictionaryValue> policies(cache_->GetPolicy()); |
74 DecodePolicyValueTree(policies.get(), policy_store); | 99 DecodePolicyValueTree(policies.get(), policy_store); |
75 return true; | 100 return true; |
76 } | 101 } |
77 | 102 |
78 void DeviceManagementPolicyProvider::Observe( | |
79 NotificationType type, | |
80 const NotificationSource& source, | |
81 const NotificationDetails& details) { | |
82 if (type == NotificationType::DEVICE_TOKEN_AVAILABLE) { | |
83 if (token_fetcher_.get() == Source<DeviceTokenFetcher>(source).ptr() && | |
84 !policy_request_pending_ && | |
85 IsPolicyStale()) { | |
86 SendPolicyRequest(); | |
87 } | |
88 } else { | |
89 NOTREACHED(); | |
90 } | |
91 } | |
92 | |
93 void DeviceManagementPolicyProvider::HandlePolicyResponse( | 103 void DeviceManagementPolicyProvider::HandlePolicyResponse( |
94 const em::DevicePolicyResponse& response) { | 104 const em::DevicePolicyResponse& response) { |
95 cache_->SetPolicy(response); | 105 if (cache_->SetPolicy(response)) |
96 NotifyStoreOfPolicyChange(); | 106 NotifyStoreOfPolicyChange(); |
97 policy_request_pending_ = false; | 107 policy_request_pending_ = false; |
108 // Reset the error delay since policy fetching succeeded this time. | |
109 policy_refresh_error_delay_ms_ = kPolicyRefreshErrorDelayInMilliseconds; | |
110 ScheduleRefreshTask(GetRefreshTaskDelay( | |
111 policy_refresh_rate_ms_, policy_refresh_max_earlier_ms_)); | |
98 } | 112 } |
99 | 113 |
100 void DeviceManagementPolicyProvider::OnError( | 114 void DeviceManagementPolicyProvider::OnError( |
101 DeviceManagementBackend::ErrorCode code) { | 115 DeviceManagementBackend::ErrorCode code) { |
102 LOG(WARNING) << "could not provide policy from the device manager (error = " | 116 LOG(WARNING) << "Could not provide policy from the device manager (error = " |
103 << code << ")"; | 117 << code << ")"; |
danno
2010/11/22 13:47:50
you may want to add a "retrying in x millis ...."
Jakob Kummerow (corp)
2010/11/22 16:56:08
Done.
| |
104 policy_request_pending_ = false; | 118 policy_request_pending_ = false; |
105 // TODO(danno): do something sensible in the error case, perhaps retry later? | 119 policy_refresh_error_delay_ms_ *= 2; |
120 if (policy_refresh_rate_ms_ && | |
121 policy_refresh_rate_ms_ < policy_refresh_error_delay_ms_) { | |
122 policy_refresh_error_delay_ms_ = policy_refresh_rate_ms_; | |
123 } | |
124 ScheduleRefreshTask(policy_refresh_error_delay_ms_); | |
125 } | |
126 | |
127 void DeviceManagementPolicyProvider::OnTokenSuccess() { | |
128 if (policy_request_pending_) | |
129 return; | |
130 SendPolicyRequest(); | |
131 } | |
132 | |
133 void DeviceManagementPolicyProvider::OnTokenError() { | |
134 LOG(WARNING) << "Could not retrieve device token."; | |
135 token_fetch_error_delay_ms_ *= 2; | |
136 if (token_fetch_error_delay_ms_ > policy_refresh_rate_ms_) | |
137 token_fetch_error_delay_ms_ = policy_refresh_rate_ms_; | |
138 ScheduleRefreshTask(token_fetch_error_delay_ms_); | |
danno
2010/11/22 13:47:50
Perhaps a second, token-specific task to address m
Jakob Kummerow (corp)
2010/11/22 16:56:08
See my answer below.
| |
106 } | 139 } |
107 | 140 |
108 void DeviceManagementPolicyProvider::Shutdown() { | 141 void DeviceManagementPolicyProvider::Shutdown() { |
109 token_service_ = NULL; | 142 token_service_ = NULL; |
110 if (token_fetcher_) | 143 if (token_fetcher_) |
111 token_fetcher_->Shutdown(); | 144 token_fetcher_->Shutdown(); |
112 } | 145 } |
113 | 146 |
114 DeviceManagementBackend* DeviceManagementPolicyProvider::GetBackend() { | 147 DeviceManagementBackend* DeviceManagementPolicyProvider::GetBackend() { |
115 if (!backend_.get()) { | 148 if (!backend_.get()) { |
116 backend_.reset(new DeviceManagementBackendImpl( | 149 backend_.reset(new DeviceManagementBackendImpl( |
117 GetDeviceManagementURL())); | 150 GetDeviceManagementURL())); |
118 } | 151 } |
119 return backend_.get(); | 152 return backend_.get(); |
120 } | 153 } |
121 | 154 |
122 void DeviceManagementPolicyProvider::Initialize() { | 155 void DeviceManagementPolicyProvider::Initialize() { |
123 registrar_.Add(this, | |
124 NotificationType::DEVICE_TOKEN_AVAILABLE, | |
125 NotificationService::AllSources()); | |
126 | |
127 const FilePath policy_path = storage_dir_.Append( | 156 const FilePath policy_path = storage_dir_.Append( |
128 FILE_PATH_LITERAL("Policy")); | 157 FILE_PATH_LITERAL("Policy")); |
129 cache_.reset(new DeviceManagementPolicyCache(policy_path)); | 158 cache_.reset(new DeviceManagementPolicyCache(policy_path)); |
130 cache_->LoadPolicyFromFile(); | 159 cache_->LoadPolicyFromFile(); |
131 | 160 |
132 // Defer initialization that requires the IOThread until after the IOThread | 161 // Defer initialization that requires the IOThread until after the IOThread |
133 // has been initialized. | 162 // has been initialized. |
134 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 163 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
135 new InitializeAfterIOThreadExistsTask(AsWeakPtr())); | 164 new InitializeAfterIOThreadExistsTask(AsWeakPtr())); |
136 } | 165 } |
137 | 166 |
138 void DeviceManagementPolicyProvider::InitializeAfterIOThreadExists() { | 167 void DeviceManagementPolicyProvider::InitializeAfterIOThreadExists() { |
139 const FilePath token_path = storage_dir_.Append( | 168 const FilePath token_path = storage_dir_.Append( |
140 FILE_PATH_LITERAL("Token")); | 169 FILE_PATH_LITERAL("Token")); |
141 if (token_service_) { | 170 if (token_service_) { |
142 token_fetcher_ = | 171 token_fetcher_ = |
143 new DeviceTokenFetcher(GetBackend(), token_service_, token_path); | 172 new DeviceTokenFetcher(GetBackend(), token_service_, token_path); |
173 token_fetcher_->AddObserver(this); | |
danno
2010/11/22 13:47:50
What ensures that the observer gets removed? You p
Jakob Kummerow (corp)
2010/11/22 16:56:08
Done.
Added a registrar mechanism.
| |
144 token_fetcher_->StartFetching(); | 174 token_fetcher_->StartFetching(); |
145 } | 175 } |
146 } | 176 } |
147 | 177 |
148 void DeviceManagementPolicyProvider::SendPolicyRequest() { | 178 void DeviceManagementPolicyProvider::SendPolicyRequest() { |
149 if (!policy_request_pending_) { | 179 if (!policy_request_pending_) { |
180 policy_request_pending_ = true; | |
150 em::DevicePolicyRequest policy_request; | 181 em::DevicePolicyRequest policy_request; |
151 policy_request.set_policy_scope(kChromePolicyScope); | 182 policy_request.set_policy_scope(kChromePolicyScope); |
152 em::DevicePolicySettingRequest* setting = | 183 em::DevicePolicySettingRequest* setting = |
153 policy_request.add_setting_request(); | 184 policy_request.add_setting_request(); |
154 setting->set_key(kChromeDevicePolicySettingKey); | 185 setting->set_key(kChromeDevicePolicySettingKey); |
155 GetBackend()->ProcessPolicyRequest(token_fetcher_->GetDeviceToken(), | 186 GetBackend()->ProcessPolicyRequest(token_fetcher_->GetDeviceToken(), |
156 policy_request, | 187 policy_request, |
157 this); | 188 this); |
158 policy_request_pending_ = true; | 189 } else { |
190 LOG(WARNING) << "Not sending another PolicyRequest."; | |
159 } | 191 } |
160 } | 192 } |
161 | 193 |
162 bool DeviceManagementPolicyProvider::IsPolicyStale() const { | 194 void DeviceManagementPolicyProvider::RefreshTaskExecute() { |
danno
2010/11/22 13:47:50
Combining both the token request and the policy re
Jakob Kummerow (corp)
2010/11/22 16:56:08
I don't see what's wrong with a task that assesses
| |
163 base::Time now(base::Time::NowFromSystemTime()); | 195 refresh_task_pending_ = false; |
danno
2010/11/22 13:47:50
DCHECK(refresh_task_pending_) before?
Jakob Kummerow (corp)
2010/11/22 16:56:08
Done.
| |
164 base::Time last_policy_refresh_time = | 196 // If there is no valid device token, the token_fetcher_ apparently failed, |
165 cache_->last_policy_refresh_time(); | 197 // so it must be restarted. |
166 base::Time policy_expiration_time = | 198 if (!token_fetcher_->IsTokenValid()) { |
167 last_policy_refresh_time + base::TimeDelta::FromMinutes( | 199 if (token_fetcher_->IsTokenPending()) { |
168 kPolicyRefreshRateInMinutes); | 200 NOTREACHED(); |
169 return (now > policy_expiration_time); | 201 return; |
202 } | |
203 token_fetcher_->Restart(); | |
204 return; | |
205 } | |
206 // If there is a device token, just refresh policies. | |
207 SendPolicyRequest(); | |
208 } | |
209 | |
210 void DeviceManagementPolicyProvider::ScheduleRefreshTask( | |
211 int64 delay_in_milliseconds) { | |
212 // This check is simply a safeguard, the situation currently cannot happen. | |
213 if (refresh_task_pending_) { | |
214 NOTREACHED(); | |
215 return; | |
216 } | |
217 refresh_task_pending_ = true; | |
218 BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE, | |
219 new RefreshTask(AsWeakPtr()), | |
220 delay_in_milliseconds); | |
170 } | 221 } |
171 | 222 |
172 // static | 223 // static |
224 int64 DeviceManagementPolicyProvider::GetRefreshTaskDelay( | |
225 int64 policy_refresh_rate_ms, | |
226 int64 policy_refresh_max_random_earlier_ms) { | |
227 if (policy_refresh_max_random_earlier_ms) | |
228 policy_refresh_rate_ms -= | |
229 base::RandGenerator(policy_refresh_max_random_earlier_ms); | |
230 return policy_refresh_rate_ms; | |
231 } | |
232 | |
233 // static | |
173 std::string DeviceManagementPolicyProvider::GetDeviceManagementURL() { | 234 std::string DeviceManagementPolicyProvider::GetDeviceManagementURL() { |
174 return CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | 235 return CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
175 switches::kDeviceManagementUrl); | 236 switches::kDeviceManagementUrl); |
176 } | 237 } |
177 | 238 |
178 // static | 239 // static |
179 FilePath DeviceManagementPolicyProvider::GetOrCreateDeviceManagementDir( | 240 FilePath DeviceManagementPolicyProvider::GetOrCreateDeviceManagementDir( |
180 const FilePath& user_data_dir) { | 241 const FilePath& user_data_dir) { |
181 const FilePath device_management_dir = user_data_dir.Append( | 242 const FilePath device_management_dir = user_data_dir.Append( |
182 FILE_PATH_LITERAL("Device Management")); | 243 FILE_PATH_LITERAL("Device Management")); |
183 if (!file_util::DirectoryExists(device_management_dir)) { | 244 if (!file_util::DirectoryExists(device_management_dir)) { |
184 if (!file_util::CreateDirectory(device_management_dir)) | 245 if (!file_util::CreateDirectory(device_management_dir)) |
185 NOTREACHED(); | 246 NOTREACHED(); |
186 } | 247 } |
187 return device_management_dir; | 248 return device_management_dir; |
188 } | 249 } |
189 | 250 |
190 } // namespace policy | 251 } // namespace policy |
OLD | NEW |