Chromium Code Reviews| 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 "content/browser/download/download_request_core.h" | 5 #include "content/browser/download/download_request_core.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
| (...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 391 | 391 |
| 392 void DownloadRequestCore::OnResponseCompleted( | 392 void DownloadRequestCore::OnResponseCompleted( |
| 393 const net::URLRequestStatus& status) { | 393 const net::URLRequestStatus& status) { |
| 394 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 394 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 395 int response_code = status.is_success() ? request()->GetResponseCode() : 0; | 395 int response_code = status.is_success() ? request()->GetResponseCode() : 0; |
| 396 DVLOG(20) << __func__ << "() " << DebugString() | 396 DVLOG(20) << __func__ << "() " << DebugString() |
| 397 << " status.status() = " << status.status() | 397 << " status.status() = " << status.status() |
| 398 << " status.error() = " << status.error() | 398 << " status.error() = " << status.error() |
| 399 << " response_code = " << response_code; | 399 << " response_code = " << response_code; |
| 400 | 400 |
| 401 DownloadInterruptReason reason = HandleRequestStatus(status); | 401 DownloadInterruptReason reason = HandleRequestStatus( |
| 402 status, request()->response_headers()->HasStrongValidators()); | |
| 402 | 403 |
| 403 if (status.error() == net::ERR_ABORTED) { | 404 if (status.error() == net::ERR_ABORTED) { |
| 404 // ERR_ABORTED == something outside of the network | 405 // ERR_ABORTED == something outside of the network |
| 405 // stack cancelled the request. There aren't that many things that | 406 // stack cancelled the request. There aren't that many things that |
| 406 // could do this to a download request (whose lifetime is separated from | 407 // could do this to a download request (whose lifetime is separated from |
| 407 // the tab from which it came). We map this to USER_CANCELLED as the | 408 // the tab from which it came). We map this to USER_CANCELLED as the |
| 408 // case we know about (system suspend because of laptop close) corresponds | 409 // case we know about (system suspend because of laptop close) corresponds |
| 409 // to a user action. | 410 // to a user action. |
| 410 // TODO(asanka): A lid close or other power event should result in an | 411 // TODO(asanka): A lid close or other power event should result in an |
| 411 // interruption that doesn't discard the partial state, unlike | 412 // interruption that doesn't discard the partial state, unlike |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 493 " this=%p " | 494 " this=%p " |
| 494 " url_ = " | 495 " url_ = " |
| 495 "\"%s\"" | 496 "\"%s\"" |
| 496 " }", | 497 " }", |
| 497 reinterpret_cast<const void*>(this), | 498 reinterpret_cast<const void*>(this), |
| 498 request() ? request()->url().spec().c_str() : "<NULL request>"); | 499 request() ? request()->url().spec().c_str() : "<NULL request>"); |
| 499 } | 500 } |
| 500 | 501 |
| 501 // static | 502 // static |
| 502 DownloadInterruptReason DownloadRequestCore::HandleRequestStatus( | 503 DownloadInterruptReason DownloadRequestCore::HandleRequestStatus( |
| 503 const net::URLRequestStatus& status) { | 504 const net::URLRequestStatus& status, bool has_strong_validators) { |
| 504 net::Error error_code = net::OK; | 505 net::Error error_code = net::OK; |
| 505 if (!status.is_success()) { | 506 if (!status.is_success()) { |
| 506 error_code = static_cast<net::Error>(status.error()); // Normal case. | 507 error_code = static_cast<net::Error>(status.error()); // Normal case. |
| 507 // Make sure that at least the fact of failure comes through. | 508 // Make sure that at least the fact of failure comes through. |
| 508 if (error_code == net::OK) | 509 if (error_code == net::OK) |
| 509 error_code = net::ERR_FAILED; | 510 error_code = net::ERR_FAILED; |
| 510 } | 511 } |
| 511 | 512 |
| 512 // ERR_CONTENT_LENGTH_MISMATCH is allowed since a number of servers in the | 513 // ERR_CONTENT_LENGTH_MISMATCH can be caused by 1 of the following reasons: |
| 513 // wild close the connection too early by mistake. Other browsers - IE9, | 514 // 1. server close the connection too early. |
|
asanka
2017/04/26 21:17:33
The more common case isn't the server closing the
qinmin
2017/04/27 18:20:54
Done. Thanks for the info.
| |
| 514 // Firefox 11.0, and Safari 5.1.4 - treat downloads as complete in both cases, | 515 // 2. The content-length header is wrong. |
| 515 // so we follow their lead. | 516 // If the download has strong validators, we can interrupt the download |
| 516 if (error_code == net::ERR_CONTENT_LENGTH_MISMATCH) | 517 // and let it resume automatically. Otherwise, resuming the download will |
| 518 // cause it to restart and the download may never complete if the error was | |
| 519 // caused by reason 2. As a result, downloads without strong validators are | |
| 520 // treated as completed here. | |
| 521 // TODO(qinmin): check the metrics from downloads with strong validators, | |
| 522 // and decide whether we should interrupt downloads without strong validators | |
| 523 // rather than complete them. | |
| 524 if (error_code == net::ERR_CONTENT_LENGTH_MISMATCH && | |
| 525 !has_strong_validators) { | |
| 517 error_code = net::OK; | 526 error_code = net::OK; |
| 527 RecordDownloadCount(COMPLETED_WITH_CONTENT_LENGTH_MISMATCH_COUNT); | |
| 528 } | |
| 529 | |
| 518 DownloadInterruptReason reason = ConvertNetErrorToInterruptReason( | 530 DownloadInterruptReason reason = ConvertNetErrorToInterruptReason( |
| 519 error_code, DOWNLOAD_INTERRUPT_FROM_NETWORK); | 531 error_code, DOWNLOAD_INTERRUPT_FROM_NETWORK); |
| 520 | 532 |
| 521 return reason; | 533 return reason; |
| 522 } | 534 } |
| 523 | 535 |
| 524 // static | 536 // static |
| 525 DownloadInterruptReason DownloadRequestCore::HandleSuccessfulServerResponse( | 537 DownloadInterruptReason DownloadRequestCore::HandleSuccessfulServerResponse( |
| 526 const net::HttpResponseHeaders& http_headers, | 538 const net::HttpResponseHeaders& http_headers, |
| 527 DownloadSaveInfo* save_info) { | 539 DownloadSaveInfo* save_info) { |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 676 // old servers that didn't implement "If-Match" and must be ignored when | 688 // old servers that didn't implement "If-Match" and must be ignored when |
| 677 // "If-Match" presents. | 689 // "If-Match" presents. |
| 678 if (has_last_modified) { | 690 if (has_last_modified) { |
| 679 request->SetExtraRequestHeaderByName( | 691 request->SetExtraRequestHeaderByName( |
| 680 net::HttpRequestHeaders::kIfUnmodifiedSince, params->last_modified(), | 692 net::HttpRequestHeaders::kIfUnmodifiedSince, params->last_modified(), |
| 681 true); | 693 true); |
| 682 } | 694 } |
| 683 } | 695 } |
| 684 | 696 |
| 685 } // namespace content | 697 } // namespace content |
| OLD | NEW |