| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 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_token_fetcher.h" | 5 #include "chrome/browser/policy/device_token_fetcher.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
| 11 #include "base/time.h" | 11 #include "base/time.h" |
| 12 #include "chrome/browser/policy/cloud_policy_cache_base.h" | 12 #include "chrome/browser/policy/cloud_policy_cache_base.h" |
| 13 #include "chrome/browser/policy/cloud_policy_constants.h" |
| 13 #include "chrome/browser/policy/cloud_policy_data_store.h" | 14 #include "chrome/browser/policy/cloud_policy_data_store.h" |
| 14 #include "chrome/browser/policy/delayed_work_scheduler.h" | 15 #include "chrome/browser/policy/delayed_work_scheduler.h" |
| 15 #include "chrome/browser/policy/device_management_service.h" | 16 #include "chrome/browser/policy/device_management_service.h" |
| 16 #include "chrome/browser/policy/enterprise_metrics.h" | 17 #include "chrome/browser/policy/enterprise_metrics.h" |
| 17 #include "chrome/browser/policy/policy_notifier.h" | 18 #include "chrome/browser/policy/policy_notifier.h" |
| 18 #include "chrome/browser/policy/proto/device_management_constants.h" | |
| 19 #include "chrome/browser/policy/proto/device_management_local.pb.h" | 19 #include "chrome/browser/policy/proto/device_management_local.pb.h" |
| 20 | 20 |
| 21 namespace { | 21 namespace { |
| 22 | 22 |
| 23 // Retry after 5 minutes (with exponential backoff) after token fetch errors. | 23 // Retry after 5 minutes (with exponential backoff) after token fetch errors. |
| 24 const int64 kTokenFetchErrorDelayMilliseconds = 5 * 60 * 1000; | 24 const int64 kTokenFetchErrorDelayMilliseconds = 5 * 60 * 1000; |
| 25 // Retry after max 3 hours after token fetch errors. | 25 // Retry after max 3 hours after token fetch errors. |
| 26 const int64 kTokenFetchErrorMaxDelayMilliseconds = 3 * 60 * 60 * 1000; | 26 const int64 kTokenFetchErrorMaxDelayMilliseconds = 3 * 60 * 60 * 1000; |
| 27 // For unmanaged devices, check once per day whether they're still unmanaged. | 27 // For unmanaged devices, check once per day whether they're still unmanaged. |
| 28 const int64 kUnmanagedDeviceRefreshRateMilliseconds = 24 * 60 * 60 * 1000; | 28 const int64 kUnmanagedDeviceRefreshRateMilliseconds = 24 * 60 * 60 * 1000; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 56 | 56 |
| 57 DeviceTokenFetcher::~DeviceTokenFetcher() { | 57 DeviceTokenFetcher::~DeviceTokenFetcher() { |
| 58 scheduler_->CancelDelayedWork(); | 58 scheduler_->CancelDelayedWork(); |
| 59 } | 59 } |
| 60 | 60 |
| 61 void DeviceTokenFetcher::FetchToken() { | 61 void DeviceTokenFetcher::FetchToken() { |
| 62 SetState(STATE_INACTIVE); | 62 SetState(STATE_INACTIVE); |
| 63 FetchTokenInternal(); | 63 FetchTokenInternal(); |
| 64 } | 64 } |
| 65 | 65 |
| 66 void DeviceTokenFetcher::FetchTokenInternal() { | |
| 67 DCHECK(state_ != STATE_TOKEN_AVAILABLE); | |
| 68 if (!data_store_->has_auth_token() || data_store_->device_id().empty()) { | |
| 69 // Maybe this device is unmanaged, just exit. The CloudPolicyController | |
| 70 // will call FetchToken() again if something changes. | |
| 71 return; | |
| 72 } | |
| 73 // Construct a new backend, which will discard any previous requests. | |
| 74 backend_.reset(service_->CreateBackend()); | |
| 75 em::DeviceRegisterRequest request; | |
| 76 request.set_type(data_store_->policy_register_type()); | |
| 77 if (!data_store_->machine_id().empty()) | |
| 78 request.set_machine_id(data_store_->machine_id()); | |
| 79 if (!data_store_->machine_model().empty()) | |
| 80 request.set_machine_model(data_store_->machine_model()); | |
| 81 backend_->ProcessRegisterRequest(data_store_->gaia_token(), | |
| 82 data_store_->oauth_token(), | |
| 83 data_store_->device_id(), | |
| 84 request, this); | |
| 85 } | |
| 86 | |
| 87 void DeviceTokenFetcher::SetUnmanagedState() { | 66 void DeviceTokenFetcher::SetUnmanagedState() { |
| 88 // The call to |cache_->SetUnmanaged()| has to happen first because it sets | 67 // The call to |cache_->SetUnmanaged()| has to happen first because it sets |
| 89 // the timestamp that |SetState()| needs to determine the correct refresh | 68 // the timestamp that |SetState()| needs to determine the correct refresh |
| 90 // time. | 69 // time. |
| 91 cache_->SetUnmanaged(); | 70 cache_->SetUnmanaged(); |
| 92 SetState(STATE_UNMANAGED); | 71 SetState(STATE_UNMANAGED); |
| 93 } | 72 } |
| 94 | 73 |
| 95 void DeviceTokenFetcher::SetSerialNumberInvalidState() { | 74 void DeviceTokenFetcher::SetSerialNumberInvalidState() { |
| 96 SetState(STATE_BAD_SERIAL); | 75 SetState(STATE_BAD_SERIAL); |
| 97 } | 76 } |
| 98 | 77 |
| 99 void DeviceTokenFetcher::Reset() { | 78 void DeviceTokenFetcher::Reset() { |
| 100 SetState(STATE_INACTIVE); | 79 SetState(STATE_INACTIVE); |
| 101 } | 80 } |
| 102 | 81 |
| 103 void DeviceTokenFetcher::HandleRegisterResponse( | 82 void DeviceTokenFetcher::Initialize(DeviceManagementService* service, |
| 104 const em::DeviceRegisterResponse& response) { | 83 CloudPolicyCacheBase* cache, |
| 105 if (response.has_device_management_token()) { | 84 CloudPolicyDataStore* data_store, |
| 106 UMA_HISTOGRAM_ENUMERATION(kMetricToken, kMetricTokenFetchOK, | 85 PolicyNotifier* notifier, |
| 107 kMetricTokenSize); | 86 DelayedWorkScheduler* scheduler) { |
| 108 data_store_->SetDeviceToken(response.device_management_token(), false); | 87 service_ = service; |
| 109 SetState(STATE_TOKEN_AVAILABLE); | 88 cache_ = cache; |
| 110 } else { | 89 notifier_ = notifier; |
| 111 NOTREACHED(); | 90 data_store_ = data_store; |
| 112 UMA_HISTOGRAM_ENUMERATION(kMetricToken, kMetricTokenFetchBadResponse, | 91 effective_token_fetch_error_delay_ms_ = kTokenFetchErrorDelayMilliseconds; |
| 113 kMetricTokenSize); | 92 state_ = STATE_INACTIVE; |
| 114 SetState(STATE_ERROR); | 93 scheduler_.reset(scheduler); |
| 115 } | 94 |
| 95 if (cache_->is_unmanaged()) |
| 96 SetState(STATE_UNMANAGED); |
| 116 } | 97 } |
| 117 | 98 |
| 118 void DeviceTokenFetcher::OnError(DeviceManagementBackend::ErrorCode code) { | 99 void DeviceTokenFetcher::FetchTokenInternal() { |
| 119 switch (code) { | 100 DCHECK(state_ != STATE_TOKEN_AVAILABLE); |
| 120 case DeviceManagementBackend::kErrorServiceManagementNotSupported: | 101 if (!data_store_->has_auth_token() || data_store_->device_id().empty()) { |
| 102 // Maybe this device is unmanaged, just exit. The CloudPolicyController |
| 103 // will call FetchToken() again if something changes. |
| 104 return; |
| 105 } |
| 106 // Reinitialize |request_job_|, discarding any previous requests. |
| 107 request_job_.reset( |
| 108 service_->CreateJob(DeviceManagementRequestJob::TYPE_REGISTRATION)); |
| 109 request_job_->SetGaiaToken(data_store_->gaia_token()); |
| 110 request_job_->SetOAuthToken(data_store_->oauth_token()); |
| 111 request_job_->SetClientID(data_store_->device_id()); |
| 112 em::DeviceRegisterRequest* request = |
| 113 request_job_->GetRequest()->mutable_register_request(); |
| 114 request->set_type(data_store_->policy_register_type()); |
| 115 if (!data_store_->machine_id().empty()) |
| 116 request->set_machine_id(data_store_->machine_id()); |
| 117 if (!data_store_->machine_model().empty()) |
| 118 request->set_machine_model(data_store_->machine_model()); |
| 119 request_job_->Start(base::Bind(&DeviceTokenFetcher::OnTokenFetchCompleted, |
| 120 base::Unretained(this))); |
| 121 } |
| 122 |
| 123 void DeviceTokenFetcher::OnTokenFetchCompleted( |
| 124 DeviceManagementStatus status, |
| 125 const em::DeviceManagementResponse& response) { |
| 126 if (status == DM_STATUS_SUCCESS && !response.has_register_response()) { |
| 127 // Handled below. |
| 128 status = DM_STATUS_RESPONSE_DECODING_ERROR; |
| 129 } |
| 130 |
| 131 switch (status) { |
| 132 case DM_STATUS_SUCCESS: { |
| 133 const em::DeviceRegisterResponse& register_response = |
| 134 response.register_response(); |
| 135 if (register_response.has_device_management_token()) { |
| 136 UMA_HISTOGRAM_ENUMERATION(kMetricToken, kMetricTokenFetchOK, |
| 137 kMetricTokenSize); |
| 138 data_store_->SetDeviceToken(register_response.device_management_token(), |
| 139 false); |
| 140 SetState(STATE_TOKEN_AVAILABLE); |
| 141 } else { |
| 142 NOTREACHED(); |
| 143 UMA_HISTOGRAM_ENUMERATION(kMetricToken, kMetricTokenFetchBadResponse, |
| 144 kMetricTokenSize); |
| 145 SetState(STATE_ERROR); |
| 146 } |
| 147 return; |
| 148 } |
| 149 case DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED: |
| 121 SetUnmanagedState(); | 150 SetUnmanagedState(); |
| 122 return; | 151 return; |
| 123 case DeviceManagementBackend::kErrorRequestFailed: | 152 case DM_STATUS_REQUEST_FAILED: |
| 124 case DeviceManagementBackend::kErrorTemporaryUnavailable: | 153 case DM_STATUS_TEMPORARY_UNAVAILABLE: |
| 125 case DeviceManagementBackend::kErrorServiceDeviceNotFound: | 154 case DM_STATUS_SERVICE_DEVICE_NOT_FOUND: |
| 126 case DeviceManagementBackend::kErrorServiceDeviceIdConflict: | 155 case DM_STATUS_SERVICE_DEVICE_ID_CONFLICT: |
| 127 SetState(STATE_TEMPORARY_ERROR); | 156 SetState(STATE_TEMPORARY_ERROR); |
| 128 return; | 157 return; |
| 129 case DeviceManagementBackend::kErrorServiceManagementTokenInvalid: | 158 case DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID: |
| 130 // Most probably the GAIA auth cookie has expired. We can not do anything | 159 // Most probably the GAIA auth cookie has expired. We can not do anything |
| 131 // until the user logs-in again. | 160 // until the user logs-in again. |
| 132 SetState(STATE_BAD_AUTH); | 161 SetState(STATE_BAD_AUTH); |
| 133 return; | 162 return; |
| 134 case DeviceManagementBackend::kErrorServiceInvalidSerialNumber: | 163 case DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER: |
| 135 SetSerialNumberInvalidState(); | 164 SetSerialNumberInvalidState(); |
| 136 return; | 165 return; |
| 137 case DeviceManagementBackend::kErrorRequestInvalid: | 166 case DM_STATUS_REQUEST_INVALID: |
| 138 case DeviceManagementBackend::kErrorHttpStatus: | 167 case DM_STATUS_HTTP_STATUS_ERROR: |
| 139 case DeviceManagementBackend::kErrorResponseDecoding: | 168 case DM_STATUS_RESPONSE_DECODING_ERROR: |
| 140 case DeviceManagementBackend::kErrorServiceActivationPending: | 169 case DM_STATUS_SERVICE_ACTIVATION_PENDING: |
| 141 case DeviceManagementBackend::kErrorServicePolicyNotFound: | 170 case DM_STATUS_SERVICE_POLICY_NOT_FOUND: |
| 142 SetState(STATE_ERROR); | 171 SetState(STATE_ERROR); |
| 143 return; | 172 return; |
| 144 } | 173 } |
| 145 NOTREACHED(); | 174 NOTREACHED(); |
| 146 SetState(STATE_ERROR); | 175 SetState(STATE_ERROR); |
| 147 } | 176 } |
| 148 | 177 |
| 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::SetState(FetcherState state) { | 178 void DeviceTokenFetcher::SetState(FetcherState state) { |
| 167 state_ = state; | 179 state_ = state; |
| 168 if (state_ != STATE_TEMPORARY_ERROR) | 180 if (state_ != STATE_TEMPORARY_ERROR) |
| 169 effective_token_fetch_error_delay_ms_ = kTokenFetchErrorDelayMilliseconds; | 181 effective_token_fetch_error_delay_ms_ = kTokenFetchErrorDelayMilliseconds; |
| 170 | 182 |
| 171 backend_.reset(); // Stop any pending requests. | 183 request_job_.reset(); // Stop any pending requests. |
| 172 | 184 |
| 173 base::Time delayed_work_at; | 185 base::Time delayed_work_at; |
| 174 switch (state_) { | 186 switch (state_) { |
| 175 case STATE_INACTIVE: | 187 case STATE_INACTIVE: |
| 176 notifier_->Inform(CloudPolicySubsystem::UNENROLLED, | 188 notifier_->Inform(CloudPolicySubsystem::UNENROLLED, |
| 177 CloudPolicySubsystem::NO_DETAILS, | 189 CloudPolicySubsystem::NO_DETAILS, |
| 178 PolicyNotifier::TOKEN_FETCHER); | 190 PolicyNotifier::TOKEN_FETCHER); |
| 179 break; | 191 break; |
| 180 case STATE_TOKEN_AVAILABLE: | 192 case STATE_TOKEN_AVAILABLE: |
| 181 notifier_->Inform(CloudPolicySubsystem::SUCCESS, | 193 notifier_->Inform(CloudPolicySubsystem::SUCCESS, |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 246 case STATE_UNMANAGED: | 258 case STATE_UNMANAGED: |
| 247 case STATE_ERROR: | 259 case STATE_ERROR: |
| 248 case STATE_TEMPORARY_ERROR: | 260 case STATE_TEMPORARY_ERROR: |
| 249 case STATE_BAD_AUTH: | 261 case STATE_BAD_AUTH: |
| 250 FetchTokenInternal(); | 262 FetchTokenInternal(); |
| 251 break; | 263 break; |
| 252 } | 264 } |
| 253 } | 265 } |
| 254 | 266 |
| 255 } // namespace policy | 267 } // namespace policy |
| OLD | NEW |