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