Chromium Code Reviews| 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 "chrome/browser/download/download_file_manager.h" | 5 #include "chrome/browser/download/download_file_manager.h" |
| 6 | 6 |
| 7 #include "base/file_util.h" | 7 #include "base/file_util.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
| 10 #include "base/task.h" | 10 #include "base/task.h" |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 30 | 30 |
| 31 namespace { | 31 namespace { |
| 32 | 32 |
| 33 // Throttle updates to the UI thread so that a fast moving download doesn't | 33 // Throttle updates to the UI thread so that a fast moving download doesn't |
| 34 // cause it to become unresponsive (in milliseconds). | 34 // cause it to become unresponsive (in milliseconds). |
| 35 const int kUpdatePeriodMs = 500; | 35 const int kUpdatePeriodMs = 500; |
| 36 | 36 |
| 37 } // namespace | 37 } // namespace |
| 38 | 38 |
| 39 DownloadFileManager::DownloadFileManager(ResourceDispatcherHost* rdh) | 39 DownloadFileManager::DownloadFileManager(ResourceDispatcherHost* rdh) |
| 40 : next_id_(0), | 40 : resource_dispatcher_host_(rdh) { |
| 41 resource_dispatcher_host_(rdh) { | |
| 42 } | 41 } |
| 43 | 42 |
| 44 DownloadFileManager::~DownloadFileManager() { | 43 DownloadFileManager::~DownloadFileManager() { |
| 45 DCHECK(downloads_.empty()); | 44 DCHECK(downloads_.empty()); |
| 46 } | 45 } |
| 47 | 46 |
| 48 void DownloadFileManager::Shutdown() { | 47 void DownloadFileManager::Shutdown() { |
| 49 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 48 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 50 BrowserThread::PostTask( | 49 BrowserThread::PostTask( |
| 51 BrowserThread::FILE, FROM_HERE, | 50 BrowserThread::FILE, FROM_HERE, |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 68 // Life of |info| ends here. No more references to it after this method. | 67 // Life of |info| ends here. No more references to it after this method. |
| 69 scoped_ptr<DownloadCreateInfo> infop(info); | 68 scoped_ptr<DownloadCreateInfo> infop(info); |
| 70 | 69 |
| 71 scoped_ptr<DownloadFile> | 70 scoped_ptr<DownloadFile> |
| 72 download_file(new DownloadFile(info, download_manager)); | 71 download_file(new DownloadFile(info, download_manager)); |
| 73 if (!download_file->Initialize(get_hash)) { | 72 if (!download_file->Initialize(get_hash)) { |
| 74 info->request_handle.CancelRequest(); | 73 info->request_handle.CancelRequest(); |
| 75 return; | 74 return; |
| 76 } | 75 } |
| 77 | 76 |
| 78 int32 id = info->download_id; | 77 DownloadId global_id(download_manager, info->download_id); |
| 79 DCHECK(GetDownloadFile(id) == NULL); | 78 DCHECK(GetDownloadFile(global_id) == NULL); |
| 80 downloads_[id] = download_file.release(); | 79 downloads_[global_id] = download_file.release(); |
| 81 | 80 |
| 82 // The file is now ready, we can un-pause the request and start saving data. | 81 // The file is now ready, we can un-pause the request and start saving data. |
| 83 info->request_handle.ResumeRequest(); | 82 info->request_handle.ResumeRequest(); |
| 84 | 83 |
| 85 StartUpdateTimer(); | 84 StartUpdateTimer(); |
| 86 | 85 |
| 87 BrowserThread::PostTask( | 86 BrowserThread::PostTask( |
| 88 BrowserThread::UI, FROM_HERE, | 87 BrowserThread::UI, FROM_HERE, |
| 89 NewRunnableMethod(download_manager, | 88 NewRunnableMethod(download_manager, |
| 90 &DownloadManager::StartDownload, id)); | 89 &DownloadManager::StartDownload, info->download_id)); |
| 91 } | 90 } |
| 92 | 91 |
| 93 DownloadFile* DownloadFileManager::GetDownloadFile(int id) { | 92 DownloadFile* DownloadFileManager::GetDownloadFile(DownloadId global_id) { |
| 94 DownloadFileMap::iterator it = downloads_.find(id); | 93 DownloadFileMap::iterator it = downloads_.find(global_id); |
| 95 return it == downloads_.end() ? NULL : it->second; | 94 return it == downloads_.end() ? NULL : it->second; |
| 96 } | 95 } |
| 97 | 96 |
| 98 void DownloadFileManager::StartUpdateTimer() { | 97 void DownloadFileManager::StartUpdateTimer() { |
| 99 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 98 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 100 if (!update_timer_.IsRunning()) { | 99 if (!update_timer_.IsRunning()) { |
| 101 update_timer_.Start(base::TimeDelta::FromMilliseconds(kUpdatePeriodMs), | 100 update_timer_.Start(base::TimeDelta::FromMilliseconds(kUpdatePeriodMs), |
| 102 this, &DownloadFileManager::UpdateInProgressDownloads); | 101 this, &DownloadFileManager::UpdateInProgressDownloads); |
| 103 } | 102 } |
| 104 } | 103 } |
| 105 | 104 |
| 106 void DownloadFileManager::StopUpdateTimer() { | 105 void DownloadFileManager::StopUpdateTimer() { |
| 107 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 106 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 108 update_timer_.Stop(); | 107 update_timer_.Stop(); |
| 109 } | 108 } |
| 110 | 109 |
| 111 void DownloadFileManager::UpdateInProgressDownloads() { | 110 void DownloadFileManager::UpdateInProgressDownloads() { |
| 112 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 111 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 113 for (DownloadFileMap::iterator i = downloads_.begin(); | 112 for (DownloadFileMap::iterator i = downloads_.begin(); |
| 114 i != downloads_.end(); ++i) { | 113 i != downloads_.end(); ++i) { |
| 115 int id = i->first; | 114 DownloadId global_id = i->first; |
| 116 DownloadFile* download_file = i->second; | 115 DownloadFile* download_file = i->second; |
| 117 DownloadManager* manager = download_file->GetDownloadManager(); | 116 DownloadManager* manager = download_file->GetDownloadManager(); |
| 118 if (manager) { | 117 if (manager) { |
| 119 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 118 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 120 NewRunnableMethod(manager, &DownloadManager::UpdateDownload, | 119 NewRunnableMethod(manager, &DownloadManager::UpdateDownload, |
| 121 id, download_file->bytes_so_far())); | 120 global_id.local(), download_file->bytes_so_far())); |
| 122 } | 121 } |
| 123 } | 122 } |
| 124 } | 123 } |
| 125 | 124 |
| 126 // Called on the IO thread once the ResourceDispatcherHost has decided that a | |
| 127 // request is a download. | |
| 128 int DownloadFileManager::GetNextId() { | |
| 129 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 130 return next_id_++; | |
| 131 } | |
| 132 | |
| 133 void DownloadFileManager::StartDownload(DownloadCreateInfo* info) { | 125 void DownloadFileManager::StartDownload(DownloadCreateInfo* info) { |
| 134 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 126 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 135 DCHECK(info); | 127 DCHECK(info); |
| 136 | 128 |
| 137 DownloadManager* manager = info->request_handle.GetDownloadManager(); | 129 DownloadManager* manager = info->request_handle.GetDownloadManager(); |
| 138 if (!manager) { | 130 if (!manager) { |
| 139 info->request_handle.CancelRequest(); | 131 info->request_handle.CancelRequest(); |
| 140 delete info; | 132 delete info; |
| 141 return; | 133 return; |
| 142 } | 134 } |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 157 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 149 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
| 158 NewRunnableMethod(this, &DownloadFileManager::CreateDownloadFile, | 150 NewRunnableMethod(this, &DownloadFileManager::CreateDownloadFile, |
| 159 info, make_scoped_refptr(manager), hash_needed)); | 151 info, make_scoped_refptr(manager), hash_needed)); |
| 160 } | 152 } |
| 161 | 153 |
| 162 // We don't forward an update to the UI thread here, since we want to throttle | 154 // We don't forward an update to the UI thread here, since we want to throttle |
| 163 // the UI update rate via a periodic timer. If the user has cancelled the | 155 // the UI update rate via a periodic timer. If the user has cancelled the |
| 164 // download (in the UI thread), we may receive a few more updates before the IO | 156 // download (in the UI thread), we may receive a few more updates before the IO |
| 165 // thread gets the cancel message: we just delete the data since the | 157 // thread gets the cancel message: we just delete the data since the |
| 166 // DownloadFile has been deleted. | 158 // DownloadFile has been deleted. |
| 167 void DownloadFileManager::UpdateDownload(int id, DownloadBuffer* buffer) { | 159 void DownloadFileManager::UpdateDownload( |
| 160 DownloadId global_id, DownloadBuffer* buffer) { | |
| 168 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 161 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 169 std::vector<DownloadBuffer::Contents> contents; | 162 std::vector<DownloadBuffer::Contents> contents; |
| 170 { | 163 { |
| 171 base::AutoLock auto_lock(buffer->lock); | 164 base::AutoLock auto_lock(buffer->lock); |
| 172 contents.swap(buffer->contents); | 165 contents.swap(buffer->contents); |
| 173 } | 166 } |
| 174 | 167 |
| 175 DownloadFile* download_file = GetDownloadFile(id); | 168 DownloadFile* download_file = GetDownloadFile(global_id); |
| 176 for (size_t i = 0; i < contents.size(); ++i) { | 169 for (size_t i = 0; i < contents.size(); ++i) { |
| 177 net::IOBuffer* data = contents[i].first; | 170 net::IOBuffer* data = contents[i].first; |
| 178 const int data_len = contents[i].second; | 171 const int data_len = contents[i].second; |
| 179 if (download_file) | 172 if (download_file) |
| 180 download_file->AppendDataToFile(data->data(), data_len); | 173 download_file->AppendDataToFile(data->data(), data_len); |
| 181 data->Release(); | 174 data->Release(); |
| 182 } | 175 } |
| 183 } | 176 } |
| 184 | 177 |
| 185 void DownloadFileManager::OnResponseCompleted( | 178 void DownloadFileManager::OnResponseCompleted( |
| 186 int id, | 179 DownloadId global_id, |
| 187 DownloadBuffer* buffer, | 180 DownloadBuffer* buffer, |
| 188 int os_error, | 181 int os_error, |
| 189 const std::string& security_info) { | 182 const std::string& security_info) { |
| 190 VLOG(20) << __FUNCTION__ << "()" << " id = " << id | 183 VLOG(20) << __FUNCTION__ << "()" << " id = " << global_id |
| 191 << " os_error = " << os_error | 184 << " os_error = " << os_error |
| 192 << " security_info = \"" << security_info << "\""; | 185 << " security_info = \"" << security_info << "\""; |
| 193 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 186 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 194 delete buffer; | 187 delete buffer; |
| 195 DownloadFile* download_file = GetDownloadFile(id); | 188 DownloadFile* download_file = GetDownloadFile(global_id); |
| 196 if (!download_file) | 189 if (!download_file) |
| 197 return; | 190 return; |
| 198 | 191 |
| 199 download_file->Finish(); | 192 download_file->Finish(); |
| 200 | 193 |
| 201 DownloadManager* download_manager = download_file->GetDownloadManager(); | 194 DownloadManager* download_manager = download_file->GetDownloadManager(); |
| 202 if (!download_manager) { | 195 if (!download_manager) { |
| 203 CancelDownload(id); | 196 CancelDownload(global_id); |
| 204 return; | 197 return; |
| 205 } | 198 } |
| 206 | 199 |
| 207 std::string hash; | 200 std::string hash; |
| 208 if (!download_file->GetSha256Hash(&hash)) | 201 if (!download_file->GetSha256Hash(&hash)) |
| 209 hash.clear(); | 202 hash.clear(); |
| 210 | 203 |
| 211 BrowserThread::PostTask( | 204 BrowserThread::PostTask( |
| 212 BrowserThread::UI, FROM_HERE, | 205 BrowserThread::UI, FROM_HERE, |
| 213 NewRunnableMethod( | 206 NewRunnableMethod( |
| 214 download_manager, &DownloadManager::OnResponseCompleted, | 207 download_manager, &DownloadManager::OnResponseCompleted, |
| 215 id, download_file->bytes_so_far(), os_error, hash)); | 208 global_id.local(), download_file->bytes_so_far(), os_error, hash)); |
| 216 // We need to keep the download around until the UI thread has finalized | 209 // We need to keep the download around until the UI thread has finalized |
| 217 // the name. | 210 // the name. |
| 218 } | 211 } |
| 219 | 212 |
| 220 // This method will be sent via a user action, or shutdown on the UI thread, and | 213 // This method will be sent via a user action, or shutdown on the UI thread, and |
| 221 // run on the download thread. Since this message has been sent from the UI | 214 // run on the download thread. Since this message has been sent from the UI |
| 222 // thread, the download may have already completed and won't exist in our map. | 215 // thread, the download may have already completed and won't exist in our map. |
| 223 void DownloadFileManager::CancelDownload(int id) { | 216 void DownloadFileManager::CancelDownload(DownloadId global_id) { |
| 224 VLOG(20) << __FUNCTION__ << "()" << " id = " << id; | 217 VLOG(20) << __FUNCTION__ << "()" << " id = " << global_id; |
| 225 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 218 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 226 DownloadFileMap::iterator it = downloads_.find(id); | 219 DownloadFileMap::iterator it = downloads_.find(global_id); |
| 227 if (it == downloads_.end()) | 220 if (it == downloads_.end()) |
| 228 return; | 221 return; |
| 229 | 222 |
| 230 DownloadFile* download_file = it->second; | 223 DownloadFile* download_file = it->second; |
| 231 VLOG(20) << __FUNCTION__ << "()" | 224 VLOG(20) << __FUNCTION__ << "()" |
| 232 << " download_file = " << download_file->DebugString(); | 225 << " download_file = " << download_file->DebugString(); |
| 233 download_file->Cancel(); | 226 download_file->Cancel(); |
| 234 | 227 |
| 235 EraseDownload(id); | 228 EraseDownload(global_id); |
| 236 } | 229 } |
| 237 | 230 |
| 238 void DownloadFileManager::CompleteDownload(int id) { | 231 void DownloadFileManager::CompleteDownload(DownloadId global_id) { |
| 239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 232 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 240 | 233 |
| 241 if (!ContainsKey(downloads_, id)) | 234 if (!ContainsKey(downloads_, global_id)) |
| 242 return; | 235 return; |
| 243 | 236 |
| 244 DownloadFile* download_file = downloads_[id]; | 237 DownloadFile* download_file = downloads_[global_id]; |
| 245 | 238 |
| 246 VLOG(20) << " " << __FUNCTION__ << "()" | 239 VLOG(20) << " " << __FUNCTION__ << "()" |
| 247 << " id = " << id | 240 << " id = " << global_id |
| 248 << " download_file = " << download_file->DebugString(); | 241 << " download_file = " << download_file->DebugString(); |
| 249 | 242 |
| 250 download_file->Detach(); | 243 download_file->Detach(); |
| 251 | 244 |
| 252 EraseDownload(id); | 245 EraseDownload(global_id); |
| 253 } | 246 } |
| 254 | 247 |
| 255 void DownloadFileManager::OnDownloadManagerShutdown(DownloadManager* manager) { | 248 void DownloadFileManager::OnDownloadManagerShutdown(DownloadManager* manager) { |
| 256 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 249 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 257 DCHECK(manager); | 250 DCHECK(manager); |
| 258 | 251 |
| 259 std::set<DownloadFile*> to_remove; | 252 std::set<DownloadFile*> to_remove; |
| 260 | 253 |
| 261 for (DownloadFileMap::iterator i = downloads_.begin(); | 254 for (DownloadFileMap::iterator i = downloads_.begin(); |
| 262 i != downloads_.end(); ++i) { | 255 i != downloads_.end(); ++i) { |
| 263 DownloadFile* download_file = i->second; | 256 DownloadFile* download_file = i->second; |
| 264 if (download_file->GetDownloadManager() == manager) { | 257 if (download_file->GetDownloadManager() == manager) { |
| 265 download_file->CancelDownloadRequest(); | 258 download_file->CancelDownloadRequest(); |
| 266 to_remove.insert(download_file); | 259 to_remove.insert(download_file); |
| 267 } | 260 } |
| 268 } | 261 } |
| 269 | 262 |
| 270 for (std::set<DownloadFile*>::iterator i = to_remove.begin(); | 263 for (std::set<DownloadFile*>::iterator i = to_remove.begin(); |
| 271 i != to_remove.end(); ++i) { | 264 i != to_remove.end(); ++i) { |
| 272 downloads_.erase((*i)->id()); | 265 downloads_.erase(DownloadId((*i)->GetDownloadManager(), (*i)->id())); |
|
Randy Smith (Not in Mondays)
2011/07/28 21:03:16
Shouldn't DownloadFile have a global id? It feels
benjhayden
2011/08/03 17:44:46
SGTM.
Randy Smith (Not in Mondays)
2011/08/03 21:10:29
(I'm taking "at the level" to mean "in the context
benjhayden
2011/08/04 17:15:00
Done.
| |
| 273 delete *i; | 266 delete *i; |
| 274 } | 267 } |
| 275 } | 268 } |
| 276 | 269 |
| 277 // Actions from the UI thread and run on the download thread | 270 // Actions from the UI thread and run on the download thread |
| 278 | 271 |
| 279 // The DownloadManager in the UI thread has provided an intermediate .crdownload | 272 // The DownloadManager in the UI thread has provided an intermediate .crdownload |
| 280 // name for the download specified by 'id'. Rename the in progress download. | 273 // name for the download specified by 'id'. Rename the in progress download. |
| 281 // | 274 // |
| 282 // There are 2 possible rename cases where this method can be called: | 275 // There are 2 possible rename cases where this method can be called: |
| 283 // 1. tmp -> foo.crdownload (not final, safe) | 276 // 1. tmp -> foo.crdownload (not final, safe) |
| 284 // 2. tmp-> Unconfirmed.xxx.crdownload (not final, dangerous) | 277 // 2. tmp-> Unconfirmed.xxx.crdownload (not final, dangerous) |
| 285 void DownloadFileManager::RenameInProgressDownloadFile( | 278 void DownloadFileManager::RenameInProgressDownloadFile( |
| 286 int id, const FilePath& full_path) { | 279 DownloadId global_id, const FilePath& full_path) { |
| 287 VLOG(20) << __FUNCTION__ << "()" << " id = " << id | 280 VLOG(20) << __FUNCTION__ << "()" << " id = " << global_id |
| 288 << " full_path = \"" << full_path.value() << "\""; | 281 << " full_path = \"" << full_path.value() << "\""; |
| 289 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 282 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 290 | 283 |
| 291 DownloadFile* download_file = GetDownloadFile(id); | 284 DownloadFile* download_file = GetDownloadFile(global_id); |
| 292 if (!download_file) | 285 if (!download_file) |
| 293 return; | 286 return; |
| 294 | 287 |
| 295 VLOG(20) << __FUNCTION__ << "()" | 288 VLOG(20) << __FUNCTION__ << "()" |
| 296 << " download_file = " << download_file->DebugString(); | 289 << " download_file = " << download_file->DebugString(); |
| 297 | 290 |
| 298 if (!download_file->Rename(full_path)) { | 291 if (!download_file->Rename(full_path)) { |
| 299 // Error. Between the time the UI thread generated 'full_path' to the time | 292 // Error. Between the time the UI thread generated 'full_path' to the time |
| 300 // this code runs, something happened that prevents us from renaming. | 293 // this code runs, something happened that prevents us from renaming. |
| 301 CancelDownloadOnRename(id); | 294 CancelDownloadOnRename(global_id); |
| 302 } | 295 } |
| 303 } | 296 } |
| 304 | 297 |
| 305 // The DownloadManager in the UI thread has provided a final name for the | 298 // The DownloadManager in the UI thread has provided a final name for the |
| 306 // download specified by 'id'. Rename the download that's in the process | 299 // download specified by 'id'. Rename the download that's in the process |
| 307 // of completing. | 300 // of completing. |
| 308 // | 301 // |
| 309 // There are 2 possible rename cases where this method can be called: | 302 // There are 2 possible rename cases where this method can be called: |
| 310 // 1. foo.crdownload -> foo (final, safe) | 303 // 1. foo.crdownload -> foo (final, safe) |
| 311 // 2. Unconfirmed.xxx.crdownload -> xxx (final, validated) | 304 // 2. Unconfirmed.xxx.crdownload -> xxx (final, validated) |
| 312 void DownloadFileManager::RenameCompletingDownloadFile( | 305 void DownloadFileManager::RenameCompletingDownloadFile( |
| 313 int id, const FilePath& full_path, bool overwrite_existing_file) { | 306 DownloadId global_id, |
| 314 VLOG(20) << __FUNCTION__ << "()" << " id = " << id | 307 const FilePath& full_path, |
| 308 bool overwrite_existing_file) { | |
| 309 VLOG(20) << __FUNCTION__ << "()" << " id = " << global_id | |
| 315 << " overwrite_existing_file = " << overwrite_existing_file | 310 << " overwrite_existing_file = " << overwrite_existing_file |
| 316 << " full_path = \"" << full_path.value() << "\""; | 311 << " full_path = \"" << full_path.value() << "\""; |
| 317 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 312 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 318 | 313 |
| 319 DownloadFile* download_file = GetDownloadFile(id); | 314 DownloadFile* download_file = GetDownloadFile(global_id); |
| 320 if (!download_file) | 315 if (!download_file) |
| 321 return; | 316 return; |
| 322 | 317 |
| 323 DCHECK(download_file->GetDownloadManager()); | 318 DCHECK(download_file->GetDownloadManager()); |
| 324 DownloadManager* download_manager = download_file->GetDownloadManager(); | 319 DownloadManager* download_manager = download_file->GetDownloadManager(); |
| 325 | 320 |
| 326 VLOG(20) << __FUNCTION__ << "()" | 321 VLOG(20) << __FUNCTION__ << "()" |
| 327 << " download_file = " << download_file->DebugString(); | 322 << " download_file = " << download_file->DebugString(); |
| 328 | 323 |
| 329 int uniquifier = 0; | 324 int uniquifier = 0; |
| 330 FilePath new_path = full_path; | 325 FilePath new_path = full_path; |
| 331 if (!overwrite_existing_file) { | 326 if (!overwrite_existing_file) { |
| 332 // Make our name unique at this point, as if a dangerous file is | 327 // Make our name unique at this point, as if a dangerous file is |
| 333 // downloading and a 2nd download is started for a file with the same | 328 // downloading and a 2nd download is started for a file with the same |
| 334 // name, they would have the same path. This is because we uniquify | 329 // name, they would have the same path. This is because we uniquify |
| 335 // the name on download start, and at that time the first file does | 330 // the name on download start, and at that time the first file does |
| 336 // not exists yet, so the second file gets the same name. | 331 // not exists yet, so the second file gets the same name. |
| 337 // This should not happen in the SAFE case, and we check for that in the UI | 332 // This should not happen in the SAFE case, and we check for that in the UI |
| 338 // thread. | 333 // thread. |
| 339 uniquifier = download_util::GetUniquePathNumber(new_path); | 334 uniquifier = download_util::GetUniquePathNumber(new_path); |
| 340 if (uniquifier > 0) { | 335 if (uniquifier > 0) { |
| 341 download_util::AppendNumberToPath(&new_path, uniquifier); | 336 download_util::AppendNumberToPath(&new_path, uniquifier); |
| 342 } | 337 } |
| 343 } | 338 } |
| 344 | 339 |
| 345 // Rename the file, overwriting if necessary. | 340 // Rename the file, overwriting if necessary. |
| 346 if (!download_file->Rename(new_path)) { | 341 if (!download_file->Rename(new_path)) { |
| 347 // Error. Between the time the UI thread generated 'full_path' to the time | 342 // Error. Between the time the UI thread generated 'full_path' to the time |
| 348 // this code runs, something happened that prevents us from renaming. | 343 // this code runs, something happened that prevents us from renaming. |
| 349 CancelDownloadOnRename(id); | 344 CancelDownloadOnRename(global_id); |
| 350 return; | 345 return; |
| 351 } | 346 } |
| 352 | 347 |
| 353 #if defined(OS_MACOSX) | 348 #if defined(OS_MACOSX) |
| 354 // Done here because we only want to do this once; see | 349 // Done here because we only want to do this once; see |
| 355 // http://crbug.com/13120 for details. | 350 // http://crbug.com/13120 for details. |
| 356 download_file->AnnotateWithSourceInformation(); | 351 download_file->AnnotateWithSourceInformation(); |
| 357 #endif | 352 #endif |
| 358 | 353 |
| 359 BrowserThread::PostTask( | 354 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, NewRunnableMethod( |
| 360 BrowserThread::UI, FROM_HERE, | 355 download_manager, &DownloadManager::OnDownloadRenamedToFinalName, |
| 361 NewRunnableMethod( | 356 global_id.local(), new_path, uniquifier)); |
| 362 download_manager, &DownloadManager::OnDownloadRenamedToFinalName, id, | |
| 363 new_path, uniquifier)); | |
| 364 } | 357 } |
| 365 | 358 |
| 366 // Called only from RenameInProgressDownloadFile and | 359 // Called only from RenameInProgressDownloadFile and |
| 367 // RenameCompletingDownloadFile on the FILE thread. | 360 // RenameCompletingDownloadFile on the FILE thread. |
| 368 void DownloadFileManager::CancelDownloadOnRename(int id) { | 361 void DownloadFileManager::CancelDownloadOnRename(DownloadId global_id) { |
| 369 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 362 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 370 | 363 |
| 371 DownloadFile* download_file = GetDownloadFile(id); | 364 DownloadFile* download_file = GetDownloadFile(global_id); |
| 372 if (!download_file) | 365 if (!download_file) |
| 373 return; | 366 return; |
| 374 | 367 |
| 375 DownloadManager* download_manager = download_file->GetDownloadManager(); | 368 DownloadManager* download_manager = download_file->GetDownloadManager(); |
| 376 if (!download_manager) { | 369 if (!download_manager) { |
| 377 // Without a download manager, we can't cancel the request normally, so we | 370 // Without a download manager, we can't cancel the request normally, so we |
| 378 // need to do it here. The normal path will also update the download | 371 // need to do it here. The normal path will also update the download |
| 379 // history before cancelling the request. | 372 // history before cancelling the request. |
| 380 download_file->CancelDownloadRequest(); | 373 download_file->CancelDownloadRequest(); |
| 381 return; | 374 return; |
| 382 } | 375 } |
| 383 | 376 |
| 384 BrowserThread::PostTask( | 377 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, NewRunnableMethod( |
| 385 BrowserThread::UI, FROM_HERE, | 378 download_manager, &DownloadManager::DownloadCancelled, |
| 386 NewRunnableMethod(download_manager, | 379 global_id.local())); |
| 387 &DownloadManager::DownloadCancelled, id)); | |
| 388 } | 380 } |
| 389 | 381 |
| 390 void DownloadFileManager::EraseDownload(int id) { | 382 void DownloadFileManager::EraseDownload(DownloadId global_id) { |
| 391 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 383 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 392 | 384 |
| 393 if (!ContainsKey(downloads_, id)) | 385 if (!ContainsKey(downloads_, global_id)) |
| 394 return; | 386 return; |
| 395 | 387 |
| 396 DownloadFile* download_file = downloads_[id]; | 388 DownloadFile* download_file = downloads_[global_id]; |
| 397 | 389 |
| 398 VLOG(20) << " " << __FUNCTION__ << "()" | 390 VLOG(20) << " " << __FUNCTION__ << "()" |
| 399 << " id = " << id | 391 << " id = " << global_id |
| 400 << " download_file = " << download_file->DebugString(); | 392 << " download_file = " << download_file->DebugString(); |
| 401 | 393 |
| 402 downloads_.erase(id); | 394 downloads_.erase(global_id); |
| 403 | 395 |
| 404 delete download_file; | 396 delete download_file; |
| 405 | 397 |
| 406 if (downloads_.empty()) | 398 if (downloads_.empty()) |
| 407 StopUpdateTimer(); | 399 StopUpdateTimer(); |
| 408 } | 400 } |
| OLD | NEW |