| OLD | NEW |
| 1 // Copyright (c) 2012 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_management_backend_impl.h" | 5 #include "chrome/browser/policy/device_management_backend_impl.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include "base/bind.h" |
| 8 #include <vector> | |
| 9 | |
| 10 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
| 11 #include "base/stringprintf.h" | 9 #include "base/stl_util.h" |
| 12 #include "base/sys_info.h" | |
| 13 #include "chrome/browser/policy/device_management_service.h" | 10 #include "chrome/browser/policy/device_management_service.h" |
| 14 #include "chrome/browser/policy/enterprise_metrics.h" | 11 #include "chrome/browser/policy/enterprise_metrics.h" |
| 15 #include "chrome/common/chrome_version_info.h" | |
| 16 #include "content/public/common/url_fetcher.h" | |
| 17 #include "net/base/escape.h" | |
| 18 #include "net/url_request/url_request_status.h" | |
| 19 | |
| 20 #if defined(OS_CHROMEOS) | |
| 21 #include "chrome/browser/chromeos/system/statistics_provider.h" | |
| 22 #endif | |
| 23 | 12 |
| 24 namespace em = enterprise_management; | 13 namespace em = enterprise_management; |
| 25 | 14 |
| 26 namespace policy { | 15 namespace policy { |
| 27 | 16 |
| 28 // Name constants for URL query parameters. | |
| 29 const char DeviceManagementBackendImpl::kParamAgent[] = "agent"; | |
| 30 const char DeviceManagementBackendImpl::kParamAppType[] = "apptype"; | |
| 31 const char DeviceManagementBackendImpl::kParamDeviceID[] = "deviceid"; | |
| 32 const char DeviceManagementBackendImpl::kParamDeviceType[] = "devicetype"; | |
| 33 const char DeviceManagementBackendImpl::kParamOAuthToken[] = "oauth_token"; | |
| 34 const char DeviceManagementBackendImpl::kParamPlatform[] = "platform"; | |
| 35 const char DeviceManagementBackendImpl::kParamRequest[] = "request"; | |
| 36 const char DeviceManagementBackendImpl::kParamUserAffiliation[] = | |
| 37 "user_affiliation"; | |
| 38 | |
| 39 // String constants for the device and app type we report to the server. | |
| 40 const char DeviceManagementBackendImpl::kValueAppType[] = "Chrome"; | |
| 41 const char DeviceManagementBackendImpl::kValueDeviceType[] = "2"; | |
| 42 const char DeviceManagementBackendImpl::kValueRequestAutoEnrollment[] = | |
| 43 "enterprise_check"; | |
| 44 const char DeviceManagementBackendImpl::kValueRequestPolicy[] = "policy"; | |
| 45 const char DeviceManagementBackendImpl::kValueRequestRegister[] = "register"; | |
| 46 const char DeviceManagementBackendImpl::kValueRequestUnregister[] = | |
| 47 "unregister"; | |
| 48 const char DeviceManagementBackendImpl::kValueUserAffiliationManaged[] = | |
| 49 "managed"; | |
| 50 const char DeviceManagementBackendImpl::kValueUserAffiliationNone[] = "none"; | |
| 51 | |
| 52 namespace { | 17 namespace { |
| 53 | 18 |
| 54 const char kValueAgent[] = "%s %s(%s)"; | 19 // CloudPolicyDataStore::DeviceManagement is being phased out; for now we |
| 55 const char kValuePlatform[] = "%s|%s|%s"; | 20 // convert here to support legacy code. |
| 21 DeviceManagementBackend::ErrorCode ConvertStatus( |
| 22 DeviceManagementStatus status) { |
| 23 switch (status) { |
| 24 case DM_STATUS_SUCCESS: |
| 25 NOTREACHED(); |
| 26 return DeviceManagementBackend::kErrorRequestFailed; |
| 27 case DM_STATUS_REQUEST_INVALID: |
| 28 return DeviceManagementBackend::kErrorRequestInvalid; |
| 29 case DM_STATUS_REQUEST_FAILED: |
| 30 return DeviceManagementBackend::kErrorRequestFailed; |
| 31 case DM_STATUS_TEMPORARY_UNAVAILABLE: |
| 32 return DeviceManagementBackend::kErrorTemporaryUnavailable; |
| 33 case DM_STATUS_HTTP_STATUS_ERROR: |
| 34 return DeviceManagementBackend::kErrorHttpStatus; |
| 35 case DM_STATUS_RESPONSE_DECODING_ERROR: |
| 36 return DeviceManagementBackend::kErrorResponseDecoding; |
| 37 case DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED: |
| 38 return DeviceManagementBackend::kErrorServiceManagementNotSupported; |
| 39 case DM_STATUS_SERVICE_DEVICE_NOT_FOUND: |
| 40 return DeviceManagementBackend::kErrorServiceDeviceNotFound; |
| 41 case DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID: |
| 42 return DeviceManagementBackend::kErrorServiceManagementTokenInvalid; |
| 43 case DM_STATUS_SERVICE_ACTIVATION_PENDING: |
| 44 return DeviceManagementBackend::kErrorServiceActivationPending; |
| 45 case DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER: |
| 46 return DeviceManagementBackend::kErrorServiceInvalidSerialNumber; |
| 47 case DM_STATUS_SERVICE_DEVICE_ID_CONFLICT: |
| 48 return DeviceManagementBackend::kErrorServiceDeviceIdConflict; |
| 49 case DM_STATUS_SERVICE_POLICY_NOT_FOUND: |
| 50 return DeviceManagementBackend::kErrorServicePolicyNotFound; |
| 51 } |
| 56 | 52 |
| 57 const char kPostContentType[] = "application/protobuf"; | 53 NOTREACHED(); |
| 58 | 54 return DeviceManagementBackend::kErrorRequestFailed; |
| 59 const char kServiceTokenAuthHeader[] = "Authorization: GoogleLogin auth="; | |
| 60 const char kDMTokenAuthHeader[] = "Authorization: GoogleDMToken token="; | |
| 61 | |
| 62 // HTTP Error Codes of the DM Server with their concrete meanings in the context | |
| 63 // of the DM Server communication. | |
| 64 const int kSuccess = 200; | |
| 65 const int kInvalidArgument = 400; | |
| 66 const int kInvalidAuthCookieOrDMToken = 401; | |
| 67 const int kDeviceManagementNotAllowed = 403; | |
| 68 const int kInvalidURL = 404; // This error is not coming from the GFE. | |
| 69 const int kInvalidSerialNumber = 405; | |
| 70 const int kDeviceIdConflict = 409; | |
| 71 const int kDeviceNotFound = 410; | |
| 72 const int kPendingApproval = 412; | |
| 73 const int kInternalServerError = 500; | |
| 74 const int kServiceUnavailable = 503; | |
| 75 const int kPolicyNotFound = 902; // This error is not sent as HTTP status code. | |
| 76 | |
| 77 // TODO(pastarmovj): Legacy error codes are here for compatibility only. They | |
| 78 // should be removed once the DM Server has been updated. | |
| 79 const int kPendingApprovalLegacy = 491; | |
| 80 const int kDeviceNotFoundLegacy = 901; | |
| 81 | |
| 82 #if defined(OS_CHROMEOS) | |
| 83 // Machine info keys. | |
| 84 const char kMachineInfoHWClass[] = "hardware_class"; | |
| 85 const char kMachineInfoBoard[] = "CHROMEOS_RELEASE_BOARD"; | |
| 86 #endif | |
| 87 | |
| 88 // Helper class for URL query parameter encoding/decoding. | |
| 89 class URLQueryParameters { | |
| 90 public: | |
| 91 URLQueryParameters() {} | |
| 92 | |
| 93 // Add a query parameter. | |
| 94 void Put(const std::string& name, const std::string& value); | |
| 95 | |
| 96 // Produce the query string, taking care of properly encoding and assembling | |
| 97 // the names and values. | |
| 98 std::string Encode(); | |
| 99 | |
| 100 private: | |
| 101 typedef std::vector<std::pair<std::string, std::string> > ParameterMap; | |
| 102 ParameterMap params_; | |
| 103 | |
| 104 DISALLOW_COPY_AND_ASSIGN(URLQueryParameters); | |
| 105 }; | |
| 106 | |
| 107 void URLQueryParameters::Put(const std::string& name, | |
| 108 const std::string& value) { | |
| 109 params_.push_back(std::make_pair(name, value)); | |
| 110 } | 55 } |
| 111 | 56 |
| 112 std::string URLQueryParameters::Encode() { | 57 // Conversion helper to support legacy code. |
| 113 std::string result; | 58 UserAffiliation ConvertAffiliation( |
| 114 for (ParameterMap::const_iterator entry(params_.begin()); | 59 CloudPolicyDataStore::UserAffiliation affiliation) { |
| 115 entry != params_.end(); | 60 switch (affiliation) { |
| 116 ++entry) { | 61 case CloudPolicyDataStore::USER_AFFILIATION_MANAGED: |
| 117 if (entry != params_.begin()) | 62 return USER_AFFILIATION_MANAGED; |
| 118 result += '&'; | 63 case CloudPolicyDataStore::USER_AFFILIATION_NONE: |
| 119 result += net::EscapeQueryParamValue(entry->first, true); | 64 return USER_AFFILIATION_NONE; |
| 120 result += '='; | |
| 121 result += net::EscapeQueryParamValue(entry->second, true); | |
| 122 } | 65 } |
| 123 return result; | 66 |
| 67 NOTREACHED(); |
| 68 return USER_AFFILIATION_NONE; |
| 124 } | 69 } |
| 125 | 70 |
| 126 } // namespace | 71 } // namespace |
| 127 | 72 |
| 128 // A base class containing the common code for the jobs created by the backend | |
| 129 // implementation. Subclasses provide custom code for handling actual register, | |
| 130 // unregister, and policy jobs. | |
| 131 class DeviceManagementJobBase | |
| 132 : public DeviceManagementService::DeviceManagementJob { | |
| 133 public: | |
| 134 virtual ~DeviceManagementJobBase() {} | |
| 135 | |
| 136 // DeviceManagementJob overrides: | |
| 137 virtual void HandleResponse(const net::URLRequestStatus& status, | |
| 138 int response_code, | |
| 139 const net::ResponseCookies& cookies, | |
| 140 const std::string& data); | |
| 141 virtual GURL GetURL(const std::string& server_url); | |
| 142 virtual void ConfigureRequest(content::URLFetcher* fetcher); | |
| 143 | |
| 144 protected: | |
| 145 // Constructs a device management job running for the given backend. | |
| 146 DeviceManagementJobBase(DeviceManagementBackendImpl* backend_impl, | |
| 147 const std::string& request_type, | |
| 148 const std::string& device_id) | |
| 149 : backend_impl_(backend_impl) { | |
| 150 query_params_.Put(DeviceManagementBackendImpl::kParamRequest, request_type); | |
| 151 query_params_.Put(DeviceManagementBackendImpl::kParamDeviceType, | |
| 152 DeviceManagementBackendImpl::kValueDeviceType); | |
| 153 query_params_.Put(DeviceManagementBackendImpl::kParamAppType, | |
| 154 DeviceManagementBackendImpl::kValueAppType); | |
| 155 query_params_.Put(DeviceManagementBackendImpl::kParamDeviceID, device_id); | |
| 156 query_params_.Put(DeviceManagementBackendImpl::kParamAgent, | |
| 157 DeviceManagementBackendImpl::GetAgentString()); | |
| 158 query_params_.Put(DeviceManagementBackendImpl::kParamPlatform, | |
| 159 DeviceManagementBackendImpl::GetPlatformString()); | |
| 160 } | |
| 161 | |
| 162 void SetQueryParam(const std::string& name, const std::string& value) { | |
| 163 query_params_.Put(name, value); | |
| 164 } | |
| 165 | |
| 166 void SetGaiaAuthToken(const std::string& gaia_auth_token) { | |
| 167 gaia_auth_token_ = gaia_auth_token; | |
| 168 } | |
| 169 | |
| 170 void SetDeviceManagementToken(const std::string& device_management_token) { | |
| 171 device_management_token_ = device_management_token; | |
| 172 } | |
| 173 | |
| 174 void SetPayload(const em::DeviceManagementRequest& request) { | |
| 175 if (!request.SerializeToString(&payload_)) { | |
| 176 NOTREACHED(); | |
| 177 LOG(ERROR) << "Failed to serialize request."; | |
| 178 } | |
| 179 } | |
| 180 | |
| 181 private: | |
| 182 // Implemented by subclasses to handle decoded responses and errors. | |
| 183 virtual void OnResponse( | |
| 184 const em::DeviceManagementResponse& response) = 0; | |
| 185 virtual void OnError(DeviceManagementBackend::ErrorCode error) = 0; | |
| 186 | |
| 187 // The backend this job is handling a request for. | |
| 188 DeviceManagementBackendImpl* backend_impl_; | |
| 189 | |
| 190 // Query parameters. | |
| 191 URLQueryParameters query_params_; | |
| 192 | |
| 193 // Auth token (if applicaple). | |
| 194 std::string gaia_auth_token_; | |
| 195 | |
| 196 // Device management token (if applicable). | |
| 197 std::string device_management_token_; | |
| 198 | |
| 199 // The payload. | |
| 200 std::string payload_; | |
| 201 | |
| 202 DISALLOW_COPY_AND_ASSIGN(DeviceManagementJobBase); | |
| 203 }; | |
| 204 | |
| 205 void DeviceManagementJobBase::HandleResponse( | |
| 206 const net::URLRequestStatus& status, | |
| 207 int response_code, | |
| 208 const net::ResponseCookies& cookies, | |
| 209 const std::string& data) { | |
| 210 // Delete ourselves when this is done. | |
| 211 scoped_ptr<DeviceManagementJob> scoped_killer(this); | |
| 212 backend_impl_->JobDone(this); | |
| 213 backend_impl_ = NULL; | |
| 214 | |
| 215 if (status.status() != net::URLRequestStatus::SUCCESS) { | |
| 216 OnError(DeviceManagementBackend::kErrorRequestFailed); | |
| 217 return; | |
| 218 } | |
| 219 | |
| 220 switch (response_code) { | |
| 221 case kSuccess: { | |
| 222 em::DeviceManagementResponse response; | |
| 223 if (!response.ParseFromString(data)) { | |
| 224 OnError(DeviceManagementBackend::kErrorResponseDecoding); | |
| 225 return; | |
| 226 } | |
| 227 OnResponse(response); | |
| 228 return; | |
| 229 } | |
| 230 case kInvalidArgument: { | |
| 231 OnError(DeviceManagementBackend::kErrorRequestInvalid); | |
| 232 return; | |
| 233 } | |
| 234 case kInvalidAuthCookieOrDMToken: { | |
| 235 OnError(DeviceManagementBackend::kErrorServiceManagementTokenInvalid); | |
| 236 return; | |
| 237 } | |
| 238 case kDeviceManagementNotAllowed: { | |
| 239 OnError(DeviceManagementBackend::kErrorServiceManagementNotSupported); | |
| 240 return; | |
| 241 } | |
| 242 case kPendingApprovalLegacy: | |
| 243 case kPendingApproval: { | |
| 244 OnError(DeviceManagementBackend::kErrorServiceActivationPending); | |
| 245 return; | |
| 246 } | |
| 247 case kInvalidURL: | |
| 248 case kInternalServerError: | |
| 249 case kServiceUnavailable: { | |
| 250 OnError(DeviceManagementBackend::kErrorTemporaryUnavailable); | |
| 251 return; | |
| 252 } | |
| 253 case kDeviceNotFoundLegacy: | |
| 254 case kDeviceNotFound: { | |
| 255 OnError(DeviceManagementBackend::kErrorServiceDeviceNotFound); | |
| 256 return; | |
| 257 } | |
| 258 case kPolicyNotFound: { | |
| 259 OnError(DeviceManagementBackend::kErrorServicePolicyNotFound); | |
| 260 break; | |
| 261 } | |
| 262 case kInvalidSerialNumber: { | |
| 263 OnError(DeviceManagementBackend::kErrorServiceInvalidSerialNumber); | |
| 264 break; | |
| 265 } | |
| 266 case kDeviceIdConflict: { | |
| 267 OnError(DeviceManagementBackend::kErrorServiceDeviceIdConflict); | |
| 268 break; | |
| 269 } | |
| 270 default: { | |
| 271 VLOG(1) << "Unexpected HTTP status in response from DMServer : " | |
| 272 << response_code << "."; | |
| 273 // Handle all unknown 5xx HTTP error codes as temporary and any other | |
| 274 // unknown error as one that needs more time to recover. | |
| 275 if (response_code >= 500 && response_code <= 599) | |
| 276 OnError(DeviceManagementBackend::kErrorTemporaryUnavailable); | |
| 277 else | |
| 278 OnError(DeviceManagementBackend::kErrorHttpStatus); | |
| 279 return; | |
| 280 } | |
| 281 } | |
| 282 } | |
| 283 | |
| 284 GURL DeviceManagementJobBase::GetURL( | |
| 285 const std::string& server_url) { | |
| 286 return GURL(server_url + '?' + query_params_.Encode()); | |
| 287 } | |
| 288 | |
| 289 void DeviceManagementJobBase::ConfigureRequest(content::URLFetcher* fetcher) { | |
| 290 fetcher->SetUploadData(kPostContentType, payload_); | |
| 291 std::string extra_headers; | |
| 292 if (!gaia_auth_token_.empty()) | |
| 293 extra_headers += kServiceTokenAuthHeader + gaia_auth_token_ + "\n"; | |
| 294 if (!device_management_token_.empty()) | |
| 295 extra_headers += kDMTokenAuthHeader + device_management_token_ + "\n"; | |
| 296 fetcher->SetExtraRequestHeaders(extra_headers); | |
| 297 } | |
| 298 | |
| 299 // Handles device registration jobs. | |
| 300 class DeviceManagementRegisterJob : public DeviceManagementJobBase { | |
| 301 public: | |
| 302 DeviceManagementRegisterJob( | |
| 303 DeviceManagementBackendImpl* backend_impl, | |
| 304 const std::string& gaia_auth_token, | |
| 305 const std::string& oauth_token, | |
| 306 const std::string& device_id, | |
| 307 const em::DeviceRegisterRequest& request, | |
| 308 DeviceManagementBackend::DeviceRegisterResponseDelegate* delegate) | |
| 309 : DeviceManagementJobBase( | |
| 310 backend_impl, | |
| 311 DeviceManagementBackendImpl::kValueRequestRegister, | |
| 312 device_id), | |
| 313 delegate_(delegate) { | |
| 314 if (!oauth_token.empty()) | |
| 315 SetQueryParam(DeviceManagementBackendImpl::kParamOAuthToken, oauth_token); | |
| 316 else if (!gaia_auth_token.empty()) | |
| 317 SetGaiaAuthToken(gaia_auth_token); | |
| 318 em::DeviceManagementRequest request_wrapper; | |
| 319 request_wrapper.mutable_register_request()->CopyFrom(request); | |
| 320 SetPayload(request_wrapper); | |
| 321 } | |
| 322 virtual ~DeviceManagementRegisterJob() {} | |
| 323 | |
| 324 private: | |
| 325 // DeviceManagementJobBase overrides. | |
| 326 virtual void OnError(DeviceManagementBackend::ErrorCode error) OVERRIDE { | |
| 327 MetricToken sample; | |
| 328 switch (error) { | |
| 329 case DeviceManagementBackend::kErrorRequestInvalid: | |
| 330 case DeviceManagementBackend::kErrorRequestFailed: | |
| 331 sample = kMetricTokenFetchRequestFailed; | |
| 332 break; | |
| 333 case DeviceManagementBackend::kErrorServiceDeviceNotFound: | |
| 334 sample = kMetricTokenFetchDeviceNotFound; | |
| 335 break; | |
| 336 case DeviceManagementBackend::kErrorServiceManagementNotSupported: | |
| 337 sample = kMetricTokenFetchManagementNotSupported; | |
| 338 break; | |
| 339 case DeviceManagementBackend::kErrorResponseDecoding: | |
| 340 sample = kMetricTokenFetchBadResponse; | |
| 341 break; | |
| 342 case DeviceManagementBackend::kErrorServiceInvalidSerialNumber: | |
| 343 sample = kMetricTokenFetchInvalidSerialNumber; | |
| 344 break; | |
| 345 case DeviceManagementBackend::kErrorServiceDeviceIdConflict: | |
| 346 sample = kMetricTokenFetchDeviceIdConflict; | |
| 347 break; | |
| 348 default: | |
| 349 sample = kMetricTokenFetchServerFailed; | |
| 350 break; | |
| 351 } | |
| 352 UMA_HISTOGRAM_ENUMERATION(kMetricToken, sample, kMetricTokenSize); | |
| 353 delegate_->OnError(error); | |
| 354 } | |
| 355 virtual void OnResponse( | |
| 356 const em::DeviceManagementResponse& response) OVERRIDE { | |
| 357 UMA_HISTOGRAM_ENUMERATION(kMetricToken, kMetricTokenFetchResponseReceived, | |
| 358 kMetricTokenSize); | |
| 359 delegate_->HandleRegisterResponse(response.register_response()); | |
| 360 } | |
| 361 | |
| 362 DeviceManagementBackend::DeviceRegisterResponseDelegate* delegate_; | |
| 363 | |
| 364 DISALLOW_COPY_AND_ASSIGN(DeviceManagementRegisterJob); | |
| 365 }; | |
| 366 | |
| 367 // Handles device unregistration jobs. | |
| 368 class DeviceManagementUnregisterJob : public DeviceManagementJobBase { | |
| 369 public: | |
| 370 DeviceManagementUnregisterJob( | |
| 371 DeviceManagementBackendImpl* backend_impl, | |
| 372 const std::string& device_management_token, | |
| 373 const std::string& device_id, | |
| 374 const em::DeviceUnregisterRequest& request, | |
| 375 DeviceManagementBackend::DeviceUnregisterResponseDelegate* delegate) | |
| 376 : DeviceManagementJobBase( | |
| 377 backend_impl, | |
| 378 DeviceManagementBackendImpl::kValueRequestUnregister, | |
| 379 device_id), | |
| 380 delegate_(delegate) { | |
| 381 SetDeviceManagementToken(device_management_token); | |
| 382 em::DeviceManagementRequest request_wrapper; | |
| 383 request_wrapper.mutable_unregister_request()->CopyFrom(request); | |
| 384 SetPayload(request_wrapper); | |
| 385 } | |
| 386 virtual ~DeviceManagementUnregisterJob() {} | |
| 387 | |
| 388 private: | |
| 389 // DeviceManagementJobBase overrides. | |
| 390 virtual void OnError(DeviceManagementBackend::ErrorCode error) OVERRIDE { | |
| 391 delegate_->OnError(error); | |
| 392 } | |
| 393 virtual void OnResponse( | |
| 394 const em::DeviceManagementResponse& response) OVERRIDE { | |
| 395 delegate_->HandleUnregisterResponse(response.unregister_response()); | |
| 396 } | |
| 397 | |
| 398 DeviceManagementBackend::DeviceUnregisterResponseDelegate* delegate_; | |
| 399 | |
| 400 DISALLOW_COPY_AND_ASSIGN(DeviceManagementUnregisterJob); | |
| 401 }; | |
| 402 | |
| 403 // Handles policy request jobs. | |
| 404 class DeviceManagementPolicyJob : public DeviceManagementJobBase { | |
| 405 public: | |
| 406 DeviceManagementPolicyJob( | |
| 407 DeviceManagementBackendImpl* backend_impl, | |
| 408 const std::string& device_management_token, | |
| 409 const std::string& device_id, | |
| 410 const std::string& user_affiliation, | |
| 411 const em::DevicePolicyRequest& request, | |
| 412 const em::DeviceStatusReportRequest* device_status, | |
| 413 DeviceManagementBackend::DevicePolicyResponseDelegate* delegate) | |
| 414 : DeviceManagementJobBase( | |
| 415 backend_impl, | |
| 416 DeviceManagementBackendImpl::kValueRequestPolicy, | |
| 417 device_id), | |
| 418 delegate_(delegate) { | |
| 419 SetDeviceManagementToken(device_management_token); | |
| 420 SetQueryParam(DeviceManagementBackendImpl::kParamUserAffiliation, | |
| 421 user_affiliation); | |
| 422 em::DeviceManagementRequest request_wrapper; | |
| 423 request_wrapper.mutable_policy_request()->CopyFrom(request); | |
| 424 if (device_status != NULL) { | |
| 425 request_wrapper.mutable_device_status_report_request()->CopyFrom( | |
| 426 *device_status); | |
| 427 } | |
| 428 SetPayload(request_wrapper); | |
| 429 } | |
| 430 virtual ~DeviceManagementPolicyJob() {} | |
| 431 | |
| 432 private: | |
| 433 // DeviceManagementJobBase overrides. | |
| 434 virtual void OnError(DeviceManagementBackend::ErrorCode error) OVERRIDE { | |
| 435 MetricPolicy sample; | |
| 436 switch (error) { | |
| 437 case DeviceManagementBackend::kErrorRequestInvalid: | |
| 438 case DeviceManagementBackend::kErrorRequestFailed: | |
| 439 sample = kMetricPolicyFetchRequestFailed; | |
| 440 break; | |
| 441 case DeviceManagementBackend::kErrorServicePolicyNotFound: | |
| 442 sample = kMetricPolicyFetchNotFound; | |
| 443 break; | |
| 444 case DeviceManagementBackend::kErrorServiceManagementTokenInvalid: | |
| 445 sample = kMetricPolicyFetchInvalidToken; | |
| 446 break; | |
| 447 case DeviceManagementBackend::kErrorResponseDecoding: | |
| 448 sample = kMetricPolicyFetchBadResponse; | |
| 449 break; | |
| 450 default: | |
| 451 sample = kMetricPolicyFetchServerFailed; | |
| 452 break; | |
| 453 } | |
| 454 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, sample, kMetricPolicySize); | |
| 455 delegate_->OnError(error); | |
| 456 } | |
| 457 virtual void OnResponse( | |
| 458 const em::DeviceManagementResponse& response) OVERRIDE { | |
| 459 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyFetchResponseReceived, | |
| 460 kMetricPolicySize); | |
| 461 delegate_->HandlePolicyResponse(response.policy_response()); | |
| 462 } | |
| 463 | |
| 464 DeviceManagementBackend::DevicePolicyResponseDelegate* delegate_; | |
| 465 | |
| 466 DISALLOW_COPY_AND_ASSIGN(DeviceManagementPolicyJob); | |
| 467 }; | |
| 468 | |
| 469 // Handles auto enrollment request jobs. These are used to determine if a new | |
| 470 // ChromiumOS device should automatically enter the enterprise enrollment screen | |
| 471 // during the OOBE flow. | |
| 472 class DeviceManagementAutoEnrollmentJob : public DeviceManagementJobBase { | |
| 473 public: | |
| 474 DeviceManagementAutoEnrollmentJob( | |
| 475 DeviceManagementBackendImpl* backend_impl, | |
| 476 const std::string& device_id, | |
| 477 const em::DeviceAutoEnrollmentRequest& request, | |
| 478 DeviceManagementBackend::DeviceAutoEnrollmentResponseDelegate* delegate) | |
| 479 : DeviceManagementJobBase( | |
| 480 backend_impl, | |
| 481 DeviceManagementBackendImpl::kValueRequestAutoEnrollment, | |
| 482 device_id), | |
| 483 delegate_(delegate) { | |
| 484 em::DeviceManagementRequest request_wrapper; | |
| 485 request_wrapper.mutable_auto_enrollment_request()->CopyFrom(request); | |
| 486 SetPayload(request_wrapper); | |
| 487 } | |
| 488 virtual ~DeviceManagementAutoEnrollmentJob() {} | |
| 489 | |
| 490 private: | |
| 491 // DeviceManagementJobBase overrides. | |
| 492 virtual void OnError(DeviceManagementBackend::ErrorCode error) OVERRIDE { | |
| 493 delegate_->OnError(error); | |
| 494 } | |
| 495 virtual void OnResponse( | |
| 496 const em::DeviceManagementResponse& response) OVERRIDE { | |
| 497 delegate_->HandleAutoEnrollmentResponse( | |
| 498 response.auto_enrollment_response()); | |
| 499 } | |
| 500 | |
| 501 DeviceManagementBackend::DeviceAutoEnrollmentResponseDelegate* delegate_; | |
| 502 | |
| 503 DISALLOW_COPY_AND_ASSIGN(DeviceManagementAutoEnrollmentJob); | |
| 504 }; | |
| 505 | |
| 506 DeviceManagementBackendImpl::DeviceManagementBackendImpl( | 73 DeviceManagementBackendImpl::DeviceManagementBackendImpl( |
| 507 DeviceManagementService* service) | 74 DeviceManagementService* service) |
| 508 : service_(service) { | 75 : service_(service) { |
| 509 } | 76 } |
| 510 | 77 |
| 511 DeviceManagementBackendImpl::~DeviceManagementBackendImpl() { | 78 DeviceManagementBackendImpl::~DeviceManagementBackendImpl() { |
| 512 for (JobSet::iterator job(pending_jobs_.begin()); | 79 STLDeleteElements(&pending_jobs_); |
| 513 job != pending_jobs_.end(); | |
| 514 ++job) { | |
| 515 service_->RemoveJob(*job); | |
| 516 delete *job; | |
| 517 } | |
| 518 pending_jobs_.clear(); | |
| 519 } | |
| 520 | |
| 521 std::string DeviceManagementBackendImpl::GetAgentString() { | |
| 522 CR_DEFINE_STATIC_LOCAL(std::string, agent, ()); | |
| 523 if (!agent.empty()) | |
| 524 return agent; | |
| 525 | |
| 526 chrome::VersionInfo version_info; | |
| 527 agent = base::StringPrintf(kValueAgent, | |
| 528 version_info.Name().c_str(), | |
| 529 version_info.Version().c_str(), | |
| 530 version_info.LastChange().c_str()); | |
| 531 return agent; | |
| 532 } | |
| 533 | |
| 534 std::string DeviceManagementBackendImpl::GetPlatformString() { | |
| 535 CR_DEFINE_STATIC_LOCAL(std::string, platform, ()); | |
| 536 if (!platform.empty()) | |
| 537 return platform; | |
| 538 | |
| 539 std::string os_name(base::SysInfo::OperatingSystemName()); | |
| 540 std::string os_hardware(base::SysInfo::CPUArchitecture()); | |
| 541 | |
| 542 #if defined(OS_CHROMEOS) | |
| 543 chromeos::system::StatisticsProvider* provider = | |
| 544 chromeos::system::StatisticsProvider::GetInstance(); | |
| 545 | |
| 546 std::string hwclass; | |
| 547 std::string board; | |
| 548 if (!provider->GetMachineStatistic(kMachineInfoHWClass, &hwclass) || | |
| 549 !provider->GetMachineStatistic(kMachineInfoBoard, &board)) { | |
| 550 LOG(ERROR) << "Failed to get machine information"; | |
| 551 } | |
| 552 os_name += ",CrOS," + board; | |
| 553 os_hardware += "," + hwclass; | |
| 554 #endif | |
| 555 | |
| 556 std::string os_version("-"); | |
| 557 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS) | |
| 558 int32 os_major_version = 0; | |
| 559 int32 os_minor_version = 0; | |
| 560 int32 os_bugfix_version = 0; | |
| 561 base::SysInfo::OperatingSystemVersionNumbers(&os_major_version, | |
| 562 &os_minor_version, | |
| 563 &os_bugfix_version); | |
| 564 os_version = base::StringPrintf("%d.%d.%d", | |
| 565 os_major_version, | |
| 566 os_minor_version, | |
| 567 os_bugfix_version); | |
| 568 #endif | |
| 569 | |
| 570 platform = base::StringPrintf(kValuePlatform, | |
| 571 os_name.c_str(), | |
| 572 os_hardware.c_str(), | |
| 573 os_version.c_str()); | |
| 574 return platform; | |
| 575 } | |
| 576 | |
| 577 void DeviceManagementBackendImpl::JobDone(DeviceManagementJobBase* job) { | |
| 578 pending_jobs_.erase(job); | |
| 579 } | |
| 580 | |
| 581 void DeviceManagementBackendImpl::AddJob(DeviceManagementJobBase* job) { | |
| 582 pending_jobs_.insert(job); | |
| 583 service_->AddJob(job); | |
| 584 } | 80 } |
| 585 | 81 |
| 586 void DeviceManagementBackendImpl::ProcessRegisterRequest( | 82 void DeviceManagementBackendImpl::ProcessRegisterRequest( |
| 587 const std::string& gaia_auth_token, | 83 const std::string& gaia_auth_token, |
| 588 const std::string& oauth_token, | 84 const std::string& oauth_token, |
| 589 const std::string& device_id, | 85 const std::string& device_id, |
| 590 const em::DeviceRegisterRequest& request, | 86 const em::DeviceRegisterRequest& request, |
| 591 DeviceRegisterResponseDelegate* delegate) { | 87 DeviceRegisterResponseDelegate* delegate) { |
| 592 UMA_HISTOGRAM_ENUMERATION(kMetricToken, kMetricTokenFetchRequested, | 88 UMA_HISTOGRAM_ENUMERATION(kMetricToken, kMetricTokenFetchRequested, |
| 593 kMetricTokenSize); | 89 kMetricTokenSize); |
| 594 AddJob(new DeviceManagementRegisterJob(this, gaia_auth_token, oauth_token, | 90 DeviceManagementRequestJob* job = |
| 595 device_id, request, delegate)); | 91 service_->CreateJob(DeviceManagementRequestJob::TYPE_REGISTRATION); |
| 92 job->SetGaiaToken(gaia_auth_token); |
| 93 job->SetOAuthToken(oauth_token); |
| 94 job->SetClientID(device_id); |
| 95 job->GetRequest()->mutable_register_request()->CopyFrom(request); |
| 96 job->Start(base::Bind(&DeviceManagementBackendImpl::OnRegistrationDone, |
| 97 base::Unretained(this), job, delegate)); |
| 98 pending_jobs_.insert(job); |
| 596 } | 99 } |
| 597 | 100 |
| 598 void DeviceManagementBackendImpl::ProcessUnregisterRequest( | 101 void DeviceManagementBackendImpl::ProcessUnregisterRequest( |
| 599 const std::string& device_management_token, | 102 const std::string& device_management_token, |
| 600 const std::string& device_id, | 103 const std::string& device_id, |
| 601 const em::DeviceUnregisterRequest& request, | 104 const em::DeviceUnregisterRequest& request, |
| 602 DeviceUnregisterResponseDelegate* delegate) { | 105 DeviceUnregisterResponseDelegate* delegate) { |
| 603 AddJob(new DeviceManagementUnregisterJob(this, device_management_token, | 106 DeviceManagementRequestJob* job = |
| 604 device_id, request, delegate)); | 107 service_->CreateJob(DeviceManagementRequestJob::TYPE_UNREGISTRATION); |
| 108 job->SetDMToken(device_management_token); |
| 109 job->SetClientID(device_id); |
| 110 job->GetRequest()->mutable_unregister_request(); |
| 111 job->Start(base::Bind(&DeviceManagementBackendImpl::OnUnregistrationDone, |
| 112 base::Unretained(this), job, delegate)); |
| 113 pending_jobs_.insert(job); |
| 605 } | 114 } |
| 606 | 115 |
| 607 void DeviceManagementBackendImpl::ProcessPolicyRequest( | 116 void DeviceManagementBackendImpl::ProcessPolicyRequest( |
| 608 const std::string& device_management_token, | 117 const std::string& device_management_token, |
| 609 const std::string& device_id, | 118 const std::string& device_id, |
| 610 CloudPolicyDataStore::UserAffiliation affiliation, | 119 CloudPolicyDataStore::UserAffiliation affiliation, |
| 611 const em::DevicePolicyRequest& request, | 120 const em::DevicePolicyRequest& request, |
| 612 const em::DeviceStatusReportRequest* device_status, | 121 const em::DeviceStatusReportRequest* device_status, |
| 613 DevicePolicyResponseDelegate* delegate) { | 122 DevicePolicyResponseDelegate* delegate) { |
| 614 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyFetchRequested, | 123 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyFetchRequested, |
| 615 kMetricPolicySize); | 124 kMetricPolicySize); |
| 616 AddJob(new DeviceManagementPolicyJob(this, device_management_token, device_id, | 125 DeviceManagementRequestJob* job = |
| 617 UserAffiliationToString(affiliation), | 126 service_->CreateJob(DeviceManagementRequestJob::TYPE_POLICY_FETCH); |
| 618 request, device_status, delegate)); | 127 job->SetDMToken(device_management_token); |
| 128 job->SetClientID(device_id); |
| 129 job->SetUserAffiliation(ConvertAffiliation(affiliation)); |
| 130 job->GetRequest()->mutable_policy_request()->CopyFrom(request); |
| 131 if (device_status) { |
| 132 job->GetRequest()->mutable_device_status_report_request()->CopyFrom( |
| 133 *device_status); |
| 134 } |
| 135 job->Start(base::Bind(&DeviceManagementBackendImpl::OnPolicyFetchDone, |
| 136 base::Unretained(this), job, delegate)); |
| 137 pending_jobs_.insert(job); |
| 619 } | 138 } |
| 620 | 139 |
| 621 void DeviceManagementBackendImpl::ProcessAutoEnrollmentRequest( | 140 void DeviceManagementBackendImpl::ProcessAutoEnrollmentRequest( |
| 622 const std::string& device_id, | 141 const std::string& device_id, |
| 623 const em::DeviceAutoEnrollmentRequest& request, | 142 const em::DeviceAutoEnrollmentRequest& request, |
| 624 DeviceAutoEnrollmentResponseDelegate* delegate) { | 143 DeviceAutoEnrollmentResponseDelegate* delegate) { |
| 625 AddJob(new DeviceManagementAutoEnrollmentJob(this, device_id, request, | 144 DeviceManagementRequestJob* job = |
| 626 delegate)); | 145 service_->CreateJob(DeviceManagementRequestJob::TYPE_AUTO_ENROLLMENT); |
| 146 job->SetClientID(device_id); |
| 147 job->GetRequest()->mutable_auto_enrollment_request()->CopyFrom(request); |
| 148 job->Start(base::Bind(&DeviceManagementBackendImpl::OnAutoEnrollmentDone, |
| 149 base::Unretained(this), job, delegate)); |
| 150 pending_jobs_.insert(job); |
| 627 } | 151 } |
| 628 | 152 |
| 629 // static | 153 void DeviceManagementBackendImpl::OnRegistrationDone( |
| 630 const char* DeviceManagementBackendImpl::UserAffiliationToString( | 154 DeviceManagementRequestJob* job, |
| 631 CloudPolicyDataStore::UserAffiliation affiliation) { | 155 DeviceRegisterResponseDelegate* delegate, |
| 632 switch (affiliation) { | 156 DeviceManagementStatus status, |
| 633 case CloudPolicyDataStore::USER_AFFILIATION_MANAGED: | 157 const enterprise_management::DeviceManagementResponse& response) { |
| 634 return kValueUserAffiliationManaged; | 158 pending_jobs_.erase(job); |
| 635 case CloudPolicyDataStore::USER_AFFILIATION_NONE: | 159 if (status == DM_STATUS_SUCCESS) |
| 636 return kValueUserAffiliationNone; | 160 delegate->HandleRegisterResponse(response.register_response()); |
| 637 } | 161 else |
| 638 NOTREACHED(); | 162 delegate->OnError(ConvertStatus(status)); |
| 639 return kValueUserAffiliationNone; | 163 delete job; |
| 164 } |
| 165 |
| 166 void DeviceManagementBackendImpl::OnUnregistrationDone( |
| 167 DeviceManagementRequestJob* job, |
| 168 DeviceUnregisterResponseDelegate* delegate, |
| 169 DeviceManagementStatus status, |
| 170 const enterprise_management::DeviceManagementResponse& response) { |
| 171 pending_jobs_.erase(job); |
| 172 if (status == DM_STATUS_SUCCESS) |
| 173 delegate->HandleUnregisterResponse(response.unregister_response()); |
| 174 else |
| 175 delegate->OnError(ConvertStatus(status)); |
| 176 delete job; |
| 177 } |
| 178 |
| 179 void DeviceManagementBackendImpl::OnPolicyFetchDone( |
| 180 DeviceManagementRequestJob* job, |
| 181 DevicePolicyResponseDelegate* delegate, |
| 182 DeviceManagementStatus status, |
| 183 const enterprise_management::DeviceManagementResponse& response) { |
| 184 pending_jobs_.erase(job); |
| 185 if (status == DM_STATUS_SUCCESS) |
| 186 delegate->HandlePolicyResponse(response.policy_response()); |
| 187 else |
| 188 delegate->OnError(ConvertStatus(status)); |
| 189 delete job; |
| 190 } |
| 191 |
| 192 void DeviceManagementBackendImpl::OnAutoEnrollmentDone( |
| 193 DeviceManagementRequestJob* job, |
| 194 DeviceAutoEnrollmentResponseDelegate* delegate, |
| 195 DeviceManagementStatus status, |
| 196 const enterprise_management::DeviceManagementResponse& response) { |
| 197 pending_jobs_.erase(job); |
| 198 if (status == DM_STATUS_SUCCESS) |
| 199 delegate->HandleAutoEnrollmentResponse(response.auto_enrollment_response()); |
| 200 else |
| 201 delegate->OnError(ConvertStatus(status)); |
| 202 delete job; |
| 640 } | 203 } |
| 641 | 204 |
| 642 } // namespace policy | 205 } // namespace policy |
| OLD | NEW |