| 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 "components/policy/core/common/cloud/device_management_service.h" | 5 #include "components/policy/core/common/cloud/device_management_service.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 169 void HandleResponse(const net::URLRequestStatus& status, | 169 void HandleResponse(const net::URLRequestStatus& status, |
| 170 int response_code, | 170 int response_code, |
| 171 const std::string& data); | 171 const std::string& data); |
| 172 | 172 |
| 173 // Gets the URL to contact. | 173 // Gets the URL to contact. |
| 174 GURL GetURL(const std::string& server_url); | 174 GURL GetURL(const std::string& server_url); |
| 175 | 175 |
| 176 // Configures the fetcher, setting up payload and headers. | 176 // Configures the fetcher, setting up payload and headers. |
| 177 void ConfigureRequest(net::URLFetcher* fetcher); | 177 void ConfigureRequest(net::URLFetcher* fetcher); |
| 178 | 178 |
| 179 // Returns true if this job should be retried. |fetcher| has just completed, | 179 enum RetryMethod { |
| 180 // and can be inspected to determine if the request failed and should be | 180 // No retry required for this request. |
| 181 // retried. | 181 NO_RETRY, |
| 182 bool ShouldRetry(const net::URLFetcher* fetcher); | 182 // Should retry immediately (no delay). |
| 183 RETRY_IMMEDIATELY, |
| 184 // Should retry after a delay. |
| 185 RETRY_WITH_DELAY |
| 186 }; |
| 187 |
| 188 // Returns if and how this job should be retried. |fetcher| has just |
| 189 // completed, and can be inspected to determine if the request failed and |
| 190 // should be retried. |
| 191 RetryMethod ShouldRetry(const net::URLFetcher* fetcher); |
| 192 |
| 193 // Returns the delay before the next retry with the specified RetryMethod. |
| 194 int GetRetryDelay(RetryMethod method); |
| 183 | 195 |
| 184 // Invoked right before retrying this job. | 196 // Invoked right before retrying this job. |
| 185 void PrepareRetry(); | 197 void PrepareRetry(); |
| 186 | 198 |
| 187 // Number of times that this job has been retried due to connection errors. | |
| 188 int retries_count() { return retries_count_; } | |
| 189 | |
| 190 // Get weak pointer | 199 // Get weak pointer |
| 191 base::WeakPtr<DeviceManagementRequestJobImpl> GetWeakPtr() { | 200 base::WeakPtr<DeviceManagementRequestJobImpl> GetWeakPtr() { |
| 192 return weak_ptr_factory_.GetWeakPtr(); | 201 return weak_ptr_factory_.GetWeakPtr(); |
| 193 } | 202 } |
| 194 | 203 |
| 195 protected: | 204 protected: |
| 196 // DeviceManagementRequestJob: | 205 // DeviceManagementRequestJob: |
| 197 void Run() override; | 206 void Run() override; |
| 198 | 207 |
| 199 private: | 208 private: |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 342 CHECK(request_.SerializeToString(&payload)); | 351 CHECK(request_.SerializeToString(&payload)); |
| 343 fetcher->SetUploadData(kPostContentType, payload); | 352 fetcher->SetUploadData(kPostContentType, payload); |
| 344 std::string extra_headers; | 353 std::string extra_headers; |
| 345 if (!gaia_token_.empty()) | 354 if (!gaia_token_.empty()) |
| 346 extra_headers += kServiceTokenAuthHeader + gaia_token_ + "\n"; | 355 extra_headers += kServiceTokenAuthHeader + gaia_token_ + "\n"; |
| 347 if (!dm_token_.empty()) | 356 if (!dm_token_.empty()) |
| 348 extra_headers += kDMTokenAuthHeader + dm_token_ + "\n"; | 357 extra_headers += kDMTokenAuthHeader + dm_token_ + "\n"; |
| 349 fetcher->SetExtraRequestHeaders(extra_headers); | 358 fetcher->SetExtraRequestHeaders(extra_headers); |
| 350 } | 359 } |
| 351 | 360 |
| 352 bool DeviceManagementRequestJobImpl::ShouldRetry( | 361 DeviceManagementRequestJobImpl::RetryMethod |
| 353 const net::URLFetcher* fetcher) { | 362 DeviceManagementRequestJobImpl::ShouldRetry(const net::URLFetcher* fetcher) { |
| 354 if (FailedWithProxy(fetcher) && !bypass_proxy_) { | 363 if (FailedWithProxy(fetcher) && !bypass_proxy_) { |
| 355 // Retry the job if it failed due to a broken proxy, by bypassing the | 364 // Retry the job immediately if it failed due to a broken proxy, by |
| 356 // proxy on the next try. | 365 // bypassing the proxy on the next try. |
| 357 bypass_proxy_ = true; | 366 bypass_proxy_ = true; |
| 358 return true; | 367 return RETRY_IMMEDIATELY; |
| 359 } | 368 } |
| 360 | 369 |
| 361 // Early device policy fetches on ChromeOS and Auto-Enrollment checks are | 370 // Early device policy fetches on ChromeOS and Auto-Enrollment checks are |
| 362 // often interrupted during ChromeOS startup when network is not yet ready. | 371 // often interrupted during ChromeOS startup when network is not yet ready. |
| 363 // Allowing the fetcher to retry once after that is enough to recover; allow | 372 // Allowing the fetcher to retry once after that is enough to recover; allow |
| 364 // it to retry up to 3 times just in case. | 373 // it to retry up to 3 times just in case. |
| 365 if (IsConnectionError(fetcher->GetStatus()) && retries_count_ < kMaxRetries) { | 374 if (IsConnectionError(fetcher->GetStatus()) && retries_count_ < kMaxRetries) { |
| 366 ++retries_count_; | 375 ++retries_count_; |
| 367 return true; | 376 if (type_ == DeviceManagementRequestJob::TYPE_POLICY_FETCH) { |
| 377 // We must not delay when retrying policy fetch, because it is a blocking |
| 378 // call when logging in. |
| 379 return RETRY_IMMEDIATELY; |
| 380 } else { |
| 381 return RETRY_WITH_DELAY; |
| 382 } |
| 368 } | 383 } |
| 369 | 384 |
| 370 // The request didn't fail, or the limit of retry attempts has been reached; | 385 // The request didn't fail, or the limit of retry attempts has been reached; |
| 371 // forward the result to the job owner. | 386 // forward the result to the job owner. |
| 372 return false; | 387 return NO_RETRY; |
| 388 } |
| 389 |
| 390 int DeviceManagementRequestJobImpl::GetRetryDelay(RetryMethod method) { |
| 391 switch (method) { |
| 392 case RETRY_WITH_DELAY: |
| 393 return g_retry_delay_ms << (retries_count_ - 1); |
| 394 case RETRY_IMMEDIATELY: |
| 395 return 0; |
| 396 default: |
| 397 NOTREACHED(); |
| 398 return 0; |
| 399 } |
| 373 } | 400 } |
| 374 | 401 |
| 375 void DeviceManagementRequestJobImpl::PrepareRetry() { | 402 void DeviceManagementRequestJobImpl::PrepareRetry() { |
| 376 if (!retry_callback_.is_null()) | 403 if (!retry_callback_.is_null()) |
| 377 retry_callback_.Run(this); | 404 retry_callback_.Run(this); |
| 378 } | 405 } |
| 379 | 406 |
| 380 void DeviceManagementRequestJobImpl::ReportError(DeviceManagementStatus code) { | 407 void DeviceManagementRequestJobImpl::ReportError(DeviceManagementStatus code) { |
| 381 em::DeviceManagementResponse dummy_response; | 408 em::DeviceManagementResponse dummy_response; |
| 382 callback_.Run(code, net::OK, dummy_response); | 409 callback_.Run(code, net::OK, dummy_response); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 400 AddParameter(dm_protocol::kParamDeviceID, client_id); | 427 AddParameter(dm_protocol::kParamDeviceID, client_id); |
| 401 } | 428 } |
| 402 | 429 |
| 403 em::DeviceManagementRequest* DeviceManagementRequestJob::GetRequest() { | 430 em::DeviceManagementRequest* DeviceManagementRequestJob::GetRequest() { |
| 404 return &request_; | 431 return &request_; |
| 405 } | 432 } |
| 406 | 433 |
| 407 DeviceManagementRequestJob::DeviceManagementRequestJob( | 434 DeviceManagementRequestJob::DeviceManagementRequestJob( |
| 408 JobType type, | 435 JobType type, |
| 409 const std::string& agent_parameter, | 436 const std::string& agent_parameter, |
| 410 const std::string& platform_parameter) { | 437 const std::string& platform_parameter) |
| 438 : type_(type) { |
| 411 AddParameter(dm_protocol::kParamRequest, JobTypeToRequestType(type)); | 439 AddParameter(dm_protocol::kParamRequest, JobTypeToRequestType(type)); |
| 412 AddParameter(dm_protocol::kParamDeviceType, dm_protocol::kValueDeviceType); | 440 AddParameter(dm_protocol::kParamDeviceType, dm_protocol::kValueDeviceType); |
| 413 AddParameter(dm_protocol::kParamAppType, dm_protocol::kValueAppType); | 441 AddParameter(dm_protocol::kParamAppType, dm_protocol::kValueAppType); |
| 414 AddParameter(dm_protocol::kParamAgent, agent_parameter); | 442 AddParameter(dm_protocol::kParamAgent, agent_parameter); |
| 415 AddParameter(dm_protocol::kParamPlatform, platform_parameter); | 443 AddParameter(dm_protocol::kParamPlatform, platform_parameter); |
| 416 } | 444 } |
| 417 | 445 |
| 418 void DeviceManagementRequestJob::SetRetryCallback( | 446 void DeviceManagementRequestJob::SetRetryCallback( |
| 419 const RetryCallback& retry_callback) { | 447 const RetryCallback& retry_callback) { |
| 420 retry_callback_ = retry_callback; | 448 retry_callback_ = retry_callback; |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 535 const net::URLFetcher* source) { | 563 const net::URLFetcher* source) { |
| 536 JobFetcherMap::iterator entry(pending_jobs_.find(source)); | 564 JobFetcherMap::iterator entry(pending_jobs_.find(source)); |
| 537 if (entry == pending_jobs_.end()) { | 565 if (entry == pending_jobs_.end()) { |
| 538 NOTREACHED() << "Callback from foreign URL fetcher"; | 566 NOTREACHED() << "Callback from foreign URL fetcher"; |
| 539 return; | 567 return; |
| 540 } | 568 } |
| 541 | 569 |
| 542 DeviceManagementRequestJobImpl* job = entry->second; | 570 DeviceManagementRequestJobImpl* job = entry->second; |
| 543 pending_jobs_.erase(entry); | 571 pending_jobs_.erase(entry); |
| 544 | 572 |
| 545 if (job->ShouldRetry(source)) { | 573 DeviceManagementRequestJobImpl::RetryMethod retry_method = |
| 574 job->ShouldRetry(source); |
| 575 if (retry_method != DeviceManagementRequestJobImpl::RetryMethod::NO_RETRY) { |
| 546 job->PrepareRetry(); | 576 job->PrepareRetry(); |
| 547 int delay = g_retry_delay_ms << (job->retries_count() - 1); | 577 int delay = job->GetRetryDelay(retry_method); |
| 548 LOG(WARNING) << "Dmserver request failed, retrying in " << delay / 1000 | 578 LOG(WARNING) << "Dmserver request failed, retrying in " << delay / 1000 |
| 549 << "s."; | 579 << "s."; |
| 550 task_runner_->PostDelayedTask( | 580 task_runner_->PostDelayedTask( |
| 551 FROM_HERE, | 581 FROM_HERE, |
| 552 base::Bind(&DeviceManagementService::StartJobAfterDelay, | 582 base::Bind(&DeviceManagementService::StartJobAfterDelay, |
| 553 weak_ptr_factory_.GetWeakPtr(), job->GetWeakPtr()), | 583 weak_ptr_factory_.GetWeakPtr(), job->GetWeakPtr()), |
| 554 base::TimeDelta::FromMilliseconds(delay)); | 584 base::TimeDelta::FromMilliseconds(delay)); |
| 555 } else { | 585 } else { |
| 556 std::string data; | 586 std::string data; |
| 557 source->GetResponseAsString(&data); | 587 source->GetResponseAsString(&data); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 578 } | 608 } |
| 579 } | 609 } |
| 580 | 610 |
| 581 const JobQueue::iterator elem = | 611 const JobQueue::iterator elem = |
| 582 std::find(queued_jobs_.begin(), queued_jobs_.end(), job); | 612 std::find(queued_jobs_.begin(), queued_jobs_.end(), job); |
| 583 if (elem != queued_jobs_.end()) | 613 if (elem != queued_jobs_.end()) |
| 584 queued_jobs_.erase(elem); | 614 queued_jobs_.erase(elem); |
| 585 } | 615 } |
| 586 | 616 |
| 587 } // namespace policy | 617 } // namespace policy |
| OLD | NEW |