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

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

Issue 342020: First of several patches to get rid of MessageLoop caching now that we have C... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 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) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 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.h" 5 #include "chrome/browser/download/download_file.h"
6 6
7 #include "base/file_util.h" 7 #include "base/file_util.h"
8 #include "base/path_service.h" 8 #include "base/path_service.h"
9 #include "base/stl_util-inl.h" 9 #include "base/stl_util-inl.h"
10 #include "base/string_util.h" 10 #include "base/string_util.h"
11 #include "base/task.h" 11 #include "base/task.h"
12 #include "base/thread.h" 12 #include "base/thread.h"
13 #include "build/build_config.h" 13 #include "build/build_config.h"
14 #include "chrome/browser/browser_process.h" 14 #include "chrome/browser/chrome_thread.h"
15 #include "chrome/browser/download/download_manager.h" 15 #include "chrome/browser/download/download_manager.h"
16 #include "chrome/browser/net/chrome_url_request_context.h" 16 #include "chrome/browser/net/chrome_url_request_context.h"
17 #include "chrome/browser/profile.h" 17 #include "chrome/browser/profile.h"
18 #include "chrome/browser/renderer_host/resource_dispatcher_host.h" 18 #include "chrome/browser/renderer_host/resource_dispatcher_host.h"
19 #include "chrome/browser/tab_contents/tab_util.h" 19 #include "chrome/browser/tab_contents/tab_util.h"
20 #include "chrome/browser/tab_contents/tab_contents.h" 20 #include "chrome/browser/tab_contents/tab_contents.h"
21 #include "chrome/common/chrome_paths.h" 21 #include "chrome/common/chrome_paths.h"
22 #include "chrome/common/platform_util.h" 22 #include "chrome/common/platform_util.h"
23 #include "googleurl/src/gurl.h" 23 #include "googleurl/src/gurl.h"
24 #include "net/base/io_buffer.h" 24 #include "net/base/io_buffer.h"
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 #elif defined(OS_MACOSX) 152 #elif defined(OS_MACOSX)
153 file_metadata::AddQuarantineMetadataToFile(full_path_, source_url_, 153 file_metadata::AddQuarantineMetadataToFile(full_path_, source_url_,
154 referrer_url_); 154 referrer_url_);
155 file_metadata::AddOriginMetadataToFile(full_path_, source_url_, 155 file_metadata::AddOriginMetadataToFile(full_path_, source_url_,
156 referrer_url_); 156 referrer_url_);
157 #endif 157 #endif
158 } 158 }
159 159
160 // DownloadFileManager implementation ------------------------------------------ 160 // DownloadFileManager implementation ------------------------------------------
161 161
162 DownloadFileManager::DownloadFileManager(MessageLoop* ui_loop, 162 DownloadFileManager::DownloadFileManager(ResourceDispatcherHost* rdh)
163 ResourceDispatcherHost* rdh)
164 : next_id_(0), 163 : next_id_(0),
165 ui_loop_(ui_loop),
166 file_loop_(NULL),
167 io_loop_(NULL),
168 resource_dispatcher_host_(rdh) { 164 resource_dispatcher_host_(rdh) {
169 } 165 }
170 166
171 DownloadFileManager::~DownloadFileManager() { 167 DownloadFileManager::~DownloadFileManager() {
172 // Check for clean shutdown. 168 // Check for clean shutdown.
173 DCHECK(downloads_.empty()); 169 DCHECK(downloads_.empty());
174 ui_progress_.clear(); 170 ui_progress_.clear();
175 } 171 }
176 172
177 void DownloadFileManager::Initialize() {
178 io_loop_ = g_browser_process->io_thread()->message_loop();
179 file_loop_ = g_browser_process->file_thread()->message_loop();
180 }
181
182 // Called during the browser shutdown process to clean up any state (open files, 173 // Called during the browser shutdown process to clean up any state (open files,
183 // timers) that live on the download_thread_. 174 // timers) that live on the download_thread_.
184 void DownloadFileManager::Shutdown() { 175 void DownloadFileManager::Shutdown() {
185 DCHECK(MessageLoop::current() == ui_loop_); 176 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
186 StopUpdateTimer(); 177 StopUpdateTimer();
187 file_loop_->PostTask(FROM_HERE, 178 ChromeThread::PostTask(
188 NewRunnableMethod(this, 179 ChromeThread::FILE, FROM_HERE,
189 &DownloadFileManager::OnShutdown)); 180 NewRunnableMethod(this, &DownloadFileManager::OnShutdown));
190 } 181 }
191 182
192 // Cease download thread operations. 183 // Cease download thread operations.
193 void DownloadFileManager::OnShutdown() { 184 void DownloadFileManager::OnShutdown() {
194 DCHECK(MessageLoop::current() == file_loop_); 185 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
195 // Delete any partial downloads during shutdown. 186 // Delete any partial downloads during shutdown.
196 for (DownloadFileMap::iterator it = downloads_.begin(); 187 for (DownloadFileMap::iterator it = downloads_.begin();
197 it != downloads_.end(); ++it) { 188 it != downloads_.end(); ++it) {
198 DownloadFile* download = it->second; 189 DownloadFile* download = it->second;
199 if (download->in_progress()) 190 if (download->in_progress())
200 download->Cancel(); 191 download->Cancel();
201 delete download; 192 delete download;
202 } 193 }
203 downloads_.clear(); 194 downloads_.clear();
204 } 195 }
205 196
206 // Lookup one in-progress download. 197 // Lookup one in-progress download.
207 DownloadFile* DownloadFileManager::LookupDownload(int id) { 198 DownloadFile* DownloadFileManager::LookupDownload(int id) {
208 DownloadFileMap::iterator it = downloads_.find(id); 199 DownloadFileMap::iterator it = downloads_.find(id);
209 return it == downloads_.end() ? NULL : it->second; 200 return it == downloads_.end() ? NULL : it->second;
210 } 201 }
211 202
212 // The UI progress is updated on the file thread and removed on the UI thread. 203 // The UI progress is updated on the file thread and removed on the UI thread.
213 void DownloadFileManager::RemoveDownloadFromUIProgress(int id) { 204 void DownloadFileManager::RemoveDownloadFromUIProgress(int id) {
214 DCHECK(MessageLoop::current() == ui_loop_); 205 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
215 AutoLock lock(progress_lock_); 206 AutoLock lock(progress_lock_);
216 if (ui_progress_.find(id) != ui_progress_.end()) 207 if (ui_progress_.find(id) != ui_progress_.end())
217 ui_progress_.erase(id); 208 ui_progress_.erase(id);
218 } 209 }
219 210
220 // Throttle updates to the UI thread by only posting update notifications at a 211 // Throttle updates to the UI thread by only posting update notifications at a
221 // regularly controlled interval. 212 // regularly controlled interval.
222 void DownloadFileManager::StartUpdateTimer() { 213 void DownloadFileManager::StartUpdateTimer() {
223 DCHECK(MessageLoop::current() == ui_loop_); 214 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
224 if (!update_timer_.IsRunning()) { 215 if (!update_timer_.IsRunning()) {
225 update_timer_.Start(base::TimeDelta::FromMilliseconds(kUpdatePeriodMs), 216 update_timer_.Start(base::TimeDelta::FromMilliseconds(kUpdatePeriodMs),
226 this, &DownloadFileManager::UpdateInProgressDownloads); 217 this, &DownloadFileManager::UpdateInProgressDownloads);
227 } 218 }
228 } 219 }
229 220
230 void DownloadFileManager::StopUpdateTimer() { 221 void DownloadFileManager::StopUpdateTimer() {
231 DCHECK(MessageLoop::current() == ui_loop_); 222 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
232 update_timer_.Stop(); 223 update_timer_.Stop();
233 } 224 }
234 225
235 // Called on the IO thread once the ResourceDispatcherHost has decided that a 226 // Called on the IO thread once the ResourceDispatcherHost has decided that a
236 // request is a download. 227 // request is a download.
237 int DownloadFileManager::GetNextId() { 228 int DownloadFileManager::GetNextId() {
238 DCHECK(MessageLoop::current() == io_loop_); 229 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
239 return next_id_++; 230 return next_id_++;
240 } 231 }
241 232
242 // Notifications sent from the IO thread and run on the download thread: 233 // Notifications sent from the IO thread and run on the download thread:
243 234
244 // The IO thread created 'info', but the download thread (this method) uses it 235 // The IO thread created 'info', but the download thread (this method) uses it
245 // to create a DownloadFile, then passes 'info' to the UI thread where it is 236 // to create a DownloadFile, then passes 'info' to the UI thread where it is
246 // finally consumed and deleted. 237 // finally consumed and deleted.
247 void DownloadFileManager::StartDownload(DownloadCreateInfo* info) { 238 void DownloadFileManager::StartDownload(DownloadCreateInfo* info) {
248 DCHECK(MessageLoop::current() == file_loop_); 239 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
249 DCHECK(info); 240 DCHECK(info);
250 241
251 DownloadFile* download = new DownloadFile(info); 242 DownloadFile* download = new DownloadFile(info);
252 if (!download->Initialize()) { 243 if (!download->Initialize()) {
253 // Couldn't open, cancel the operation. The UI thread does not yet know 244 // Couldn't open, cancel the operation. The UI thread does not yet know
254 // about this download so we have to clean up 'info'. We need to get back 245 // about this download so we have to clean up 'info'. We need to get back
255 // to the IO thread to cancel the network request and CancelDownloadRequest 246 // to the IO thread to cancel the network request and CancelDownloadRequest
256 // on the UI thread is the safe way to do that. 247 // on the UI thread is the safe way to do that.
257 ChromeThread::PostTask( 248 ChromeThread::PostTask(
258 ChromeThread::IO, FROM_HERE, 249 ChromeThread::IO, FROM_HERE,
259 NewRunnableFunction(&DownloadManager::OnCancelDownloadRequest, 250 NewRunnableFunction(&DownloadManager::OnCancelDownloadRequest,
260 resource_dispatcher_host_, 251 resource_dispatcher_host_,
261 info->child_id, 252 info->child_id,
262 info->request_id)); 253 info->request_id));
263 delete info; 254 delete info;
264 delete download; 255 delete download;
265 return; 256 return;
266 } 257 }
267 258
268 DCHECK(LookupDownload(info->download_id) == NULL); 259 DCHECK(LookupDownload(info->download_id) == NULL);
269 downloads_[info->download_id] = download; 260 downloads_[info->download_id] = download;
270 info->path = download->full_path(); 261 info->path = download->full_path();
271 { 262 {
272 AutoLock lock(progress_lock_); 263 AutoLock lock(progress_lock_);
273 ui_progress_[info->download_id] = info->received_bytes; 264 ui_progress_[info->download_id] = info->received_bytes;
274 } 265 }
275 266
276 ui_loop_->PostTask(FROM_HERE, 267 ChromeThread::PostTask(
277 NewRunnableMethod(this, 268 ChromeThread::UI, FROM_HERE,
278 &DownloadFileManager::OnStartDownload, 269 NewRunnableMethod(this, &DownloadFileManager::OnStartDownload, info));
279 info));
280 } 270 }
281 271
282 // We don't forward an update to the UI thread here, since we want to throttle 272 // We don't forward an update to the UI thread here, since we want to throttle
283 // the UI update rate via a periodic timer. If the user has cancelled the 273 // the UI update rate via a periodic timer. If the user has cancelled the
284 // download (in the UI thread), we may receive a few more updates before the IO 274 // download (in the UI thread), we may receive a few more updates before the IO
285 // thread gets the cancel message: we just delete the data since the 275 // thread gets the cancel message: we just delete the data since the
286 // DownloadFile has been deleted. 276 // DownloadFile has been deleted.
287 void DownloadFileManager::UpdateDownload(int id, DownloadBuffer* buffer) { 277 void DownloadFileManager::UpdateDownload(int id, DownloadBuffer* buffer) {
288 DCHECK(MessageLoop::current() == file_loop_); 278 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
289 std::vector<DownloadBuffer::Contents> contents; 279 std::vector<DownloadBuffer::Contents> contents;
290 { 280 {
291 AutoLock auto_lock(buffer->lock); 281 AutoLock auto_lock(buffer->lock);
292 contents.swap(buffer->contents); 282 contents.swap(buffer->contents);
293 } 283 }
294 284
295 DownloadFile* download = LookupDownload(id); 285 DownloadFile* download = LookupDownload(id);
296 for (size_t i = 0; i < contents.size(); ++i) { 286 for (size_t i = 0; i < contents.size(); ++i) {
297 net::IOBuffer* data = contents[i].first; 287 net::IOBuffer* data = contents[i].first;
298 const int data_len = contents[i].second; 288 const int data_len = contents[i].second;
299 if (download) 289 if (download)
300 download->AppendDataToFile(data->data(), data_len); 290 download->AppendDataToFile(data->data(), data_len);
301 data->Release(); 291 data->Release();
302 } 292 }
303 293
304 if (download) { 294 if (download) {
305 AutoLock lock(progress_lock_); 295 AutoLock lock(progress_lock_);
306 ui_progress_[download->id()] = download->bytes_so_far(); 296 ui_progress_[download->id()] = download->bytes_so_far();
307 } 297 }
308 } 298 }
309 299
310 void DownloadFileManager::DownloadFinished(int id, DownloadBuffer* buffer) { 300 void DownloadFileManager::DownloadFinished(int id, DownloadBuffer* buffer) {
311 DCHECK(MessageLoop::current() == file_loop_); 301 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
312 delete buffer; 302 delete buffer;
313 DownloadFileMap::iterator it = downloads_.find(id); 303 DownloadFileMap::iterator it = downloads_.find(id);
314 if (it != downloads_.end()) { 304 if (it != downloads_.end()) {
315 DownloadFile* download = it->second; 305 DownloadFile* download = it->second;
316 download->set_in_progress(false); 306 download->set_in_progress(false);
317 307
318 ui_loop_->PostTask(FROM_HERE, 308 ChromeThread::PostTask(
319 NewRunnableMethod(this, 309 ChromeThread::UI, FROM_HERE,
320 &DownloadFileManager::OnDownloadFinished, 310 NewRunnableMethod(
321 id, 311 this, &DownloadFileManager::OnDownloadFinished,
322 download->bytes_so_far())); 312 id, download->bytes_so_far()));
323 313
324 // We need to keep the download around until the UI thread has finalized 314 // We need to keep the download around until the UI thread has finalized
325 // the name. 315 // the name.
326 if (download->path_renamed()) { 316 if (download->path_renamed()) {
327 downloads_.erase(it); 317 downloads_.erase(it);
328 delete download; 318 delete download;
329 } 319 }
330 } 320 }
331 321
332 if (downloads_.empty()) 322 if (downloads_.empty())
333 ui_loop_->PostTask(FROM_HERE, NewRunnableMethod( 323 ChromeThread::PostTask(
334 this, &DownloadFileManager::StopUpdateTimer)); 324 ChromeThread::UI, FROM_HERE,
325 NewRunnableMethod(this, &DownloadFileManager::StopUpdateTimer));
335 } 326 }
336 327
337 // This method will be sent via a user action, or shutdown on the UI thread, and 328 // This method will be sent via a user action, or shutdown on the UI thread, and
338 // run on the download thread. Since this message has been sent from the UI 329 // run on the download thread. Since this message has been sent from the UI
339 // thread, the download may have already completed and won't exist in our map. 330 // thread, the download may have already completed and won't exist in our map.
340 void DownloadFileManager::CancelDownload(int id) { 331 void DownloadFileManager::CancelDownload(int id) {
341 DCHECK(MessageLoop::current() == file_loop_); 332 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
342 DownloadFileMap::iterator it = downloads_.find(id); 333 DownloadFileMap::iterator it = downloads_.find(id);
343 if (it != downloads_.end()) { 334 if (it != downloads_.end()) {
344 DownloadFile* download = it->second; 335 DownloadFile* download = it->second;
345 download->set_in_progress(false); 336 download->set_in_progress(false);
346 337
347 download->Cancel(); 338 download->Cancel();
348 339
349 ui_loop_->PostTask(FROM_HERE, 340 ChromeThread::PostTask(
350 NewRunnableMethod(this, 341 ChromeThread::UI, FROM_HERE,
351 &DownloadFileManager::RemoveDownloadFromUIProgress, 342 NewRunnableMethod(
352 download->id())); 343 this, &DownloadFileManager::RemoveDownloadFromUIProgress,
344 download->id()));
353 345
354 if (download->path_renamed()) { 346 if (download->path_renamed()) {
355 downloads_.erase(it); 347 downloads_.erase(it);
356 delete download; 348 delete download;
357 } 349 }
358 } 350 }
359 351
360 if (downloads_.empty()) 352 if (downloads_.empty()) {
361 ui_loop_->PostTask(FROM_HERE, NewRunnableMethod( 353 ChromeThread::PostTask(
362 this, &DownloadFileManager::StopUpdateTimer)); 354 ChromeThread::UI, FROM_HERE,
355 NewRunnableMethod(this, &DownloadFileManager::StopUpdateTimer));
356 }
363 } 357 }
364 358
365 // Our periodic timer has fired so send the UI thread updates on all in progress 359 // Our periodic timer has fired so send the UI thread updates on all in progress
366 // downloads. 360 // downloads.
367 void DownloadFileManager::UpdateInProgressDownloads() { 361 void DownloadFileManager::UpdateInProgressDownloads() {
368 DCHECK(MessageLoop::current() == ui_loop_); 362 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
369 AutoLock lock(progress_lock_); 363 AutoLock lock(progress_lock_);
370 ProgressMap::iterator it = ui_progress_.begin(); 364 ProgressMap::iterator it = ui_progress_.begin();
371 for (; it != ui_progress_.end(); ++it) { 365 for (; it != ui_progress_.end(); ++it) {
372 const int id = it->first; 366 const int id = it->first;
373 DownloadManager* manager = LookupManager(id); 367 DownloadManager* manager = LookupManager(id);
374 if (manager) 368 if (manager)
375 manager->UpdateDownload(id, it->second); 369 manager->UpdateDownload(id, it->second);
376 } 370 }
377 } 371 }
378 372
379 // Notifications sent from the download thread and run on the UI thread. 373 // Notifications sent from the download thread and run on the UI thread.
380 374
381 // Lookup the DownloadManager for this TabContents' profile and inform it of 375 // Lookup the DownloadManager for this TabContents' profile and inform it of
382 // a new download. 376 // a new download.
383 // TODO(paulg): When implementing download restart via the Downloads tab, 377 // TODO(paulg): When implementing download restart via the Downloads tab,
384 // there will be no 'render_process_id' or 'render_view_id'. 378 // there will be no 'render_process_id' or 'render_view_id'.
385 void DownloadFileManager::OnStartDownload(DownloadCreateInfo* info) { 379 void DownloadFileManager::OnStartDownload(DownloadCreateInfo* info) {
386 DCHECK(MessageLoop::current() == ui_loop_); 380 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
387 DownloadManager* manager = DownloadManagerFromRenderIds(info->child_id, 381 DownloadManager* manager = DownloadManagerFromRenderIds(info->child_id,
388 info->render_view_id); 382 info->render_view_id);
389 if (!manager) { 383 if (!manager) {
390 ChromeThread::PostTask( 384 ChromeThread::PostTask(
391 ChromeThread::IO, FROM_HERE, 385 ChromeThread::IO, FROM_HERE,
392 NewRunnableFunction(&DownloadManager::OnCancelDownloadRequest, 386 NewRunnableFunction(&DownloadManager::OnCancelDownloadRequest,
393 resource_dispatcher_host_, 387 resource_dispatcher_host_,
394 info->child_id, 388 info->child_id,
395 info->request_id)); 389 info->request_id));
396 delete info; 390 delete info;
(...skipping 19 matching lines...) Expand all
416 NOTREACHED(); 410 NOTREACHED();
417 411
418 // StartDownload will clean up |info|. 412 // StartDownload will clean up |info|.
419 manager->StartDownload(info); 413 manager->StartDownload(info);
420 } 414 }
421 415
422 // Update the Download Manager with the finish state, and remove the request 416 // Update the Download Manager with the finish state, and remove the request
423 // tracking entries. 417 // tracking entries.
424 void DownloadFileManager::OnDownloadFinished(int id, 418 void DownloadFileManager::OnDownloadFinished(int id,
425 int64 bytes_so_far) { 419 int64 bytes_so_far) {
426 DCHECK(MessageLoop::current() == ui_loop_); 420 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
427 DownloadManager* manager = LookupManager(id); 421 DownloadManager* manager = LookupManager(id);
428 if (manager) 422 if (manager)
429 manager->DownloadFinished(id, bytes_so_far); 423 manager->DownloadFinished(id, bytes_so_far);
430 RemoveDownload(id, manager); 424 RemoveDownload(id, manager);
431 RemoveDownloadFromUIProgress(id); 425 RemoveDownloadFromUIProgress(id);
432 } 426 }
433 427
434 void DownloadFileManager::DownloadUrl( 428 void DownloadFileManager::DownloadUrl(
435 const GURL& url, 429 const GURL& url,
436 const GURL& referrer, 430 const GURL& referrer,
437 const std::string& referrer_charset, 431 const std::string& referrer_charset,
438 int render_process_host_id, 432 int render_process_host_id,
439 int render_view_id, 433 int render_view_id,
440 URLRequestContextGetter* request_context_getter) { 434 URLRequestContextGetter* request_context_getter) {
441 DCHECK(MessageLoop::current() == ui_loop_); 435 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
442 base::Thread* thread = g_browser_process->io_thread(); 436 ChromeThread::PostTask(
443 if (thread) { 437 ChromeThread::IO, FROM_HERE,
444 thread->message_loop()->PostTask(FROM_HERE,
445 NewRunnableMethod(this, 438 NewRunnableMethod(this,
446 &DownloadFileManager::OnDownloadUrl, 439 &DownloadFileManager::OnDownloadUrl,
447 url, 440 url,
448 referrer, 441 referrer,
449 referrer_charset, 442 referrer_charset,
450 render_process_host_id, 443 render_process_host_id,
451 render_view_id, 444 render_view_id,
452 request_context_getter)); 445 request_context_getter));
453 }
454 } 446 }
455 447
456 // Relate a download ID to its owning DownloadManager. 448 // Relate a download ID to its owning DownloadManager.
457 DownloadManager* DownloadFileManager::LookupManager(int download_id) { 449 DownloadManager* DownloadFileManager::LookupManager(int download_id) {
458 DCHECK(MessageLoop::current() == ui_loop_); 450 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
459 DownloadManagerMap::iterator it = managers_.find(download_id); 451 DownloadManagerMap::iterator it = managers_.find(download_id);
460 if (it != managers_.end()) 452 if (it != managers_.end())
461 return it->second; 453 return it->second;
462 return NULL; 454 return NULL;
463 } 455 }
464 456
465 // Utility function for look up table maintenance, called on the UI thread. 457 // Utility function for look up table maintenance, called on the UI thread.
466 // A manager may have multiple downloads in progress, so we just look up the 458 // A manager may have multiple downloads in progress, so we just look up the
467 // one download (id) and remove it from the set, and remove the set if it 459 // one download (id) and remove it from the set, and remove the set if it
468 // becomes empty. 460 // becomes empty.
469 void DownloadFileManager::RemoveDownload(int id, DownloadManager* manager) { 461 void DownloadFileManager::RemoveDownload(int id, DownloadManager* manager) {
470 DCHECK(MessageLoop::current() == ui_loop_); 462 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
471 if (manager) { 463 if (manager) {
472 RequestMap::iterator it = requests_.find(manager); 464 RequestMap::iterator it = requests_.find(manager);
473 if (it != requests_.end()) { 465 if (it != requests_.end()) {
474 DownloadRequests& downloads = it->second; 466 DownloadRequests& downloads = it->second;
475 DownloadRequests::iterator rit = downloads.find(id); 467 DownloadRequests::iterator rit = downloads.find(id);
476 if (rit != downloads.end()) 468 if (rit != downloads.end())
477 downloads.erase(rit); 469 downloads.erase(rit);
478 if (downloads.empty()) 470 if (downloads.empty())
479 requests_.erase(it); 471 requests_.erase(it);
480 } 472 }
(...skipping 17 matching lines...) Expand all
498 Profile* profile = contents->profile(); 490 Profile* profile = contents->profile();
499 if (profile) 491 if (profile)
500 return profile->GetDownloadManager(); 492 return profile->GetDownloadManager();
501 } 493 }
502 494
503 return NULL; 495 return NULL;
504 } 496 }
505 497
506 // Called by DownloadManagers in their destructor, and only on the UI thread. 498 // Called by DownloadManagers in their destructor, and only on the UI thread.
507 void DownloadFileManager::RemoveDownloadManager(DownloadManager* manager) { 499 void DownloadFileManager::RemoveDownloadManager(DownloadManager* manager) {
508 DCHECK(MessageLoop::current() == ui_loop_); 500 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
509 DCHECK(manager); 501 DCHECK(manager);
510 RequestMap::iterator it = requests_.find(manager); 502 RequestMap::iterator it = requests_.find(manager);
511 if (it == requests_.end()) 503 if (it == requests_.end())
512 return; 504 return;
513 505
514 const DownloadRequests& requests = it->second; 506 const DownloadRequests& requests = it->second;
515 DownloadRequests::const_iterator i = requests.begin(); 507 DownloadRequests::const_iterator i = requests.begin();
516 for (; i != requests.end(); ++i) { 508 for (; i != requests.end(); ++i) {
517 DownloadManagerMap::iterator dit = managers_.find(*i); 509 DownloadManagerMap::iterator dit = managers_.find(*i);
518 if (dit != managers_.end()) { 510 if (dit != managers_.end()) {
519 DCHECK(dit->second == manager); 511 DCHECK(dit->second == manager);
520 managers_.erase(dit); 512 managers_.erase(dit);
521 } 513 }
522 } 514 }
523 515
524 requests_.erase(it); 516 requests_.erase(it);
525 } 517 }
526 518
527 519
528 // Notifications from the UI thread and run on the IO thread 520 // Notifications from the UI thread and run on the IO thread
529 521
530 // Initiate a request for URL to be downloaded. 522 // Initiate a request for URL to be downloaded.
531 void DownloadFileManager::OnDownloadUrl( 523 void DownloadFileManager::OnDownloadUrl(
532 const GURL& url, 524 const GURL& url,
533 const GURL& referrer, 525 const GURL& referrer,
534 const std::string& referrer_charset, 526 const std::string& referrer_charset,
535 int render_process_host_id, 527 int render_process_host_id,
536 int render_view_id, 528 int render_view_id,
537 URLRequestContextGetter* request_context_getter) { 529 URLRequestContextGetter* request_context_getter) {
538 DCHECK(MessageLoop::current() == io_loop_); 530 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
539 531
540 URLRequestContext* context = request_context_getter->GetURLRequestContext(); 532 URLRequestContext* context = request_context_getter->GetURLRequestContext();
541 context->set_referrer_charset(referrer_charset); 533 context->set_referrer_charset(referrer_charset);
542 534
543 resource_dispatcher_host_->BeginDownload(url, 535 resource_dispatcher_host_->BeginDownload(url,
544 referrer, 536 referrer,
545 render_process_host_id, 537 render_process_host_id,
546 render_view_id, 538 render_view_id,
547 context); 539 context);
548 } 540 }
549 541
550 // Actions from the UI thread and run on the download thread 542 // Actions from the UI thread and run on the download thread
551 543
552 // Open a download, or show it in a file explorer window. We run on this 544 // Open a download, or show it in a file explorer window. We run on this
553 // thread to avoid blocking the UI with (potentially) slow Shell operations. 545 // thread to avoid blocking the UI with (potentially) slow Shell operations.
554 // TODO(paulg): File 'stat' operations. 546 // TODO(paulg): File 'stat' operations.
555 #if !defined(OS_MACOSX) 547 #if !defined(OS_MACOSX)
556 void DownloadFileManager::OnShowDownloadInShell(const FilePath& full_path) { 548 void DownloadFileManager::OnShowDownloadInShell(const FilePath& full_path) {
557 DCHECK(MessageLoop::current() == file_loop_); 549 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
558 platform_util::ShowItemInFolder(full_path); 550 platform_util::ShowItemInFolder(full_path);
559 } 551 }
560 #endif 552 #endif
561 553
562 // Launches the selected download using ShellExecute 'open' verb. For windows, 554 // Launches the selected download using ShellExecute 'open' verb. For windows,
563 // if there is a valid parent window, the 'safer' version will be used which can 555 // if there is a valid parent window, the 'safer' version will be used which can
564 // display a modal dialog asking for user consent on dangerous files. 556 // display a modal dialog asking for user consent on dangerous files.
565 #if !defined(OS_MACOSX) 557 #if !defined(OS_MACOSX)
566 void DownloadFileManager::OnOpenDownloadInShell(const FilePath& full_path, 558 void DownloadFileManager::OnOpenDownloadInShell(const FilePath& full_path,
567 const GURL& url, 559 const GURL& url,
568 gfx::NativeView parent_window) { 560 gfx::NativeView parent_window) {
569 DCHECK(MessageLoop::current() == file_loop_); 561 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
570 #if defined(OS_WIN) 562 #if defined(OS_WIN)
571 if (NULL != parent_window) { 563 if (NULL != parent_window) {
572 win_util::SaferOpenItemViaShell(parent_window, L"", full_path, 564 win_util::SaferOpenItemViaShell(parent_window, L"", full_path,
573 UTF8ToWide(url.spec())); 565 UTF8ToWide(url.spec()));
574 return; 566 return;
575 } 567 }
576 #endif 568 #endif
577 platform_util::OpenItem(full_path); 569 platform_util::OpenItem(full_path);
578 } 570 }
579 #endif // OS_MACOSX 571 #endif // OS_MACOSX
580 572
581 // The DownloadManager in the UI thread has provided a final name for the 573 // The DownloadManager in the UI thread has provided a final name for the
582 // download specified by 'id'. Rename the in progress download, and remove it 574 // download specified by 'id'. Rename the in progress download, and remove it
583 // from our table if it has been completed or cancelled already. 575 // from our table if it has been completed or cancelled already.
584 void DownloadFileManager::OnFinalDownloadName(int id, 576 void DownloadFileManager::OnFinalDownloadName(int id,
585 const FilePath& full_path, 577 const FilePath& full_path,
586 DownloadManager* manager) { 578 DownloadManager* manager) {
587 DCHECK(MessageLoop::current() == file_loop_); 579 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
588 DownloadFileMap::iterator it = downloads_.find(id); 580 DownloadFileMap::iterator it = downloads_.find(id);
589 if (it == downloads_.end()) 581 if (it == downloads_.end())
590 return; 582 return;
591 583
592 file_util::CreateDirectory(full_path.DirName()); 584 file_util::CreateDirectory(full_path.DirName());
593 585
594 DownloadFile* download = it->second; 586 DownloadFile* download = it->second;
595 if (download->Rename(full_path)) { 587 if (download->Rename(full_path)) {
596 #if defined(OS_MACOSX) 588 #if defined(OS_MACOSX)
597 // Done here because we only want to do this once; see 589 // Done here because we only want to do this once; see
598 // http://crbug.com/13120 for details. 590 // http://crbug.com/13120 for details.
599 download->AnnotateWithSourceInformation(); 591 download->AnnotateWithSourceInformation();
600 #endif 592 #endif
601 ui_loop_->PostTask(FROM_HERE, 593 ChromeThread::PostTask(
602 NewRunnableMethod(manager, 594 ChromeThread::UI, FROM_HERE,
603 &DownloadManager::DownloadRenamedToFinalName, 595 NewRunnableMethod(
604 id, 596 manager, &DownloadManager::DownloadRenamedToFinalName, id,
605 full_path)); 597 full_path));
606 } else { 598 } else {
607 // Error. Between the time the UI thread generated 'full_path' to the time 599 // Error. Between the time the UI thread generated 'full_path' to the time
608 // this code runs, something happened that prevents us from renaming. 600 // this code runs, something happened that prevents us from renaming.
609 DownloadManagerMap::iterator dmit = managers_.find(download->id()); 601 DownloadManagerMap::iterator dmit = managers_.find(download->id());
610 if (dmit != managers_.end()) { 602 if (dmit != managers_.end()) {
611 DownloadManager* dlm = dmit->second; 603 DownloadManager* dlm = dmit->second;
612 ui_loop_->PostTask(FROM_HERE, 604 ChromeThread::PostTask(
613 NewRunnableMethod(dlm, 605 ChromeThread::UI, FROM_HERE,
614 &DownloadManager::DownloadCancelled, 606 NewRunnableMethod(dlm, &DownloadManager::DownloadCancelled, id));
615 id));
616 } else { 607 } else {
617 ChromeThread::PostTask( 608 ChromeThread::PostTask(
618 ChromeThread::IO, FROM_HERE, 609 ChromeThread::IO, FROM_HERE,
619 NewRunnableFunction(&DownloadManager::OnCancelDownloadRequest, 610 NewRunnableFunction(&DownloadManager::OnCancelDownloadRequest,
620 resource_dispatcher_host_, 611 resource_dispatcher_host_,
621 download->child_id(), 612 download->child_id(),
622 download->request_id())); 613 download->request_id()));
623 } 614 }
624 } 615 }
625 616
626 // If the download has completed before we got this final name, we remove it 617 // If the download has completed before we got this final name, we remove it
627 // from our in progress map. 618 // from our in progress map.
628 if (!download->in_progress()) { 619 if (!download->in_progress()) {
629 downloads_.erase(it); 620 downloads_.erase(it);
630 delete download; 621 delete download;
631 } 622 }
632 623
633 if (downloads_.empty()) 624 if (downloads_.empty()) {
634 ui_loop_->PostTask(FROM_HERE, NewRunnableMethod( 625 ChromeThread::PostTask(
635 this, &DownloadFileManager::StopUpdateTimer)); 626 ChromeThread::UI, FROM_HERE,
627 NewRunnableMethod(this, &DownloadFileManager::StopUpdateTimer));
628 }
636 } 629 }
637 630
638 // static 631 // static
639 void DownloadFileManager::DeleteFile(const FilePath& path) { 632 void DownloadFileManager::DeleteFile(const FilePath& path) {
640 // Make sure we only delete files. 633 // Make sure we only delete files.
641 if (!file_util::DirectoryExists(path)) 634 if (!file_util::DirectoryExists(path))
642 file_util::Delete(path, false); 635 file_util::Delete(path, false);
643 } 636 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698