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

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

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

Powered by Google App Engine
This is Rietveld 408576698