| 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 (net::OK != download_file->Initialize(get_hash)) { | 63 if (net::OK != 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(FROM_HERE, | 91 update_timer_.Start(FROM_HERE, |
| 92 base::TimeDelta::FromMilliseconds(kUpdatePeriodMs), | 92 base::TimeDelta::FromMilliseconds(kUpdatePeriodMs), |
| 93 this, &DownloadFileManager::UpdateInProgressDownloads); | 93 this, &DownloadFileManager::UpdateInProgressDownloads); |
| 94 } | 94 } |
| 95 } | 95 } |
| 96 | 96 |
| 97 void DownloadFileManager::StopUpdateTimer() { | 97 void DownloadFileManager::StopUpdateTimer() { |
| 98 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 98 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 99 update_timer_.Stop(); | 99 update_timer_.Stop(); |
| 100 } | 100 } |
| 101 | 101 |
| 102 void DownloadFileManager::UpdateInProgressDownloads() { | 102 void DownloadFileManager::UpdateInProgressDownloads() { |
| 103 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 103 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 104 for (DownloadFileMap::iterator i = downloads_.begin(); | 104 for (DownloadFileMap::iterator i = downloads_.begin(); |
| 105 i != downloads_.end(); ++i) { | 105 i != downloads_.end(); ++i) { |
| 106 int id = i->first; | 106 DownloadId global_id = i->first; |
| 107 DownloadFile* download_file = i->second; | 107 DownloadFile* download_file = i->second; |
| 108 DownloadManager* manager = download_file->GetDownloadManager(); | 108 DownloadManager* manager = download_file->GetDownloadManager(); |
| 109 if (manager) { | 109 if (manager) { |
| 110 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 110 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 111 NewRunnableMethod(manager, &DownloadManager::UpdateDownload, | 111 NewRunnableMethod(manager, &DownloadManager::UpdateDownload, |
| 112 id, download_file->bytes_so_far())); | 112 global_id.local(), download_file->bytes_so_far())); |
| 113 } | 113 } |
| 114 } | 114 } |
| 115 } | 115 } |
| 116 | 116 |
| 117 int DownloadFileManager::GetNextId() { | |
| 118 return next_id_.GetNext(); | |
| 119 } | |
| 120 | |
| 121 void DownloadFileManager::StartDownload(DownloadCreateInfo* info) { | 117 void DownloadFileManager::StartDownload(DownloadCreateInfo* info) { |
| 122 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 118 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 123 DCHECK(info); | 119 DCHECK(info); |
| 124 | 120 |
| 125 DownloadManager* manager = info->request_handle.GetDownloadManager(); | 121 DownloadManager* manager = info->request_handle.GetDownloadManager(); |
| 126 if (!manager) { | 122 if (!manager) { |
| 127 info->request_handle.CancelRequest(); | 123 info->request_handle.CancelRequest(); |
| 128 delete info; | 124 delete info; |
| 129 return; | 125 return; |
| 130 } | 126 } |
| 131 | 127 |
| 132 // TODO(phajdan.jr): fix the duplication of path info below. | 128 // TODO(phajdan.jr): fix the duplication of path info below. |
| 133 info->path = info->save_info.file_path; | 129 info->path = info->save_info.file_path; |
| 134 | 130 |
| 135 manager->CreateDownloadItem(info); | 131 manager->CreateDownloadItem(info); |
| 136 bool hash_needed = manager->delegate()->GenerateFileHash(); | 132 bool hash_needed = manager->delegate()->GenerateFileHash(); |
| 137 | 133 |
| 138 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 134 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
| 139 NewRunnableMethod(this, &DownloadFileManager::CreateDownloadFile, | 135 NewRunnableMethod(this, &DownloadFileManager::CreateDownloadFile, |
| 140 info, make_scoped_refptr(manager), hash_needed)); | 136 info, make_scoped_refptr(manager), hash_needed)); |
| 141 } | 137 } |
| 142 | 138 |
| 143 // We don't forward an update to the UI thread here, since we want to throttle | 139 // 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 | 140 // 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 | 141 // 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 | 142 // thread gets the cancel message: we just delete the data since the |
| 147 // DownloadFile has been deleted. | 143 // DownloadFile has been deleted. |
| 148 void DownloadFileManager::UpdateDownload(int id, DownloadBuffer* buffer) { | 144 void DownloadFileManager::UpdateDownload( |
| 145 DownloadId global_id, DownloadBuffer* buffer) { |
| 149 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 146 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 150 std::vector<DownloadBuffer::Contents> contents; | 147 std::vector<DownloadBuffer::Contents> contents; |
| 151 { | 148 { |
| 152 base::AutoLock auto_lock(buffer->lock); | 149 base::AutoLock auto_lock(buffer->lock); |
| 153 contents.swap(buffer->contents); | 150 contents.swap(buffer->contents); |
| 154 } | 151 } |
| 155 | 152 |
| 156 DownloadFile* download_file = GetDownloadFile(id); | 153 DownloadFile* download_file = GetDownloadFile(global_id); |
| 157 bool had_error = false; | 154 bool had_error = false; |
| 158 for (size_t i = 0; i < contents.size(); ++i) { | 155 for (size_t i = 0; i < contents.size(); ++i) { |
| 159 net::IOBuffer* data = contents[i].first; | 156 net::IOBuffer* data = contents[i].first; |
| 160 const int data_len = contents[i].second; | 157 const int data_len = contents[i].second; |
| 161 if (!had_error && download_file) { | 158 if (!had_error && download_file) { |
| 162 net::Error write_result = | 159 net::Error write_result = |
| 163 download_file->AppendDataToFile(data->data(), data_len); | 160 download_file->AppendDataToFile(data->data(), data_len); |
| 164 if (write_result != net::OK) { | 161 if (write_result != net::OK) { |
| 165 // Write failed: interrupt the download. | 162 // Write failed: interrupt the download. |
| 166 DownloadManager* download_manager = download_file->GetDownloadManager(); | 163 DownloadManager* download_manager = download_file->GetDownloadManager(); |
| 167 had_error = true; | 164 had_error = true; |
| 168 | 165 |
| 169 int64 bytes_downloaded = download_file->bytes_so_far(); | 166 int64 bytes_downloaded = download_file->bytes_so_far(); |
| 170 // Calling this here in case we get more data, to avoid | 167 // Calling this here in case we get more data, to avoid |
| 171 // processing data after an error. That could lead to | 168 // processing data after an error. That could lead to |
| 172 // files that are corrupted if the later processing succeeded. | 169 // files that are corrupted if the later processing succeeded. |
| 173 CancelDownload(id); | 170 CancelDownload(global_id); |
| 174 download_file = NULL; // Was deleted in |CancelDownload|. | 171 download_file = NULL; // Was deleted in |CancelDownload|. |
| 175 | 172 |
| 176 if (download_manager) { | 173 if (download_manager) { |
| 177 BrowserThread::PostTask( | 174 BrowserThread::PostTask( |
| 178 BrowserThread::UI, | 175 BrowserThread::UI, |
| 179 FROM_HERE, | 176 FROM_HERE, |
| 180 NewRunnableMethod( | 177 NewRunnableMethod( |
| 181 download_manager, | 178 download_manager, |
| 182 &DownloadManager::OnDownloadError, | 179 &DownloadManager::OnDownloadError, |
| 183 id, | 180 global_id.local(), |
| 184 bytes_downloaded, | 181 bytes_downloaded, |
| 185 write_result)); | 182 write_result)); |
| 186 } | 183 } |
| 187 } | 184 } |
| 188 } | 185 } |
| 189 data->Release(); | 186 data->Release(); |
| 190 } | 187 } |
| 191 } | 188 } |
| 192 | 189 |
| 193 void DownloadFileManager::OnResponseCompleted( | 190 void DownloadFileManager::OnResponseCompleted( |
| 194 int id, | 191 DownloadId global_id, |
| 195 DownloadBuffer* buffer, | 192 DownloadBuffer* buffer, |
| 196 net::Error net_error, | 193 net::Error net_error, |
| 197 const std::string& security_info) { | 194 const std::string& security_info) { |
| 198 VLOG(20) << __FUNCTION__ << "()" << " id = " << id | 195 VLOG(20) << __FUNCTION__ << "()" << " id = " << global_id |
| 199 << " net_error = " << net_error | 196 << " net_error = " << net_error |
| 200 << " security_info = \"" << security_info << "\""; | 197 << " security_info = \"" << security_info << "\""; |
| 201 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 198 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 202 delete buffer; | 199 delete buffer; |
| 203 DownloadFile* download_file = GetDownloadFile(id); | 200 DownloadFile* download_file = GetDownloadFile(global_id); |
| 204 if (!download_file) | 201 if (!download_file) |
| 205 return; | 202 return; |
| 206 | 203 |
| 207 download_file->Finish(); | 204 download_file->Finish(); |
| 208 | 205 |
| 209 DownloadManager* download_manager = download_file->GetDownloadManager(); | 206 DownloadManager* download_manager = download_file->GetDownloadManager(); |
| 210 if (!download_manager) { | 207 if (!download_manager) { |
| 211 CancelDownload(id); | 208 CancelDownload(global_id); |
| 212 return; | 209 return; |
| 213 } | 210 } |
| 214 | 211 |
| 215 std::string hash; | 212 std::string hash; |
| 216 if (!download_file->GetSha256Hash(&hash)) | 213 if (!download_file->GetSha256Hash(&hash)) |
| 217 hash.clear(); | 214 hash.clear(); |
| 218 | 215 |
| 219 // ERR_CONNECTION_CLOSED is allowed since a number of servers in the wild | 216 // ERR_CONNECTION_CLOSED is allowed since a number of servers in the wild |
| 220 // advertise a larger Content-Length than the amount of bytes in the message | 217 // advertise a larger Content-Length than the amount of bytes in the message |
| 221 // body, and then close the connection. Other browsers - IE8, Firefox 4.0.1, | 218 // body, and then close the connection. Other browsers - IE8, Firefox 4.0.1, |
| 222 // and Safari 5.0.4 - treat the download as complete in this case, so we | 219 // and Safari 5.0.4 - treat the download as complete in this case, so we |
| 223 // follow their lead. | 220 // follow their lead. |
| 224 if (net_error == net::OK || net_error == net::ERR_CONNECTION_CLOSED) { | 221 if (net_error == net::OK || net_error == net::ERR_CONNECTION_CLOSED) { |
| 225 BrowserThread::PostTask( | 222 BrowserThread::PostTask( |
| 226 BrowserThread::UI, | 223 BrowserThread::UI, |
| 227 FROM_HERE, | 224 FROM_HERE, |
| 228 NewRunnableMethod( | 225 NewRunnableMethod( |
| 229 download_manager, | 226 download_manager, |
| 230 &DownloadManager::OnResponseCompleted, | 227 &DownloadManager::OnResponseCompleted, |
| 231 id, | 228 global_id.local(), |
| 232 download_file->bytes_so_far(), | 229 download_file->bytes_so_far(), |
| 233 hash)); | 230 hash)); |
| 234 } else { | 231 } else { |
| 235 BrowserThread::PostTask( | 232 BrowserThread::PostTask( |
| 236 BrowserThread::UI, | 233 BrowserThread::UI, |
| 237 FROM_HERE, | 234 FROM_HERE, |
| 238 NewRunnableMethod( | 235 NewRunnableMethod( |
| 239 download_manager, | 236 download_manager, |
| 240 &DownloadManager::OnDownloadError, | 237 &DownloadManager::OnDownloadError, |
| 241 id, | 238 global_id.local(), |
| 242 download_file->bytes_so_far(), | 239 download_file->bytes_so_far(), |
| 243 net_error)); | 240 net_error)); |
| 244 } | 241 } |
| 245 // We need to keep the download around until the UI thread has finalized | 242 // We need to keep the download around until the UI thread has finalized |
| 246 // the name. | 243 // the name. |
| 247 } | 244 } |
| 248 | 245 |
| 249 // This method will be sent via a user action, or shutdown on the UI thread, and | 246 // This method will be sent via a user action, or shutdown on the UI thread, and |
| 250 // run on the download thread. Since this message has been sent from the UI | 247 // run on the download thread. Since this message has been sent from the UI |
| 251 // thread, the download may have already completed and won't exist in our map. | 248 // thread, the download may have already completed and won't exist in our map. |
| 252 void DownloadFileManager::CancelDownload(int id) { | 249 void DownloadFileManager::CancelDownload(DownloadId global_id) { |
| 253 VLOG(20) << __FUNCTION__ << "()" << " id = " << id; | 250 VLOG(20) << __FUNCTION__ << "()" << " id = " << global_id; |
| 254 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 251 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 255 DownloadFileMap::iterator it = downloads_.find(id); | 252 DownloadFileMap::iterator it = downloads_.find(global_id); |
| 256 if (it == downloads_.end()) | 253 if (it == downloads_.end()) |
| 257 return; | 254 return; |
| 258 | 255 |
| 259 DownloadFile* download_file = it->second; | 256 DownloadFile* download_file = it->second; |
| 260 VLOG(20) << __FUNCTION__ << "()" | 257 VLOG(20) << __FUNCTION__ << "()" |
| 261 << " download_file = " << download_file->DebugString(); | 258 << " download_file = " << download_file->DebugString(); |
| 262 download_file->Cancel(); | 259 download_file->Cancel(); |
| 263 | 260 |
| 264 EraseDownload(id); | 261 EraseDownload(global_id); |
| 265 } | 262 } |
| 266 | 263 |
| 267 void DownloadFileManager::CompleteDownload(int id) { | 264 void DownloadFileManager::CompleteDownload(DownloadId global_id) { |
| 268 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 265 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 269 | 266 |
| 270 if (!ContainsKey(downloads_, id)) | 267 if (!ContainsKey(downloads_, global_id)) |
| 271 return; | 268 return; |
| 272 | 269 |
| 273 DownloadFile* download_file = downloads_[id]; | 270 DownloadFile* download_file = downloads_[global_id]; |
| 274 | 271 |
| 275 VLOG(20) << " " << __FUNCTION__ << "()" | 272 VLOG(20) << " " << __FUNCTION__ << "()" |
| 276 << " id = " << id | 273 << " id = " << global_id |
| 277 << " download_file = " << download_file->DebugString(); | 274 << " download_file = " << download_file->DebugString(); |
| 278 | 275 |
| 279 download_file->Detach(); | 276 download_file->Detach(); |
| 280 | 277 |
| 281 EraseDownload(id); | 278 EraseDownload(global_id); |
| 282 } | 279 } |
| 283 | 280 |
| 284 void DownloadFileManager::OnDownloadManagerShutdown(DownloadManager* manager) { | 281 void DownloadFileManager::OnDownloadManagerShutdown(DownloadManager* manager) { |
| 285 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 282 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 286 DCHECK(manager); | 283 DCHECK(manager); |
| 287 | 284 |
| 288 std::set<DownloadFile*> to_remove; | 285 std::set<DownloadFile*> to_remove; |
| 289 | 286 |
| 290 for (DownloadFileMap::iterator i = downloads_.begin(); | 287 for (DownloadFileMap::iterator i = downloads_.begin(); |
| 291 i != downloads_.end(); ++i) { | 288 i != downloads_.end(); ++i) { |
| 292 DownloadFile* download_file = i->second; | 289 DownloadFile* download_file = i->second; |
| 293 if (download_file->GetDownloadManager() == manager) { | 290 if (download_file->GetDownloadManager() == manager) { |
| 294 download_file->CancelDownloadRequest(); | 291 download_file->CancelDownloadRequest(); |
| 295 to_remove.insert(download_file); | 292 to_remove.insert(download_file); |
| 296 } | 293 } |
| 297 } | 294 } |
| 298 | 295 |
| 299 for (std::set<DownloadFile*>::iterator i = to_remove.begin(); | 296 for (std::set<DownloadFile*>::iterator i = to_remove.begin(); |
| 300 i != to_remove.end(); ++i) { | 297 i != to_remove.end(); ++i) { |
| 301 downloads_.erase((*i)->id()); | 298 downloads_.erase(DownloadId((*i)->GetDownloadManager(), (*i)->id())); |
| 302 delete *i; | 299 delete *i; |
| 303 } | 300 } |
| 304 } | 301 } |
| 305 | 302 |
| 306 // Actions from the UI thread and run on the download thread | 303 // Actions from the UI thread and run on the download thread |
| 307 | 304 |
| 308 // The DownloadManager in the UI thread has provided an intermediate .crdownload | 305 // The DownloadManager in the UI thread has provided an intermediate .crdownload |
| 309 // name for the download specified by 'id'. Rename the in progress download. | 306 // name for the download specified by 'id'. Rename the in progress download. |
| 310 // | 307 // |
| 311 // There are 2 possible rename cases where this method can be called: | 308 // There are 2 possible rename cases where this method can be called: |
| 312 // 1. tmp -> foo.crdownload (not final, safe) | 309 // 1. tmp -> foo.crdownload (not final, safe) |
| 313 // 2. tmp-> Unconfirmed.xxx.crdownload (not final, dangerous) | 310 // 2. tmp-> Unconfirmed.xxx.crdownload (not final, dangerous) |
| 314 void DownloadFileManager::RenameInProgressDownloadFile( | 311 void DownloadFileManager::RenameInProgressDownloadFile( |
| 315 int id, const FilePath& full_path) { | 312 DownloadId global_id, const FilePath& full_path) { |
| 316 VLOG(20) << __FUNCTION__ << "()" << " id = " << id | 313 VLOG(20) << __FUNCTION__ << "()" << " id = " << global_id |
| 317 << " full_path = \"" << full_path.value() << "\""; | 314 << " full_path = \"" << full_path.value() << "\""; |
| 318 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 315 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 319 | 316 |
| 320 DownloadFile* download_file = GetDownloadFile(id); | 317 DownloadFile* download_file = GetDownloadFile(global_id); |
| 321 if (!download_file) | 318 if (!download_file) |
| 322 return; | 319 return; |
| 323 | 320 |
| 324 VLOG(20) << __FUNCTION__ << "()" | 321 VLOG(20) << __FUNCTION__ << "()" |
| 325 << " download_file = " << download_file->DebugString(); | 322 << " download_file = " << download_file->DebugString(); |
| 326 | 323 |
| 327 net::Error rename_error = download_file->Rename(full_path); | 324 net::Error rename_error = download_file->Rename(full_path); |
| 328 if (net::OK != rename_error) { | 325 if (net::OK != rename_error) { |
| 329 // 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 |
| 330 // this code runs, something happened that prevents us from renaming. | 327 // this code runs, something happened that prevents us from renaming. |
| 331 CancelDownloadOnRename(id, rename_error); | 328 CancelDownloadOnRename(global_id, rename_error); |
| 332 } | 329 } |
| 333 } | 330 } |
| 334 | 331 |
| 335 // The DownloadManager in the UI thread has provided a final name for the | 332 // The DownloadManager in the UI thread has provided a final name for the |
| 336 // download specified by 'id'. Rename the download that's in the process | 333 // download specified by 'id'. Rename the download that's in the process |
| 337 // of completing. | 334 // of completing. |
| 338 // | 335 // |
| 339 // There are 2 possible rename cases where this method can be called: | 336 // There are 2 possible rename cases where this method can be called: |
| 340 // 1. foo.crdownload -> foo (final, safe) | 337 // 1. foo.crdownload -> foo (final, safe) |
| 341 // 2. Unconfirmed.xxx.crdownload -> xxx (final, validated) | 338 // 2. Unconfirmed.xxx.crdownload -> xxx (final, validated) |
| 342 void DownloadFileManager::RenameCompletingDownloadFile( | 339 void DownloadFileManager::RenameCompletingDownloadFile( |
| 343 int id, const FilePath& full_path, bool overwrite_existing_file) { | 340 DownloadId global_id, |
| 344 VLOG(20) << __FUNCTION__ << "()" << " id = " << id | 341 const FilePath& full_path, |
| 342 bool overwrite_existing_file) { |
| 343 VLOG(20) << __FUNCTION__ << "()" << " id = " << global_id |
| 345 << " overwrite_existing_file = " << overwrite_existing_file | 344 << " overwrite_existing_file = " << overwrite_existing_file |
| 346 << " full_path = \"" << full_path.value() << "\""; | 345 << " full_path = \"" << full_path.value() << "\""; |
| 347 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 346 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 348 | 347 |
| 349 DownloadFile* download_file = GetDownloadFile(id); | 348 DownloadFile* download_file = GetDownloadFile(global_id); |
| 350 if (!download_file) | 349 if (!download_file) |
| 351 return; | 350 return; |
| 352 | 351 |
| 353 DCHECK(download_file->GetDownloadManager()); | 352 DCHECK(download_file->GetDownloadManager()); |
| 354 DownloadManager* download_manager = download_file->GetDownloadManager(); | 353 DownloadManager* download_manager = download_file->GetDownloadManager(); |
| 355 | 354 |
| 356 VLOG(20) << __FUNCTION__ << "()" | 355 VLOG(20) << __FUNCTION__ << "()" |
| 357 << " download_file = " << download_file->DebugString(); | 356 << " download_file = " << download_file->DebugString(); |
| 358 | 357 |
| 359 int uniquifier = 0; | 358 int uniquifier = 0; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 370 if (uniquifier > 0) { | 369 if (uniquifier > 0) { |
| 371 DownloadFile::AppendNumberToPath(&new_path, uniquifier); | 370 DownloadFile::AppendNumberToPath(&new_path, uniquifier); |
| 372 } | 371 } |
| 373 } | 372 } |
| 374 | 373 |
| 375 // Rename the file, overwriting if necessary. | 374 // Rename the file, overwriting if necessary. |
| 376 net::Error rename_error = download_file->Rename(full_path); | 375 net::Error rename_error = download_file->Rename(full_path); |
| 377 if (net::OK != rename_error) { | 376 if (net::OK != rename_error) { |
| 378 // Error. Between the time the UI thread generated 'full_path' to the time | 377 // Error. Between the time the UI thread generated 'full_path' to the time |
| 379 // this code runs, something happened that prevents us from renaming. | 378 // this code runs, something happened that prevents us from renaming. |
| 380 CancelDownloadOnRename(id, rename_error); | 379 CancelDownloadOnRename(global_id, rename_error); |
| 381 return; | 380 return; |
| 382 } | 381 } |
| 383 | 382 |
| 384 #if defined(OS_MACOSX) | 383 #if defined(OS_MACOSX) |
| 385 // Done here because we only want to do this once; see | 384 // Done here because we only want to do this once; see |
| 386 // http://crbug.com/13120 for details. | 385 // http://crbug.com/13120 for details. |
| 387 download_file->AnnotateWithSourceInformation(); | 386 download_file->AnnotateWithSourceInformation(); |
| 388 #endif | 387 #endif |
| 389 | 388 |
| 390 BrowserThread::PostTask( | 389 BrowserThread::PostTask( |
| 391 BrowserThread::UI, FROM_HERE, | 390 BrowserThread::UI, FROM_HERE, |
| 392 NewRunnableMethod( | 391 NewRunnableMethod( |
| 393 download_manager, &DownloadManager::OnDownloadRenamedToFinalName, id, | 392 download_manager, &DownloadManager::OnDownloadRenamedToFinalName, |
| 394 new_path, uniquifier)); | 393 global_id.local(), new_path, uniquifier)); |
| 395 } | 394 } |
| 396 | 395 |
| 397 // Called only from RenameInProgressDownloadFile and | 396 // Called only from RenameInProgressDownloadFile and |
| 398 // RenameCompletingDownloadFile on the FILE thread. | 397 // RenameCompletingDownloadFile on the FILE thread. |
| 399 void DownloadFileManager::CancelDownloadOnRename(int id, | 398 void DownloadFileManager::CancelDownloadOnRename( |
| 400 net::Error rename_error) { | 399 DownloadId global_id, net::Error rename_error) { |
| 401 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 400 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 402 | 401 |
| 403 DownloadFile* download_file = GetDownloadFile(id); | 402 DownloadFile* download_file = GetDownloadFile(global_id); |
| 404 if (!download_file) | 403 if (!download_file) |
| 405 return; | 404 return; |
| 406 | 405 |
| 407 DownloadManager* download_manager = download_file->GetDownloadManager(); | 406 DownloadManager* download_manager = download_file->GetDownloadManager(); |
| 408 if (!download_manager) { | 407 if (!download_manager) { |
| 409 // Without a download manager, we can't cancel the request normally, so we | 408 // Without a download manager, we can't cancel the request normally, so we |
| 410 // need to do it here. The normal path will also update the download | 409 // need to do it here. The normal path will also update the download |
| 411 // history before canceling the request. | 410 // history before canceling the request. |
| 412 download_file->CancelDownloadRequest(); | 411 download_file->CancelDownloadRequest(); |
| 413 return; | 412 return; |
| 414 } | 413 } |
| 415 | 414 |
| 416 BrowserThread::PostTask( | 415 BrowserThread::PostTask( |
| 417 BrowserThread::UI, FROM_HERE, | 416 BrowserThread::UI, FROM_HERE, |
| 418 NewRunnableMethod(download_manager, | 417 NewRunnableMethod(download_manager, |
| 419 &DownloadManager::OnDownloadError, | 418 &DownloadManager::OnDownloadError, |
| 420 id, | 419 global_id.local(), |
| 421 download_file->bytes_so_far(), | 420 download_file->bytes_so_far(), |
| 422 rename_error)); | 421 rename_error)); |
| 423 } | 422 } |
| 424 | 423 |
| 425 void DownloadFileManager::EraseDownload(int id) { | 424 void DownloadFileManager::EraseDownload(DownloadId global_id) { |
| 426 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 425 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 427 | 426 |
| 428 if (!ContainsKey(downloads_, id)) | 427 if (!ContainsKey(downloads_, global_id)) |
| 429 return; | 428 return; |
| 430 | 429 |
| 431 DownloadFile* download_file = downloads_[id]; | 430 DownloadFile* download_file = downloads_[global_id]; |
| 432 | 431 |
| 433 VLOG(20) << " " << __FUNCTION__ << "()" | 432 VLOG(20) << " " << __FUNCTION__ << "()" |
| 434 << " id = " << id | 433 << " id = " << global_id |
| 435 << " download_file = " << download_file->DebugString(); | 434 << " download_file = " << download_file->DebugString(); |
| 436 | 435 |
| 437 downloads_.erase(id); | 436 downloads_.erase(global_id); |
| 438 | 437 |
| 439 delete download_file; | 438 delete download_file; |
| 440 | 439 |
| 441 if (downloads_.empty()) | 440 if (downloads_.empty()) |
| 442 StopUpdateTimer(); | 441 StopUpdateTimer(); |
| 443 } | 442 } |
| OLD | NEW |