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" |
11 #include "base/message_loop_proxy.h" | |
11 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
12 #include "base/metrics/stats_counters.h" | 13 #include "base/metrics/stats_counters.h" |
13 #include "base/stringprintf.h" | 14 #include "base/stringprintf.h" |
14 #include "content/browser/download/download_buffer.h" | |
15 #include "content/browser/download/download_create_info.h" | 15 #include "content/browser/download/download_create_info.h" |
16 #include "content/browser/download/download_file_manager.h" | 16 #include "content/browser/download/download_file_manager.h" |
17 #include "content/browser/download/download_interrupt_reasons_impl.h" | 17 #include "content/browser/download/download_interrupt_reasons_impl.h" |
18 #include "content/browser/download/download_manager_impl.h" | 18 #include "content/browser/download/download_manager_impl.h" |
19 #include "content/browser/download/download_request_handle.h" | 19 #include "content/browser/download/download_request_handle.h" |
20 #include "content/browser/download/byte_stream.h" | |
20 #include "content/browser/download/download_stats.h" | 21 #include "content/browser/download/download_stats.h" |
21 #include "content/browser/renderer_host/resource_dispatcher_host_impl.h" | 22 #include "content/browser/renderer_host/resource_dispatcher_host_impl.h" |
22 #include "content/browser/renderer_host/resource_request_info_impl.h" | 23 #include "content/browser/renderer_host/resource_request_info_impl.h" |
23 #include "content/public/browser/browser_thread.h" | 24 #include "content/public/browser/browser_thread.h" |
24 #include "content/public/browser/download_interrupt_reasons.h" | 25 #include "content/public/browser/download_interrupt_reasons.h" |
25 #include "content/public/browser/download_item.h" | 26 #include "content/public/browser/download_item.h" |
26 #include "content/public/browser/download_manager_delegate.h" | 27 #include "content/public/browser/download_manager_delegate.h" |
27 #include "content/public/common/resource_response.h" | 28 #include "content/public/common/resource_response.h" |
28 #include "net/base/io_buffer.h" | 29 #include "net/base/io_buffer.h" |
29 #include "net/base/net_errors.h" | 30 #include "net/base/net_errors.h" |
30 #include "net/http/http_response_headers.h" | 31 #include "net/http/http_response_headers.h" |
31 #include "net/url_request/url_request_context.h" | 32 #include "net/url_request/url_request_context.h" |
32 | 33 |
33 using content::BrowserThread; | 34 using content::BrowserThread; |
34 using content::DownloadId; | 35 using content::DownloadId; |
35 using content::DownloadItem; | 36 using content::DownloadItem; |
36 using content::DownloadManager; | 37 using content::DownloadManager; |
37 using content::ResourceDispatcherHostImpl; | 38 using content::ResourceDispatcherHostImpl; |
38 using content::ResourceRequestInfoImpl; | 39 using content::ResourceRequestInfoImpl; |
39 | 40 |
40 namespace { | 41 namespace { |
41 | 42 |
43 static const int kDownloadPipeSize = 100 * 1024; | |
44 | |
42 void CallStartedCBOnUIThread( | 45 void CallStartedCBOnUIThread( |
43 const DownloadResourceHandler::OnStartedCallback& started_cb, | 46 const DownloadResourceHandler::OnStartedCallback& started_cb, |
44 DownloadId id, | 47 DownloadId id, |
45 net::Error error) { | 48 net::Error error) { |
46 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 49 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
47 if (started_cb.is_null()) | 50 if (started_cb.is_null()) |
48 return; | 51 return; |
49 started_cb.Run(id, error); | 52 started_cb.Run(id, error); |
50 } | 53 } |
51 | 54 |
52 } // namespace | 55 } // namespace |
53 | 56 |
54 DownloadResourceHandler::DownloadResourceHandler( | 57 DownloadResourceHandler::DownloadResourceHandler( |
55 int render_process_host_id, | 58 int render_process_host_id, |
56 int render_view_id, | 59 int render_view_id, |
57 int request_id, | 60 int request_id, |
58 const GURL& url, | 61 const GURL& url, |
59 DownloadFileManager* download_file_manager, | 62 DownloadFileManager* download_file_manager, |
60 net::URLRequest* request, | 63 net::URLRequest* request, |
61 const DownloadResourceHandler::OnStartedCallback& started_cb, | 64 const DownloadResourceHandler::OnStartedCallback& started_cb, |
62 const content::DownloadSaveInfo& save_info) | 65 const content::DownloadSaveInfo& save_info) |
63 : download_id_(DownloadId::Invalid()), | 66 : download_id_(DownloadId::Invalid()), |
64 global_id_(render_process_host_id, request_id), | 67 global_id_(render_process_host_id, request_id), |
65 render_view_id_(render_view_id), | 68 render_view_id_(render_view_id), |
66 content_length_(0), | 69 content_length_(0), |
67 download_file_manager_(download_file_manager), | 70 download_file_manager_(download_file_manager), |
68 request_(request), | 71 request_(request), |
69 started_cb_(started_cb), | 72 started_cb_(started_cb), |
70 save_info_(save_info), | 73 save_info_(save_info), |
71 buffer_(new content::DownloadBuffer), | |
72 is_paused_(false), | |
73 last_buffer_size_(0), | 74 last_buffer_size_(0), |
74 bytes_read_(0) { | 75 bytes_read_(0) { |
75 download_stats::RecordDownloadCount(download_stats::UNTHROTTLED_COUNT); | 76 download_stats::RecordDownloadCount(download_stats::UNTHROTTLED_COUNT); |
76 } | 77 } |
77 | 78 |
78 bool DownloadResourceHandler::OnUploadProgress(int request_id, | 79 bool DownloadResourceHandler::OnUploadProgress(int request_id, |
79 uint64 position, | 80 uint64 position, |
80 uint64 size) { | 81 uint64 size) { |
81 return true; | 82 return true; |
82 } | 83 } |
(...skipping 30 matching lines...) Expand all Loading... | |
113 set_content_length(response->content_length); | 114 set_content_length(response->content_length); |
114 | 115 |
115 const ResourceRequestInfoImpl* request_info = | 116 const ResourceRequestInfoImpl* request_info = |
116 ResourceRequestInfoImpl::ForRequest(request_); | 117 ResourceRequestInfoImpl::ForRequest(request_); |
117 | 118 |
118 // Deleted in DownloadManager. | 119 // Deleted in DownloadManager. |
119 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo( | 120 scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo( |
120 base::Time::Now(), 0, content_length_, DownloadItem::IN_PROGRESS, | 121 base::Time::Now(), 0, content_length_, DownloadItem::IN_PROGRESS, |
121 request_->net_log(), request_info->has_user_gesture(), | 122 request_->net_log(), request_info->has_user_gesture(), |
122 request_info->transition_type())); | 123 request_info->transition_type())); |
124 | |
125 // Create the ByteStream pipe for sending data to the download sink. | |
126 scoped_ptr<content::ByteStreamOutput> pipe_output; | |
127 CreateByteStream( | |
128 base::MessageLoopProxy::current(), | |
129 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE), | |
130 kDownloadPipeSize, &pipe_input_, &pipe_output); | |
131 pipe_input_->RegisterCallback( | |
132 // We're refcounted, so this is a safe callback to pass around. | |
133 base::Bind(&DownloadResourceHandler::ResumeRequest, this)); | |
134 | |
123 info->url_chain = request_->url_chain(); | 135 info->url_chain = request_->url_chain(); |
124 info->referrer_url = GURL(request_->referrer()); | 136 info->referrer_url = GURL(request_->referrer()); |
125 info->start_time = base::Time::Now(); | 137 info->start_time = base::Time::Now(); |
126 info->received_bytes = save_info_.offset; | 138 info->received_bytes = save_info_.offset; |
127 info->total_bytes = content_length_; | 139 info->total_bytes = content_length_; |
128 info->state = DownloadItem::IN_PROGRESS; | 140 info->state = DownloadItem::IN_PROGRESS; |
129 info->has_user_gesture = request_info->has_user_gesture(); | 141 info->has_user_gesture = request_info->has_user_gesture(); |
130 info->content_disposition = content_disposition_; | 142 info->content_disposition = content_disposition_; |
131 info->mime_type = response->mime_type; | 143 info->mime_type = response->mime_type; |
132 info->remote_address = request_->GetSocketAddress().host(); | 144 info->remote_address = request_->GetSocketAddress().host(); |
(...skipping 24 matching lines...) Expand all Loading... | |
157 "Accept-Ranges", | 169 "Accept-Ranges", |
158 &accept_ranges_)) { | 170 &accept_ranges_)) { |
159 accept_ranges_ = ""; | 171 accept_ranges_ = ""; |
160 } | 172 } |
161 | 173 |
162 info->prompt_user_for_save_location = | 174 info->prompt_user_for_save_location = |
163 save_info_.prompt_for_save_location && save_info_.file_path.empty(); | 175 save_info_.prompt_for_save_location && save_info_.file_path.empty(); |
164 info->referrer_charset = request_->context()->referrer_charset(); | 176 info->referrer_charset = request_->context()->referrer_charset(); |
165 info->save_info = save_info_; | 177 info->save_info = save_info_; |
166 | 178 |
167 | |
168 BrowserThread::PostTask( | 179 BrowserThread::PostTask( |
169 BrowserThread::UI, FROM_HERE, | 180 BrowserThread::UI, FROM_HERE, |
170 base::Bind(&DownloadResourceHandler::StartOnUIThread, this, | 181 base::Bind(&DownloadResourceHandler::StartOnUIThread, this, |
171 base::Passed(&info), request_handle)); | 182 base::Passed(info.Pass()), |
172 | 183 base::Passed(pipe_output.Pass()), |
173 // We can't start saving the data before we create the file on disk and have a | 184 request_handle)); |
174 // download id. The request will be un-paused in | |
175 // DownloadFileManager::CreateDownloadFile. | |
176 ResourceDispatcherHostImpl::Get()->PauseRequest(global_id_.child_id, | |
177 global_id_.request_id, | |
178 true); | |
179 | 185 |
180 return true; | 186 return true; |
181 } | 187 } |
182 | 188 |
183 void DownloadResourceHandler::CallStartedCB(DownloadId id, net::Error error) { | 189 void DownloadResourceHandler::CallStartedCB(DownloadId id, net::Error error) { |
184 if (started_cb_.is_null()) | 190 if (started_cb_.is_null()) |
185 return; | 191 return; |
186 BrowserThread::PostTask( | 192 BrowserThread::PostTask( |
187 BrowserThread::UI, FROM_HERE, | 193 BrowserThread::UI, FROM_HERE, |
188 base::Bind(&CallStartedCBOnUIThread, started_cb_, id, error)); | 194 base::Bind(&CallStartedCBOnUIThread, started_cb_, id, error)); |
(...skipping 15 matching lines...) Expand all Loading... | |
204 *buf_size = min_size < 0 ? kReadBufSize : min_size; | 210 *buf_size = min_size < 0 ? kReadBufSize : min_size; |
205 last_buffer_size_ = *buf_size; | 211 last_buffer_size_ = *buf_size; |
206 read_buffer_ = new net::IOBuffer(*buf_size); | 212 read_buffer_ = new net::IOBuffer(*buf_size); |
207 } | 213 } |
208 *buf = read_buffer_.get(); | 214 *buf = read_buffer_.get(); |
209 return true; | 215 return true; |
210 } | 216 } |
211 | 217 |
212 // Pass the buffer to the download file writer. | 218 // Pass the buffer to the download file writer. |
213 bool DownloadResourceHandler::OnReadCompleted(int request_id, int* bytes_read) { | 219 bool DownloadResourceHandler::OnReadCompleted(int request_id, int* bytes_read) { |
220 if (!read_buffer_) { | |
benjhayden
2012/05/21 14:36:45
Could Darin review the ResourceHandler-related par
Randy Smith (Not in Mondays)
2012/05/23 03:33:15
Sure, I'll ask him. Even if he does, though, I'd
| |
221 // Ignore spurious OnReadCompleted! PauseRequest(true) called from within | |
222 // OnReadCompleted tells the ResourceDispatcherHost that we did not consume | |
223 // the data. PauseRequest(false) then repeats the last OnReadCompleted | |
224 // call. We pause the request after we transmit the buffer onwards, so | |
225 // the ResourceDispatcherHost pause mechanism does not fit our use | |
226 // case very well. | |
227 // Note that this test makes redundant the DCHECK() below; it's being left | |
228 // in in hopes that the TODO will be executed soon. | |
229 // TODO(darin): Fix the ResourceDispatcherHost to avoid this hack! | |
230 return true; | |
231 } | |
232 | |
214 base::TimeTicks now(base::TimeTicks::Now()); | 233 base::TimeTicks now(base::TimeTicks::Now()); |
215 if (!last_read_time_.is_null()) { | 234 if (!last_read_time_.is_null()) { |
216 double seconds_since_last_read = (now - last_read_time_).InSecondsF(); | 235 double seconds_since_last_read = (now - last_read_time_).InSecondsF(); |
217 if (now == last_read_time_) | 236 if (now == last_read_time_) |
218 // Use 1/10 ms as a "very small number" so that we avoid | 237 // Use 1/10 ms as a "very small number" so that we avoid |
219 // divide-by-zero error and still record a very high potential bandwidth. | 238 // divide-by-zero error and still record a very high potential bandwidth. |
220 seconds_since_last_read = 0.00001; | 239 seconds_since_last_read = 0.00001; |
221 | 240 |
222 double actual_bandwidth = (*bytes_read)/seconds_since_last_read; | 241 double actual_bandwidth = (*bytes_read)/seconds_since_last_read; |
223 double potential_bandwidth = last_buffer_size_/seconds_since_last_read; | 242 double potential_bandwidth = last_buffer_size_/seconds_since_last_read; |
224 download_stats::RecordBandwidth(actual_bandwidth, potential_bandwidth); | 243 download_stats::RecordBandwidth(actual_bandwidth, potential_bandwidth); |
225 } | 244 } |
226 last_read_time_ = now; | 245 last_read_time_ = now; |
227 | 246 |
228 if (!*bytes_read) | 247 if (!*bytes_read) |
229 return true; | 248 return true; |
230 bytes_read_ += *bytes_read; | 249 bytes_read_ += *bytes_read; |
231 DCHECK(read_buffer_); | 250 DCHECK(read_buffer_); |
232 // Swap the data. | |
233 net::IOBuffer* io_buffer = NULL; | |
234 read_buffer_.swap(&io_buffer); | |
235 size_t vector_size = buffer_->AddData(io_buffer, *bytes_read); | |
236 bool need_update = (vector_size == 1); // Buffer was empty. | |
237 | 251 |
238 // We are passing ownership of this buffer to the download file manager. | 252 // Take the data ship it down the pipe. If the pipe is full, pause the |
239 if (need_update) { | 253 // request; the pipe callback will resume it. |
240 BrowserThread::PostTask( | 254 if (!pipe_input_->Write(read_buffer_, *bytes_read)) { |
241 BrowserThread::FILE, FROM_HERE, | 255 ResourceDispatcherHostImpl::Get()->PauseRequest(global_id_.child_id, |
242 base::Bind(&DownloadFileManager::UpdateDownload, | 256 global_id_.request_id, |
243 download_file_manager_, download_id_, buffer_)); | 257 true); |
258 last_pause_time_ = now; | |
244 } | 259 } |
245 | 260 |
246 // We schedule a pause outside of the read loop if there is too much file | 261 read_buffer_ = NULL; // Drop our reference. |
247 // writing work to do. | |
248 if (vector_size > kLoadsToWrite) | |
249 StartPauseTimer(); | |
250 | 262 |
251 return true; | 263 return true; |
252 } | 264 } |
253 | 265 |
254 bool DownloadResourceHandler::OnResponseCompleted( | 266 bool DownloadResourceHandler::OnResponseCompleted( |
255 int request_id, | 267 int request_id, |
256 const net::URLRequestStatus& status, | 268 const net::URLRequestStatus& status, |
257 const std::string& security_info) { | 269 const std::string& security_info) { |
258 VLOG(20) << __FUNCTION__ << "()" << DebugString() | 270 VLOG(20) << __FUNCTION__ << "()" << DebugString() |
259 << " request_id = " << request_id | 271 << " request_id = " << request_id |
260 << " status.status() = " << status.status() | 272 << " status.status() = " << status.status() |
261 << " status.error() = " << status.error(); | 273 << " status.error() = " << status.error(); |
262 int response = status.is_success() ? request_->GetResponseCode() : 0; | 274 int response = status.is_success() ? request_->GetResponseCode() : 0; |
263 if (download_id_.IsValid()) { | 275 if (download_id_.IsValid()) { |
264 OnResponseCompletedInternal(request_id, status, security_info, response); | 276 OnResponseCompletedInternal(request_id, status, security_info, response); |
265 } else { | 277 } else { |
266 // We got cancelled before the task which sets the id ran on the IO thread. | 278 // We got cancelled before the task which sets the id ran on the IO thread. |
267 // Wait for it. | 279 // Wait for it. |
268 BrowserThread::PostTaskAndReply( | 280 BrowserThread::PostTaskAndReply( |
269 BrowserThread::UI, FROM_HERE, | 281 BrowserThread::UI, FROM_HERE, |
270 base::Bind(&base::DoNothing), | 282 base::Bind(&base::DoNothing), |
271 base::Bind(&DownloadResourceHandler::OnResponseCompletedInternal, this, | 283 base::Bind(&DownloadResourceHandler::OnResponseCompletedInternal, this, |
272 request_id, status, security_info, response)); | 284 request_id, status, security_info, response)); |
273 } | 285 } |
274 // Can't trust request_ being value after this point. | 286 // Can't trust request_ being value after this point. |
275 request_ = NULL; | 287 request_ = NULL; |
288 | |
289 // Stats | |
290 download_stats::RecordNetworkBandwidth( | |
291 bytes_read_, base::TimeTicks::Now() - download_start_time_, | |
292 total_pause_time_); | |
293 | |
276 return true; | 294 return true; |
277 } | 295 } |
278 | 296 |
279 void DownloadResourceHandler::OnResponseCompletedInternal( | 297 void DownloadResourceHandler::OnResponseCompletedInternal( |
280 int request_id, | 298 int request_id, |
281 const net::URLRequestStatus& status, | 299 const net::URLRequestStatus& status, |
282 const std::string& security_info, | 300 const std::string& security_info, |
283 int response_code) { | 301 int response_code) { |
284 // NOTE: |request_| may be a dangling pointer at this point. | 302 // NOTE: |request_| may be a dangling pointer at this point. |
285 VLOG(20) << __FUNCTION__ << "()" | 303 VLOG(20) << __FUNCTION__ << "()" |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
325 break; | 343 break; |
326 } | 344 } |
327 } | 345 } |
328 } | 346 } |
329 | 347 |
330 download_stats::RecordAcceptsRanges(accept_ranges_, bytes_read_); | 348 download_stats::RecordAcceptsRanges(accept_ranges_, bytes_read_); |
331 | 349 |
332 // If the callback was already run on the UI thread, this will be a noop. | 350 // If the callback was already run on the UI thread, this will be a noop. |
333 CallStartedCB(download_id_, error_code); | 351 CallStartedCB(download_id_, error_code); |
334 | 352 |
335 // We transfer ownership to |DownloadFileManager| to delete |buffer_|, | 353 // Send the info down the pipe. Conditional is in case we get |
336 // so that any functions queued up on the FILE thread are executed | 354 // OnResponseCompleted without OnResponseStarted. |
337 // before deletion. | 355 if (pipe_input_.get()) |
338 BrowserThread::PostTask( | 356 pipe_input_->Close(reason); |
339 BrowserThread::FILE, FROM_HERE, | 357 |
340 base::Bind(&DownloadFileManager::OnResponseCompleted, | 358 pipe_input_.reset(); // We no longer need the pipe. |
341 download_file_manager_, download_id_, reason, security_info)); | |
342 buffer_ = NULL; // The buffer is longer needed by |DownloadResourceHandler|. | |
343 read_buffer_ = NULL; | 359 read_buffer_ = NULL; |
344 } | 360 } |
345 | 361 |
346 void DownloadResourceHandler::OnRequestClosed() { | 362 void DownloadResourceHandler::OnRequestClosed() { |
347 UMA_HISTOGRAM_TIMES("SB2.DownloadDuration", | 363 UMA_HISTOGRAM_TIMES("SB2.DownloadDuration", |
348 base::TimeTicks::Now() - download_start_time_); | 364 base::TimeTicks::Now() - download_start_time_); |
349 } | 365 } |
350 | 366 |
351 void DownloadResourceHandler::StartOnUIThread( | 367 void DownloadResourceHandler::StartOnUIThread( |
352 scoped_ptr<DownloadCreateInfo> info, | 368 scoped_ptr<DownloadCreateInfo> info, |
369 scoped_ptr<content::ByteStreamOutput> pipe, | |
353 const DownloadRequestHandle& handle) { | 370 const DownloadRequestHandle& handle) { |
354 DownloadManager* download_manager = handle.GetDownloadManager(); | 371 DownloadManager* download_manager = handle.GetDownloadManager(); |
355 if (!download_manager) { | 372 if (!download_manager) { |
356 // NULL in unittests or if the page closed right after starting the | 373 // NULL in unittests or if the page closed right after starting the |
357 // download. | 374 // download. |
358 CallStartedCB(download_id_, net::ERR_ACCESS_DENIED); | 375 CallStartedCB(download_id_, net::ERR_ACCESS_DENIED); |
359 return; | 376 return; |
360 } | 377 } |
361 DownloadId download_id = download_manager->delegate()->GetNextId(); | 378 DownloadId download_id = download_manager->delegate()->GetNextId(); |
362 info->download_id = download_id; | 379 info->download_id = download_id; |
363 BrowserThread::PostTask( | 380 BrowserThread::PostTask( |
364 BrowserThread::IO, FROM_HERE, | 381 BrowserThread::IO, FROM_HERE, |
365 base::Bind(&DownloadResourceHandler::set_download_id, this, | 382 base::Bind(&DownloadResourceHandler::set_download_id, this, |
366 info->download_id)); | 383 info->download_id)); |
367 // It's safe to continue on with download initiation before we have | 384 // It's safe to continue on with download initiation before we have |
368 // confirmation that that download_id_ has been set on the IO thread, as any | 385 // confirmation that that download_id_ has been set on the IO thread, as any |
369 // messages generated by the UI thread that affect the IO thread will be | 386 // messages generated by the UI thread that affect the IO thread will be |
370 // behind the message posted above. | 387 // behind the message posted above. |
371 download_file_manager_->StartDownload(info.release(), handle); | 388 download_file_manager_->StartDownload(info.Pass(), pipe.Pass(), handle); |
372 CallStartedCB(download_id, net::OK); | 389 CallStartedCB(download_id, net::OK); |
373 } | 390 } |
374 | 391 |
375 void DownloadResourceHandler::set_download_id(content::DownloadId id) { | 392 void DownloadResourceHandler::set_download_id(content::DownloadId id) { |
376 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 393 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
377 download_id_ = id; | 394 download_id_ = id; |
378 } | 395 } |
379 | 396 |
380 // If the content-length header is not present (or contains something other | 397 // If the content-length header is not present (or contains something other |
381 // than numbers), the incoming content_length is -1 (unknown size). | 398 // than numbers), the incoming content_length is -1 (unknown size). |
382 // Set the content length to 0 to indicate unknown size to DownloadManager. | 399 // Set the content length to 0 to indicate unknown size to DownloadManager. |
383 void DownloadResourceHandler::set_content_length(const int64& content_length) { | 400 void DownloadResourceHandler::set_content_length(const int64& content_length) { |
384 content_length_ = 0; | 401 content_length_ = 0; |
385 if (content_length > 0) | 402 if (content_length > 0) |
386 content_length_ = content_length; | 403 content_length_ = content_length; |
387 } | 404 } |
388 | 405 |
389 void DownloadResourceHandler::set_content_disposition( | 406 void DownloadResourceHandler::set_content_disposition( |
390 const std::string& content_disposition) { | 407 const std::string& content_disposition) { |
391 content_disposition_ = content_disposition; | 408 content_disposition_ = content_disposition; |
392 } | 409 } |
393 | 410 |
394 void DownloadResourceHandler::CheckWriteProgress() { | |
395 if (!buffer_.get()) | |
396 return; // The download completed while we were waiting to run. | |
397 | |
398 size_t contents_size = buffer_->size(); | |
399 | |
400 bool should_pause = contents_size > kLoadsToWrite; | |
401 | |
402 // We'll come back later and see if it's okay to unpause the request. | |
403 if (should_pause) | |
404 StartPauseTimer(); | |
405 | |
406 if (is_paused_ != should_pause) { | |
407 ResourceDispatcherHostImpl::Get()->PauseRequest(global_id_.child_id, | |
408 global_id_.request_id, | |
409 should_pause); | |
410 is_paused_ = should_pause; | |
411 } | |
412 } | |
413 | |
414 DownloadResourceHandler::~DownloadResourceHandler() { | 411 DownloadResourceHandler::~DownloadResourceHandler() { |
415 // This won't do anything if the callback was called before. | 412 // This won't do anything if the callback was called before. |
416 // If it goes through, it will likely be because OnWillStart() returned | 413 // If it goes through, it will likely be because OnWillStart() returned |
417 // false somewhere in the chain of resource handlers. | 414 // false somewhere in the chain of resource handlers. |
418 CallStartedCB(download_id_, net::ERR_ACCESS_DENIED); | 415 CallStartedCB(download_id_, net::ERR_ACCESS_DENIED); |
416 | |
417 // Remove output pipe callback if a pipe exists. | |
418 if (pipe_input_.get()) | |
419 pipe_input_->RegisterCallback(base::Closure()); | |
419 } | 420 } |
420 | 421 |
421 void DownloadResourceHandler::StartPauseTimer() { | 422 void DownloadResourceHandler::ResumeRequest() { |
422 if (!pause_timer_.IsRunning()) | 423 ResourceDispatcherHostImpl::Get()->PauseRequest(global_id_.child_id, |
423 pause_timer_.Start(FROM_HERE, | 424 global_id_.request_id, |
424 base::TimeDelta::FromMilliseconds(kThrottleTimeMs), this, | 425 false); |
425 &DownloadResourceHandler::CheckWriteProgress); | 426 total_pause_time_ += (base::TimeTicks::Now() - last_pause_time_); |
426 } | 427 } |
427 | 428 |
428 std::string DownloadResourceHandler::DebugString() const { | 429 std::string DownloadResourceHandler::DebugString() const { |
429 return base::StringPrintf("{" | 430 return base::StringPrintf("{" |
430 " url_ = " "\"%s\"" | 431 " url_ = " "\"%s\"" |
431 " download_id_ = " "%d" | 432 " download_id_ = " "%d" |
432 " global_id_ = {" | 433 " global_id_ = {" |
433 " child_id = " "%d" | 434 " child_id = " "%d" |
434 " request_id = " "%d" | 435 " request_id = " "%d" |
435 " }" | 436 " }" |
436 " render_view_id_ = " "%d" | 437 " render_view_id_ = " "%d" |
437 " save_info_.file_path = \"%" PRFilePath "\"" | 438 " save_info_.file_path = \"%" PRFilePath "\"" |
438 " }", | 439 " }", |
439 request_ ? | 440 request_ ? |
440 request_->url().spec().c_str() : | 441 request_->url().spec().c_str() : |
441 "<NULL request>", | 442 "<NULL request>", |
442 download_id_.local(), | 443 download_id_.local(), |
443 global_id_.child_id, | 444 global_id_.child_id, |
444 global_id_.request_id, | 445 global_id_.request_id, |
445 render_view_id_, | 446 render_view_id_, |
446 save_info_.file_path.value().c_str()); | 447 save_info_.file_path.value().c_str()); |
447 } | 448 } |
OLD | NEW |