Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(92)

Side by Side Diff: chrome/browser/download/download_file_manager.cc

Issue 3127008: Preliminary work on resuming downloads whose connections have expired.
Patch Set: Waiting to send download automation error message until after other downloads are canceled. Created 10 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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/stl_util-inl.h" 8 #include "base/stl_util-inl.h"
9 #include "base/task.h" 9 #include "base/task.h"
10 #include "base/utf_string_conversions.h" 10 #include "base/utf_string_conversions.h"
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 void DownloadFileManager::OnShutdown() { 71 void DownloadFileManager::OnShutdown() {
72 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); 72 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
73 StopUpdateTimer(); 73 StopUpdateTimer();
74 STLDeleteValues(&downloads_); 74 STLDeleteValues(&downloads_);
75 } 75 }
76 76
77 void DownloadFileManager::CreateDownloadFile( 77 void DownloadFileManager::CreateDownloadFile(
78 DownloadCreateInfo* info, DownloadManager* download_manager) { 78 DownloadCreateInfo* info, DownloadManager* download_manager) {
79 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); 79 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
80 80
81 scoped_ptr<DownloadFile> download_file( 81 // See if we are reusing a download ID.
82 new DownloadFile(info, download_manager)); 82 DownloadFile* download_file = NULL;
83 if (!download_file->Initialize()) { 83 if (info->download_id != -1) {
84 ChromeThread::PostTask( 84 DownloadFileMap::iterator item = downloads_.find(info->download_id);
Paweł Hajdan Jr. 2010/10/01 09:03:55 This is wrong, as said (and I think fixed) in http
85 ChromeThread::IO, FROM_HERE, 85 if (item != downloads_.end()) {
86 NewRunnableFunction(&download_util::CancelDownloadRequest, 86 download_file = item->second;
87 resource_dispatcher_host_, 87 download_file->ReOpen();
88 info->child_id, 88 }
89 info->request_id)); 89 }
90 delete info; 90 if (!download_file) {
91 return; 91 download_file = new DownloadFile(info, download_manager);
92 if (!download_file->Initialize()) {
93 ChromeThread::PostTask(
94 ChromeThread::IO,
95 FROM_HERE,
96 NewRunnableFunction(&download_util::CancelDownloadRequest,
97 resource_dispatcher_host_,
98 info->child_id,
99 info->request_id));
100 delete info;
101 return;
102 }
103
104 DCHECK(GetDownloadFile(info->download_id) == NULL);
105 downloads_[info->download_id] = download_file;
92 } 106 }
93 107
94 DCHECK(GetDownloadFile(info->download_id) == NULL);
95 downloads_[info->download_id] = download_file.release();
96 // TODO(phajdan.jr): fix the duplication of path info below. 108 // TODO(phajdan.jr): fix the duplication of path info below.
97 info->path = info->save_info.file_path; 109 info->path = info->save_info.file_path;
98 110
99 // The file is now ready, we can un-pause the request and start saving data. 111 // The file is now ready, we can un-pause the request and start saving data.
100 ChromeThread::PostTask( 112 ChromeThread::PostTask(
101 ChromeThread::IO, FROM_HERE, 113 ChromeThread::IO,
102 NewRunnableMethod(this, &DownloadFileManager::ResumeDownloadRequest, 114 FROM_HERE,
103 info->child_id, info->request_id)); 115 NewRunnableMethod(this,
116 &DownloadFileManager::ResumeDownloadRequest,
117 info->child_id,
118 info->request_id));
104 119
105 StartUpdateTimer(); 120 StartUpdateTimer();
106 121
107 ChromeThread::PostTask( 122 ChromeThread::PostTask(
108 ChromeThread::UI, FROM_HERE, 123 ChromeThread::UI,
124 FROM_HERE,
109 NewRunnableMethod(download_manager, 125 NewRunnableMethod(download_manager,
110 &DownloadManager::StartDownload, info)); 126 &DownloadManager::StartDownload,
127 info));
111 } 128 }
112 129
113 void DownloadFileManager::ResumeDownloadRequest(int child_id, int request_id) { 130 void DownloadFileManager::ResumeDownloadRequest(int child_id, int request_id) {
114 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); 131 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
115 132
116 // This balances the pause in DownloadResourceHandler::OnResponseStarted. 133 // This balances the pause in DownloadResourceHandler::OnResponseStarted.
117 resource_dispatcher_host_->PauseRequest(child_id, request_id, false); 134 resource_dispatcher_host_->PauseRequest(child_id, request_id, false);
118 } 135 }
119 136
120 DownloadFile* DownloadFileManager::GetDownloadFile(int id) { 137 DownloadFile* DownloadFileManager::GetDownloadFile(int id) {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 info->request_id)); 189 info->request_id));
173 delete info; 190 delete info;
174 return; 191 return;
175 } 192 }
176 193
177 ChromeThread::PostTask(ChromeThread::FILE, FROM_HERE, 194 ChromeThread::PostTask(ChromeThread::FILE, FROM_HERE,
178 NewRunnableMethod(this, &DownloadFileManager::CreateDownloadFile, 195 NewRunnableMethod(this, &DownloadFileManager::CreateDownloadFile,
179 info, manager)); 196 info, manager));
180 } 197 }
181 198
199 int DownloadFileManager::GetDownloadId(const GURL& url,
200 const FilePath& path) const {
201 FilePath crpath = download_util::GetCrDownloadPath(path);
202 DownloadFileMap::const_iterator it = downloads_.begin();
203 DownloadFileMap::const_iterator last = downloads_.end();
204 for (; it != last; ++it) {
205 const DownloadFile* download = it->second;
206 if (download && (download->MatchesUrlAndPath(url, crpath)))
207 return download->id();
208 }
209 return -1;
210 }
211
182 // We don't forward an update to the UI thread here, since we want to throttle 212 // We don't forward an update to the UI thread here, since we want to throttle
183 // the UI update rate via a periodic timer. If the user has cancelled the 213 // the UI update rate via a periodic timer. If the user has cancelled the
184 // download (in the UI thread), we may receive a few more updates before the IO 214 // download (in the UI thread), we may receive a few more updates before the IO
185 // thread gets the cancel message: we just delete the data since the 215 // thread gets the cancel message: we just delete the data since the
186 // DownloadFile has been deleted. 216 // DownloadFile has been deleted.
187 void DownloadFileManager::UpdateDownload(int id, DownloadBuffer* buffer) { 217 void DownloadFileManager::UpdateDownload(int id, DownloadBuffer* buffer) {
188 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); 218 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
189 std::vector<DownloadBuffer::Contents> contents; 219 std::vector<DownloadBuffer::Contents> contents;
190 { 220 {
191 AutoLock auto_lock(buffer->lock); 221 AutoLock auto_lock(buffer->lock);
192 contents.swap(buffer->contents); 222 contents.swap(buffer->contents);
193 } 223 }
194 224
195 DownloadFile* download = GetDownloadFile(id); 225 DownloadFile* download = GetDownloadFile(id);
196 for (size_t i = 0; i < contents.size(); ++i) { 226 for (size_t i = 0; i < contents.size(); ++i) {
197 net::IOBuffer* data = contents[i].first; 227 net::IOBuffer* data = contents[i].first;
198 const int data_len = contents[i].second; 228 const int data_len = contents[i].second;
199 if (download) 229 if (download)
200 download->AppendDataToFile(data->data(), data_len); 230 download->AppendDataToFile(data->data(), data_len);
201 data->Release(); 231 data->Release();
202 } 232 }
203 } 233 }
204 234
205 void DownloadFileManager::OnResponseCompleted(int id, DownloadBuffer* buffer) { 235 void DownloadFileManager::OnResponseCompleted(
236 int id,
237 DownloadBuffer* buffer,
238 int os_error,
239 const std::string& security_info) {
206 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); 240 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
207 delete buffer; 241 delete buffer;
208 DownloadFileMap::iterator it = downloads_.find(id); 242 DownloadFile* download = GetDownloadFile(id);
209 if (it != downloads_.end()) { 243 if (download) {
210 DownloadFile* download = it->second; 244 // Closes the file. In the case of an error, it closes the temporary
245 // (.crdownload) one; otherwise it closes the original download file name.
246 DCHECK(!os_error ==
247 !download_util::IsCrDownloadPath(download->full_path()));
211 download->Finish(); 248 download->Finish();
212 249
213 DownloadManager* download_manager = download->GetDownloadManager(); 250 DownloadManager* download_manager = download->GetDownloadManager();
214 if (download_manager) { 251 if (download_manager) {
215 ChromeThread::PostTask( 252 ChromeThread::PostTask(
216 ChromeThread::UI, FROM_HERE, 253 ChromeThread::UI,
254 FROM_HERE,
217 NewRunnableMethod( 255 NewRunnableMethod(
218 download_manager, &DownloadManager::OnAllDataSaved, 256 download_manager,
219 id, download->bytes_so_far())); 257 &DownloadManager::OnResponseCompleted,
258 id,
259 download->bytes_so_far(),
260 os_error));
220 } 261 }
221 262
222 // We need to keep the download around until the UI thread has finalized 263 // We need to keep the download around until the UI thread has finalized
223 // the name. 264 // the name.
224 if (download->path_renamed()) { 265 if (download->path_renamed()) {
225 downloads_.erase(it); 266 downloads_.erase(downloads_.find(id));
226 delete download; 267 delete download;
227 } 268 }
228 } 269 }
229 270
230 if (downloads_.empty()) 271 if (downloads_.empty())
231 StopUpdateTimer(); 272 StopUpdateTimer();
232 } 273 }
233 274
234 // This method will be sent via a user action, or shutdown on the UI thread, and 275 // This method will be sent via a user action, or shutdown on the UI thread, and
235 // run on the download thread. Since this message has been sent from the UI 276 // run on the download thread. Since this message has been sent from the UI
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 downloads_.erase((*i)->id()); 312 downloads_.erase((*i)->id());
272 delete *i; 313 delete *i;
273 } 314 }
274 } 315 }
275 316
276 // Actions from the UI thread and run on the download thread 317 // Actions from the UI thread and run on the download thread
277 318
278 // The DownloadManager in the UI thread has provided an intermediate .crdownload 319 // The DownloadManager in the UI thread has provided an intermediate .crdownload
279 // name for the download specified by 'id'. Rename the in progress download. 320 // name for the download specified by 'id'. Rename the in progress download.
280 void DownloadFileManager::OnIntermediateDownloadName( 321 void DownloadFileManager::OnIntermediateDownloadName(
281 int id, const FilePath& full_path, DownloadManager* download_manager) 322 int id, const FilePath& full_path, DownloadManager* download_manager) {
282 {
283 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); 323 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
284 DownloadFileMap::iterator it = downloads_.find(id); 324 DownloadFileMap::iterator it = downloads_.find(id);
285 if (it == downloads_.end()) 325 if (it == downloads_.end())
286 return; 326 return;
287 327
288 DownloadFile* download = it->second; 328 DownloadFile* download = it->second;
289 if (!download->Rename(full_path, false)) { 329 if (!download->Rename(full_path, false)) {
290 // Error. Between the time the UI thread generated 'full_path' to the time 330 // Error. Between the time the UI thread generated 'full_path' to the time
291 // this code runs, something happened that prevents us from renaming. 331 // this code runs, something happened that prevents us from renaming.
292 CancelDownloadOnRename(id); 332 CancelDownloadOnRename(id);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
357 if (!download_manager) { 397 if (!download_manager) {
358 download->CancelDownloadRequest(resource_dispatcher_host_); 398 download->CancelDownloadRequest(resource_dispatcher_host_);
359 return; 399 return;
360 } 400 }
361 401
362 ChromeThread::PostTask( 402 ChromeThread::PostTask(
363 ChromeThread::UI, FROM_HERE, 403 ChromeThread::UI, FROM_HERE,
364 NewRunnableMethod(download_manager, 404 NewRunnableMethod(download_manager,
365 &DownloadManager::DownloadCancelled, id)); 405 &DownloadManager::DownloadCancelled, id));
366 } 406 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698