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

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

Issue 10074001: Initial implementation of the ByteStream refactor. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 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 | 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_file_manager.h" 5 #include "content/browser/download/download_file_manager.h"
6 6
7 #include <set> 7 #include <set>
8 #include <string> 8 #include <string>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/file_util.h" 11 #include "base/file_util.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/stl_util.h" 13 #include "base/stl_util.h"
14 #include "base/utf_string_conversions.h" 14 #include "base/utf_string_conversions.h"
15 #include "content/browser/download/base_file.h" 15 #include "content/browser/download/base_file.h"
16 #include "content/browser/download/download_buffer.h"
17 #include "content/browser/download/download_create_info.h" 16 #include "content/browser/download/download_create_info.h"
18 #include "content/browser/download/download_file_impl.h" 17 #include "content/browser/download/download_file_impl.h"
19 #include "content/browser/download/download_interrupt_reasons_impl.h" 18 #include "content/browser/download/download_interrupt_reasons_impl.h"
20 #include "content/browser/download/download_request_handle.h" 19 #include "content/browser/download/download_request_handle.h"
21 #include "content/browser/download/download_stats.h" 20 #include "content/browser/download/download_stats.h"
22 #include "content/browser/web_contents/web_contents_impl.h" 21 #include "content/browser/web_contents/web_contents_impl.h"
23 #include "content/public/browser/browser_thread.h" 22 #include "content/public/browser/browser_thread.h"
24 #include "content/public/browser/download_manager.h" 23 #include "content/public/browser/download_manager.h"
25 #include "content/public/browser/download_manager_delegate.h" 24 #include "content/public/browser/download_manager_delegate.h"
26 #include "googleurl/src/gurl.h" 25 #include "googleurl/src/gurl.h"
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 download_manager, 112 download_manager,
114 info->download_id.local(), 113 info->download_id.local(),
115 0, 114 0,
116 "", 115 "",
117 content::ConvertNetErrorToInterruptReason( 116 content::ConvertNetErrorToInterruptReason(
118 init_result, content::DOWNLOAD_INTERRUPT_FROM_DISK))); 117 init_result, content::DOWNLOAD_INTERRUPT_FROM_DISK)));
119 } else { 118 } else {
120 DCHECK(GetDownloadFile(info->download_id) == NULL); 119 DCHECK(GetDownloadFile(info->download_id) == NULL);
121 downloads_[info->download_id] = download_file.release(); 120 downloads_[info->download_id] = download_file.release();
122 121
123 // The file is now ready, we can un-pause the request and start saving data.
124 request_handle.ResumeRequest();
125
126 StartUpdateTimer(); 122 StartUpdateTimer();
127 } 123 }
128 124
129 BrowserThread::PostTask( 125 BrowserThread::PostTask(
130 BrowserThread::UI, FROM_HERE, 126 BrowserThread::UI, FROM_HERE,
131 base::Bind(&DownloadManager::StartDownload, download_manager, 127 base::Bind(&DownloadManager::StartDownload, download_manager,
132 info->download_id.local())); 128 info->download_id.local()));
133 } 129 }
134 130
135 DownloadFile* DownloadFileManager::GetDownloadFile( 131 DownloadFile* DownloadFileManager::GetDownloadFile(
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 net::BoundNetLog bound_net_log = 184 net::BoundNetLog bound_net_log =
189 manager->CreateDownloadItem(info, request_handle); 185 manager->CreateDownloadItem(info, request_handle);
190 bool hash_needed = manager->GenerateFileHash(); 186 bool hash_needed = manager->GenerateFileHash();
191 187
192 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 188 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
193 base::Bind(&DownloadFileManager::CreateDownloadFile, this, 189 base::Bind(&DownloadFileManager::CreateDownloadFile, this,
194 info, request_handle, make_scoped_refptr(manager), 190 info, request_handle, make_scoped_refptr(manager),
195 hash_needed, bound_net_log)); 191 hash_needed, bound_net_log));
196 } 192 }
197 193
198 // We don't forward an update to the UI thread here, since we want to throttle
199 // the UI update rate via a periodic timer. If the user has cancelled the
200 // download (in the UI thread), we may receive a few more updates before the IO
201 // thread gets the cancel message: we just delete the data since the
202 // DownloadFile has been deleted.
203 void DownloadFileManager::UpdateDownload(
204 DownloadId global_id, content::DownloadBuffer* buffer) {
205 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
206 scoped_ptr<content::ContentVector> contents(buffer->ReleaseContents());
207
208 download_stats::RecordFileThreadReceiveBuffers(contents->size());
209
210 DownloadFile* download_file = GetDownloadFile(global_id);
211 bool had_error = false;
212 for (size_t i = 0; i < contents->size(); ++i) {
213 net::IOBuffer* data = (*contents)[i].first;
214 const int data_len = (*contents)[i].second;
215 if (!had_error && download_file) {
216 net::Error write_result =
217 download_file->AppendDataToFile(data->data(), data_len);
218 if (write_result != net::OK) {
219 // Write failed: interrupt the download.
220 DownloadManager* download_manager =
221 download_file->GetDownloadManager();
222 had_error = true;
223
224 int64 bytes_downloaded = download_file->BytesSoFar();
225 std::string hash_state(download_file->GetHashState());
226
227 // Calling this here in case we get more data, to avoid
228 // processing data after an error. That could lead to
229 // files that are corrupted if the later processing succeeded.
230 CancelDownload(global_id);
231 download_file = NULL; // Was deleted in |CancelDownload|.
232
233 if (download_manager) {
234 BrowserThread::PostTask(
235 BrowserThread::UI, FROM_HERE,
236 base::Bind(&DownloadManager::OnDownloadInterrupted,
237 download_manager,
238 global_id.local(),
239 bytes_downloaded,
240 hash_state,
241 content::ConvertNetErrorToInterruptReason(
242 write_result,
243 content::DOWNLOAD_INTERRUPT_FROM_DISK)));
244 }
245 }
246 }
247 data->Release();
248 }
249 }
250
251 void DownloadFileManager::OnResponseCompleted(
252 DownloadId global_id,
253 content::DownloadInterruptReason reason,
254 const std::string& security_info) {
255 VLOG(20) << __FUNCTION__ << "()" << " id = " << global_id
256 << " reason = " << InterruptReasonDebugString(reason)
257 << " security_info = \"" << security_info << "\"";
258 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
259 DownloadFile* download_file = GetDownloadFile(global_id);
260 if (!download_file)
261 return;
262
263 download_file->Finish();
264
265 DownloadManager* download_manager = download_file->GetDownloadManager();
266 if (!download_manager) {
267 CancelDownload(global_id);
268 return;
269 }
270
271 if (reason == content::DOWNLOAD_INTERRUPT_REASON_NONE) {
272 std::string hash;
273 if (!download_file->GetHash(&hash) ||
274 BaseFile::IsEmptyHash(hash)) {
275 hash.clear();
276 }
277
278 BrowserThread::PostTask(
279 BrowserThread::UI, FROM_HERE,
280 base::Bind(&DownloadManager::OnResponseCompleted,
281 download_manager, global_id.local(),
282 download_file->BytesSoFar(), hash));
283 } else {
284 BrowserThread::PostTask(
285 BrowserThread::UI, FROM_HERE,
286 base::Bind(&DownloadManager::OnDownloadInterrupted,
287 download_manager,
288 global_id.local(),
289 download_file->BytesSoFar(),
290 download_file->GetHashState(),
291 reason));
292 }
293 // We need to keep the download around until the UI thread has finalized
294 // the name.
295 }
296
297 // This method will be sent via a user action, or shutdown on the UI thread, and 194 // This method will be sent via a user action, or shutdown on the UI thread, and
298 // run on the download thread. Since this message has been sent from the UI 195 // run on the download thread. Since this message has been sent from the UI
299 // thread, the download may have already completed and won't exist in our map. 196 // thread, the download may have already completed and won't exist in our map.
300 void DownloadFileManager::CancelDownload(DownloadId global_id) { 197 void DownloadFileManager::CancelDownload(DownloadId global_id) {
301 VLOG(20) << __FUNCTION__ << "()" << " id = " << global_id; 198 VLOG(20) << __FUNCTION__ << "()" << " id = " << global_id;
302 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 199 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
303 DownloadFileMap::iterator it = downloads_.find(global_id); 200 DownloadFileMap::iterator it = downloads_.find(global_id);
304 if (it == downloads_.end()) 201 if (it == downloads_.end())
305 return; 202 return;
306 203
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
488 << " id = " << global_id 385 << " id = " << global_id
489 << " download_file = " << download_file->DebugString(); 386 << " download_file = " << download_file->DebugString();
490 387
491 downloads_.erase(global_id); 388 downloads_.erase(global_id);
492 389
493 delete download_file; 390 delete download_file;
494 391
495 if (downloads_.empty()) 392 if (downloads_.empty())
496 StopUpdateTimer(); 393 StopUpdateTimer();
497 } 394 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698