OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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> | |
8 #include <string> | |
Randy Smith (Not in Mondays)
2011/10/28 17:42:31
Why the extra includes?
achuithb
2011/10/28 19:37:37
To satisfy gcl lint (include what you use). We are
| |
9 | |
10 #include "base/bind.h" | |
7 #include "base/file_util.h" | 11 #include "base/file_util.h" |
8 #include "base/logging.h" | 12 #include "base/logging.h" |
9 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
10 #include "base/task.h" | |
11 #include "base/utf_string_conversions.h" | 14 #include "base/utf_string_conversions.h" |
12 #include "content/browser/browser_thread.h" | 15 #include "content/browser/browser_thread.h" |
13 #include "content/browser/download/download_buffer.h" | 16 #include "content/browser/download/download_buffer.h" |
14 #include "content/browser/download/download_create_info.h" | 17 #include "content/browser/download/download_create_info.h" |
15 #include "content/browser/download/download_file.h" | 18 #include "content/browser/download/download_file.h" |
16 #include "content/browser/download/download_manager.h" | 19 #include "content/browser/download/download_manager.h" |
17 #include "content/browser/download/download_request_handle.h" | 20 #include "content/browser/download/download_request_handle.h" |
18 #include "content/browser/renderer_host/resource_dispatcher_host.h" | 21 #include "content/browser/renderer_host/resource_dispatcher_host.h" |
19 #include "content/browser/tab_contents/tab_contents.h" | 22 #include "content/browser/tab_contents/tab_contents.h" |
20 #include "content/public/browser/download_manager_delegate.h" | 23 #include "content/public/browser/download_manager_delegate.h" |
(...skipping 13 matching lines...) Expand all Loading... | |
34 } | 37 } |
35 | 38 |
36 DownloadFileManager::~DownloadFileManager() { | 39 DownloadFileManager::~DownloadFileManager() { |
37 DCHECK(downloads_.empty()); | 40 DCHECK(downloads_.empty()); |
38 } | 41 } |
39 | 42 |
40 void DownloadFileManager::Shutdown() { | 43 void DownloadFileManager::Shutdown() { |
41 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 44 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
42 BrowserThread::PostTask( | 45 BrowserThread::PostTask( |
43 BrowserThread::FILE, FROM_HERE, | 46 BrowserThread::FILE, FROM_HERE, |
44 NewRunnableMethod(this, &DownloadFileManager::OnShutdown)); | 47 base::Bind(&DownloadFileManager::OnShutdown, this)); |
45 } | 48 } |
46 | 49 |
47 void DownloadFileManager::OnShutdown() { | 50 void DownloadFileManager::OnShutdown() { |
48 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 51 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
49 StopUpdateTimer(); | 52 StopUpdateTimer(); |
50 STLDeleteValues(&downloads_); | 53 STLDeleteValues(&downloads_); |
51 } | 54 } |
52 | 55 |
53 void DownloadFileManager::CreateDownloadFile( | 56 void DownloadFileManager::CreateDownloadFile( |
54 DownloadCreateInfo* info, const DownloadRequestHandle& request_handle, | 57 DownloadCreateInfo* info, const DownloadRequestHandle& request_handle, |
(...skipping 16 matching lines...) Expand all Loading... | |
71 DCHECK(GetDownloadFile(global_id) == NULL); | 74 DCHECK(GetDownloadFile(global_id) == NULL); |
72 downloads_[global_id] = download_file.release(); | 75 downloads_[global_id] = download_file.release(); |
73 | 76 |
74 // The file is now ready, we can un-pause the request and start saving data. | 77 // The file is now ready, we can un-pause the request and start saving data. |
75 request_handle.ResumeRequest(); | 78 request_handle.ResumeRequest(); |
76 | 79 |
77 StartUpdateTimer(); | 80 StartUpdateTimer(); |
78 | 81 |
79 BrowserThread::PostTask( | 82 BrowserThread::PostTask( |
80 BrowserThread::UI, FROM_HERE, | 83 BrowserThread::UI, FROM_HERE, |
81 NewRunnableMethod(download_manager, | 84 base::Bind(&DownloadManager::StartDownload, download_manager, |
82 &DownloadManager::StartDownload, info->download_id)); | 85 info->download_id)); |
83 } | 86 } |
84 | 87 |
85 DownloadFile* DownloadFileManager::GetDownloadFile(DownloadId global_id) { | 88 DownloadFile* DownloadFileManager::GetDownloadFile(DownloadId global_id) { |
86 DownloadFileMap::iterator it = downloads_.find(global_id); | 89 DownloadFileMap::iterator it = downloads_.find(global_id); |
87 return it == downloads_.end() ? NULL : it->second; | 90 return it == downloads_.end() ? NULL : it->second; |
88 } | 91 } |
89 | 92 |
90 void DownloadFileManager::StartUpdateTimer() { | 93 void DownloadFileManager::StartUpdateTimer() { |
91 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 94 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
92 if (!update_timer_.IsRunning()) { | 95 if (!update_timer_.IsRunning()) { |
(...skipping 10 matching lines...) Expand all Loading... | |
103 | 106 |
104 void DownloadFileManager::UpdateInProgressDownloads() { | 107 void DownloadFileManager::UpdateInProgressDownloads() { |
105 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
106 for (DownloadFileMap::iterator i = downloads_.begin(); | 109 for (DownloadFileMap::iterator i = downloads_.begin(); |
107 i != downloads_.end(); ++i) { | 110 i != downloads_.end(); ++i) { |
108 DownloadId global_id = i->first; | 111 DownloadId global_id = i->first; |
109 DownloadFile* download_file = i->second; | 112 DownloadFile* download_file = i->second; |
110 DownloadManager* manager = download_file->GetDownloadManager(); | 113 DownloadManager* manager = download_file->GetDownloadManager(); |
111 if (manager) { | 114 if (manager) { |
112 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 115 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
113 NewRunnableMethod(manager, &DownloadManager::UpdateDownload, | 116 base::Bind(&DownloadManager::UpdateDownload, manager, |
114 global_id.local(), download_file->bytes_so_far())); | 117 global_id.local(), download_file->bytes_so_far())); |
115 } | 118 } |
116 } | 119 } |
117 } | 120 } |
118 | 121 |
119 void DownloadFileManager::StartDownload( | 122 void DownloadFileManager::StartDownload( |
120 DownloadCreateInfo* info, const DownloadRequestHandle& request_handle) { | 123 DownloadCreateInfo* info, const DownloadRequestHandle& request_handle) { |
121 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 124 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
122 DCHECK(info); | 125 DCHECK(info); |
123 | 126 |
124 DownloadManager* manager = request_handle.GetDownloadManager(); | 127 DownloadManager* manager = request_handle.GetDownloadManager(); |
125 if (!manager) { | 128 if (!manager) { |
126 request_handle.CancelRequest(); | 129 request_handle.CancelRequest(); |
127 delete info; | 130 delete info; |
128 return; | 131 return; |
129 } | 132 } |
130 | 133 |
131 // TODO(phajdan.jr): fix the duplication of path info below. | 134 // TODO(phajdan.jr): fix the duplication of path info below. |
132 info->path = info->save_info.file_path; | 135 info->path = info->save_info.file_path; |
133 | 136 |
134 manager->CreateDownloadItem(info, request_handle); | 137 manager->CreateDownloadItem(info, request_handle); |
135 bool hash_needed = manager->delegate()->GenerateFileHash(); | 138 bool hash_needed = manager->delegate()->GenerateFileHash(); |
136 | 139 |
137 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 140 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
138 NewRunnableMethod(this, &DownloadFileManager::CreateDownloadFile, | 141 base::Bind(&DownloadFileManager::CreateDownloadFile, this, |
139 info, request_handle, make_scoped_refptr(manager), | 142 info, request_handle, make_scoped_refptr(manager), |
140 hash_needed)); | 143 hash_needed)); |
141 } | 144 } |
142 | 145 |
143 // We don't forward an update to the UI thread here, since we want to throttle | 146 // We don't forward an update to the UI thread here, since we want to throttle |
144 // the UI update rate via a periodic timer. If the user has cancelled the | 147 // the UI update rate via a periodic timer. If the user has cancelled the |
145 // download (in the UI thread), we may receive a few more updates before the IO | 148 // download (in the UI thread), we may receive a few more updates before the IO |
146 // thread gets the cancel message: we just delete the data since the | 149 // thread gets the cancel message: we just delete the data since the |
147 // DownloadFile has been deleted. | 150 // DownloadFile has been deleted. |
148 void DownloadFileManager::UpdateDownload( | 151 void DownloadFileManager::UpdateDownload( |
149 DownloadId global_id, content::DownloadBuffer* buffer) { | 152 DownloadId global_id, content::DownloadBuffer* buffer) { |
150 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 153 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
(...skipping 14 matching lines...) Expand all Loading... | |
165 | 168 |
166 int64 bytes_downloaded = download_file->bytes_so_far(); | 169 int64 bytes_downloaded = download_file->bytes_so_far(); |
167 // Calling this here in case we get more data, to avoid | 170 // Calling this here in case we get more data, to avoid |
168 // processing data after an error. That could lead to | 171 // processing data after an error. That could lead to |
169 // files that are corrupted if the later processing succeeded. | 172 // files that are corrupted if the later processing succeeded. |
170 CancelDownload(global_id); | 173 CancelDownload(global_id); |
171 download_file = NULL; // Was deleted in |CancelDownload|. | 174 download_file = NULL; // Was deleted in |CancelDownload|. |
172 | 175 |
173 if (download_manager) { | 176 if (download_manager) { |
174 BrowserThread::PostTask( | 177 BrowserThread::PostTask( |
175 BrowserThread::UI, | 178 BrowserThread::UI, FROM_HERE, |
176 FROM_HERE, | 179 base::Bind(&DownloadManager::OnDownloadInterrupted, |
177 NewRunnableMethod( | 180 download_manager, global_id.local(), bytes_downloaded, |
178 download_manager, | 181 ConvertNetErrorToInterruptReason( |
179 &DownloadManager::OnDownloadInterrupted, | 182 write_result, DOWNLOAD_INTERRUPT_FROM_DISK))); |
180 global_id.local(), | |
181 bytes_downloaded, | |
182 ConvertNetErrorToInterruptReason( | |
183 write_result, | |
184 DOWNLOAD_INTERRUPT_FROM_DISK))); | |
185 } | 183 } |
186 } | 184 } |
187 } | 185 } |
188 data->Release(); | 186 data->Release(); |
189 } | 187 } |
190 } | 188 } |
191 | 189 |
192 void DownloadFileManager::OnResponseCompleted( | 190 void DownloadFileManager::OnResponseCompleted( |
193 DownloadId global_id, | 191 DownloadId global_id, |
194 InterruptReason reason, | 192 InterruptReason reason, |
(...skipping 13 matching lines...) Expand all Loading... | |
208 CancelDownload(global_id); | 206 CancelDownload(global_id); |
209 return; | 207 return; |
210 } | 208 } |
211 | 209 |
212 std::string hash; | 210 std::string hash; |
213 if (!download_file->GetSha256Hash(&hash)) | 211 if (!download_file->GetSha256Hash(&hash)) |
214 hash.clear(); | 212 hash.clear(); |
215 | 213 |
216 if (reason == DOWNLOAD_INTERRUPT_REASON_NONE) { | 214 if (reason == DOWNLOAD_INTERRUPT_REASON_NONE) { |
217 BrowserThread::PostTask( | 215 BrowserThread::PostTask( |
218 BrowserThread::UI, | 216 BrowserThread::UI, FROM_HERE, |
219 FROM_HERE, | 217 base::Bind(&DownloadManager::OnResponseCompleted, |
220 NewRunnableMethod( | 218 download_manager, global_id.local(), |
221 download_manager, | 219 download_file->bytes_so_far(), hash)); |
222 &DownloadManager::OnResponseCompleted, | |
223 global_id.local(), | |
224 download_file->bytes_so_far(), | |
225 hash)); | |
226 } else { | 220 } else { |
227 BrowserThread::PostTask( | 221 BrowserThread::PostTask( |
228 BrowserThread::UI, | 222 BrowserThread::UI, FROM_HERE, |
229 FROM_HERE, | 223 base::Bind(&DownloadManager::OnDownloadInterrupted, |
230 NewRunnableMethod( | 224 download_manager, global_id.local(), |
231 download_manager, | 225 download_file->bytes_so_far(), reason)); |
232 &DownloadManager::OnDownloadInterrupted, | |
233 global_id.local(), | |
234 download_file->bytes_so_far(), | |
235 reason)); | |
236 } | 226 } |
237 // We need to keep the download around until the UI thread has finalized | 227 // We need to keep the download around until the UI thread has finalized |
238 // the name. | 228 // the name. |
239 } | 229 } |
240 | 230 |
241 // This method will be sent via a user action, or shutdown on the UI thread, and | 231 // This method will be sent via a user action, or shutdown on the UI thread, and |
242 // run on the download thread. Since this message has been sent from the UI | 232 // run on the download thread. Since this message has been sent from the UI |
243 // thread, the download may have already completed and won't exist in our map. | 233 // thread, the download may have already completed and won't exist in our map. |
244 void DownloadFileManager::CancelDownload(DownloadId global_id) { | 234 void DownloadFileManager::CancelDownload(DownloadId global_id) { |
245 VLOG(20) << __FUNCTION__ << "()" << " id = " << global_id; | 235 VLOG(20) << __FUNCTION__ << "()" << " id = " << global_id; |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
376 } | 366 } |
377 | 367 |
378 #if defined(OS_MACOSX) | 368 #if defined(OS_MACOSX) |
379 // Done here because we only want to do this once; see | 369 // Done here because we only want to do this once; see |
380 // http://crbug.com/13120 for details. | 370 // http://crbug.com/13120 for details. |
381 download_file->AnnotateWithSourceInformation(); | 371 download_file->AnnotateWithSourceInformation(); |
382 #endif | 372 #endif |
383 | 373 |
384 BrowserThread::PostTask( | 374 BrowserThread::PostTask( |
385 BrowserThread::UI, FROM_HERE, | 375 BrowserThread::UI, FROM_HERE, |
386 NewRunnableMethod( | 376 base::Bind(&DownloadManager::OnDownloadRenamedToFinalName, |
387 download_manager, &DownloadManager::OnDownloadRenamedToFinalName, | 377 download_manager, global_id.local(), new_path, uniquifier)); |
388 global_id.local(), new_path, uniquifier)); | |
389 } | 378 } |
390 | 379 |
391 // Called only from RenameInProgressDownloadFile and | 380 // Called only from RenameInProgressDownloadFile and |
392 // RenameCompletingDownloadFile on the FILE thread. | 381 // RenameCompletingDownloadFile on the FILE thread. |
393 void DownloadFileManager::CancelDownloadOnRename( | 382 void DownloadFileManager::CancelDownloadOnRename( |
394 DownloadId global_id, net::Error rename_error) { | 383 DownloadId global_id, net::Error rename_error) { |
395 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 384 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
396 | 385 |
397 DownloadFile* download_file = GetDownloadFile(global_id); | 386 DownloadFile* download_file = GetDownloadFile(global_id); |
398 if (!download_file) | 387 if (!download_file) |
399 return; | 388 return; |
400 | 389 |
401 DownloadManager* download_manager = download_file->GetDownloadManager(); | 390 DownloadManager* download_manager = download_file->GetDownloadManager(); |
402 if (!download_manager) { | 391 if (!download_manager) { |
403 // Without a download manager, we can't cancel the request normally, so we | 392 // Without a download manager, we can't cancel the request normally, so we |
404 // need to do it here. The normal path will also update the download | 393 // need to do it here. The normal path will also update the download |
405 // history before canceling the request. | 394 // history before canceling the request. |
406 download_file->CancelDownloadRequest(); | 395 download_file->CancelDownloadRequest(); |
407 return; | 396 return; |
408 } | 397 } |
409 | 398 |
410 BrowserThread::PostTask( | 399 BrowserThread::PostTask( |
411 BrowserThread::UI, FROM_HERE, | 400 BrowserThread::UI, FROM_HERE, |
412 NewRunnableMethod(download_manager, | 401 base::Bind(&DownloadManager::OnDownloadInterrupted, |
413 &DownloadManager::OnDownloadInterrupted, | 402 download_manager, global_id.local(), |
414 global_id.local(), | 403 download_file->bytes_so_far(), |
415 download_file->bytes_so_far(), | 404 ConvertNetErrorToInterruptReason( |
416 ConvertNetErrorToInterruptReason( | 405 rename_error, DOWNLOAD_INTERRUPT_FROM_DISK))); |
417 rename_error, | |
418 DOWNLOAD_INTERRUPT_FROM_DISK))); | |
419 } | 406 } |
420 | 407 |
421 void DownloadFileManager::EraseDownload(DownloadId global_id) { | 408 void DownloadFileManager::EraseDownload(DownloadId global_id) { |
422 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 409 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
423 | 410 |
424 if (!ContainsKey(downloads_, global_id)) | 411 if (!ContainsKey(downloads_, global_id)) |
425 return; | 412 return; |
426 | 413 |
427 DownloadFile* download_file = downloads_[global_id]; | 414 DownloadFile* download_file = downloads_[global_id]; |
428 | 415 |
429 VLOG(20) << " " << __FUNCTION__ << "()" | 416 VLOG(20) << " " << __FUNCTION__ << "()" |
430 << " id = " << global_id | 417 << " id = " << global_id |
431 << " download_file = " << download_file->DebugString(); | 418 << " download_file = " << download_file->DebugString(); |
432 | 419 |
433 downloads_.erase(global_id); | 420 downloads_.erase(global_id); |
434 | 421 |
435 delete download_file; | 422 delete download_file; |
436 | 423 |
437 if (downloads_.empty()) | 424 if (downloads_.empty()) |
438 StopUpdateTimer(); | 425 StopUpdateTimer(); |
439 } | 426 } |
OLD | NEW |