Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(40)

Side by Side Diff: chrome/browser/policy/device_token_fetcher.cc

Issue 11946017: Remove old cloud policy code. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address nits. Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/policy/device_token_fetcher.h"
6
7 #include <algorithm>
8
9 #include "base/bind.h"
10 #include "base/metrics/histogram.h"
11 #include "base/time.h"
12 #include "chrome/browser/policy/cloud_policy_cache_base.h"
13 #include "chrome/browser/policy/cloud_policy_constants.h"
14 #include "chrome/browser/policy/cloud_policy_data_store.h"
15 #include "chrome/browser/policy/delayed_work_scheduler.h"
16 #include "chrome/browser/policy/device_management_service.h"
17 #include "chrome/browser/policy/enterprise_metrics.h"
18 #include "chrome/browser/policy/policy_notifier.h"
19 #include "chrome/browser/policy/proto/device_management_local.pb.h"
20
21 namespace em = enterprise_management;
22
23 namespace policy {
24
25 namespace {
26
27 // Retry after 5 minutes (with exponential backoff) after token fetch errors.
28 const int64 kTokenFetchErrorDelayMilliseconds = 5 * 60 * 1000;
29 // Retry after max 3 hours after token fetch errors.
30 const int64 kTokenFetchErrorMaxDelayMilliseconds = 3 * 60 * 60 * 1000;
31 // For unmanaged devices, check once per day whether they're still unmanaged.
32 const int64 kUnmanagedDeviceRefreshRateMilliseconds = 24 * 60 * 60 * 1000;
33
34 // Records the UMA metric corresponding to |status|, if it represents an error.
35 // Also records that a fetch response was received.
36 void SampleErrorStatus(DeviceManagementStatus status) {
37 UMA_HISTOGRAM_ENUMERATION(kMetricToken, kMetricTokenFetchResponseReceived,
38 kMetricTokenSize);
39 int sample = -1;
40 switch (status) {
41 case DM_STATUS_SUCCESS:
42 return;
43 case DM_STATUS_REQUEST_FAILED:
44 case DM_STATUS_REQUEST_INVALID:
45 case DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID:
46 sample = kMetricTokenFetchRequestFailed;
47 break;
48 case DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED:
49 sample = kMetricTokenFetchManagementNotSupported;
50 break;
51 case DM_STATUS_SERVICE_DEVICE_NOT_FOUND:
52 sample = kMetricTokenFetchDeviceNotFound;
53 break;
54 case DM_STATUS_SERVICE_DEVICE_ID_CONFLICT:
55 sample = kMetricTokenFetchDeviceIdConflict;
56 break;
57 case DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER:
58 sample = kMetricTokenFetchInvalidSerialNumber;
59 break;
60 case DM_STATUS_RESPONSE_DECODING_ERROR:
61 sample = kMetricTokenFetchBadResponse;
62 break;
63 case DM_STATUS_SERVICE_MISSING_LICENSES:
64 sample = kMetricMissingLicenses;
65 break;
66 case DM_STATUS_TEMPORARY_UNAVAILABLE:
67 case DM_STATUS_SERVICE_ACTIVATION_PENDING:
68 case DM_STATUS_SERVICE_POLICY_NOT_FOUND:
69 case DM_STATUS_HTTP_STATUS_ERROR:
70 sample = kMetricTokenFetchServerFailed;
71 break;
72 }
73 if (sample != -1)
74 UMA_HISTOGRAM_ENUMERATION(kMetricToken, sample, kMetricTokenSize);
75 else
76 NOTREACHED();
77 }
78
79 // Translates the DeviceRegisterResponse::DeviceMode |mode| to the enum used
80 // internally to represent different device modes.
81 DeviceMode TranslateProtobufDeviceMode(
82 em::DeviceRegisterResponse::DeviceMode mode) {
83 switch (mode) {
84 case em::DeviceRegisterResponse::ENTERPRISE:
85 return DEVICE_MODE_ENTERPRISE;
86 case em::DeviceRegisterResponse::RETAIL:
87 return DEVICE_MODE_KIOSK;
88 }
89 LOG(ERROR) << "Unknown enrollment mode in registration response: " << mode;
90 return DEVICE_MODE_PENDING;
91 }
92
93 } // namespace
94
95 DeviceTokenFetcher::DeviceTokenFetcher(
96 DeviceManagementService* service,
97 CloudPolicyCacheBase* cache,
98 CloudPolicyDataStore* data_store,
99 PolicyNotifier* notifier)
100 : effective_token_fetch_error_delay_ms_(
101 kTokenFetchErrorDelayMilliseconds) {
102 Initialize(service,
103 cache,
104 data_store,
105 notifier,
106 new DelayedWorkScheduler);
107 }
108
109 DeviceTokenFetcher::DeviceTokenFetcher(
110 DeviceManagementService* service,
111 CloudPolicyCacheBase* cache,
112 CloudPolicyDataStore* data_store,
113 PolicyNotifier* notifier,
114 DelayedWorkScheduler* scheduler)
115 : effective_token_fetch_error_delay_ms_(
116 kTokenFetchErrorDelayMilliseconds) {
117 Initialize(service, cache, data_store, notifier, scheduler);
118 }
119
120 DeviceTokenFetcher::~DeviceTokenFetcher() {
121 scheduler_->CancelDelayedWork();
122 }
123
124 void DeviceTokenFetcher::FetchToken() {
125 SetState(STATE_INACTIVE);
126 FetchTokenInternal();
127 }
128
129 void DeviceTokenFetcher::SetUnmanagedState() {
130 // The call to |cache_->SetUnmanaged()| has to happen first because it sets
131 // the timestamp that |SetState()| needs to determine the correct refresh
132 // time.
133 cache_->SetUnmanaged();
134 SetState(STATE_UNMANAGED);
135 }
136
137 void DeviceTokenFetcher::SetSerialNumberInvalidState() {
138 SetState(STATE_BAD_SERIAL);
139 }
140
141 void DeviceTokenFetcher::SetMissingLicensesState() {
142 SetState(STATE_MISSING_LICENSES);
143 }
144
145 void DeviceTokenFetcher::Reset() {
146 SetState(STATE_INACTIVE);
147 }
148
149 void DeviceTokenFetcher::Initialize(DeviceManagementService* service,
150 CloudPolicyCacheBase* cache,
151 CloudPolicyDataStore* data_store,
152 PolicyNotifier* notifier,
153 DelayedWorkScheduler* scheduler) {
154 service_ = service;
155 cache_ = cache;
156 notifier_ = notifier;
157 data_store_ = data_store;
158 effective_token_fetch_error_delay_ms_ = kTokenFetchErrorDelayMilliseconds;
159 state_ = STATE_INACTIVE;
160 scheduler_.reset(scheduler);
161
162 if (cache_->is_unmanaged())
163 SetState(STATE_UNMANAGED);
164 }
165
166 void DeviceTokenFetcher::FetchTokenInternal() {
167 DCHECK(state_ != STATE_TOKEN_AVAILABLE);
168 if (!data_store_->has_auth_token() || data_store_->device_id().empty()) {
169 // Maybe this device is unmanaged, just exit. The CloudPolicyController
170 // will call FetchToken() again if something changes.
171 return;
172 }
173 // Reinitialize |request_job_|, discarding any previous requests.
174 request_job_.reset(
175 service_->CreateJob(DeviceManagementRequestJob::TYPE_REGISTRATION));
176 request_job_->SetGaiaToken(data_store_->gaia_token());
177 request_job_->SetOAuthToken(data_store_->oauth_token());
178 request_job_->SetClientID(data_store_->device_id());
179 em::DeviceRegisterRequest* request =
180 request_job_->GetRequest()->mutable_register_request();
181 request->set_type(data_store_->policy_register_type());
182 if (!data_store_->machine_id().empty())
183 request->set_machine_id(data_store_->machine_id());
184 if (!data_store_->machine_model().empty())
185 request->set_machine_model(data_store_->machine_model());
186 if (data_store_->known_machine_id())
187 request->set_auto_enrolled(true);
188 if (data_store_->reregister())
189 request->set_reregister(true);
190 request_job_->Start(base::Bind(&DeviceTokenFetcher::OnTokenFetchCompleted,
191 base::Unretained(this)));
192 UMA_HISTOGRAM_ENUMERATION(kMetricToken, kMetricTokenFetchRequested,
193 kMetricTokenSize);
194 }
195
196 void DeviceTokenFetcher::OnTokenFetchCompleted(
197 DeviceManagementStatus status,
198 const em::DeviceManagementResponse& response) {
199 if (status == DM_STATUS_SUCCESS && !response.has_register_response()) {
200 // Handled below.
201 status = DM_STATUS_RESPONSE_DECODING_ERROR;
202 }
203
204 LOG_IF(ERROR, status != DM_STATUS_SUCCESS) << "DMServer returned error code: "
205 << status;
206 SampleErrorStatus(status);
207
208 switch (status) {
209 case DM_STATUS_SUCCESS: {
210 const em::DeviceRegisterResponse& register_response =
211 response.register_response();
212 if (register_response.has_device_management_token()) {
213 UMA_HISTOGRAM_ENUMERATION(kMetricToken, kMetricTokenFetchOK,
214 kMetricTokenSize);
215
216 if (data_store_->policy_register_type() ==
217 em::DeviceRegisterRequest::DEVICE) {
218 DeviceMode mode = DEVICE_MODE_ENTERPRISE;
219 if (register_response.has_enrollment_type()) {
220 mode = TranslateProtobufDeviceMode(
221 register_response.enrollment_type());
222 }
223 if (mode == DEVICE_MODE_PENDING) {
224 LOG(ERROR) << "Enrollment mode missing or unknown!";
225 SetState(STATE_BAD_ENROLLMENT_MODE);
226 return;
227 }
228 data_store_->set_device_mode(mode);
229 }
230 data_store_->SetDeviceToken(register_response.device_management_token(),
231 false);
232 SetState(STATE_TOKEN_AVAILABLE);
233 } else {
234 NOTREACHED();
235 UMA_HISTOGRAM_ENUMERATION(kMetricToken, kMetricTokenFetchBadResponse,
236 kMetricTokenSize);
237 SetState(STATE_ERROR);
238 }
239 return;
240 }
241 case DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED:
242 SetUnmanagedState();
243 return;
244 case DM_STATUS_REQUEST_FAILED:
245 case DM_STATUS_TEMPORARY_UNAVAILABLE:
246 case DM_STATUS_SERVICE_DEVICE_NOT_FOUND:
247 case DM_STATUS_SERVICE_DEVICE_ID_CONFLICT:
248 SetState(STATE_TEMPORARY_ERROR);
249 return;
250 case DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID:
251 // Most probably the GAIA auth cookie has expired. We can not do anything
252 // until the user logs-in again.
253 SetState(STATE_BAD_AUTH);
254 return;
255 case DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER:
256 SetSerialNumberInvalidState();
257 return;
258 case DM_STATUS_SERVICE_MISSING_LICENSES:
259 SetMissingLicensesState();
260 return;
261 case DM_STATUS_REQUEST_INVALID:
262 case DM_STATUS_HTTP_STATUS_ERROR:
263 case DM_STATUS_RESPONSE_DECODING_ERROR:
264 case DM_STATUS_SERVICE_ACTIVATION_PENDING:
265 case DM_STATUS_SERVICE_POLICY_NOT_FOUND:
266 SetState(STATE_ERROR);
267 return;
268 }
269 NOTREACHED();
270 SetState(STATE_ERROR);
271 }
272
273 void DeviceTokenFetcher::SetState(FetcherState state) {
274 state_ = state;
275 if (state_ != STATE_TEMPORARY_ERROR)
276 effective_token_fetch_error_delay_ms_ = kTokenFetchErrorDelayMilliseconds;
277
278 request_job_.reset(); // Stop any pending requests.
279
280 base::Time delayed_work_at;
281 switch (state_) {
282 case STATE_INACTIVE:
283 notifier_->Inform(CloudPolicySubsystem::UNENROLLED,
284 CloudPolicySubsystem::NO_DETAILS,
285 PolicyNotifier::TOKEN_FETCHER);
286 break;
287 case STATE_TOKEN_AVAILABLE:
288 notifier_->Inform(CloudPolicySubsystem::SUCCESS,
289 CloudPolicySubsystem::NO_DETAILS,
290 PolicyNotifier::TOKEN_FETCHER);
291 break;
292 case STATE_BAD_SERIAL:
293 notifier_->Inform(CloudPolicySubsystem::UNENROLLED,
294 CloudPolicySubsystem::BAD_SERIAL_NUMBER,
295 PolicyNotifier::TOKEN_FETCHER);
296 break;
297 case STATE_BAD_ENROLLMENT_MODE:
298 notifier_->Inform(CloudPolicySubsystem::UNENROLLED,
299 CloudPolicySubsystem::BAD_ENROLLMENT_MODE,
300 PolicyNotifier::TOKEN_FETCHER);
301 break;
302 case STATE_MISSING_LICENSES:
303 notifier_->Inform(CloudPolicySubsystem::UNENROLLED,
304 CloudPolicySubsystem::MISSING_LICENSES,
305 PolicyNotifier::TOKEN_FETCHER);
306 break;
307 case STATE_UNMANAGED:
308 delayed_work_at = cache_->last_policy_refresh_time() +
309 base::TimeDelta::FromMilliseconds(
310 kUnmanagedDeviceRefreshRateMilliseconds);
311 notifier_->Inform(CloudPolicySubsystem::UNMANAGED,
312 CloudPolicySubsystem::NO_DETAILS,
313 PolicyNotifier::TOKEN_FETCHER);
314 break;
315 case STATE_TEMPORARY_ERROR:
316 delayed_work_at = base::Time::Now() +
317 base::TimeDelta::FromMilliseconds(
318 effective_token_fetch_error_delay_ms_);
319 effective_token_fetch_error_delay_ms_ =
320 std::min(effective_token_fetch_error_delay_ms_ * 2,
321 kTokenFetchErrorMaxDelayMilliseconds);
322 notifier_->Inform(CloudPolicySubsystem::NETWORK_ERROR,
323 CloudPolicySubsystem::DMTOKEN_NETWORK_ERROR,
324 PolicyNotifier::TOKEN_FETCHER);
325 break;
326 case STATE_ERROR:
327 effective_token_fetch_error_delay_ms_ =
328 kTokenFetchErrorMaxDelayMilliseconds;
329 delayed_work_at = base::Time::Now() +
330 base::TimeDelta::FromMilliseconds(
331 effective_token_fetch_error_delay_ms_);
332 notifier_->Inform(CloudPolicySubsystem::NETWORK_ERROR,
333 CloudPolicySubsystem::DMTOKEN_NETWORK_ERROR,
334 PolicyNotifier::TOKEN_FETCHER);
335 break;
336 case STATE_BAD_AUTH:
337 // Can't do anything, need to wait for new credentials.
338 notifier_->Inform(CloudPolicySubsystem::BAD_GAIA_TOKEN,
339 CloudPolicySubsystem::NO_DETAILS,
340 PolicyNotifier::TOKEN_FETCHER);
341 break;
342 }
343
344 scheduler_->CancelDelayedWork();
345 if (!delayed_work_at.is_null()) {
346 base::Time now(base::Time::Now());
347 int64 delay = std::max<int64>((delayed_work_at - now).InMilliseconds(), 0);
348 scheduler_->PostDelayedWork(
349 base::Bind(&DeviceTokenFetcher::DoWork, base::Unretained(this)), delay);
350 }
351
352 // Inform the cache if a token fetch attempt has failed.
353 if (state_ != STATE_INACTIVE && state_ != STATE_TOKEN_AVAILABLE)
354 cache_->SetFetchingDone();
355 }
356
357 void DeviceTokenFetcher::DoWork() {
358 switch (state_) {
359 case STATE_INACTIVE:
360 case STATE_TOKEN_AVAILABLE:
361 case STATE_BAD_SERIAL:
362 case STATE_BAD_ENROLLMENT_MODE:
363 case STATE_MISSING_LICENSES:
364 break;
365 case STATE_UNMANAGED:
366 case STATE_ERROR:
367 case STATE_TEMPORARY_ERROR:
368 case STATE_BAD_AUTH:
369 FetchTokenInternal();
370 break;
371 }
372 }
373
374 } // namespace policy
OLDNEW
« no previous file with comments | « chrome/browser/policy/device_token_fetcher.h ('k') | chrome/browser/policy/device_token_fetcher_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698