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> | 7 #include <set> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 } | 48 } |
49 | 49 |
50 void DownloadFileManager::OnShutdown() { | 50 void DownloadFileManager::OnShutdown() { |
51 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 51 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
52 StopUpdateTimer(); | 52 StopUpdateTimer(); |
53 STLDeleteValues(&downloads_); | 53 STLDeleteValues(&downloads_); |
54 } | 54 } |
55 | 55 |
56 void DownloadFileManager::CreateDownloadFile( | 56 void DownloadFileManager::CreateDownloadFile( |
57 DownloadCreateInfo* info, const DownloadRequestHandle& request_handle, | 57 DownloadCreateInfo* info, const DownloadRequestHandle& request_handle, |
58 DownloadManager* download_manager, bool get_hash) { | 58 DownloadManagerInterface* download_manager, bool get_hash) { |
59 DCHECK(info); | 59 DCHECK(info); |
60 VLOG(20) << __FUNCTION__ << "()" << " info = " << info->DebugString(); | 60 VLOG(20) << __FUNCTION__ << "()" << " info = " << info->DebugString(); |
61 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 61 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
62 | 62 |
63 // Life of |info| ends here. No more references to it after this method. | 63 // Life of |info| ends here. No more references to it after this method. |
64 scoped_ptr<DownloadCreateInfo> infop(info); | 64 scoped_ptr<DownloadCreateInfo> infop(info); |
65 | 65 |
66 scoped_ptr<DownloadFile> | 66 scoped_ptr<DownloadFile> |
67 download_file(new DownloadFile(info, request_handle, download_manager)); | 67 download_file(new DownloadFile(info, request_handle, download_manager)); |
68 if (net::OK != download_file->Initialize(get_hash)) { | 68 if (net::OK != download_file->Initialize(get_hash)) { |
69 request_handle.CancelRequest(); | 69 request_handle.CancelRequest(); |
70 return; | 70 return; |
71 } | 71 } |
72 | 72 |
73 DCHECK(GetDownloadFile(info->download_id) == NULL); | 73 DCHECK(GetDownloadFile(info->download_id) == NULL); |
74 downloads_[info->download_id] = download_file.release(); | 74 downloads_[info->download_id] = download_file.release(); |
75 | 75 |
76 // The file is now ready, we can un-pause the request and start saving data. | 76 // The file is now ready, we can un-pause the request and start saving data. |
77 request_handle.ResumeRequest(); | 77 request_handle.ResumeRequest(); |
78 | 78 |
79 StartUpdateTimer(); | 79 StartUpdateTimer(); |
80 | 80 |
81 BrowserThread::PostTask( | 81 BrowserThread::PostTask( |
82 BrowserThread::UI, FROM_HERE, | 82 BrowserThread::UI, FROM_HERE, |
83 base::Bind(&DownloadManager::StartDownload, download_manager, | 83 base::Bind(&DownloadManagerInterface::StartDownload, download_manager, |
84 info->download_id.local())); | 84 info->download_id.local())); |
85 } | 85 } |
86 | 86 |
87 DownloadFile* DownloadFileManager::GetDownloadFile(DownloadId global_id) { | 87 DownloadFile* DownloadFileManager::GetDownloadFile(DownloadId global_id) { |
88 DownloadFileMap::iterator it = downloads_.find(global_id); | 88 DownloadFileMap::iterator it = downloads_.find(global_id); |
89 return it == downloads_.end() ? NULL : it->second; | 89 return it == downloads_.end() ? NULL : it->second; |
90 } | 90 } |
91 | 91 |
92 void DownloadFileManager::StartUpdateTimer() { | 92 void DownloadFileManager::StartUpdateTimer() { |
93 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 93 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
94 if (!update_timer_.IsRunning()) { | 94 if (!update_timer_.IsRunning()) { |
95 update_timer_.Start(FROM_HERE, | 95 update_timer_.Start(FROM_HERE, |
96 base::TimeDelta::FromMilliseconds(kUpdatePeriodMs), | 96 base::TimeDelta::FromMilliseconds(kUpdatePeriodMs), |
97 this, &DownloadFileManager::UpdateInProgressDownloads); | 97 this, &DownloadFileManager::UpdateInProgressDownloads); |
98 } | 98 } |
99 } | 99 } |
100 | 100 |
101 void DownloadFileManager::StopUpdateTimer() { | 101 void DownloadFileManager::StopUpdateTimer() { |
102 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 102 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
103 update_timer_.Stop(); | 103 update_timer_.Stop(); |
104 } | 104 } |
105 | 105 |
106 void DownloadFileManager::UpdateInProgressDownloads() { | 106 void DownloadFileManager::UpdateInProgressDownloads() { |
107 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 107 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
108 for (DownloadFileMap::iterator i = downloads_.begin(); | 108 for (DownloadFileMap::iterator i = downloads_.begin(); |
109 i != downloads_.end(); ++i) { | 109 i != downloads_.end(); ++i) { |
110 DownloadId global_id = i->first; | 110 DownloadId global_id = i->first; |
111 DownloadFile* download_file = i->second; | 111 DownloadFile* download_file = i->second; |
112 DownloadManager* manager = download_file->GetDownloadManager(); | 112 DownloadManagerInterface* manager = download_file->GetDownloadManager(); |
113 if (manager) { | 113 if (manager) { |
114 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 114 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
115 base::Bind(&DownloadManager::UpdateDownload, manager, | 115 base::Bind(&DownloadManagerInterface::UpdateDownload, manager, |
116 global_id.local(), download_file->bytes_so_far())); | 116 global_id.local(), download_file->bytes_so_far())); |
117 } | 117 } |
118 } | 118 } |
119 } | 119 } |
120 | 120 |
121 void DownloadFileManager::StartDownload( | 121 void DownloadFileManager::StartDownload( |
122 DownloadCreateInfo* info, const DownloadRequestHandle& request_handle) { | 122 DownloadCreateInfo* info, const DownloadRequestHandle& request_handle) { |
123 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 123 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
124 DCHECK(info); | 124 DCHECK(info); |
125 | 125 |
126 DownloadManager* manager = request_handle.GetDownloadManager(); | 126 DownloadManagerInterface* manager = request_handle.GetDownloadManager(); |
127 if (!manager) { | 127 if (!manager) { |
128 request_handle.CancelRequest(); | 128 request_handle.CancelRequest(); |
129 delete info; | 129 delete info; |
130 return; | 130 return; |
131 } | 131 } |
132 | 132 |
133 // TODO(phajdan.jr): fix the duplication of path info below. | 133 // TODO(phajdan.jr): fix the duplication of path info below. |
134 info->path = info->save_info.file_path; | 134 info->path = info->save_info.file_path; |
135 | 135 |
136 manager->CreateDownloadItem(info, request_handle); | 136 manager->CreateDownloadItem(info, request_handle); |
(...skipping 18 matching lines...) Expand all Loading... |
155 DownloadFile* download_file = GetDownloadFile(global_id); | 155 DownloadFile* download_file = GetDownloadFile(global_id); |
156 bool had_error = false; | 156 bool had_error = false; |
157 for (size_t i = 0; i < contents->size(); ++i) { | 157 for (size_t i = 0; i < contents->size(); ++i) { |
158 net::IOBuffer* data = (*contents)[i].first; | 158 net::IOBuffer* data = (*contents)[i].first; |
159 const int data_len = (*contents)[i].second; | 159 const int data_len = (*contents)[i].second; |
160 if (!had_error && download_file) { | 160 if (!had_error && download_file) { |
161 net::Error write_result = | 161 net::Error write_result = |
162 download_file->AppendDataToFile(data->data(), data_len); | 162 download_file->AppendDataToFile(data->data(), data_len); |
163 if (write_result != net::OK) { | 163 if (write_result != net::OK) { |
164 // Write failed: interrupt the download. | 164 // Write failed: interrupt the download. |
165 DownloadManager* download_manager = download_file->GetDownloadManager(); | 165 DownloadManagerInterface* download_manager = |
| 166 download_file->GetDownloadManager(); |
166 had_error = true; | 167 had_error = true; |
167 | 168 |
168 int64 bytes_downloaded = download_file->bytes_so_far(); | 169 int64 bytes_downloaded = download_file->bytes_so_far(); |
169 // Calling this here in case we get more data, to avoid | 170 // Calling this here in case we get more data, to avoid |
170 // processing data after an error. That could lead to | 171 // processing data after an error. That could lead to |
171 // files that are corrupted if the later processing succeeded. | 172 // files that are corrupted if the later processing succeeded. |
172 CancelDownload(global_id); | 173 CancelDownload(global_id); |
173 download_file = NULL; // Was deleted in |CancelDownload|. | 174 download_file = NULL; // Was deleted in |CancelDownload|. |
174 | 175 |
175 if (download_manager) { | 176 if (download_manager) { |
176 BrowserThread::PostTask( | 177 BrowserThread::PostTask( |
177 BrowserThread::UI, FROM_HERE, | 178 BrowserThread::UI, FROM_HERE, |
178 base::Bind(&DownloadManager::OnDownloadInterrupted, | 179 base::Bind(&DownloadManagerInterface::OnDownloadInterrupted, |
179 download_manager, global_id.local(), bytes_downloaded, | 180 download_manager, global_id.local(), bytes_downloaded, |
180 ConvertNetErrorToInterruptReason( | 181 ConvertNetErrorToInterruptReason( |
181 write_result, DOWNLOAD_INTERRUPT_FROM_DISK))); | 182 write_result, DOWNLOAD_INTERRUPT_FROM_DISK))); |
182 } | 183 } |
183 } | 184 } |
184 } | 185 } |
185 data->Release(); | 186 data->Release(); |
186 } | 187 } |
187 } | 188 } |
188 | 189 |
189 void DownloadFileManager::OnResponseCompleted( | 190 void DownloadFileManager::OnResponseCompleted( |
190 DownloadId global_id, | 191 DownloadId global_id, |
191 InterruptReason reason, | 192 InterruptReason reason, |
192 const std::string& security_info) { | 193 const std::string& security_info) { |
193 VLOG(20) << __FUNCTION__ << "()" << " id = " << global_id | 194 VLOG(20) << __FUNCTION__ << "()" << " id = " << global_id |
194 << " reason = " << InterruptReasonDebugString(reason) | 195 << " reason = " << InterruptReasonDebugString(reason) |
195 << " security_info = \"" << security_info << "\""; | 196 << " security_info = \"" << security_info << "\""; |
196 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 197 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
197 DownloadFile* download_file = GetDownloadFile(global_id); | 198 DownloadFile* download_file = GetDownloadFile(global_id); |
198 if (!download_file) | 199 if (!download_file) |
199 return; | 200 return; |
200 | 201 |
201 download_file->Finish(); | 202 download_file->Finish(); |
202 | 203 |
203 DownloadManager* download_manager = download_file->GetDownloadManager(); | 204 DownloadManagerInterface* download_manager = |
| 205 download_file->GetDownloadManager(); |
204 if (!download_manager) { | 206 if (!download_manager) { |
205 CancelDownload(global_id); | 207 CancelDownload(global_id); |
206 return; | 208 return; |
207 } | 209 } |
208 | 210 |
209 std::string hash; | 211 std::string hash; |
210 if (!download_file->GetSha256Hash(&hash)) | 212 if (!download_file->GetSha256Hash(&hash)) |
211 hash.clear(); | 213 hash.clear(); |
212 | 214 |
213 if (reason == DOWNLOAD_INTERRUPT_REASON_NONE) { | 215 if (reason == DOWNLOAD_INTERRUPT_REASON_NONE) { |
214 BrowserThread::PostTask( | 216 BrowserThread::PostTask( |
215 BrowserThread::UI, FROM_HERE, | 217 BrowserThread::UI, FROM_HERE, |
216 base::Bind(&DownloadManager::OnResponseCompleted, | 218 base::Bind(&DownloadManagerInterface::OnResponseCompleted, |
217 download_manager, global_id.local(), | 219 download_manager, global_id.local(), |
218 download_file->bytes_so_far(), hash)); | 220 download_file->bytes_so_far(), hash)); |
219 } else { | 221 } else { |
220 BrowserThread::PostTask( | 222 BrowserThread::PostTask( |
221 BrowserThread::UI, FROM_HERE, | 223 BrowserThread::UI, FROM_HERE, |
222 base::Bind(&DownloadManager::OnDownloadInterrupted, | 224 base::Bind(&DownloadManagerInterface::OnDownloadInterrupted, |
223 download_manager, global_id.local(), | 225 download_manager, global_id.local(), |
224 download_file->bytes_so_far(), reason)); | 226 download_file->bytes_so_far(), reason)); |
225 } | 227 } |
226 // We need to keep the download around until the UI thread has finalized | 228 // We need to keep the download around until the UI thread has finalized |
227 // the name. | 229 // the name. |
228 } | 230 } |
229 | 231 |
230 // This method will be sent via a user action, or shutdown on the UI thread, and | 232 // This method will be sent via a user action, or shutdown on the UI thread, and |
231 // run on the download thread. Since this message has been sent from the UI | 233 // run on the download thread. Since this message has been sent from the UI |
232 // thread, the download may have already completed and won't exist in our map. | 234 // thread, the download may have already completed and won't exist in our map. |
(...skipping 22 matching lines...) Expand all Loading... |
255 | 257 |
256 VLOG(20) << " " << __FUNCTION__ << "()" | 258 VLOG(20) << " " << __FUNCTION__ << "()" |
257 << " id = " << global_id | 259 << " id = " << global_id |
258 << " download_file = " << download_file->DebugString(); | 260 << " download_file = " << download_file->DebugString(); |
259 | 261 |
260 download_file->Detach(); | 262 download_file->Detach(); |
261 | 263 |
262 EraseDownload(global_id); | 264 EraseDownload(global_id); |
263 } | 265 } |
264 | 266 |
265 void DownloadFileManager::OnDownloadManagerShutdown(DownloadManager* manager) { | 267 void DownloadFileManager::OnDownloadManagerShutdown( |
| 268 DownloadManagerInterface* manager) { |
266 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 269 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
267 DCHECK(manager); | 270 DCHECK(manager); |
268 | 271 |
269 std::set<DownloadFile*> to_remove; | 272 std::set<DownloadFile*> to_remove; |
270 | 273 |
271 for (DownloadFileMap::iterator i = downloads_.begin(); | 274 for (DownloadFileMap::iterator i = downloads_.begin(); |
272 i != downloads_.end(); ++i) { | 275 i != downloads_.end(); ++i) { |
273 DownloadFile* download_file = i->second; | 276 DownloadFile* download_file = i->second; |
274 if (download_file->GetDownloadManager() == manager) { | 277 if (download_file->GetDownloadManager() == manager) { |
275 download_file->CancelDownloadRequest(); | 278 download_file->CancelDownloadRequest(); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
327 VLOG(20) << __FUNCTION__ << "()" << " id = " << global_id | 330 VLOG(20) << __FUNCTION__ << "()" << " id = " << global_id |
328 << " overwrite_existing_file = " << overwrite_existing_file | 331 << " overwrite_existing_file = " << overwrite_existing_file |
329 << " full_path = \"" << full_path.value() << "\""; | 332 << " full_path = \"" << full_path.value() << "\""; |
330 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 333 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
331 | 334 |
332 DownloadFile* download_file = GetDownloadFile(global_id); | 335 DownloadFile* download_file = GetDownloadFile(global_id); |
333 if (!download_file) | 336 if (!download_file) |
334 return; | 337 return; |
335 | 338 |
336 DCHECK(download_file->GetDownloadManager()); | 339 DCHECK(download_file->GetDownloadManager()); |
337 DownloadManager* download_manager = download_file->GetDownloadManager(); | 340 DownloadManagerInterface* download_manager = |
| 341 download_file->GetDownloadManager(); |
338 | 342 |
339 VLOG(20) << __FUNCTION__ << "()" | 343 VLOG(20) << __FUNCTION__ << "()" |
340 << " download_file = " << download_file->DebugString(); | 344 << " download_file = " << download_file->DebugString(); |
341 | 345 |
342 int uniquifier = 0; | 346 int uniquifier = 0; |
343 FilePath new_path = full_path; | 347 FilePath new_path = full_path; |
344 if (!overwrite_existing_file) { | 348 if (!overwrite_existing_file) { |
345 // Make our name unique at this point, as if a dangerous file is | 349 // Make our name unique at this point, as if a dangerous file is |
346 // downloading and a 2nd download is started for a file with the same | 350 // downloading and a 2nd download is started for a file with the same |
347 // name, they would have the same path. This is because we uniquify | 351 // name, they would have the same path. This is because we uniquify |
(...skipping 17 matching lines...) Expand all Loading... |
365 } | 369 } |
366 | 370 |
367 #if defined(OS_MACOSX) | 371 #if defined(OS_MACOSX) |
368 // Done here because we only want to do this once; see | 372 // Done here because we only want to do this once; see |
369 // http://crbug.com/13120 for details. | 373 // http://crbug.com/13120 for details. |
370 download_file->AnnotateWithSourceInformation(); | 374 download_file->AnnotateWithSourceInformation(); |
371 #endif | 375 #endif |
372 | 376 |
373 BrowserThread::PostTask( | 377 BrowserThread::PostTask( |
374 BrowserThread::UI, FROM_HERE, | 378 BrowserThread::UI, FROM_HERE, |
375 base::Bind(&DownloadManager::OnDownloadRenamedToFinalName, | 379 base::Bind(&DownloadManagerInterface::OnDownloadRenamedToFinalName, |
376 download_manager, global_id.local(), new_path, uniquifier)); | 380 download_manager, global_id.local(), new_path, uniquifier)); |
377 } | 381 } |
378 | 382 |
379 // Called only from RenameInProgressDownloadFile and | 383 // Called only from RenameInProgressDownloadFile and |
380 // RenameCompletingDownloadFile on the FILE thread. | 384 // RenameCompletingDownloadFile on the FILE thread. |
381 void DownloadFileManager::CancelDownloadOnRename( | 385 void DownloadFileManager::CancelDownloadOnRename( |
382 DownloadId global_id, net::Error rename_error) { | 386 DownloadId global_id, net::Error rename_error) { |
383 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 387 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
384 | 388 |
385 DownloadFile* download_file = GetDownloadFile(global_id); | 389 DownloadFile* download_file = GetDownloadFile(global_id); |
386 if (!download_file) | 390 if (!download_file) |
387 return; | 391 return; |
388 | 392 |
389 DownloadManager* download_manager = download_file->GetDownloadManager(); | 393 DownloadManagerInterface* download_manager = |
| 394 download_file->GetDownloadManager(); |
390 if (!download_manager) { | 395 if (!download_manager) { |
391 // Without a download manager, we can't cancel the request normally, so we | 396 // Without a download manager, we can't cancel the request normally, so we |
392 // need to do it here. The normal path will also update the download | 397 // need to do it here. The normal path will also update the download |
393 // history before canceling the request. | 398 // history before canceling the request. |
394 download_file->CancelDownloadRequest(); | 399 download_file->CancelDownloadRequest(); |
395 return; | 400 return; |
396 } | 401 } |
397 | 402 |
398 BrowserThread::PostTask( | 403 BrowserThread::PostTask( |
399 BrowserThread::UI, FROM_HERE, | 404 BrowserThread::UI, FROM_HERE, |
400 base::Bind(&DownloadManager::OnDownloadInterrupted, | 405 base::Bind(&DownloadManagerInterface::OnDownloadInterrupted, |
401 download_manager, global_id.local(), | 406 download_manager, global_id.local(), |
402 download_file->bytes_so_far(), | 407 download_file->bytes_so_far(), |
403 ConvertNetErrorToInterruptReason( | 408 ConvertNetErrorToInterruptReason( |
404 rename_error, DOWNLOAD_INTERRUPT_FROM_DISK))); | 409 rename_error, DOWNLOAD_INTERRUPT_FROM_DISK))); |
405 } | 410 } |
406 | 411 |
407 void DownloadFileManager::EraseDownload(DownloadId global_id) { | 412 void DownloadFileManager::EraseDownload(DownloadId global_id) { |
408 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 413 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
409 | 414 |
410 if (!ContainsKey(downloads_, global_id)) | 415 if (!ContainsKey(downloads_, global_id)) |
411 return; | 416 return; |
412 | 417 |
413 DownloadFile* download_file = downloads_[global_id]; | 418 DownloadFile* download_file = downloads_[global_id]; |
414 | 419 |
415 VLOG(20) << " " << __FUNCTION__ << "()" | 420 VLOG(20) << " " << __FUNCTION__ << "()" |
416 << " id = " << global_id | 421 << " id = " << global_id |
417 << " download_file = " << download_file->DebugString(); | 422 << " download_file = " << download_file->DebugString(); |
418 | 423 |
419 downloads_.erase(global_id); | 424 downloads_.erase(global_id); |
420 | 425 |
421 delete download_file; | 426 delete download_file; |
422 | 427 |
423 if (downloads_.empty()) | 428 if (downloads_.empty()) |
424 StopUpdateTimer(); | 429 StopUpdateTimer(); |
425 } | 430 } |
OLD | NEW |