| 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 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 const int DownloadRequestCore::kDownloadByteStreamSize = 100 * 1024; | 104 const int DownloadRequestCore::kDownloadByteStreamSize = 100 * 1024; |
| 105 | 105 |
| 106 // static | 106 // static |
| 107 std::unique_ptr<net::URLRequest> DownloadRequestCore::CreateRequestOnIOThread( | 107 std::unique_ptr<net::URLRequest> DownloadRequestCore::CreateRequestOnIOThread( |
| 108 uint32_t download_id, | 108 uint32_t download_id, |
| 109 DownloadUrlParameters* params) { | 109 DownloadUrlParameters* params) { |
| 110 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 110 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 111 DCHECK(download_id == DownloadItem::kInvalidId || | 111 DCHECK(download_id == DownloadItem::kInvalidId || |
| 112 !params->content_initiated()) | 112 !params->content_initiated()) |
| 113 << "Content initiated downloads shouldn't specify a download ID"; | 113 << "Content initiated downloads shouldn't specify a download ID"; |
| 114 DCHECK(params->offset() >= 0); |
| 114 | 115 |
| 115 // ResourceDispatcherHost{Base} is-not-a URLRequest::Delegate, and | 116 // ResourceDispatcherHost{Base} is-not-a URLRequest::Delegate, and |
| 116 // DownloadUrlParameters can-not include resource_dispatcher_host_impl.h, so | 117 // DownloadUrlParameters can-not include resource_dispatcher_host_impl.h, so |
| 117 // we must down cast. RDHI is the only subclass of RDH as of 2012 May 4. | 118 // we must down cast. RDHI is the only subclass of RDH as of 2012 May 4. |
| 118 std::unique_ptr<net::URLRequest> request( | 119 std::unique_ptr<net::URLRequest> request( |
| 119 params->url_request_context_getter() | 120 params->url_request_context_getter() |
| 120 ->GetURLRequestContext() | 121 ->GetURLRequestContext() |
| 121 ->CreateRequest(params->url(), net::DEFAULT_PRIORITY, nullptr)); | 122 ->CreateRequest(params->url(), net::DEFAULT_PRIORITY, nullptr)); |
| 122 request->set_method(params->method()); | 123 request->set_method(params->method()); |
| 123 | 124 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 149 // validating the entry if present. | 150 // validating the entry if present. |
| 150 if (request->get_upload()) | 151 if (request->get_upload()) |
| 151 load_flags |= net::LOAD_ONLY_FROM_CACHE | net::LOAD_SKIP_CACHE_VALIDATION; | 152 load_flags |= net::LOAD_ONLY_FROM_CACHE | net::LOAD_SKIP_CACHE_VALIDATION; |
| 152 else | 153 else |
| 153 load_flags |= net::LOAD_SKIP_CACHE_VALIDATION; | 154 load_flags |= net::LOAD_SKIP_CACHE_VALIDATION; |
| 154 } else { | 155 } else { |
| 155 load_flags |= net::LOAD_DISABLE_CACHE; | 156 load_flags |= net::LOAD_DISABLE_CACHE; |
| 156 } | 157 } |
| 157 request->SetLoadFlags(load_flags); | 158 request->SetLoadFlags(load_flags); |
| 158 | 159 |
| 159 bool has_last_modified = !params->last_modified().empty(); | 160 // Add partial requests headers. |
| 160 bool has_etag = !params->etag().empty(); | 161 AddPartialRequestHeaders(request.get(), params); |
| 161 | |
| 162 // Strong validator(i.e. etag or last modified) is required in range requests | |
| 163 // for download resumption and parallel download. | |
| 164 DCHECK((params->offset() == 0 && | |
| 165 params->length() == DownloadSaveInfo::kLengthFullContent) || | |
| 166 has_etag || has_last_modified); | |
| 167 | |
| 168 // Add "Range" and "If-Range" request header fields if the range request is to | |
| 169 // retrieve bytes from {offset} to the end of the file. | |
| 170 // E.g. "Range:bytes=50-". | |
| 171 if (params->offset() > 0 && | |
| 172 params->length() == DownloadSaveInfo::kLengthFullContent && | |
| 173 (has_etag || has_last_modified)) { | |
| 174 request->SetExtraRequestHeaderByName( | |
| 175 net::HttpRequestHeaders::kRange, | |
| 176 base::StringPrintf("bytes=%" PRId64 "-", params->offset()), true); | |
| 177 | |
| 178 // In accordance with RFC 7233 Section 3.2, use If-Range to specify that | |
| 179 // the server return the entire entity if the validator doesn't match. | |
| 180 // Last-Modified can be used in the absence of ETag as a validator if the | |
| 181 // response headers satisfied the HttpUtil::HasStrongValidators() predicate. | |
| 182 // | |
| 183 // This function assumes that HasStrongValidators() was true and that the | |
| 184 // ETag and Last-Modified header values supplied are valid. | |
| 185 request->SetExtraRequestHeaderByName( | |
| 186 net::HttpRequestHeaders::kIfRange, | |
| 187 has_etag ? params->etag() : params->last_modified(), true); | |
| 188 } | |
| 189 | |
| 190 // Add "Range", "If-Match", and "If-Unmodified-Since" for range requests with | |
| 191 // last byte position specified. e.g. "Range:bytes=50-59". If the file is | |
| 192 // updated on the server, we should get http 412 response code. | |
| 193 if (params->length() != DownloadSaveInfo::kLengthFullContent && | |
| 194 (has_etag || has_last_modified)) { | |
| 195 request->SetExtraRequestHeaderByName( | |
| 196 net::HttpRequestHeaders::kRange, | |
| 197 base::StringPrintf("bytes=%" PRId64 "-%" PRId64, params->offset(), | |
| 198 params->offset() + params->length() - 1), | |
| 199 true); | |
| 200 if (has_etag) { | |
| 201 request->SetExtraRequestHeaderByName(net::HttpRequestHeaders::kIfMatch, | |
| 202 params->etag(), true); | |
| 203 } | |
| 204 // According to RFC 7232 section 3.4, "If-Unmodified-Since" is mainly for | |
| 205 // old servers that didn't implement "If-Match" and must be ignored when | |
| 206 // "If-Match" presents. | |
| 207 if (has_last_modified) { | |
| 208 request->SetExtraRequestHeaderByName( | |
| 209 net::HttpRequestHeaders::kIfUnmodifiedSince, params->last_modified(), | |
| 210 true); | |
| 211 } | |
| 212 } | |
| 213 | 162 |
| 214 // Downloads are treated as top level navigations. Hence the first-party | 163 // Downloads are treated as top level navigations. Hence the first-party |
| 215 // origin for cookies is always based on the target URL and is updated on | 164 // origin for cookies is always based on the target URL and is updated on |
| 216 // redirects. | 165 // redirects. |
| 217 request->set_first_party_for_cookies(params->url()); | 166 request->set_first_party_for_cookies(params->url()); |
| 218 request->set_first_party_url_policy( | 167 request->set_first_party_url_policy( |
| 219 net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT); | 168 net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT); |
| 220 request->set_initiator(params->initiator()); | 169 request->set_initiator(params->initiator()); |
| 221 | 170 |
| 222 for (const auto& header : params->request_headers()) | 171 for (const auto& header : params->request_headers()) |
| (...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 661 | 610 |
| 662 return DOWNLOAD_INTERRUPT_REASON_NONE; | 611 return DOWNLOAD_INTERRUPT_REASON_NONE; |
| 663 } | 612 } |
| 664 | 613 |
| 665 if (http_headers.response_code() == net::HTTP_PARTIAL_CONTENT) | 614 if (http_headers.response_code() == net::HTTP_PARTIAL_CONTENT) |
| 666 return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT; | 615 return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT; |
| 667 | 616 |
| 668 return DOWNLOAD_INTERRUPT_REASON_NONE; | 617 return DOWNLOAD_INTERRUPT_REASON_NONE; |
| 669 } | 618 } |
| 670 | 619 |
| 620 // static |
| 621 void DownloadRequestCore::AddPartialRequestHeaders( |
| 622 net::URLRequest* request, |
| 623 DownloadUrlParameters* params) { |
| 624 if (params->offset() == 0 && |
| 625 params->length() == DownloadSaveInfo::kLengthFullContent) |
| 626 return; |
| 627 |
| 628 bool has_last_modified = !params->last_modified().empty(); |
| 629 bool has_etag = !params->etag().empty(); |
| 630 |
| 631 // Strong validator(i.e. etag or last modified) is required in range requests |
| 632 // for download resumption and parallel download. |
| 633 DCHECK(has_etag || has_last_modified); |
| 634 if (!has_etag && !has_last_modified) { |
| 635 DVLOG(1) << "Creating partial request without strong validators."; |
| 636 return; |
| 637 } |
| 638 |
| 639 // Add "Range" header. |
| 640 std::string range_header = |
| 641 (params->length() == DownloadSaveInfo::kLengthFullContent) |
| 642 ? base::StringPrintf("bytes=%" PRId64 "-", params->offset()) |
| 643 : base::StringPrintf("bytes=%" PRId64 "-%" PRId64, params->offset(), |
| 644 params->offset() + params->length() - 1); |
| 645 request->SetExtraRequestHeaderByName(net::HttpRequestHeaders::kRange, |
| 646 range_header, true); |
| 647 |
| 648 // Add "If-Range" headers. |
| 649 if (params->use_if_range()) { |
| 650 // In accordance with RFC 7233 Section 3.2, use If-Range to specify that |
| 651 // the server return the entire entity if the validator doesn't match. |
| 652 // Last-Modified can be used in the absence of ETag as a validator if the |
| 653 // response headers satisfied the HttpUtil::HasStrongValidators() |
| 654 // predicate. |
| 655 // |
| 656 // This function assumes that HasStrongValidators() was true and that the |
| 657 // ETag and Last-Modified header values supplied are valid. |
| 658 request->SetExtraRequestHeaderByName( |
| 659 net::HttpRequestHeaders::kIfRange, |
| 660 has_etag ? params->etag() : params->last_modified(), true); |
| 661 return; |
| 662 } |
| 663 |
| 664 // Add "If-Match"/"If-Unmodified-Since" headers. |
| 665 if (has_etag) { |
| 666 request->SetExtraRequestHeaderByName(net::HttpRequestHeaders::kIfMatch, |
| 667 params->etag(), true); |
| 668 } |
| 669 // According to RFC 7232 section 3.4, "If-Unmodified-Since" is mainly for |
| 670 // old servers that didn't implement "If-Match" and must be ignored when |
| 671 // "If-Match" presents. |
| 672 if (has_last_modified) { |
| 673 request->SetExtraRequestHeaderByName( |
| 674 net::HttpRequestHeaders::kIfUnmodifiedSince, params->last_modified(), |
| 675 true); |
| 676 } |
| 677 } |
| 678 |
| 671 } // namespace content | 679 } // namespace content |
| OLD | NEW |