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_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 28 matching lines...) Expand all Loading... |
39 GURL tab_url; | 39 GURL tab_url; |
40 GURL tab_referrer_url; | 40 GURL tab_referrer_url; |
41 }; | 41 }; |
42 | 42 |
43 namespace { | 43 namespace { |
44 | 44 |
45 void CallStartedCBOnUIThread( | 45 void CallStartedCBOnUIThread( |
46 const DownloadUrlParameters::OnStartedCallback& started_cb, | 46 const DownloadUrlParameters::OnStartedCallback& started_cb, |
47 DownloadItem* item, | 47 DownloadItem* item, |
48 DownloadInterruptReason interrupt_reason) { | 48 DownloadInterruptReason interrupt_reason) { |
49 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 49 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
50 | 50 |
51 if (started_cb.is_null()) | 51 if (started_cb.is_null()) |
52 return; | 52 return; |
53 started_cb.Run(item, interrupt_reason); | 53 started_cb.Run(item, interrupt_reason); |
54 } | 54 } |
55 | 55 |
56 // Static function in order to prevent any accidental accesses to | 56 // Static function in order to prevent any accidental accesses to |
57 // DownloadResourceHandler members from the UI thread. | 57 // DownloadResourceHandler members from the UI thread. |
58 static void StartOnUIThread( | 58 static void StartOnUIThread( |
59 scoped_ptr<DownloadCreateInfo> info, | 59 scoped_ptr<DownloadCreateInfo> info, |
60 DownloadResourceHandler::DownloadTabInfo* tab_info, | 60 DownloadResourceHandler::DownloadTabInfo* tab_info, |
61 scoped_ptr<ByteStreamReader> stream, | 61 scoped_ptr<ByteStreamReader> stream, |
62 const DownloadUrlParameters::OnStartedCallback& started_cb) { | 62 const DownloadUrlParameters::OnStartedCallback& started_cb) { |
63 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 63 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
64 | 64 |
65 DownloadManager* download_manager = info->request_handle.GetDownloadManager(); | 65 DownloadManager* download_manager = info->request_handle.GetDownloadManager(); |
66 if (!download_manager) { | 66 if (!download_manager) { |
67 // NULL in unittests or if the page closed right after starting the | 67 // NULL in unittests or if the page closed right after starting the |
68 // download. | 68 // download. |
69 if (!started_cb.is_null()) | 69 if (!started_cb.is_null()) |
70 started_cb.Run(NULL, DOWNLOAD_INTERRUPT_REASON_USER_CANCELED); | 70 started_cb.Run(NULL, DOWNLOAD_INTERRUPT_REASON_USER_CANCELED); |
71 | 71 |
72 // |stream| gets deleted on non-FILE thread, but it's ok since | 72 // |stream| gets deleted on non-FILE thread, but it's ok since |
73 // we're not using stream_writer_ yet. | 73 // we're not using stream_writer_ yet. |
74 | 74 |
75 return; | 75 return; |
76 } | 76 } |
77 | 77 |
78 info->tab_url = tab_info->tab_url; | 78 info->tab_url = tab_info->tab_url; |
79 info->tab_referrer_url = tab_info->tab_referrer_url; | 79 info->tab_referrer_url = tab_info->tab_referrer_url; |
80 | 80 |
81 download_manager->StartDownload(info.Pass(), stream.Pass(), started_cb); | 81 download_manager->StartDownload(info.Pass(), stream.Pass(), started_cb); |
82 } | 82 } |
83 | 83 |
84 void InitializeDownloadTabInfoOnUIThread( | 84 void InitializeDownloadTabInfoOnUIThread( |
85 const DownloadRequestHandle& request_handle, | 85 const DownloadRequestHandle& request_handle, |
86 DownloadResourceHandler::DownloadTabInfo* tab_info) { | 86 DownloadResourceHandler::DownloadTabInfo* tab_info) { |
87 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 87 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
88 | 88 |
89 WebContents* web_contents = request_handle.GetWebContents(); | 89 WebContents* web_contents = request_handle.GetWebContents(); |
90 if (web_contents) { | 90 if (web_contents) { |
91 NavigationEntry* entry = web_contents->GetController().GetVisibleEntry(); | 91 NavigationEntry* entry = web_contents->GetController().GetVisibleEntry(); |
92 if (entry) { | 92 if (entry) { |
93 tab_info->tab_url = entry->GetURL(); | 93 tab_info->tab_url = entry->GetURL(); |
94 tab_info->tab_referrer_url = entry->GetReferrer().url; | 94 tab_info->tab_referrer_url = entry->GetReferrer().url; |
95 } | 95 } |
96 } | 96 } |
97 } | 97 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
143 const net::RedirectInfo& redirect_info, | 143 const net::RedirectInfo& redirect_info, |
144 ResourceResponse* response, | 144 ResourceResponse* response, |
145 bool* defer) { | 145 bool* defer) { |
146 return true; | 146 return true; |
147 } | 147 } |
148 | 148 |
149 // Send the download creation information to the download thread. | 149 // Send the download creation information to the download thread. |
150 bool DownloadResourceHandler::OnResponseStarted( | 150 bool DownloadResourceHandler::OnResponseStarted( |
151 ResourceResponse* response, | 151 ResourceResponse* response, |
152 bool* defer) { | 152 bool* defer) { |
153 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 153 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
154 // There can be only one (call) | 154 // There can be only one (call) |
155 DCHECK(!on_response_started_called_); | 155 DCHECK(!on_response_started_called_); |
156 on_response_started_called_ = true; | 156 on_response_started_called_ = true; |
157 | 157 |
158 DVLOG(20) << __FUNCTION__ << "()" << DebugString(); | 158 DVLOG(20) << __FUNCTION__ << "()" << DebugString(); |
159 download_start_time_ = base::TimeTicks::Now(); | 159 download_start_time_ = base::TimeTicks::Now(); |
160 | 160 |
161 // If it's a download, we don't want to poison the cache with it. | 161 // If it's a download, we don't want to poison the cache with it. |
162 request()->StopCaching(); | 162 request()->StopCaching(); |
163 | 163 |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 tab_info_ = NULL; | 253 tab_info_ = NULL; |
254 // Guaranteed to be called in StartOnUIThread | 254 // Guaranteed to be called in StartOnUIThread |
255 started_cb_.Reset(); | 255 started_cb_.Reset(); |
256 | 256 |
257 return true; | 257 return true; |
258 } | 258 } |
259 | 259 |
260 void DownloadResourceHandler::CallStartedCB( | 260 void DownloadResourceHandler::CallStartedCB( |
261 DownloadItem* item, | 261 DownloadItem* item, |
262 DownloadInterruptReason interrupt_reason) { | 262 DownloadInterruptReason interrupt_reason) { |
263 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 263 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
264 if (started_cb_.is_null()) | 264 if (started_cb_.is_null()) |
265 return; | 265 return; |
266 BrowserThread::PostTask( | 266 BrowserThread::PostTask( |
267 BrowserThread::UI, | 267 BrowserThread::UI, |
268 FROM_HERE, | 268 FROM_HERE, |
269 base::Bind( | 269 base::Bind( |
270 &CallStartedCBOnUIThread, started_cb_, item, interrupt_reason)); | 270 &CallStartedCBOnUIThread, started_cb_, item, interrupt_reason)); |
271 started_cb_.Reset(); | 271 started_cb_.Reset(); |
272 } | 272 } |
273 | 273 |
274 bool DownloadResourceHandler::OnWillStart(const GURL& url, bool* defer) { | 274 bool DownloadResourceHandler::OnWillStart(const GURL& url, bool* defer) { |
275 return true; | 275 return true; |
276 } | 276 } |
277 | 277 |
278 bool DownloadResourceHandler::OnBeforeNetworkStart(const GURL& url, | 278 bool DownloadResourceHandler::OnBeforeNetworkStart(const GURL& url, |
279 bool* defer) { | 279 bool* defer) { |
280 return true; | 280 return true; |
281 } | 281 } |
282 | 282 |
283 // Create a new buffer, which will be handed to the download thread for file | 283 // Create a new buffer, which will be handed to the download thread for file |
284 // writing and deletion. | 284 // writing and deletion. |
285 bool DownloadResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf, | 285 bool DownloadResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf, |
286 int* buf_size, | 286 int* buf_size, |
287 int min_size) { | 287 int min_size) { |
288 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 288 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
289 DCHECK(buf && buf_size); | 289 DCHECK(buf && buf_size); |
290 DCHECK(!read_buffer_.get()); | 290 DCHECK(!read_buffer_.get()); |
291 | 291 |
292 *buf_size = min_size < 0 ? kReadBufSize : min_size; | 292 *buf_size = min_size < 0 ? kReadBufSize : min_size; |
293 last_buffer_size_ = *buf_size; | 293 last_buffer_size_ = *buf_size; |
294 read_buffer_ = new net::IOBuffer(*buf_size); | 294 read_buffer_ = new net::IOBuffer(*buf_size); |
295 *buf = read_buffer_.get(); | 295 *buf = read_buffer_.get(); |
296 return true; | 296 return true; |
297 } | 297 } |
298 | 298 |
299 // Pass the buffer to the download file writer. | 299 // Pass the buffer to the download file writer. |
300 bool DownloadResourceHandler::OnReadCompleted(int bytes_read, bool* defer) { | 300 bool DownloadResourceHandler::OnReadCompleted(int bytes_read, bool* defer) { |
301 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 301 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
302 DCHECK(read_buffer_.get()); | 302 DCHECK(read_buffer_.get()); |
303 | 303 |
304 base::TimeTicks now(base::TimeTicks::Now()); | 304 base::TimeTicks now(base::TimeTicks::Now()); |
305 if (!last_read_time_.is_null()) { | 305 if (!last_read_time_.is_null()) { |
306 double seconds_since_last_read = (now - last_read_time_).InSecondsF(); | 306 double seconds_since_last_read = (now - last_read_time_).InSecondsF(); |
307 if (now == last_read_time_) | 307 if (now == last_read_time_) |
308 // Use 1/10 ms as a "very small number" so that we avoid | 308 // Use 1/10 ms as a "very small number" so that we avoid |
309 // divide-by-zero error and still record a very high potential bandwidth. | 309 // divide-by-zero error and still record a very high potential bandwidth. |
310 seconds_since_last_read = 0.00001; | 310 seconds_since_last_read = 0.00001; |
311 | 311 |
(...skipping 21 matching lines...) Expand all Loading... |
333 if (pause_count_ > 0) | 333 if (pause_count_ > 0) |
334 *defer = was_deferred_ = true; | 334 *defer = was_deferred_ = true; |
335 | 335 |
336 return true; | 336 return true; |
337 } | 337 } |
338 | 338 |
339 void DownloadResourceHandler::OnResponseCompleted( | 339 void DownloadResourceHandler::OnResponseCompleted( |
340 const net::URLRequestStatus& status, | 340 const net::URLRequestStatus& status, |
341 const std::string& security_info, | 341 const std::string& security_info, |
342 bool* defer) { | 342 bool* defer) { |
343 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 343 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
344 int response_code = status.is_success() ? request()->GetResponseCode() : 0; | 344 int response_code = status.is_success() ? request()->GetResponseCode() : 0; |
345 DVLOG(20) << __FUNCTION__ << "()" << DebugString() | 345 DVLOG(20) << __FUNCTION__ << "()" << DebugString() |
346 << " status.status() = " << status.status() | 346 << " status.status() = " << status.status() |
347 << " status.error() = " << status.error() | 347 << " status.error() = " << status.error() |
348 << " response_code = " << response_code; | 348 << " response_code = " << response_code; |
349 | 349 |
350 net::Error error_code = net::OK; | 350 net::Error error_code = net::OK; |
351 if (status.status() == net::URLRequestStatus::FAILED || | 351 if (status.status() == net::URLRequestStatus::FAILED || |
352 // Note cancels as failures too. | 352 // Note cancels as failures too. |
353 status.status() == net::URLRequestStatus::CANCELED) { | 353 status.status() == net::URLRequestStatus::CANCELED) { |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
456 | 456 |
457 stream_writer_.reset(); // We no longer need the stream. | 457 stream_writer_.reset(); // We no longer need the stream. |
458 read_buffer_ = NULL; | 458 read_buffer_ = NULL; |
459 } | 459 } |
460 | 460 |
461 void DownloadResourceHandler::OnDataDownloaded(int bytes_downloaded) { | 461 void DownloadResourceHandler::OnDataDownloaded(int bytes_downloaded) { |
462 NOTREACHED(); | 462 NOTREACHED(); |
463 } | 463 } |
464 | 464 |
465 void DownloadResourceHandler::PauseRequest() { | 465 void DownloadResourceHandler::PauseRequest() { |
466 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 466 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
467 | 467 |
468 ++pause_count_; | 468 ++pause_count_; |
469 } | 469 } |
470 | 470 |
471 void DownloadResourceHandler::ResumeRequest() { | 471 void DownloadResourceHandler::ResumeRequest() { |
472 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 472 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
473 DCHECK_LT(0, pause_count_); | 473 DCHECK_LT(0, pause_count_); |
474 | 474 |
475 --pause_count_; | 475 --pause_count_; |
476 | 476 |
477 if (!was_deferred_) | 477 if (!was_deferred_) |
478 return; | 478 return; |
479 if (pause_count_ > 0) | 479 if (pause_count_ > 0) |
480 return; | 480 return; |
481 | 481 |
482 was_deferred_ = false; | 482 was_deferred_ = false; |
483 if (!last_stream_pause_time_.is_null()) { | 483 if (!last_stream_pause_time_.is_null()) { |
484 total_pause_time_ += (base::TimeTicks::Now() - last_stream_pause_time_); | 484 total_pause_time_ += (base::TimeTicks::Now() - last_stream_pause_time_); |
485 last_stream_pause_time_ = base::TimeTicks(); | 485 last_stream_pause_time_ = base::TimeTicks(); |
486 } | 486 } |
487 | 487 |
488 controller()->Resume(); | 488 controller()->Resume(); |
489 } | 489 } |
490 | 490 |
491 void DownloadResourceHandler::CancelRequest() { | 491 void DownloadResourceHandler::CancelRequest() { |
492 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 492 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
493 | 493 |
494 const ResourceRequestInfo* info = GetRequestInfo(); | 494 const ResourceRequestInfo* info = GetRequestInfo(); |
495 ResourceDispatcherHostImpl::Get()->CancelRequest( | 495 ResourceDispatcherHostImpl::Get()->CancelRequest( |
496 info->GetChildID(), | 496 info->GetChildID(), |
497 info->GetRequestID()); | 497 info->GetRequestID()); |
498 // This object has been deleted. | 498 // This object has been deleted. |
499 } | 499 } |
500 | 500 |
501 std::string DownloadResourceHandler::DebugString() const { | 501 std::string DownloadResourceHandler::DebugString() const { |
502 const ResourceRequestInfo* info = GetRequestInfo(); | 502 const ResourceRequestInfo* info = GetRequestInfo(); |
503 return base::StringPrintf("{" | 503 return base::StringPrintf("{" |
504 " url_ = " "\"%s\"" | 504 " url_ = " "\"%s\"" |
505 " info = {" | 505 " info = {" |
506 " child_id = " "%d" | 506 " child_id = " "%d" |
507 " request_id = " "%d" | 507 " request_id = " "%d" |
508 " route_id = " "%d" | 508 " route_id = " "%d" |
509 " }" | 509 " }" |
510 " }", | 510 " }", |
511 request() ? | 511 request() ? |
512 request()->url().spec().c_str() : | 512 request()->url().spec().c_str() : |
513 "<NULL request>", | 513 "<NULL request>", |
514 info->GetChildID(), | 514 info->GetChildID(), |
515 info->GetRequestID(), | 515 info->GetRequestID(), |
516 info->GetRouteID()); | 516 info->GetRouteID()); |
517 } | 517 } |
518 | 518 |
519 DownloadResourceHandler::~DownloadResourceHandler() { | 519 DownloadResourceHandler::~DownloadResourceHandler() { |
520 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 520 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
521 | 521 |
522 // This won't do anything if the callback was called before. | 522 // This won't do anything if the callback was called before. |
523 // If it goes through, it will likely be because OnWillStart() returned | 523 // If it goes through, it will likely be because OnWillStart() returned |
524 // false somewhere in the chain of resource handlers. | 524 // false somewhere in the chain of resource handlers. |
525 CallStartedCB(NULL, DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED); | 525 CallStartedCB(NULL, DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED); |
526 | 526 |
527 // Remove output stream callback if a stream exists. | 527 // Remove output stream callback if a stream exists. |
528 if (stream_writer_) | 528 if (stream_writer_) |
529 stream_writer_->RegisterCallback(base::Closure()); | 529 stream_writer_->RegisterCallback(base::Closure()); |
530 | 530 |
531 // tab_info_ must be destroyed on UI thread, since | 531 // tab_info_ must be destroyed on UI thread, since |
532 // InitializeDownloadTabInfoOnUIThread might still be using it. | 532 // InitializeDownloadTabInfoOnUIThread might still be using it. |
533 if (tab_info_) | 533 if (tab_info_) |
534 BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, tab_info_); | 534 BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, tab_info_); |
535 | 535 |
536 UMA_HISTOGRAM_TIMES("SB2.DownloadDuration", | 536 UMA_HISTOGRAM_TIMES("SB2.DownloadDuration", |
537 base::TimeTicks::Now() - download_start_time_); | 537 base::TimeTicks::Now() - download_start_time_); |
538 } | 538 } |
539 | 539 |
540 } // namespace content | 540 } // namespace content |
OLD | NEW |