| 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_service.h" | 5 #include "chrome/browser/policy/device_management_service.h" |
| 6 | 6 |
| 7 #include <utility> |
| 8 |
| 7 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/compiler_specific.h" |
| 8 #include "base/message_loop.h" | 11 #include "base/message_loop.h" |
| 9 #include "base/message_loop_proxy.h" | 12 #include "base/message_loop_proxy.h" |
| 13 #include "base/stringprintf.h" |
| 14 #include "base/sys_info.h" |
| 10 #include "chrome/browser/browser_process.h" | 15 #include "chrome/browser/browser_process.h" |
| 11 #include "chrome/browser/net/chrome_net_log.h" | 16 #include "chrome/browser/net/chrome_net_log.h" |
| 12 #include "chrome/browser/policy/device_management_backend.h" | 17 #include "chrome/browser/policy/device_management_backend.h" |
| 13 #include "chrome/browser/policy/device_management_backend_impl.h" | 18 #include "chrome/browser/policy/device_management_backend_impl.h" |
| 19 #include "chrome/common/chrome_version_info.h" |
| 14 #include "content/public/browser/browser_thread.h" | 20 #include "content/public/browser/browser_thread.h" |
| 15 #include "content/public/common/content_client.h" | 21 #include "content/public/common/content_client.h" |
| 16 #include "content/public/common/url_fetcher.h" | 22 #include "content/public/common/url_fetcher.h" |
| 23 #include "googleurl/src/gurl.h" |
| 17 #include "net/base/cookie_monster.h" | 24 #include "net/base/cookie_monster.h" |
| 25 #include "net/base/escape.h" |
| 18 #include "net/base/host_resolver.h" | 26 #include "net/base/host_resolver.h" |
| 19 #include "net/base/load_flags.h" | 27 #include "net/base/load_flags.h" |
| 20 #include "net/base/net_errors.h" | 28 #include "net/base/net_errors.h" |
| 21 #include "net/base/ssl_config_service_defaults.h" | 29 #include "net/base/ssl_config_service_defaults.h" |
| 22 #include "net/http/http_network_layer.h" | 30 #include "net/http/http_network_layer.h" |
| 23 #include "net/http/http_response_headers.h" | 31 #include "net/http/http_response_headers.h" |
| 24 #include "net/proxy/proxy_service.h" | 32 #include "net/proxy/proxy_service.h" |
| 25 #include "net/url_request/url_request_context.h" | 33 #include "net/url_request/url_request_context.h" |
| 26 #include "net/url_request/url_request_context_getter.h" | 34 #include "net/url_request/url_request_context_getter.h" |
| 27 #include "net/url_request/url_request_status.h" | 35 #include "net/url_request/url_request_status.h" |
| 28 | 36 |
| 37 #if defined(OS_CHROMEOS) |
| 38 #include "chrome/browser/chromeos/system/statistics_provider.h" |
| 39 #endif |
| 40 |
| 29 using content::BrowserThread; | 41 using content::BrowserThread; |
| 30 | 42 |
| 31 namespace em = enterprise_management; | 43 namespace em = enterprise_management; |
| 32 | 44 |
| 33 namespace policy { | 45 namespace policy { |
| 34 | 46 |
| 35 namespace { | 47 namespace { |
| 36 | 48 |
| 49 const char kValueAgent[] = "%s %s(%s)"; |
| 50 const char kValuePlatform[] = "%s|%s|%s"; |
| 51 |
| 52 const char kPostContentType[] = "application/protobuf"; |
| 53 |
| 54 const char kServiceTokenAuthHeader[] = "Authorization: GoogleLogin auth="; |
| 55 const char kDMTokenAuthHeader[] = "Authorization: GoogleDMToken token="; |
| 56 |
| 57 // HTTP Error Codes of the DM Server with their concrete meanings in the context |
| 58 // of the DM Server communication. |
| 59 const int kSuccess = 200; |
| 60 const int kInvalidArgument = 400; |
| 61 const int kInvalidAuthCookieOrDMToken = 401; |
| 62 const int kDeviceManagementNotAllowed = 403; |
| 63 const int kInvalidURL = 404; // This error is not coming from the GFE. |
| 64 const int kInvalidSerialNumber = 405; |
| 65 const int kDeviceIdConflict = 409; |
| 66 const int kDeviceNotFound = 410; |
| 67 const int kPendingApproval = 412; |
| 68 const int kInternalServerError = 500; |
| 69 const int kServiceUnavailable = 503; |
| 70 const int kPolicyNotFound = 902; // This error is not sent as HTTP status code. |
| 71 |
| 72 // TODO(pastarmovj): Legacy error codes are here for compatibility only. They |
| 73 // should be removed once the DM Server has been updated. |
| 74 const int kPendingApprovalLegacy = 491; |
| 75 const int kDeviceNotFoundLegacy = 901; |
| 76 |
| 77 #if defined(OS_CHROMEOS) |
| 78 // Machine info keys. |
| 79 const char kMachineInfoHWClass[] = "hardware_class"; |
| 80 const char kMachineInfoBoard[] = "CHROMEOS_RELEASE_BOARD"; |
| 81 #endif |
| 82 |
| 37 bool IsProxyError(const net::URLRequestStatus status) { | 83 bool IsProxyError(const net::URLRequestStatus status) { |
| 38 switch (status.error()) { | 84 switch (status.error()) { |
| 39 case net::ERR_PROXY_CONNECTION_FAILED: | 85 case net::ERR_PROXY_CONNECTION_FAILED: |
| 40 case net::ERR_TUNNEL_CONNECTION_FAILED: | 86 case net::ERR_TUNNEL_CONNECTION_FAILED: |
| 41 case net::ERR_PROXY_AUTH_UNSUPPORTED: | 87 case net::ERR_PROXY_AUTH_UNSUPPORTED: |
| 42 case net::ERR_HTTPS_PROXY_TUNNEL_RESPONSE: | 88 case net::ERR_HTTPS_PROXY_TUNNEL_RESPONSE: |
| 43 case net::ERR_MANDATORY_PROXY_CONFIGURATION_FAILED: | 89 case net::ERR_MANDATORY_PROXY_CONFIGURATION_FAILED: |
| 44 case net::ERR_PROXY_CERTIFICATE_INVALID: | 90 case net::ERR_PROXY_CERTIFICATE_INVALID: |
| 45 case net::ERR_SOCKS_CONNECTION_FAILED: | 91 case net::ERR_SOCKS_CONNECTION_FAILED: |
| 46 case net::ERR_SOCKS_CONNECTION_HOST_UNREACHABLE: | 92 case net::ERR_SOCKS_CONNECTION_HOST_UNREACHABLE: |
| 47 return true; | 93 return true; |
| 48 } | 94 } |
| 49 return false; | 95 return false; |
| 50 } | 96 } |
| 51 | 97 |
| 52 bool IsProtobufMimeType(const content::URLFetcher* source) { | 98 bool IsProtobufMimeType(const content::URLFetcher* source) { |
| 53 return source->GetResponseHeaders()->HasHeaderValue( | 99 return source->GetResponseHeaders()->HasHeaderValue( |
| 54 "content-type", "application/x-protobuffer"); | 100 "content-type", "application/x-protobuffer"); |
| 55 } | 101 } |
| 56 | 102 |
| 103 const char* UserAffiliationToString(UserAffiliation affiliation) { |
| 104 switch (affiliation) { |
| 105 case USER_AFFILIATION_MANAGED: |
| 106 return dm_protocol::kValueUserAffiliationManaged; |
| 107 case USER_AFFILIATION_NONE: |
| 108 return dm_protocol::kValueUserAffiliationNone; |
| 109 } |
| 110 NOTREACHED() << "Invalid user affiliation " << affiliation; |
| 111 return dm_protocol::kValueUserAffiliationNone; |
| 112 } |
| 113 |
| 114 const char* JobTypeToRequestType(DeviceManagementRequestJob::JobType type) { |
| 115 switch (type) { |
| 116 case DeviceManagementRequestJob::TYPE_AUTO_ENROLLMENT: |
| 117 return dm_protocol::kValueRequestAutoEnrollment; |
| 118 case DeviceManagementRequestJob::TYPE_REGISTRATION: |
| 119 return dm_protocol::kValueRequestRegister; |
| 120 case DeviceManagementRequestJob::TYPE_POLICY_FETCH: |
| 121 return dm_protocol::kValueRequestPolicy; |
| 122 case DeviceManagementRequestJob::TYPE_UNREGISTRATION: |
| 123 return dm_protocol::kValueRequestUnregister; |
| 124 } |
| 125 NOTREACHED() << "Invalid job type " << type; |
| 126 return ""; |
| 127 } |
| 128 |
| 129 const std::string& GetAgentString() { |
| 130 CR_DEFINE_STATIC_LOCAL(std::string, agent, ()); |
| 131 if (!agent.empty()) |
| 132 return agent; |
| 133 |
| 134 chrome::VersionInfo version_info; |
| 135 agent = base::StringPrintf(kValueAgent, |
| 136 version_info.Name().c_str(), |
| 137 version_info.Version().c_str(), |
| 138 version_info.LastChange().c_str()); |
| 139 return agent; |
| 140 } |
| 141 |
| 142 const std::string& GetPlatformString() { |
| 143 CR_DEFINE_STATIC_LOCAL(std::string, platform, ()); |
| 144 if (!platform.empty()) |
| 145 return platform; |
| 146 |
| 147 std::string os_name(base::SysInfo::OperatingSystemName()); |
| 148 std::string os_hardware(base::SysInfo::CPUArchitecture()); |
| 149 |
| 150 #if defined(OS_CHROMEOS) |
| 151 chromeos::system::StatisticsProvider* provider = |
| 152 chromeos::system::StatisticsProvider::GetInstance(); |
| 153 |
| 154 std::string hwclass; |
| 155 std::string board; |
| 156 if (!provider->GetMachineStatistic(kMachineInfoHWClass, &hwclass) || |
| 157 !provider->GetMachineStatistic(kMachineInfoBoard, &board)) { |
| 158 LOG(ERROR) << "Failed to get machine information"; |
| 159 } |
| 160 os_name += ",CrOS," + board; |
| 161 os_hardware += "," + hwclass; |
| 162 #endif |
| 163 |
| 164 std::string os_version("-"); |
| 165 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS) |
| 166 int32 os_major_version = 0; |
| 167 int32 os_minor_version = 0; |
| 168 int32 os_bugfix_version = 0; |
| 169 base::SysInfo::OperatingSystemVersionNumbers(&os_major_version, |
| 170 &os_minor_version, |
| 171 &os_bugfix_version); |
| 172 os_version = base::StringPrintf("%d.%d.%d", |
| 173 os_major_version, |
| 174 os_minor_version, |
| 175 os_bugfix_version); |
| 176 #endif |
| 177 |
| 178 platform = base::StringPrintf(kValuePlatform, |
| 179 os_name.c_str(), |
| 180 os_hardware.c_str(), |
| 181 os_version.c_str()); |
| 182 return platform; |
| 183 } |
| 184 |
| 57 // Custom request context implementation that allows to override the user agent, | 185 // Custom request context implementation that allows to override the user agent, |
| 58 // amongst others. Wraps a baseline request context from which we reuse the | 186 // amongst others. Wraps a baseline request context from which we reuse the |
| 59 // networking components. | 187 // networking components. |
| 60 class DeviceManagementRequestContext : public net::URLRequestContext { | 188 class DeviceManagementRequestContext : public net::URLRequestContext { |
| 61 public: | 189 public: |
| 62 explicit DeviceManagementRequestContext(net::URLRequestContext* base_context); | 190 explicit DeviceManagementRequestContext(net::URLRequestContext* base_context); |
| 63 virtual ~DeviceManagementRequestContext(); | 191 virtual ~DeviceManagementRequestContext(); |
| 64 | 192 |
| 65 private: | 193 private: |
| 66 // Overridden from net::URLRequestContext: | 194 // Overridden from net::URLRequestContext: |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 129 return context_.get(); | 257 return context_.get(); |
| 130 } | 258 } |
| 131 | 259 |
| 132 scoped_refptr<base::MessageLoopProxy> | 260 scoped_refptr<base::MessageLoopProxy> |
| 133 DeviceManagementRequestContextGetter::GetIOMessageLoopProxy() const { | 261 DeviceManagementRequestContextGetter::GetIOMessageLoopProxy() const { |
| 134 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO); | 262 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO); |
| 135 } | 263 } |
| 136 | 264 |
| 137 } // namespace | 265 } // namespace |
| 138 | 266 |
| 267 // Request job implementation used with DeviceManagementService. |
| 268 class DeviceManagementRequestJobImpl : public DeviceManagementRequestJob { |
| 269 public: |
| 270 DeviceManagementRequestJobImpl(JobType type, |
| 271 DeviceManagementService* service); |
| 272 virtual ~DeviceManagementRequestJobImpl(); |
| 273 |
| 274 // Handles the URL request response. |
| 275 void HandleResponse(const net::URLRequestStatus& status, |
| 276 int response_code, |
| 277 const net::ResponseCookies& cookies, |
| 278 const std::string& data); |
| 279 |
| 280 // Gets the URL to contact. |
| 281 GURL GetURL(const std::string& server_url); |
| 282 |
| 283 // Configures the fetcher, setting up payload and headers. |
| 284 void ConfigureRequest(content::URLFetcher* fetcher); |
| 285 |
| 286 protected: |
| 287 // DeviceManagementRequestJob: |
| 288 virtual void Run() OVERRIDE; |
| 289 |
| 290 private: |
| 291 // Invokes the callback with the given error code. |
| 292 void ReportError(DeviceManagementStatus code); |
| 293 |
| 294 // Pointer to the service this job is associated with. |
| 295 DeviceManagementService* service_; |
| 296 |
| 297 DISALLOW_COPY_AND_ASSIGN(DeviceManagementRequestJobImpl); |
| 298 }; |
| 299 |
| 300 DeviceManagementRequestJobImpl::DeviceManagementRequestJobImpl( |
| 301 JobType type, |
| 302 DeviceManagementService* service) |
| 303 : DeviceManagementRequestJob(type), |
| 304 service_(service) {} |
| 305 |
| 306 DeviceManagementRequestJobImpl::~DeviceManagementRequestJobImpl() { |
| 307 service_->RemoveJob(this); |
| 308 } |
| 309 |
| 310 void DeviceManagementRequestJobImpl::Run() { |
| 311 service_->AddJob(this); |
| 312 } |
| 313 |
| 314 void DeviceManagementRequestJobImpl::HandleResponse( |
| 315 const net::URLRequestStatus& status, |
| 316 int response_code, |
| 317 const net::ResponseCookies& cookies, |
| 318 const std::string& data) { |
| 319 if (status.status() != net::URLRequestStatus::SUCCESS) { |
| 320 ReportError(DM_STATUS_REQUEST_FAILED); |
| 321 return; |
| 322 } |
| 323 |
| 324 switch (response_code) { |
| 325 case kSuccess: { |
| 326 em::DeviceManagementResponse response; |
| 327 if (!response.ParseFromString(data)) { |
| 328 ReportError(DM_STATUS_RESPONSE_DECODING_ERROR); |
| 329 return; |
| 330 } |
| 331 callback_.Run(DM_STATUS_SUCCESS, response); |
| 332 return; |
| 333 } |
| 334 case kInvalidArgument: |
| 335 ReportError(DM_STATUS_REQUEST_INVALID); |
| 336 return; |
| 337 case kInvalidAuthCookieOrDMToken: |
| 338 ReportError(DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID); |
| 339 return; |
| 340 case kDeviceManagementNotAllowed: |
| 341 ReportError(DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED); |
| 342 return; |
| 343 case kPendingApprovalLegacy: |
| 344 case kPendingApproval: |
| 345 ReportError(DM_STATUS_SERVICE_ACTIVATION_PENDING); |
| 346 return; |
| 347 case kInvalidURL: |
| 348 case kInternalServerError: |
| 349 case kServiceUnavailable: |
| 350 ReportError(DM_STATUS_TEMPORARY_UNAVAILABLE); |
| 351 return; |
| 352 case kDeviceNotFoundLegacy: |
| 353 case kDeviceNotFound: |
| 354 ReportError(DM_STATUS_SERVICE_DEVICE_NOT_FOUND); |
| 355 return; |
| 356 case kPolicyNotFound: |
| 357 ReportError(DM_STATUS_SERVICE_POLICY_NOT_FOUND); |
| 358 return; |
| 359 case kInvalidSerialNumber: |
| 360 ReportError(DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER); |
| 361 return; |
| 362 case kDeviceIdConflict: |
| 363 ReportError(DM_STATUS_SERVICE_DEVICE_ID_CONFLICT); |
| 364 return; |
| 365 default: |
| 366 VLOG(1) << "Unexpected HTTP status in response from DMServer : " |
| 367 << response_code << "."; |
| 368 // Handle all unknown 5xx HTTP error codes as temporary and any other |
| 369 // unknown error as one that needs more time to recover. |
| 370 if (response_code >= 500 && response_code <= 599) |
| 371 ReportError(DM_STATUS_TEMPORARY_UNAVAILABLE); |
| 372 else |
| 373 ReportError(DM_STATUS_HTTP_STATUS_ERROR); |
| 374 return; |
| 375 } |
| 376 } |
| 377 |
| 378 GURL DeviceManagementRequestJobImpl::GetURL( |
| 379 const std::string& server_url) { |
| 380 std::string result(server_url); |
| 381 result += '?'; |
| 382 for (ParameterMap::const_iterator entry(query_params_.begin()); |
| 383 entry != query_params_.end(); |
| 384 ++entry) { |
| 385 if (entry != query_params_.begin()) |
| 386 result += '&'; |
| 387 result += net::EscapeQueryParamValue(entry->first, true); |
| 388 result += '='; |
| 389 result += net::EscapeQueryParamValue(entry->second, true); |
| 390 } |
| 391 return GURL(result); |
| 392 } |
| 393 |
| 394 void DeviceManagementRequestJobImpl::ConfigureRequest( |
| 395 content::URLFetcher* fetcher) { |
| 396 std::string payload; |
| 397 CHECK(request_.SerializeToString(&payload)); |
| 398 fetcher->SetUploadData(kPostContentType, payload); |
| 399 std::string extra_headers; |
| 400 if (!gaia_token_.empty()) |
| 401 extra_headers += kServiceTokenAuthHeader + gaia_token_ + "\n"; |
| 402 if (!dm_token_.empty()) |
| 403 extra_headers += kDMTokenAuthHeader + dm_token_ + "\n"; |
| 404 fetcher->SetExtraRequestHeaders(extra_headers); |
| 405 } |
| 406 |
| 407 void DeviceManagementRequestJobImpl::ReportError(DeviceManagementStatus code) { |
| 408 em::DeviceManagementResponse dummy_response; |
| 409 callback_.Run(code, dummy_response); |
| 410 } |
| 411 |
| 412 DeviceManagementRequestJob::~DeviceManagementRequestJob() {} |
| 413 |
| 414 void DeviceManagementRequestJob::SetGaiaToken(const std::string& gaia_token) { |
| 415 gaia_token_ = gaia_token; |
| 416 } |
| 417 |
| 418 void DeviceManagementRequestJob::SetOAuthToken(const std::string& oauth_token) { |
| 419 AddParameter(dm_protocol::kParamOAuthToken, oauth_token); |
| 420 } |
| 421 |
| 422 void DeviceManagementRequestJob::SetUserAffiliation( |
| 423 UserAffiliation user_affiliation) { |
| 424 AddParameter(dm_protocol::kParamUserAffiliation, |
| 425 UserAffiliationToString(user_affiliation)); |
| 426 } |
| 427 |
| 428 void DeviceManagementRequestJob::SetDMToken(const std::string& dm_token) { |
| 429 dm_token_ = dm_token; |
| 430 } |
| 431 |
| 432 void DeviceManagementRequestJob::SetClientID(const std::string& client_id) { |
| 433 AddParameter(dm_protocol::kParamDeviceID, client_id); |
| 434 } |
| 435 |
| 436 em::DeviceManagementRequest* DeviceManagementRequestJob::GetRequest() { |
| 437 return &request_; |
| 438 } |
| 439 |
| 440 DeviceManagementRequestJob::DeviceManagementRequestJob(JobType type) { |
| 441 AddParameter(dm_protocol::kParamRequest, JobTypeToRequestType(type)); |
| 442 AddParameter(dm_protocol::kParamDeviceType, dm_protocol::kValueDeviceType); |
| 443 AddParameter(dm_protocol::kParamAppType, dm_protocol::kValueAppType); |
| 444 AddParameter(dm_protocol::kParamAgent, GetAgentString()); |
| 445 AddParameter(dm_protocol::kParamPlatform, GetPlatformString()); |
| 446 } |
| 447 |
| 448 void DeviceManagementRequestJob::Start(const Callback& callback) { |
| 449 callback_ = callback; |
| 450 Run(); |
| 451 } |
| 452 |
| 453 void DeviceManagementRequestJob::AddParameter(const std::string& name, |
| 454 const std::string& value) { |
| 455 query_params_.push_back(std::make_pair(name, value)); |
| 456 } |
| 457 |
| 139 DeviceManagementService::~DeviceManagementService() { | 458 DeviceManagementService::~DeviceManagementService() { |
| 140 // All running jobs should have been cancelled by now. If not, there are | 459 // All running jobs should have been cancelled by now. |
| 141 // backend objects still around, which is an error. | |
| 142 DCHECK(pending_jobs_.empty()); | 460 DCHECK(pending_jobs_.empty()); |
| 143 DCHECK(queued_jobs_.empty()); | 461 DCHECK(queued_jobs_.empty()); |
| 144 } | 462 } |
| 145 | 463 |
| 146 DeviceManagementBackend* DeviceManagementService::CreateBackend() { | 464 DeviceManagementBackend* DeviceManagementService::CreateBackend() { |
| 147 return new DeviceManagementBackendImpl(this); | 465 return new DeviceManagementBackendImpl(this); |
| 148 } | 466 } |
| 149 | 467 |
| 468 DeviceManagementRequestJob* DeviceManagementService::CreateJob( |
| 469 DeviceManagementRequestJob::JobType type) { |
| 470 return new DeviceManagementRequestJobImpl(type, this); |
| 471 } |
| 472 |
| 150 void DeviceManagementService::ScheduleInitialization(int64 delay_milliseconds) { | 473 void DeviceManagementService::ScheduleInitialization(int64 delay_milliseconds) { |
| 151 if (initialized_) | 474 if (initialized_) |
| 152 return; | 475 return; |
| 153 MessageLoop::current()->PostDelayedTask( | 476 MessageLoop::current()->PostDelayedTask( |
| 154 FROM_HERE, | 477 FROM_HERE, |
| 155 base::Bind(&DeviceManagementService::Initialize, | 478 base::Bind(&DeviceManagementService::Initialize, |
| 156 weak_ptr_factory_.GetWeakPtr()), | 479 weak_ptr_factory_.GetWeakPtr()), |
| 157 delay_milliseconds); | 480 delay_milliseconds); |
| 158 } | 481 } |
| 159 | 482 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 181 pending_jobs_.clear(); | 504 pending_jobs_.clear(); |
| 182 } | 505 } |
| 183 | 506 |
| 184 DeviceManagementService::DeviceManagementService( | 507 DeviceManagementService::DeviceManagementService( |
| 185 const std::string& server_url) | 508 const std::string& server_url) |
| 186 : server_url_(server_url), | 509 : server_url_(server_url), |
| 187 initialized_(false), | 510 initialized_(false), |
| 188 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { | 511 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { |
| 189 } | 512 } |
| 190 | 513 |
| 191 void DeviceManagementService::AddJob(DeviceManagementJob* job) { | 514 void DeviceManagementService::StartJob(DeviceManagementRequestJobImpl* job, |
| 192 if (initialized_) | |
| 193 StartJob(job, false); | |
| 194 else | |
| 195 queued_jobs_.push_back(job); | |
| 196 } | |
| 197 | |
| 198 void DeviceManagementService::RemoveJob(DeviceManagementJob* job) { | |
| 199 for (JobFetcherMap::iterator entry(pending_jobs_.begin()); | |
| 200 entry != pending_jobs_.end(); | |
| 201 ++entry) { | |
| 202 if (entry->second == job) { | |
| 203 delete entry->first; | |
| 204 pending_jobs_.erase(entry); | |
| 205 return; | |
| 206 } | |
| 207 } | |
| 208 | |
| 209 const JobQueue::iterator elem = | |
| 210 std::find(queued_jobs_.begin(), queued_jobs_.end(), job); | |
| 211 if (elem != queued_jobs_.end()) | |
| 212 queued_jobs_.erase(elem); | |
| 213 } | |
| 214 | |
| 215 void DeviceManagementService::StartJob(DeviceManagementJob* job, | |
| 216 bool bypass_proxy) { | 515 bool bypass_proxy) { |
| 217 content::URLFetcher* fetcher = content::URLFetcher::Create( | 516 content::URLFetcher* fetcher = content::URLFetcher::Create( |
| 218 0, job->GetURL(server_url_), content::URLFetcher::POST, this); | 517 0, job->GetURL(server_url_), content::URLFetcher::POST, this); |
| 219 fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | | 518 fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | |
| 220 net::LOAD_DO_NOT_SAVE_COOKIES | | 519 net::LOAD_DO_NOT_SAVE_COOKIES | |
| 221 net::LOAD_DISABLE_CACHE | | 520 net::LOAD_DISABLE_CACHE | |
| 222 (bypass_proxy ? net::LOAD_BYPASS_PROXY : 0)); | 521 (bypass_proxy ? net::LOAD_BYPASS_PROXY : 0)); |
| 223 fetcher->SetRequestContext(request_context_getter_.get()); | 522 fetcher->SetRequestContext(request_context_getter_.get()); |
| 224 job->ConfigureRequest(fetcher); | 523 job->ConfigureRequest(fetcher); |
| 225 pending_jobs_[fetcher] = job; | 524 pending_jobs_[fetcher] = job; |
| 226 fetcher->Start(); | 525 fetcher->Start(); |
| 227 } | 526 } |
| 228 | 527 |
| 229 void DeviceManagementService::OnURLFetchComplete( | 528 void DeviceManagementService::OnURLFetchComplete( |
| 230 const content::URLFetcher* source) { | 529 const content::URLFetcher* source) { |
| 231 JobFetcherMap::iterator entry(pending_jobs_.find(source)); | 530 JobFetcherMap::iterator entry(pending_jobs_.find(source)); |
| 232 if (entry != pending_jobs_.end()) { | 531 if (entry == pending_jobs_.end()) { |
| 233 DeviceManagementJob* job = entry->second; | 532 NOTREACHED() << "Callback from foreign URL fetcher"; |
| 234 pending_jobs_.erase(entry); | 533 return; |
| 534 } |
| 235 | 535 |
| 236 // Retry the job if it failed due to a broken proxy, by bypassing the | 536 DeviceManagementRequestJobImpl* job = entry->second; |
| 237 // proxy on the next try. Don't retry if this URLFetcher already bypassed | 537 pending_jobs_.erase(entry); |
| 238 // the proxy. | 538 |
| 239 bool retry = false; | 539 // Retry the job if it failed due to a broken proxy, by bypassing the |
| 240 if ((source->GetLoadFlags() & net::LOAD_BYPASS_PROXY) == 0) { | 540 // proxy on the next try. Don't retry if this URLFetcher already bypassed |
| 241 if (!source->GetStatus().is_success() && | 541 // the proxy. |
| 242 IsProxyError(source->GetStatus())) { | 542 bool retry = false; |
| 243 LOG(WARNING) << "Proxy failed while contacting dmserver."; | 543 if ((source->GetLoadFlags() & net::LOAD_BYPASS_PROXY) == 0) { |
| 244 retry = true; | 544 if (!source->GetStatus().is_success() && |
| 245 } else if (source->GetStatus().is_success() && | 545 IsProxyError(source->GetStatus())) { |
| 246 source->WasFetchedViaProxy() && | 546 LOG(WARNING) << "Proxy failed while contacting dmserver."; |
| 247 !IsProtobufMimeType(source)) { | 547 retry = true; |
| 248 // The proxy server can be misconfigured but pointing to an existing | 548 } else if (source->GetStatus().is_success() && |
| 249 // server that replies to requests. Try to recover if a successful | 549 source->WasFetchedViaProxy() && |
| 250 // request that went through a proxy returns an unexpected mime type. | 550 !IsProtobufMimeType(source)) { |
| 251 LOG(WARNING) << "Got bad mime-type in response from dmserver that was " | 551 // The proxy server can be misconfigured but pointing to an existing |
| 252 << "fetched via a proxy."; | 552 // server that replies to requests. Try to recover if a successful |
| 253 retry = true; | 553 // request that went through a proxy returns an unexpected mime type. |
| 254 } | 554 LOG(WARNING) << "Got bad mime-type in response from dmserver that was " |
| 555 << "fetched via a proxy."; |
| 556 retry = true; |
| 255 } | 557 } |
| 558 } |
| 256 | 559 |
| 257 if (retry) { | 560 if (retry) { |
| 258 LOG(WARNING) << "Retrying dmserver request without using a proxy."; | 561 LOG(WARNING) << "Retrying dmserver request without using a proxy."; |
| 259 StartJob(job, true); | 562 StartJob(job, true); |
| 260 } else { | |
| 261 std::string data; | |
| 262 source->GetResponseAsString(&data); | |
| 263 job->HandleResponse(source->GetStatus(), source->GetResponseCode(), | |
| 264 source->GetCookies(), data); | |
| 265 } | |
| 266 } else { | 563 } else { |
| 267 NOTREACHED() << "Callback from foreign URL fetcher"; | 564 std::string data; |
| 565 source->GetResponseAsString(&data); |
| 566 job->HandleResponse(source->GetStatus(), source->GetResponseCode(), |
| 567 source->GetCookies(), data); |
| 268 } | 568 } |
| 269 delete source; | 569 delete source; |
| 270 } | 570 } |
| 271 | 571 |
| 572 void DeviceManagementService::AddJob(DeviceManagementRequestJobImpl* job) { |
| 573 if (initialized_) |
| 574 StartJob(job, false); |
| 575 else |
| 576 queued_jobs_.push_back(job); |
| 577 } |
| 578 |
| 579 void DeviceManagementService::RemoveJob(DeviceManagementRequestJobImpl* job) { |
| 580 for (JobFetcherMap::iterator entry(pending_jobs_.begin()); |
| 581 entry != pending_jobs_.end(); |
| 582 ++entry) { |
| 583 if (entry->second == job) { |
| 584 delete entry->first; |
| 585 pending_jobs_.erase(entry); |
| 586 return; |
| 587 } |
| 588 } |
| 589 |
| 590 const JobQueue::iterator elem = |
| 591 std::find(queued_jobs_.begin(), queued_jobs_.end(), job); |
| 592 if (elem != queued_jobs_.end()) |
| 593 queued_jobs_.erase(elem); |
| 594 } |
| 595 |
| 272 } // namespace policy | 596 } // namespace policy |
| OLD | NEW |