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

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

Issue 2805091: Download code cleanup: (Closed)
Patch Set: rebased Created 10 years, 5 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/task.h" 8 #include "base/task.h"
9 #include "base/utf_string_conversions.h" 9 #include "base/utf_string_conversions.h"
10 #include "build/build_config.h" 10 #include "build/build_config.h"
11 #include "chrome/browser/chrome_thread.h" 11 #include "chrome/browser/chrome_thread.h"
12 #include "chrome/browser/download/download_manager.h" 12 #include "chrome/browser/download/download_manager.h"
13 #include "chrome/browser/download/download_util.h"
13 #include "chrome/browser/history/download_types.h" 14 #include "chrome/browser/history/download_types.h"
14 #include "chrome/browser/net/chrome_url_request_context.h" 15 #include "chrome/browser/net/chrome_url_request_context.h"
15 #include "chrome/browser/platform_util.h" 16 #include "chrome/browser/platform_util.h"
16 #include "chrome/browser/profile.h" 17 #include "chrome/browser/profile.h"
17 #include "chrome/browser/renderer_host/resource_dispatcher_host.h" 18 #include "chrome/browser/renderer_host/resource_dispatcher_host.h"
18 #include "chrome/browser/tab_contents/tab_util.h" 19 #include "chrome/browser/tab_contents/tab_util.h"
19 #include "chrome/browser/tab_contents/tab_contents.h" 20 #include "chrome/browser/tab_contents/tab_contents.h"
20 #include "googleurl/src/gurl.h" 21 #include "googleurl/src/gurl.h"
21 22
22 #if defined(OS_WIN) 23 #if defined(OS_WIN)
(...skipping 12 matching lines...) Expand all
35 } // namespace 36 } // namespace
36 37
37 DownloadFileManager::DownloadFileManager(ResourceDispatcherHost* rdh) 38 DownloadFileManager::DownloadFileManager(ResourceDispatcherHost* rdh)
38 : next_id_(0), 39 : next_id_(0),
39 resource_dispatcher_host_(rdh) { 40 resource_dispatcher_host_(rdh) {
40 } 41 }
41 42
42 DownloadFileManager::~DownloadFileManager() { 43 DownloadFileManager::~DownloadFileManager() {
43 // Check for clean shutdown. 44 // Check for clean shutdown.
44 DCHECK(downloads_.empty()); 45 DCHECK(downloads_.empty());
45 ui_progress_.clear();
46 } 46 }
47 47
48 // Called during the browser shutdown process to clean up any state (open files, 48 // Called during the browser shutdown process to clean up any state (open files,
49 // timers) that live on the download_thread_. 49 // timers) that live on the download_thread_.
50 void DownloadFileManager::Shutdown() { 50 void DownloadFileManager::Shutdown() {
51 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 51 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
52 StopUpdateTimer(); 52 StopUpdateTimer();
53 ChromeThread::PostTask( 53 ChromeThread::PostTask(
54 ChromeThread::FILE, FROM_HERE, 54 ChromeThread::FILE, FROM_HERE,
55 NewRunnableMethod(this, &DownloadFileManager::OnShutdown)); 55 NewRunnableMethod(this, &DownloadFileManager::OnShutdown));
56 } 56 }
57 57
58 // Cease download thread operations. 58 // Cease download thread operations.
59 void DownloadFileManager::OnShutdown() { 59 void DownloadFileManager::OnShutdown() {
60 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); 60 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
61 // Delete any partial downloads during shutdown. 61 // Delete any partial downloads during shutdown.
62 for (DownloadFileMap::iterator it = downloads_.begin(); 62 for (DownloadFileMap::iterator it = downloads_.begin();
63 it != downloads_.end(); ++it) { 63 it != downloads_.end(); ++it) {
64 DownloadFile* download = it->second; 64 DownloadFile* download = it->second;
65 if (download->in_progress()) 65 if (download->in_progress())
66 download->Cancel(); 66 download->Cancel();
67 delete download; 67 delete download;
68 } 68 }
69 downloads_.clear(); 69 downloads_.clear();
70 } 70 }
71 71
72 // Initiate a request for URL to be downloaded. Called from UI thread,
73 // runs on IO thread.
74 void DownloadFileManager::OnDownloadUrl(
75 const GURL& url,
76 const GURL& referrer,
77 const std::string& referrer_charset,
78 const DownloadSaveInfo& save_info,
79 int render_process_host_id,
80 int render_view_id,
81 URLRequestContextGetter* request_context_getter) {
82 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
83
84 URLRequestContext* context = request_context_getter->GetURLRequestContext();
85 context->set_referrer_charset(referrer_charset);
86
87 // Show "Save As" UI.
88 bool prompt_for_save_location = true;
89 resource_dispatcher_host_->BeginDownload(url,
90 referrer,
91 save_info,
92 prompt_for_save_location,
93 render_process_host_id,
94 render_view_id,
95 context);
96 }
97
98 // Notifications sent from the download thread and run on the UI thread. 72 // Notifications sent from the download thread and run on the UI thread.
99 73
100 // Lookup the DownloadManager for this TabContents' profile and inform it of 74 // Lookup the DownloadManager for this TabContents' profile and inform it of
101 // a new download. 75 // a new download.
102 // TODO(paulg): When implementing download restart via the Downloads tab, 76 // TODO(paulg): When implementing download restart via the Downloads tab,
103 // there will be no 'render_process_id' or 'render_view_id'. 77 // there will be no 'render_process_id' or 'render_view_id'.
104 void DownloadFileManager::OnStartDownload(DownloadCreateInfo* info) { 78 void DownloadFileManager::OnStartDownload(DownloadCreateInfo* info) {
105 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 79 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
106 DownloadManager* manager = DownloadManagerFromRenderIds(info->child_id, 80 DownloadManager* manager = DownloadManagerFromRenderIds(info->child_id,
107 info->render_view_id); 81 info->render_view_id);
108 if (!manager) { 82 if (!manager) {
109 ChromeThread::PostTask( 83 ChromeThread::PostTask(
110 ChromeThread::IO, FROM_HERE, 84 ChromeThread::IO, FROM_HERE,
111 NewRunnableFunction(&DownloadManager::OnCancelDownloadRequest, 85 NewRunnableFunction(&download_util::CancelDownloadRequest,
112 resource_dispatcher_host_, 86 resource_dispatcher_host_,
113 info->child_id, 87 info->child_id,
114 info->request_id)); 88 info->request_id));
115 delete info; 89 delete info;
116 return; 90 return;
117 } 91 }
118 92
119 StartUpdateTimer(); 93 StartUpdateTimer();
120 94
121 // Add the download manager to our request maps for future updates. We want to 95 // Add the download manager to our request maps for future updates. We want to
(...skipping 14 matching lines...) Expand all
136 110
137 // StartDownload will clean up |info|. 111 // StartDownload will clean up |info|.
138 manager->StartDownload(info); 112 manager->StartDownload(info);
139 } 113 }
140 114
141 // Update the Download Manager with the finish state, and remove the request 115 // Update the Download Manager with the finish state, and remove the request
142 // tracking entries. 116 // tracking entries.
143 void DownloadFileManager::OnDownloadFinished(int id, 117 void DownloadFileManager::OnDownloadFinished(int id,
144 int64 bytes_so_far) { 118 int64 bytes_so_far) {
145 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 119 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
146 DownloadManager* manager = LookupManager(id); 120 DownloadManager* manager = GetDownloadManager(id);
147 if (manager) 121 if (manager)
148 manager->DownloadFinished(id, bytes_so_far); 122 manager->DownloadFinished(id, bytes_so_far);
149 RemoveDownload(id, manager); 123 RemoveDownload(id, manager);
150 RemoveDownloadFromUIProgress(id); 124 RemoveDownloadFromUIProgress(id);
151 } 125 }
152 126
153 // Lookup one in-progress download. 127 // Lookup one in-progress download.
154 DownloadFile* DownloadFileManager::LookupDownload(int id) { 128 DownloadFile* DownloadFileManager::GetDownloadFile(int id) {
155 DownloadFileMap::iterator it = downloads_.find(id); 129 DownloadFileMap::iterator it = downloads_.find(id);
156 return it == downloads_.end() ? NULL : it->second; 130 return it == downloads_.end() ? NULL : it->second;
157 } 131 }
158 132
159 // The UI progress is updated on the file thread and removed on the UI thread. 133 // The UI progress is updated on the file thread and removed on the UI thread.
160 void DownloadFileManager::RemoveDownloadFromUIProgress(int id) { 134 void DownloadFileManager::RemoveDownloadFromUIProgress(int id) {
161 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 135 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
162 AutoLock lock(progress_lock_); 136 AutoLock lock(progress_lock_);
163 if (ui_progress_.find(id) != ui_progress_.end()) 137 if (ui_progress_.find(id) != ui_progress_.end())
164 ui_progress_.erase(id); 138 ui_progress_.erase(id);
(...skipping 15 matching lines...) Expand all
180 } 154 }
181 155
182 // Our periodic timer has fired so send the UI thread updates on all in progress 156 // Our periodic timer has fired so send the UI thread updates on all in progress
183 // downloads. 157 // downloads.
184 void DownloadFileManager::UpdateInProgressDownloads() { 158 void DownloadFileManager::UpdateInProgressDownloads() {
185 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 159 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
186 AutoLock lock(progress_lock_); 160 AutoLock lock(progress_lock_);
187 ProgressMap::iterator it = ui_progress_.begin(); 161 ProgressMap::iterator it = ui_progress_.begin();
188 for (; it != ui_progress_.end(); ++it) { 162 for (; it != ui_progress_.end(); ++it) {
189 const int id = it->first; 163 const int id = it->first;
190 DownloadManager* manager = LookupManager(id); 164 DownloadManager* manager = GetDownloadManager(id);
191 if (manager) 165 if (manager)
192 manager->UpdateDownload(id, it->second); 166 manager->UpdateDownload(id, it->second);
193 } 167 }
194 } 168 }
195 169
196 // Called on the IO thread once the ResourceDispatcherHost has decided that a 170 // Called on the IO thread once the ResourceDispatcherHost has decided that a
197 // request is a download. 171 // request is a download.
198 int DownloadFileManager::GetNextId() { 172 int DownloadFileManager::GetNextId() {
199 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); 173 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
200 return next_id_++; 174 return next_id_++;
201 } 175 }
202 176
203 // Notifications sent from the IO thread and run on the download thread: 177 // Notifications sent from the IO thread and run on the download thread:
204 178
205 // The IO thread created 'info', but the download thread (this method) uses it 179 // The IO thread created 'info', but the download thread (this method) uses it
206 // to create a DownloadFile, then passes 'info' to the UI thread where it is 180 // to create a DownloadFile, then passes 'info' to the UI thread where it is
207 // finally consumed and deleted. 181 // finally consumed and deleted.
208 void DownloadFileManager::StartDownload(DownloadCreateInfo* info) { 182 void DownloadFileManager::StartDownload(DownloadCreateInfo* info) {
209 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); 183 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
210 DCHECK(info); 184 DCHECK(info);
211 185
212 DownloadFile* download = new DownloadFile(info); 186 DownloadFile* download = new DownloadFile(info);
213 if (!download->Initialize()) { 187 if (!download->Initialize()) {
214 // Couldn't open, cancel the operation. The UI thread does not yet know 188 // Couldn't open, cancel the operation. The UI thread does not yet know
215 // about this download so we have to clean up 'info'. We need to get back 189 // about this download so we have to clean up 'info'. We need to get back
216 // to the IO thread to cancel the network request and CancelDownloadRequest 190 // to the IO thread to cancel the network request and CancelDownloadRequest
217 // on the UI thread is the safe way to do that. 191 // on the UI thread is the safe way to do that.
218 ChromeThread::PostTask( 192 ChromeThread::PostTask(
219 ChromeThread::IO, FROM_HERE, 193 ChromeThread::IO, FROM_HERE,
220 NewRunnableFunction(&DownloadManager::OnCancelDownloadRequest, 194 NewRunnableFunction(&download_util::CancelDownloadRequest,
221 resource_dispatcher_host_, 195 resource_dispatcher_host_,
222 info->child_id, 196 info->child_id,
223 info->request_id)); 197 info->request_id));
224 delete info; 198 delete info;
225 delete download; 199 delete download;
226 return; 200 return;
227 } 201 }
228 202
229 DCHECK(LookupDownload(info->download_id) == NULL); 203 DCHECK(GetDownloadFile(info->download_id) == NULL);
230 downloads_[info->download_id] = download; 204 downloads_[info->download_id] = download;
231 info->path = download->full_path(); 205 info->path = download->full_path();
232 { 206 {
233 AutoLock lock(progress_lock_); 207 AutoLock lock(progress_lock_);
234 ui_progress_[info->download_id] = info->received_bytes; 208 ui_progress_[info->download_id] = info->received_bytes;
235 } 209 }
236 210
237 ChromeThread::PostTask( 211 ChromeThread::PostTask(
238 ChromeThread::UI, FROM_HERE, 212 ChromeThread::UI, FROM_HERE,
239 NewRunnableMethod(this, &DownloadFileManager::OnStartDownload, info)); 213 NewRunnableMethod(this, &DownloadFileManager::OnStartDownload, info));
240 } 214 }
241 215
242 // We don't forward an update to the UI thread here, since we want to throttle 216 // We don't forward an update to the UI thread here, since we want to throttle
243 // the UI update rate via a periodic timer. If the user has cancelled the 217 // the UI update rate via a periodic timer. If the user has cancelled the
244 // download (in the UI thread), we may receive a few more updates before the IO 218 // download (in the UI thread), we may receive a few more updates before the IO
245 // thread gets the cancel message: we just delete the data since the 219 // thread gets the cancel message: we just delete the data since the
246 // DownloadFile has been deleted. 220 // DownloadFile has been deleted.
247 void DownloadFileManager::UpdateDownload(int id, DownloadBuffer* buffer) { 221 void DownloadFileManager::UpdateDownload(int id, DownloadBuffer* buffer) {
248 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); 222 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
249 std::vector<DownloadBuffer::Contents> contents; 223 std::vector<DownloadBuffer::Contents> contents;
250 { 224 {
251 AutoLock auto_lock(buffer->lock); 225 AutoLock auto_lock(buffer->lock);
252 contents.swap(buffer->contents); 226 contents.swap(buffer->contents);
253 } 227 }
254 228
255 DownloadFile* download = LookupDownload(id); 229 DownloadFile* download = GetDownloadFile(id);
256 for (size_t i = 0; i < contents.size(); ++i) { 230 for (size_t i = 0; i < contents.size(); ++i) {
257 net::IOBuffer* data = contents[i].first; 231 net::IOBuffer* data = contents[i].first;
258 const int data_len = contents[i].second; 232 const int data_len = contents[i].second;
259 if (download) 233 if (download)
260 download->AppendDataToFile(data->data(), data_len); 234 download->AppendDataToFile(data->data(), data_len);
261 data->Release(); 235 data->Release();
262 } 236 }
263 237
264 if (download) { 238 if (download) {
265 AutoLock lock(progress_lock_); 239 AutoLock lock(progress_lock_);
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 } 293 }
320 } 294 }
321 295
322 if (downloads_.empty()) { 296 if (downloads_.empty()) {
323 ChromeThread::PostTask( 297 ChromeThread::PostTask(
324 ChromeThread::UI, FROM_HERE, 298 ChromeThread::UI, FROM_HERE,
325 NewRunnableMethod(this, &DownloadFileManager::StopUpdateTimer)); 299 NewRunnableMethod(this, &DownloadFileManager::StopUpdateTimer));
326 } 300 }
327 } 301 }
328 302
329 void DownloadFileManager::DownloadUrl(
330 const GURL& url,
331 const GURL& referrer,
332 const std::string& referrer_charset,
333 const DownloadSaveInfo& save_info,
334 int render_process_host_id,
335 int render_view_id,
336 URLRequestContextGetter* request_context_getter) {
337 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
338 ChromeThread::PostTask(
339 ChromeThread::IO, FROM_HERE,
340 NewRunnableMethod(this,
341 &DownloadFileManager::OnDownloadUrl,
342 url,
343 referrer,
344 referrer_charset,
345 save_info,
346 render_process_host_id,
347 render_view_id,
348 request_context_getter));
349 }
350
351 // Relate a download ID to its owning DownloadManager. 303 // Relate a download ID to its owning DownloadManager.
352 DownloadManager* DownloadFileManager::LookupManager(int download_id) { 304 DownloadManager* DownloadFileManager::GetDownloadManager(int download_id) {
353 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 305 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
354 DownloadManagerMap::iterator it = managers_.find(download_id); 306 DownloadManagerMap::iterator it = managers_.find(download_id);
355 if (it != managers_.end()) 307 if (it != managers_.end())
356 return it->second; 308 return it->second;
357 return NULL; 309 return NULL;
358 } 310 }
359 311
360 // Utility function for look up table maintenance, called on the UI thread. 312 // Utility function for look up table maintenance, called on the UI thread.
361 // A manager may have multiple downloads in progress, so we just look up the 313 // A manager may have multiple downloads in progress, so we just look up the
362 // one download (id) and remove it from the set, and remove the set if it 314 // one download (id) and remove it from the set, and remove the set if it
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 // this code runs, something happened that prevents us from renaming. 432 // this code runs, something happened that prevents us from renaming.
481 DownloadManagerMap::iterator dmit = managers_.find(download->id()); 433 DownloadManagerMap::iterator dmit = managers_.find(download->id());
482 if (dmit != managers_.end()) { 434 if (dmit != managers_.end()) {
483 DownloadManager* dlm = dmit->second; 435 DownloadManager* dlm = dmit->second;
484 ChromeThread::PostTask( 436 ChromeThread::PostTask(
485 ChromeThread::UI, FROM_HERE, 437 ChromeThread::UI, FROM_HERE,
486 NewRunnableMethod(dlm, &DownloadManager::DownloadCancelled, id)); 438 NewRunnableMethod(dlm, &DownloadManager::DownloadCancelled, id));
487 } else { 439 } else {
488 ChromeThread::PostTask( 440 ChromeThread::PostTask(
489 ChromeThread::IO, FROM_HERE, 441 ChromeThread::IO, FROM_HERE,
490 NewRunnableFunction(&DownloadManager::OnCancelDownloadRequest, 442 NewRunnableFunction(&download_util::CancelDownloadRequest,
491 resource_dispatcher_host_, 443 resource_dispatcher_host_,
492 download->child_id(), 444 download->child_id(),
493 download->request_id())); 445 download->request_id()));
494 } 446 }
495 } 447 }
496 448
497 // If the download has completed before we got this final name, we remove it 449 // If the download has completed before we got this final name, we remove it
498 // from our in progress map. 450 // from our in progress map.
499 if (!download->in_progress()) { 451 if (!download->in_progress()) {
500 downloads_.erase(it); 452 downloads_.erase(it);
501 delete download; 453 delete download;
502 } 454 }
503 455
504 if (downloads_.empty()) { 456 if (downloads_.empty()) {
505 ChromeThread::PostTask( 457 ChromeThread::PostTask(
506 ChromeThread::UI, FROM_HERE, 458 ChromeThread::UI, FROM_HERE,
507 NewRunnableMethod(this, &DownloadFileManager::StopUpdateTimer)); 459 NewRunnableMethod(this, &DownloadFileManager::StopUpdateTimer));
508 } 460 }
509 } 461 }
510 462
OLDNEW
« no previous file with comments | « chrome/browser/download/download_file_manager.h ('k') | chrome/browser/download/download_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698