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

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

Issue 148133007: [Downloads] Always call DM::StartDownload() for explicit downloads. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 9 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 | Annotate | Revision Log
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_resource_handler.h" 5 #include "content/browser/download/download_resource_handler.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 16 matching lines...) Expand all
27 #include "content/public/common/resource_response.h" 27 #include "content/public/common/resource_response.h"
28 #include "net/base/io_buffer.h" 28 #include "net/base/io_buffer.h"
29 #include "net/base/net_errors.h" 29 #include "net/base/net_errors.h"
30 #include "net/http/http_response_headers.h" 30 #include "net/http/http_response_headers.h"
31 #include "net/http/http_status_code.h" 31 #include "net/http/http_status_code.h"
32 #include "net/url_request/url_request_context.h" 32 #include "net/url_request/url_request_context.h"
33 33
34 namespace content { 34 namespace content {
35 namespace { 35 namespace {
36 36
37 void CallStartedCBOnUIThread(
38 const DownloadUrlParameters::OnStartedCallback& started_cb,
39 DownloadItem* item,
40 DownloadInterruptReason interrupt_reason) {
41 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
42
43 if (started_cb.is_null())
44 return;
45 started_cb.Run(item, interrupt_reason);
46 }
47
48 // Static function in order to prevent any accidental accesses to 37 // Static function in order to prevent any accidental accesses to
49 // DownloadResourceHandler members from the UI thread. 38 // DownloadResourceHandler members from the UI thread.
Randy Smith (Not in Mondays) 2014/03/18 21:07:28 nit: This comment seems outdated; it implies that
asanka 2014/03/19 20:37:06 Removed comment.
50 static void StartOnUIThread( 39 void StartOnUIThread(
51 scoped_ptr<DownloadCreateInfo> info, 40 scoped_ptr<DownloadCreateInfo> info,
52 scoped_ptr<ByteStreamReader> stream, 41 scoped_ptr<ByteStreamReader> stream,
53 const DownloadUrlParameters::OnStartedCallback& started_cb) { 42 const DownloadUrlParameters::OnStartedCallback& started_cb) {
54 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 43 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
55 44
56 DownloadManager* download_manager = info->request_handle.GetDownloadManager(); 45 DownloadManager* download_manager = info->request_handle.GetDownloadManager();
57 if (!download_manager) { 46 if (!download_manager) {
58 // NULL in unittests or if the page closed right after starting the 47 // NULL in unittests or if the page closed right after starting the
59 // download. 48 // download.
60 if (!started_cb.is_null()) 49 if (!started_cb.is_null())
61 started_cb.Run(NULL, DOWNLOAD_INTERRUPT_REASON_USER_CANCELED); 50 started_cb.Run(NULL, DOWNLOAD_INTERRUPT_REASON_USER_CANCELED);
62 51
63 // |stream| gets deleted on non-FILE thread, but it's ok since 52 // |stream| gets deleted on non-FILE thread, but it's ok since
64 // we're not using stream_writer_ yet. 53 // we're not using stream_writer_ yet.
65 54
66 return; 55 return;
67 } 56 }
68 57
69 download_manager->StartDownload(info.Pass(), stream.Pass(), started_cb); 58 download_manager->StartDownload(info.Pass(), stream.Pass(), started_cb);
70 } 59 }
71 60
61 DownloadInterruptReason HTTPResponseCodeToInterruptReason(int response_code) {
62 switch (response_code) {
63 case -1: // Non-HTTP request.
64 case net::HTTP_OK:
65 case net::HTTP_CREATED:
66 case net::HTTP_ACCEPTED:
67 case net::HTTP_NON_AUTHORITATIVE_INFORMATION:
68 case net::HTTP_RESET_CONTENT:
69 case net::HTTP_PARTIAL_CONTENT:
70 return DOWNLOAD_INTERRUPT_REASON_NONE;
71 case net::HTTP_NO_CONTENT:
72 case net::HTTP_NOT_FOUND:
73 return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT;
74 case net::HTTP_PRECONDITION_FAILED:
75 // Failed our 'If-Unmodified-Since' or 'If-Match'; see
76 // download_manager_impl.cc BeginDownload()
77 return DOWNLOAD_INTERRUPT_REASON_SERVER_PRECONDITION;
78 case net::HTTP_REQUESTED_RANGE_NOT_SATISFIABLE:
79 // Retry by downloading from the start automatically:
80 // If we haven't received data when we get this error, we won't.
81 return DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE;
82 // TODO(asanka): Add handling for 5xx errors with backoff semantics.
83 default: // All other errors.
84 // Redirection and informational codes should have been handled earlier
85 // in the stack.
86 DCHECK_NE(3, response_code / 100);
87 DCHECK_NE(1, response_code / 100);
88 return DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED;
89 }
90 }
91
72 } // namespace 92 } // namespace
73 93
74 const int DownloadResourceHandler::kDownloadByteStreamSize = 100 * 1024; 94 const int DownloadResourceHandler::kDownloadByteStreamSize = 100 * 1024;
75 95
76 DownloadResourceHandler::DownloadResourceHandler( 96 DownloadResourceHandler::DownloadResourceHandler(
77 uint32 id, 97 uint32 id,
78 net::URLRequest* request, 98 net::URLRequest* request,
79 const DownloadUrlParameters::OnStartedCallback& started_cb, 99 const DownloadUrlParameters::OnStartedCallback& started_cb,
80 scoped_ptr<DownloadSaveInfo> save_info) 100 scoped_ptr<DownloadSaveInfo> save_info)
81 : ResourceHandler(request), 101 : ResourceHandler(request),
82 download_id_(id), 102 download_id_(id),
83 started_cb_(started_cb), 103 started_cb_(started_cb),
84 save_info_(save_info.Pass()), 104 save_info_(save_info.Pass()),
85 last_buffer_size_(0), 105 last_buffer_size_(0),
86 bytes_read_(0), 106 bytes_read_(0),
87 pause_count_(0), 107 pause_count_(0),
88 was_deferred_(false), 108 was_deferred_(false),
89 on_response_started_called_(false) { 109 download_manager_notified_(false) {
90 RecordDownloadCount(UNTHROTTLED_COUNT); 110 RecordDownloadCount(UNTHROTTLED_COUNT);
91 } 111 }
92 112
93 bool DownloadResourceHandler::OnUploadProgress(int request_id, 113 bool DownloadResourceHandler::OnUploadProgress(int request_id,
94 uint64 position, 114 uint64 position,
95 uint64 size) { 115 uint64 size) {
96 return true; 116 return true;
97 } 117 }
98 118
99 bool DownloadResourceHandler::OnRequestRedirected( 119 bool DownloadResourceHandler::OnRequestRedirected(
100 int request_id, 120 int request_id,
101 const GURL& url, 121 const GURL& url,
102 ResourceResponse* response, 122 ResourceResponse* response,
103 bool* defer) { 123 bool* defer) {
104 // We treat a download as a main frame load, and thus update the policy URL 124 // We treat a download as a main frame load, and thus update the policy URL
105 // on redirects. 125 // on redirects.
106 request()->set_first_party_for_cookies(url); 126 request()->set_first_party_for_cookies(url);
107 return true; 127 return true;
108 } 128 }
109 129
110 // Send the download creation information to the download thread. 130 // Send the download creation information to the download thread.
111 bool DownloadResourceHandler::OnResponseStarted( 131 bool DownloadResourceHandler::OnResponseStarted(
112 int request_id, 132 int request_id,
113 ResourceResponse* response, 133 ResourceResponse* response,
114 bool* defer) { 134 bool* defer) {
115 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 135 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
116 // There can be only one (call)
117 DCHECK(!on_response_started_called_);
118 on_response_started_called_ = true;
119
120 VLOG(20) << __FUNCTION__ << "()" << DebugString() 136 VLOG(20) << __FUNCTION__ << "()" << DebugString()
121 << " request_id = " << request_id; 137 << " request_id = " << request_id;
122 download_start_time_ = base::TimeTicks::Now(); 138 download_start_time_ = base::TimeTicks::Now();
123 139
124 // If it's a download, we don't want to poison the cache with it. 140 // If it's a download, we don't want to poison the cache with it.
125 request()->StopCaching(); 141 request()->StopCaching();
126 142
127 // Lower priority as well, so downloads don't contend for resources 143 // Lower priority as well, so downloads don't contend for resources
128 // with main frames. 144 // with main frames.
129 request()->SetPriority(net::IDLE); 145 request()->SetPriority(net::IDLE);
130 146
147 const net::HttpResponseHeaders* headers = request()->response_headers();
148 DownloadInterruptReason interrupt_reason =
149 (headers ? HTTPResponseCodeToInterruptReason(headers->response_code())
150 : DOWNLOAD_INTERRUPT_REASON_NONE);
151
152 if (interrupt_reason != DOWNLOAD_INTERRUPT_REASON_NONE)
153 NotifyDownloadManagerOfFailedRequest(interrupt_reason);
154 else
155 NotifyDownloadManagerOfSuccessfulResponseStart(response);
156
157 return true;
158 }
159
160 void DownloadResourceHandler::NotifyDownloadManagerOfSuccessfulResponseStart(
161 ResourceResponse* response) {
162 // NotifyDownloadManagerOfFailedRequest or
163 // NotifyDownloadManagerOfSuccessfulResponseStart can only be called once.
164 DCHECK(!download_manager_notified_);
165 download_manager_notified_ = true;
166
167 const ResourceRequestInfoImpl* request_info = GetRequestInfo();
168 const net::HttpResponseHeaders* headers = request()->response_headers();
169
131 // If the content-length header is not present (or contains something other 170 // If the content-length header is not present (or contains something other
132 // than numbers), the incoming content_length is -1 (unknown size). 171 // than numbers), the incoming content_length is -1 (unknown size).
133 // Set the content length to 0 to indicate unknown size to DownloadManager. 172 // Set the content length to 0 to indicate unknown size to DownloadManager.
134 int64 content_length = 173 int64 content_length =
135 response->head.content_length > 0 ? response->head.content_length : 0; 174 response->head.content_length > 0 ? response->head.content_length : 0;
Randy Smith (Not in Mondays) 2014/03/18 21:07:28 nit, question: It feels a little funny to be both
asanka 2014/03/19 20:37:06 The URLRequestJob provides the expected content le
136 175
137 const ResourceRequestInfoImpl* request_info = GetRequestInfo();
138
139 // Deleted in DownloadManager.
140 scoped_ptr<DownloadCreateInfo> info( 176 scoped_ptr<DownloadCreateInfo> info(
141 new DownloadCreateInfo(base::Time::Now(), 177 new DownloadCreateInfo(base::Time::Now(),
142 content_length, 178 content_length,
143 request()->net_log(), 179 request()->net_log(),
144 request_info->HasUserGesture(), 180 request_info->HasUserGesture(),
145 request_info->GetPageTransition(), 181 request_info->GetPageTransition(),
146 save_info_.Pass())); 182 save_info_.Pass()));
147 183
148 // Create the ByteStream for sending data to the download sink.
149 scoped_ptr<ByteStreamReader> stream_reader;
150 CreateByteStream(
151 base::MessageLoopProxy::current(),
152 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE),
153 kDownloadByteStreamSize, &stream_writer_, &stream_reader);
154 stream_writer_->RegisterCallback(
155 base::Bind(&DownloadResourceHandler::ResumeRequest, AsWeakPtr()));
156
157 info->download_id = download_id_;
158 info->url_chain = request()->url_chain();
159 info->referrer_url = GURL(request()->referrer());
160 info->mime_type = response->head.mime_type;
161 info->remote_address = request()->GetSocketAddress().host();
162 request()->GetResponseHeaderByName("content-disposition",
163 &info->content_disposition);
164 RecordDownloadMimeType(info->mime_type);
165 RecordDownloadContentDisposition(info->content_disposition);
166
167 info->request_handle =
168 DownloadRequestHandle(AsWeakPtr(), request_info->GetChildID(),
169 request_info->GetRouteID(),
170 request_info->GetRequestID());
171
172 // Get the last modified time and etag.
173 const net::HttpResponseHeaders* headers = request()->response_headers();
174 if (headers) { 184 if (headers) {
175 if (headers->HasStrongValidators()) { 185 if (headers->HasStrongValidators()) {
176 // If we don't have strong validators as per RFC 2616 section 13.3.3, then 186 // If we don't have strong validators as per RFC 2616 section 13.3.3, then
177 // we neither store nor use them for range requests. 187 // we neither store nor use them for range requests.
178 if (!headers->EnumerateHeader(NULL, "Last-Modified", 188 if (!headers->EnumerateHeader(NULL, "Last-Modified",
179 &info->last_modified)) 189 &info->last_modified))
180 info->last_modified.clear(); 190 info->last_modified.clear();
181 if (!headers->EnumerateHeader(NULL, "ETag", &info->etag)) 191 if (!headers->EnumerateHeader(NULL, "ETag", &info->etag))
182 info->etag.clear(); 192 info->etag.clear();
183 } 193 }
184 194
185 int status = headers->response_code(); 195 int status = headers->response_code();
186 if (2 == status / 100 && status != net::HTTP_PARTIAL_CONTENT) { 196 if (2 == status / 100 && status != net::HTTP_PARTIAL_CONTENT) {
187 // Success & not range response; if we asked for a range, we didn't 197 // Success & not range response; if we asked for a range, we didn't
188 // get it--reset the file pointers to reflect that. 198 // get it--reset the file pointers to reflect that.
189 info->save_info->offset = 0; 199 info->save_info->offset = 0;
190 info->save_info->hash_state = ""; 200 info->save_info->hash_state = "";
191 } 201 }
192 202
193 if (!headers->GetMimeType(&info->original_mime_type)) 203 if (!headers->GetMimeType(&info->original_mime_type))
194 info->original_mime_type.clear(); 204 info->original_mime_type.clear();
195 } 205 }
196 206
207 info->download_id = download_id_;
208 info->url_chain = request()->url_chain();
209 info->referrer_url = GURL(request()->referrer());
210
211 scoped_ptr<ByteStreamReader> stream_reader;
212 // Create the ByteStream for sending data to the download sink.
213 CreateByteStream(
214 base::MessageLoopProxy::current(),
215 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE),
216 kDownloadByteStreamSize,
217 &stream_writer_,
218 &stream_reader);
219 stream_writer_->RegisterCallback(
220 base::Bind(&DownloadResourceHandler::ResumeRequest, AsWeakPtr()));
221
222 info->mime_type = response->head.mime_type;
223 info->remote_address = request()->GetSocketAddress().host();
224 request()->GetResponseHeaderByName("content-disposition",
225 &info->content_disposition);
Randy Smith (Not in Mondays) 2014/03/18 21:07:28 nit, suggestion: It makes some sense to me to swit
asanka 2014/03/19 20:37:06 Done.
226 RecordDownloadMimeType(info->mime_type);
227 RecordDownloadContentDisposition(info->content_disposition);
228
229 info->request_handle = DownloadRequestHandle(AsWeakPtr(),
230 request_info->GetChildID(),
231 request_info->GetRouteID(),
232 request_info->GetRequestID());
233
197 BrowserThread::PostTask( 234 BrowserThread::PostTask(
198 BrowserThread::UI, FROM_HERE, 235 BrowserThread::UI, FROM_HERE,
199 base::Bind(&StartOnUIThread, 236 base::Bind(&StartOnUIThread,
200 base::Passed(&info), 237 base::Passed(&info),
201 base::Passed(&stream_reader), 238 base::Passed(&stream_reader),
202 // Pass to StartOnUIThread so that variable 239 // Pass to StartOnUIThread so that variable
203 // access is always on IO thread but function 240 // access is always on IO thread but function
204 // is called on UI thread. 241 // is called on UI thread.
205 started_cb_)); 242 started_cb_));
206 // Guaranteed to be called in StartOnUIThread 243 // Guaranteed to be called in StartOnUIThread
207 started_cb_.Reset(); 244 started_cb_.Reset();
208
209 return true;
210 } 245 }
211 246
212 void DownloadResourceHandler::CallStartedCB( 247 void DownloadResourceHandler::NotifyDownloadManagerOfFailedRequest(
213 DownloadItem* item,
214 DownloadInterruptReason interrupt_reason) { 248 DownloadInterruptReason interrupt_reason) {
215 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 249 // NotifyDownloadManagerOfFailedRequest or
216 if (started_cb_.is_null()) 250 // NotifyDownloadManagerOfSuccessfulResponseStart can only be called once.
217 return; 251 DCHECK(!download_manager_notified_);
218 BrowserThread::PostTask( 252 DCHECK_NE(DOWNLOAD_INTERRUPT_REASON_NONE, interrupt_reason);
219 BrowserThread::UI, 253 download_manager_notified_ = true;
220 FROM_HERE, 254
221 base::Bind( 255 const ResourceRequestInfoImpl* request_info = GetRequestInfo();
222 &CallStartedCBOnUIThread, started_cb_, item, interrupt_reason)); 256
257 scoped_ptr<DownloadCreateInfo> info(
258 new DownloadCreateInfo(base::Time::Now(),
259 -1,
260 request()->net_log(),
261 false,
262 request_info->GetPageTransition(),
263 save_info_.Pass()));
264 info->download_id = download_id_;
265 info->url_chain = request()->url_chain();
266 info->referrer_url = GURL(request()->referrer());
267 info->interrupt_reason = interrupt_reason;
268 info->remote_address = request()->GetSocketAddress().host();
269 info->request_handle = DownloadRequestHandle(AsWeakPtr(),
270 request_info->GetChildID(),
271 request_info->GetRouteID(),
272 request_info->GetRequestID());
273
274 scoped_ptr<ByteStreamReader> stream_reader;
275 BrowserThread::PostTask(BrowserThread::UI,
276 FROM_HERE,
277 base::Bind(&StartOnUIThread,
278 base::Passed(&info),
279 base::Passed(&stream_reader),
Randy Smith (Not in Mondays) 2014/03/18 21:07:28 nit: I think it'd be clearer to cons up a null one
asanka 2014/03/19 20:37:06 Done.
280 started_cb_));
223 started_cb_.Reset(); 281 started_cb_.Reset();
224 } 282 }
225 283
226 bool DownloadResourceHandler::OnWillStart(int request_id, 284 bool DownloadResourceHandler::OnWillStart(int request_id,
227 const GURL& url, 285 const GURL& url,
228 bool* defer) { 286 bool* defer) {
229 return true; 287 return true;
230 } 288 }
231 289
232 bool DownloadResourceHandler::OnBeforeNetworkStart(int request_id, 290 bool DownloadResourceHandler::OnBeforeNetworkStart(int request_id,
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 double potential_bandwidth = last_buffer_size_/seconds_since_last_read; 328 double potential_bandwidth = last_buffer_size_/seconds_since_last_read;
271 RecordBandwidth(actual_bandwidth, potential_bandwidth); 329 RecordBandwidth(actual_bandwidth, potential_bandwidth);
272 } 330 }
273 last_read_time_ = now; 331 last_read_time_ = now;
274 332
275 if (!bytes_read) 333 if (!bytes_read)
276 return true; 334 return true;
277 bytes_read_ += bytes_read; 335 bytes_read_ += bytes_read;
278 DCHECK(read_buffer_.get()); 336 DCHECK(read_buffer_.get());
279 337
338 // If this was an error response, then stream_writer_ would be NULL.
339 if (!stream_writer_) {
340 read_buffer_ = NULL;
341 return true;
342 }
343
280 // Take the data ship it down the stream. If the stream is full, pause the 344 // Take the data ship it down the stream. If the stream is full, pause the
281 // request; the stream callback will resume it. 345 // request; the stream callback will resume it.
282 if (!stream_writer_->Write(read_buffer_, bytes_read)) { 346 if (!stream_writer_->Write(read_buffer_, bytes_read)) {
283 PauseRequest(); 347 PauseRequest();
284 *defer = was_deferred_ = true; 348 *defer = was_deferred_ = true;
285 last_stream_pause_time_ = now; 349 last_stream_pause_time_ = now;
286 } 350 }
287 351
288 read_buffer_ = NULL; // Drop our reference. 352 read_buffer_ = NULL; // Drop our reference.
289 353
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 // stack cancelled the request. There aren't that many things that 398 // stack cancelled the request. There aren't that many things that
335 // could do this to a download request (whose lifetime is separated from 399 // could do this to a download request (whose lifetime is separated from
336 // the tab from which it came). We map this to USER_CANCELLED as the 400 // the tab from which it came). We map this to USER_CANCELLED as the
337 // case we know about (system suspend because of laptop close) corresponds 401 // case we know about (system suspend because of laptop close) corresponds
338 // to a user action. 402 // to a user action.
339 // TODO(ahendrickson) -- Find a better set of codes to use here, as 403 // TODO(ahendrickson) -- Find a better set of codes to use here, as
340 // CANCELED/ERR_ABORTED can occur for reasons other than user cancel. 404 // CANCELED/ERR_ABORTED can occur for reasons other than user cancel.
341 reason = DOWNLOAD_INTERRUPT_REASON_USER_CANCELED; 405 reason = DOWNLOAD_INTERRUPT_REASON_USER_CANCELED;
342 } 406 }
343 407
344 if (status.is_success() &&
345 reason == DOWNLOAD_INTERRUPT_REASON_NONE &&
346 request()->response_headers()) {
347 // Handle server's response codes.
348 switch(response_code) {
349 case -1: // Non-HTTP request.
350 case net::HTTP_OK:
351 case net::HTTP_CREATED:
352 case net::HTTP_ACCEPTED:
353 case net::HTTP_NON_AUTHORITATIVE_INFORMATION:
354 case net::HTTP_RESET_CONTENT:
355 case net::HTTP_PARTIAL_CONTENT:
356 // Expected successful codes.
357 break;
358 case net::HTTP_NO_CONTENT:
359 case net::HTTP_NOT_FOUND:
360 reason = DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT;
361 break;
362 case net::HTTP_PRECONDITION_FAILED:
363 // Failed our 'If-Unmodified-Since' or 'If-Match'; see
364 // download_manager_impl.cc BeginDownload()
365 reason = DOWNLOAD_INTERRUPT_REASON_SERVER_PRECONDITION;
366 break;
367 case net::HTTP_REQUESTED_RANGE_NOT_SATISFIABLE:
368 // Retry by downloading from the start automatically:
369 // If we haven't received data when we get this error, we won't.
370 reason = DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE;
371 break;
372 default: // All other errors.
373 // Redirection and informational codes should have been handled earlier
374 // in the stack.
375 DCHECK_NE(3, response_code / 100);
376 DCHECK_NE(1, response_code / 100);
377 reason = DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED;
378 break;
379 }
380 }
381
382 std::string accept_ranges; 408 std::string accept_ranges;
383 bool has_strong_validators = false; 409 bool has_strong_validators = false;
384 if (request()->response_headers()) { 410 if (request()->response_headers()) {
385 request()->response_headers()->EnumerateHeader( 411 request()->response_headers()->EnumerateHeader(
386 NULL, "Accept-Ranges", &accept_ranges); 412 NULL, "Accept-Ranges", &accept_ranges);
387 has_strong_validators = 413 has_strong_validators =
388 request()->response_headers()->HasStrongValidators(); 414 request()->response_headers()->HasStrongValidators();
389 } 415 }
390 RecordAcceptsRanges(accept_ranges, bytes_read_, has_strong_validators); 416 RecordAcceptsRanges(accept_ranges, bytes_read_, has_strong_validators);
391 RecordNetworkBlockage(base::TimeTicks::Now() - download_start_time_, 417 RecordNetworkBlockage(base::TimeTicks::Now() - download_start_time_,
392 total_pause_time_); 418 total_pause_time_);
393 419
394 CallStartedCB(NULL, reason); 420 // If OnResponseCompleted() is called without a corresponding
395 421 // OnResponseStarted() call, then the DownloadManager wouldn't have been
396 // Send the info down the stream. Conditional is in case we get 422 // notified.
397 // OnResponseCompleted without OnResponseStarted. 423 if (!download_manager_notified_ &&
398 if (stream_writer_) 424 status.status() != net::URLRequestStatus::CANCELED) {
425 DCHECK_NE(DOWNLOAD_INTERRUPT_REASON_NONE, reason);
426 NotifyDownloadManagerOfFailedRequest(reason);
427 } else if (stream_writer_) {
428 // Send the info down the stream. Conditional is in case we get
429 // OnResponseCompleted without OnResponseStarted.
399 stream_writer_->Close(reason); 430 stream_writer_->Close(reason);
431 stream_writer_.reset(); // We no longer need the stream.
432 }
400 433
401 // If the error mapped to something unknown, record it so that 434 // If the error mapped to something unknown, record it so that
402 // we can drill down. 435 // we can drill down.
403 if (reason == DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED) { 436 if (reason == DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED) {
404 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Download.MapErrorNetworkFailed", 437 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Download.MapErrorNetworkFailed",
405 std::abs(status.error()), 438 std::abs(status.error()),
406 net::GetAllErrorCodesForUma()); 439 net::GetAllErrorCodesForUma());
407 } 440 }
408 441
409 stream_writer_.reset(); // We no longer need the stream.
410 read_buffer_ = NULL; 442 read_buffer_ = NULL;
411 } 443 }
412 444
413 void DownloadResourceHandler::OnDataDownloaded( 445 void DownloadResourceHandler::OnDataDownloaded(
414 int request_id, 446 int request_id,
415 int bytes_downloaded) { 447 int bytes_downloaded) {
416 NOTREACHED(); 448 NOTREACHED();
417 } 449 }
418 450
419 void DownloadResourceHandler::PauseRequest() { 451 void DownloadResourceHandler::PauseRequest() {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
466 request()->url().spec().c_str() : 498 request()->url().spec().c_str() :
467 "<NULL request>", 499 "<NULL request>",
468 info->GetChildID(), 500 info->GetChildID(),
469 info->GetRequestID(), 501 info->GetRequestID(),
470 info->GetRouteID()); 502 info->GetRouteID());
471 } 503 }
472 504
473 DownloadResourceHandler::~DownloadResourceHandler() { 505 DownloadResourceHandler::~DownloadResourceHandler() {
474 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 506 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
475 507
476 // This won't do anything if the callback was called before. 508 // DownloadManager would not be notified if:
477 // If it goes through, it will likely be because OnWillStart() returned 509 //
478 // false somewhere in the chain of resource handlers. 510 // - The Content-Type or Content-Disposition indicated that the entity should
479 CallStartedCB(NULL, DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED); 511 // be downloaded, but the response code was not 2xx. BufferedResourceHandler
512 // will create a DownloadResourceHandler, but won't invoke it.
513 // TODO(asanka): Fix this so that ResourceHandlers are only created if they
514 // are going to be used.
515 //
516 // - OnWillStart() returned false somewhere in the chain of resource handlers.
517 if (!download_manager_notified_ && !started_cb_.is_null())
Randy Smith (Not in Mondays) 2014/03/18 21:07:28 DCHECK opportunity? Shouldn't these two condition
asanka 2014/03/19 20:37:06 After verifying the OnWillStart() pathway, I decid
518 BrowserThread::PostTask(
519 BrowserThread::UI,
520 FROM_HERE,
521 base::Bind(started_cb_,
Randy Smith (Not in Mondays) 2014/03/18 21:07:28 Is the eventual intent to get rid of started_cb?
asanka 2014/03/19 20:37:06 Yeah. I'd like to get rid of started_cb_. I added
522 static_cast<DownloadItem*>(NULL),
523 DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED));
480 524
481 // Remove output stream callback if a stream exists. 525 // Remove output stream callback if a stream exists.
482 if (stream_writer_) 526 if (stream_writer_)
483 stream_writer_->RegisterCallback(base::Closure()); 527 stream_writer_->RegisterCallback(base::Closure());
484 528
485 UMA_HISTOGRAM_TIMES("SB2.DownloadDuration", 529 UMA_HISTOGRAM_TIMES("SB2.DownloadDuration",
486 base::TimeTicks::Now() - download_start_time_); 530 base::TimeTicks::Now() - download_start_time_);
487 } 531 }
488 532
489 } // namespace content 533 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698