Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(511)

Side by Side Diff: content/browser/download/download_request_core.cc

Issue 2786523002: Add control to use If-Range header for range request. (Closed)
Patch Set: Rebase. Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « content/browser/download/download_request_core.h ('k') | content/browser/download/download_request_core_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698