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

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

Issue 6969009: Reduced the lifetime of DownloadCreateInfo. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Removed structure accessors from DownloadItem, per request. Created 9 years, 7 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 | 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 "chrome/browser/download/download_manager.h" 5 #include "chrome/browser/download/download_manager.h"
6 6
7 #include "base/callback.h" 7 #include "base/callback.h"
8 #include "base/file_util.h" 8 #include "base/file_util.h"
9 #include "base/i18n/case_conversion.h" 9 #include "base/i18n/case_conversion.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 } 244 }
245 245
246 // We have received a message from DownloadFileManager about a new download. We 246 // We have received a message from DownloadFileManager about a new download. We
247 // create a download item and store it in our download map, and inform the 247 // create a download item and store it in our download map, and inform the
248 // history system of a new download. Since this method can be called while the 248 // history system of a new download. Since this method can be called while the
249 // history service thread is still reading the persistent state, we do not 249 // history service thread is still reading the persistent state, we do not
250 // insert the new DownloadItem into 'history_downloads_' or inform our 250 // insert the new DownloadItem into 'history_downloads_' or inform our
251 // observers at this point. OnCreateDownloadEntryComplete() handles that 251 // observers at this point. OnCreateDownloadEntryComplete() handles that
252 // finalization of the the download creation as a callback from the 252 // finalization of the the download creation as a callback from the
253 // history thread. 253 // history thread.
254 void DownloadManager::StartDownload(DownloadCreateInfo* info) { 254 void DownloadManager::StartDownload(int32 download_id) {
255 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 255 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
256 256
257 DownloadItem* download = GetActiveDownloadItem(download_id);
258 if (!download)
259 return;
260
257 // Create a client to verify download URL with safebrowsing. 261 // Create a client to verify download URL with safebrowsing.
258 // It deletes itself after the callback. 262 // It deletes itself after the callback.
259 scoped_refptr<DownloadSBClient> sb_client = new DownloadSBClient( 263 scoped_refptr<DownloadSBClient> sb_client = new DownloadSBClient(
260 info->download_id, info->url_chain, info->referrer_url); 264 download_id, download->url_chain(), download->referrer_url());
261 sb_client->CheckDownloadUrl( 265 sb_client->CheckDownloadUrl(
262 info, NewCallback(this, &DownloadManager::CheckDownloadUrlDone)); 266 NewCallback(this, &DownloadManager::CheckDownloadUrlDone));
263 } 267 }
264 268
265 void DownloadManager::CheckDownloadUrlDone(DownloadCreateInfo* info, 269 void DownloadManager::CheckDownloadUrlDone(int32 download_id,
266 bool is_dangerous_url) { 270 bool is_dangerous_url) {
267 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 271 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
268 DCHECK(info);
269 272
270 info->is_dangerous_url = is_dangerous_url; 273 DownloadItem* download = GetActiveDownloadItem(download_id);
274 if (!download)
275 return;
276
277 download->set_dangerous_url(is_dangerous_url);
278
279 DownloadItem::DownloadStateInfo state(*download);
271 280
272 // Check whether this download is for an extension install or not. 281 // Check whether this download is for an extension install or not.
273 // Allow extensions to be explicitly saved. 282 // Allow extensions to be explicitly saved.
274 if (!info->prompt_user_for_save_location) { 283 if (!state.prompt_user_for_save_location) {
275 if (UserScript::IsURLUserScript(info->url(), info->mime_type) || 284 if (UserScript::IsURLUserScript(download->url(), download->mime_type()) ||
276 info->mime_type == Extension::kMimeType) { 285 (download->mime_type() == Extension::kMimeType)) {
277 info->is_extension_install = true; 286 state.is_extension_install = true;
278 } 287 }
279 } 288 }
280 289
281 if (info->save_info.file_path.empty()) { 290 if (state.force_file_name.empty()) {
282 FilePath generated_name; 291 FilePath generated_name;
283 download_util::GenerateFileNameFromInfo(info, &generated_name); 292 download_util::GenerateFileNameFromRequest(download->url(),
293 download->content_disposition(),
294 download->referrer_charset(),
295 download->mime_type(),
296 &generated_name);
284 297
285 // Freeze the user's preference for showing a Save As dialog. We're going 298 // Freeze the user's preference for showing a Save As dialog. We're going
286 // to bounce around a bunch of threads and we don't want to worry about race 299 // to bounce around a bunch of threads and we don't want to worry about race
287 // conditions where the user changes this pref out from under us. 300 // conditions where the user changes this pref out from under us.
288 if (download_prefs_->PromptForDownload()) { 301 if (download_prefs_->PromptForDownload()) {
289 // But ignore the user's preference for the following scenarios: 302 // But ignore the user's preference for the following scenarios:
290 // 1) Extension installation. Note that we only care here about the case 303 // 1) Extension installation. Note that we only care here about the case
291 // where an extension is installed, not when one is downloaded with 304 // where an extension is installed, not when one is downloaded with
292 // "save as...". 305 // "save as...".
293 // 2) Filetypes marked "always open." If the user just wants this file 306 // 2) Filetypes marked "always open." If the user just wants this file
294 // opened, don't bother asking where to keep it. 307 // opened, don't bother asking where to keep it.
295 if (!info->is_extension_install && 308 if (!state.is_extension_install &&
296 !ShouldOpenFileBasedOnExtension(generated_name)) 309 !ShouldOpenFileBasedOnExtension(generated_name))
297 info->prompt_user_for_save_location = true; 310 state.prompt_user_for_save_location = true;
298 } 311 }
299 if (download_prefs_->IsDownloadPathManaged()) { 312 if (download_prefs_->IsDownloadPathManaged()) {
300 info->prompt_user_for_save_location = false; 313 state.prompt_user_for_save_location = false;
301 } 314 }
302 315
303 // Determine the proper path for a download, by either one of the following: 316 // Determine the proper path for a download, by either one of the following:
304 // 1) using the default download directory. 317 // 1) using the default download directory.
305 // 2) prompting the user. 318 // 2) prompting the user.
306 if (info->prompt_user_for_save_location && !last_download_path_.empty()) { 319 if (state.prompt_user_for_save_location && !last_download_path_.empty()) {
307 info->suggested_path = last_download_path_; 320 state.suggested_path = last_download_path_;
308 } else { 321 } else {
309 info->suggested_path = download_prefs_->download_path(); 322 state.suggested_path = download_prefs_->download_path();
310 } 323 }
311 info->suggested_path = info->suggested_path.Append(generated_name); 324 state.suggested_path = state.suggested_path.Append(generated_name);
312 } else { 325 } else {
313 info->suggested_path = info->save_info.file_path; 326 state.suggested_path = state.force_file_name;
314 } 327 }
315 328
316 if (!info->prompt_user_for_save_location && 329 if (!state.prompt_user_for_save_location && state.force_file_name.empty()) {
317 info->save_info.file_path.empty()) { 330 state.is_dangerous_file = download_util::IsDangerous(
318 info->is_dangerous_file = download_util::IsDangerous( 331 download->url(),
319 info, profile(), ShouldOpenFileBasedOnExtension(info->suggested_path)); 332 download->referrer_url(),
333 state.suggested_path,
334 state.has_user_gesture,
335 state.is_extension_install,
336 profile(),
337 ShouldOpenFileBasedOnExtension(state.suggested_path));
320 } 338 }
321 339
322 // We need to move over to the download thread because we don't want to stat 340 // We need to move over to the download thread because we don't want to stat
323 // the suggested path on the UI thread. 341 // the suggested path on the UI thread.
324 // We can only access preferences on the UI thread, so check the download path 342 // We can only access preferences on the UI thread, so check the download path
325 // now and pass the value to the FILE thread. 343 // now and pass the value to the FILE thread.
326 BrowserThread::PostTask( 344 BrowserThread::PostTask(
327 BrowserThread::FILE, FROM_HERE, 345 BrowserThread::FILE, FROM_HERE,
328 NewRunnableMethod( 346 NewRunnableMethod(
329 this, 347 this,
330 &DownloadManager::CheckIfSuggestedPathExists, 348 &DownloadManager::CheckIfSuggestedPathExists,
331 info, 349 download_id,
350 state,
332 download_prefs()->download_path())); 351 download_prefs()->download_path()));
333 } 352 }
334 353
335 void DownloadManager::CheckIfSuggestedPathExists(DownloadCreateInfo* info, 354 void DownloadManager::CheckIfSuggestedPathExists(
336 const FilePath& default_path) { 355 int32 download_id,
356 DownloadItem::DownloadStateInfo state,
357 const FilePath& default_path) {
337 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 358 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
338 DCHECK(info);
339 359
340 // Make sure the default download directory exists. 360 // Make sure the default download directory exists.
341 // TODO(phajdan.jr): only create the directory when we're sure the user 361 // TODO(phajdan.jr): only create the directory when we're sure the user
342 // is going to save there and not to another directory of his choice. 362 // is going to save there and not to another directory of his choice.
343 file_util::CreateDirectory(default_path); 363 file_util::CreateDirectory(default_path);
344 364
345 // Check writability of the suggested path. If we can't write to it, default 365 // Check writability of the suggested path. If we can't write to it, default
346 // to the user's "My Documents" directory. We'll prompt them in this case. 366 // to the user's "My Documents" directory. We'll prompt them in this case.
347 FilePath dir = info->suggested_path.DirName(); 367 FilePath dir = state.suggested_path.DirName();
348 FilePath filename = info->suggested_path.BaseName(); 368 FilePath filename = state.suggested_path.BaseName();
349 if (!file_util::PathIsWritable(dir)) { 369 if (!file_util::PathIsWritable(dir)) {
350 VLOG(1) << "Unable to write to directory \"" << dir.value() << "\""; 370 VLOG(1) << "Unable to write to directory \"" << dir.value() << "\"";
351 info->prompt_user_for_save_location = true; 371 state.prompt_user_for_save_location = true;
352 PathService::Get(chrome::DIR_USER_DOCUMENTS, &info->suggested_path); 372 PathService::Get(chrome::DIR_USER_DOCUMENTS, &state.suggested_path);
353 info->suggested_path = info->suggested_path.Append(filename); 373 state.suggested_path = state.suggested_path.Append(filename);
354 } 374 }
355 375
356 // If the download is deemed dangerous, we'll use a temporary name for it. 376 // If the download is deemed dangerous, we'll use a temporary name for it.
357 if (info->IsDangerous()) { 377 if (state.IsDangerous()) {
358 info->original_name = FilePath(info->suggested_path).BaseName(); 378 state.target_name = FilePath(state.suggested_path).BaseName();
359 // Create a temporary file to hold the file until the user approves its 379 // Create a temporary file to hold the file until the user approves its
360 // download. 380 // download.
361 FilePath::StringType file_name; 381 FilePath::StringType file_name;
362 FilePath path; 382 FilePath path;
363 #if defined(OS_WIN) 383 #if defined(OS_WIN)
364 string16 unconfirmed_prefix = 384 string16 unconfirmed_prefix =
365 l10n_util::GetStringUTF16(IDS_DOWNLOAD_UNCONFIRMED_PREFIX); 385 l10n_util::GetStringUTF16(IDS_DOWNLOAD_UNCONFIRMED_PREFIX);
366 #else 386 #else
367 std::string unconfirmed_prefix = 387 std::string unconfirmed_prefix =
368 l10n_util::GetStringUTF8(IDS_DOWNLOAD_UNCONFIRMED_PREFIX); 388 l10n_util::GetStringUTF8(IDS_DOWNLOAD_UNCONFIRMED_PREFIX);
369 #endif 389 #endif
370 390
371 while (path.empty()) { 391 while (path.empty()) {
372 base::SStringPrintf( 392 base::SStringPrintf(
373 &file_name, 393 &file_name,
374 unconfirmed_prefix.append( 394 unconfirmed_prefix.append(
375 FILE_PATH_LITERAL(" %d.crdownload")).c_str(), 395 FILE_PATH_LITERAL(" %d.crdownload")).c_str(),
376 base::RandInt(0, 100000)); 396 base::RandInt(0, 100000));
377 path = dir.Append(file_name); 397 path = dir.Append(file_name);
378 if (file_util::PathExists(path)) 398 if (file_util::PathExists(path))
379 path = FilePath(); 399 path = FilePath();
380 } 400 }
381 info->suggested_path = path; 401 state.suggested_path = path;
382 } else { 402 } else {
383 // Do not add the path uniquifier if we are saving to a specific path as in 403 // Do not add the path uniquifier if we are saving to a specific path as in
384 // the drag-out case. 404 // the drag-out case.
385 if (info->save_info.file_path.empty()) { 405 if (state.force_file_name.empty()) {
386 info->path_uniquifier = download_util::GetUniquePathNumberWithCrDownload( 406 state.path_uniquifier = download_util::GetUniquePathNumberWithCrDownload(
387 info->suggested_path); 407 state.suggested_path);
388 } 408 }
389 // We know the final path, build it if necessary. 409 // We know the final path, build it if necessary.
390 if (info->path_uniquifier > 0) { 410 if (state.path_uniquifier > 0) {
391 download_util::AppendNumberToPath(&(info->suggested_path), 411 download_util::AppendNumberToPath(&(state.suggested_path),
392 info->path_uniquifier); 412 state.path_uniquifier);
393 // Setting path_uniquifier to 0 to make sure we don't try to unique it 413 // Setting path_uniquifier to 0 to make sure we don't try to unique it
394 // later on. 414 // later on.
395 info->path_uniquifier = 0; 415 state.path_uniquifier = 0;
396 } else if (info->path_uniquifier == -1) { 416 } else if (state.path_uniquifier == -1) {
397 // We failed to find a unique path. We have to prompt the user. 417 // We failed to find a unique path. We have to prompt the user.
398 VLOG(1) << "Unable to find a unique path for suggested path \"" 418 VLOG(1) << "Unable to find a unique path for suggested path \""
399 << info->suggested_path.value() << "\""; 419 << state.suggested_path.value() << "\"";
400 info->prompt_user_for_save_location = true; 420 state.prompt_user_for_save_location = true;
401 } 421 }
402 } 422 }
403 423
404 // Create an empty file at the suggested path so that we don't allocate the 424 // Create an empty file at the suggested path so that we don't allocate the
405 // same "non-existant" path to multiple downloads. 425 // same "non-existant" path to multiple downloads.
406 // See: http://code.google.com/p/chromium/issues/detail?id=3662 426 // See: http://code.google.com/p/chromium/issues/detail?id=3662
407 if (!info->prompt_user_for_save_location && 427 if (!state.prompt_user_for_save_location &&
408 info->save_info.file_path.empty()) { 428 state.force_file_name.empty()) {
409 if (info->IsDangerous()) 429 if (state.IsDangerous())
410 file_util::WriteFile(info->suggested_path, "", 0); 430 file_util::WriteFile(state.suggested_path, "", 0);
411 else 431 else
412 file_util::WriteFile(download_util::GetCrDownloadPath( 432 file_util::WriteFile(download_util::GetCrDownloadPath(
413 info->suggested_path), "", 0); 433 state.suggested_path), "", 0);
414 } 434 }
415 435
416 BrowserThread::PostTask( 436 BrowserThread::PostTask(
417 BrowserThread::UI, FROM_HERE, 437 BrowserThread::UI, FROM_HERE,
418 NewRunnableMethod(this, 438 NewRunnableMethod(this,
419 &DownloadManager::OnPathExistenceAvailable, 439 &DownloadManager::OnPathExistenceAvailable,
420 info)); 440 download_id,
441 state));
421 } 442 }
422 443
423 void DownloadManager::OnPathExistenceAvailable(DownloadCreateInfo* info) { 444 void DownloadManager::OnPathExistenceAvailable(
424 VLOG(20) << __FUNCTION__ << "()" << " info = " << info->DebugString(); 445 int32 download_id, DownloadItem::DownloadStateInfo new_state) {
425 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 446 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
426 DCHECK(info);
427 447
428 if (info->prompt_user_for_save_location) { 448 DownloadItem* download = GetActiveDownloadItem(download_id);
449 if (!download)
450 return;
451
452 VLOG(20) << __FUNCTION__ << "()"
453 << " download = " << download->DebugString(true);
454
455 download->SetFileCheckResults(new_state);
456
457 DownloadItem::DownloadStateInfo state(*download);
458
459 if (state.prompt_user_for_save_location) {
429 // We must ask the user for the place to put the download. 460 // We must ask the user for the place to put the download.
430 if (!select_file_dialog_.get()) 461 if (!select_file_dialog_.get())
431 select_file_dialog_ = SelectFileDialog::Create(this); 462 select_file_dialog_ = SelectFileDialog::Create(this);
432 463
433 TabContents* contents = info->process_handle.GetTabContents(); 464 DownloadProcessHandle process_handle = download->process_handle();
465 TabContents* contents = process_handle.GetTabContents();
434 SelectFileDialog::FileTypeInfo file_type_info; 466 SelectFileDialog::FileTypeInfo file_type_info;
435 FilePath::StringType extension = info->suggested_path.Extension(); 467 FilePath::StringType extension = state.suggested_path.Extension();
436 if (!extension.empty()) { 468 if (!extension.empty()) {
437 extension.erase(extension.begin()); // drop the . 469 extension.erase(extension.begin()); // drop the .
438 file_type_info.extensions.resize(1); 470 file_type_info.extensions.resize(1);
439 file_type_info.extensions[0].push_back(extension); 471 file_type_info.extensions[0].push_back(extension);
440 } 472 }
441 file_type_info.include_all_files = true; 473 file_type_info.include_all_files = true;
442 gfx::NativeWindow owning_window = 474 gfx::NativeWindow owning_window =
443 contents ? platform_util::GetTopLevel(contents->GetNativeView()) : NULL; 475 contents ? platform_util::GetTopLevel(contents->GetNativeView()) : NULL;
476 // |id_ptr| will be deleted in either FileSelected() or
477 // FileSelectionCancelled().
478 int32* id_ptr = new int32;
479 *id_ptr = download_id;
444 select_file_dialog_->SelectFile(SelectFileDialog::SELECT_SAVEAS_FILE, 480 select_file_dialog_->SelectFile(SelectFileDialog::SELECT_SAVEAS_FILE,
445 string16(), 481 string16(),
446 info->suggested_path, 482 state.suggested_path,
447 &file_type_info, 0, FILE_PATH_LITERAL(""), 483 &file_type_info, 0, FILE_PATH_LITERAL(""),
448 contents, owning_window, info); 484 contents, owning_window,
485 reinterpret_cast<void *>(id_ptr));
449 FOR_EACH_OBSERVER(Observer, observers_, 486 FOR_EACH_OBSERVER(Observer, observers_,
450 SelectFileDialogDisplayed(info->download_id)); 487 SelectFileDialogDisplayed(download_id));
451 } else { 488 } else {
452 // No prompting for download, just continue with the suggested name. 489 // No prompting for download, just continue with the suggested name.
453 info->path = info->suggested_path; 490 ContinueDownloadWithPath(download_id, state.suggested_path);
454 AttachDownloadItem(info);
455 } 491 }
456 } 492 }
457 493
458 void DownloadManager::CreateDownloadItem(DownloadCreateInfo* info) { 494 void DownloadManager::CreateDownloadItem(DownloadCreateInfo* info) {
459 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 495 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
460 496
461 DownloadItem* download = new DownloadItem(this, *info, 497 DownloadItem* download = new DownloadItem(this, *info,
462 profile_->IsOffTheRecord()); 498 profile_->IsOffTheRecord());
463 DCHECK(!ContainsKey(in_progress_, info->download_id)); 499 int32 download_id = info->download_id;
464 DCHECK(!ContainsKey(active_downloads_, info->download_id)); 500 DCHECK(!ContainsKey(in_progress_, download_id));
501 DCHECK(!ContainsKey(active_downloads_, download_id));
465 downloads_.insert(download); 502 downloads_.insert(download);
466 active_downloads_[info->download_id] = download; 503 active_downloads_[download_id] = download;
467 } 504 }
468 505
469 void DownloadManager::AttachDownloadItem(DownloadCreateInfo* info) { 506 void DownloadManager::ContinueDownloadWithPath(int32 download_id,
470 VLOG(20) << __FUNCTION__ << "()" << " info = " << info->DebugString(); 507 const FilePath& chosen_file) {
471
472 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 508 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
473 509
474 // Life of |info| ends here. No more references to it after this method.
475 scoped_ptr<DownloadCreateInfo> infop(info);
476
477 // NOTE(ahendrickson) Eventually |active_downloads_| will replace 510 // NOTE(ahendrickson) Eventually |active_downloads_| will replace
478 // |in_progress_|, but we don't want to change the semantics yet. 511 // |in_progress_|, but we don't want to change the semantics yet.
479 DCHECK(!ContainsKey(in_progress_, info->download_id)); 512 DCHECK(!ContainsKey(in_progress_, download_id));
480 DCHECK(ContainsKey(active_downloads_, info->download_id)); 513 DownloadItem* download = GetActiveDownloadItem(download_id);
481 DownloadItem* download = active_downloads_[info->download_id];
482 DCHECK(download != NULL);
483 DCHECK(ContainsKey(downloads_, download)); 514 DCHECK(ContainsKey(downloads_, download));
515 if (!download)
516 return;
484 517
485 download->SetFileCheckResults(info->path, 518 // Make sure the initial file name is set only once.
486 info->is_dangerous_file, 519 DCHECK(download->full_path().empty());
487 info->is_dangerous_url, 520 download->set_path(chosen_file);
488 info->path_uniquifier, 521 download->UpdateTarget();
489 info->prompt_user_for_save_location, 522
490 info->is_extension_install, 523 VLOG(20) << __FUNCTION__ << "()"
491 info->original_name); 524 << " download = " << download->DebugString(true);
492 in_progress_[info->download_id] = download; 525
526 in_progress_[download_id] = download;
493 UpdateAppIcon(); // Reflect entry into in_progress_. 527 UpdateAppIcon(); // Reflect entry into in_progress_.
494 528
495 // Rename to intermediate name. 529 // Rename to intermediate name.
496 FilePath download_path; 530 FilePath download_path;
497 if (info->IsDangerous()) { 531 if (download->IsDangerous()) {
498 // The download is not safe. We can now rename the file to its 532 // The download is not safe. We can now rename the file to its
499 // tentative name using RenameInProgressDownloadFile. 533 // tentative name using RenameInProgressDownloadFile.
500 // NOTE: The |Rename| below will be a no-op for dangerous files, as we're 534 // NOTE: The |Rename| below will be a no-op for dangerous files, as we're
501 // renaming it to the same name. 535 // renaming it to the same name.
502 download_path = info->path; 536 download_path = download->full_path();
503 } else { 537 } else {
504 // The download is a safe download. We need to 538 // The download is a safe download. We need to
505 // rename it to its intermediate '.crdownload' path. The final 539 // rename it to its intermediate '.crdownload' path. The final
506 // name after user confirmation will be set from 540 // name after user confirmation will be set from
507 // DownloadItem::OnDownloadCompleting. 541 // DownloadItem::OnDownloadCompleting.
508 download_path = download_util::GetCrDownloadPath(info->path); 542 download_path =
543 download_util::GetCrDownloadPath(download->full_path());
509 } 544 }
510 545
511 BrowserThread::PostTask( 546 BrowserThread::PostTask(
512 BrowserThread::FILE, FROM_HERE, 547 BrowserThread::FILE, FROM_HERE,
513 NewRunnableMethod( 548 NewRunnableMethod(
514 file_manager_, &DownloadFileManager::RenameInProgressDownloadFile, 549 file_manager_, &DownloadFileManager::RenameInProgressDownloadFile,
515 download->id(), download_path)); 550 download->id(), download_path));
516 551
517 download->Rename(download_path); 552 download->Rename(download_path);
518 553
519 download_history_->AddEntry(*info, download, 554 download_history_->AddEntry(download,
520 NewCallback(this, &DownloadManager::OnCreateDownloadEntryComplete)); 555 NewCallback(this, &DownloadManager::OnCreateDownloadEntryComplete));
521 } 556 }
522 557
523 void DownloadManager::UpdateDownload(int32 download_id, int64 size) { 558 void DownloadManager::UpdateDownload(int32 download_id, int64 size) {
524 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 559 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
525 DownloadMap::iterator it = active_downloads_.find(download_id); 560 DownloadMap::iterator it = active_downloads_.find(download_id);
526 if (it != active_downloads_.end()) { 561 if (it != active_downloads_.end()) {
527 DownloadItem* download = it->second; 562 DownloadItem* download = it->second;
528 if (download->IsInProgress()) { 563 if (download->IsInProgress()) {
529 download->Update(size); 564 download->Update(size);
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
723 int os_error) { 758 int os_error) {
724 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 759 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
725 DownloadMap::iterator it = active_downloads_.find(download_id); 760 DownloadMap::iterator it = active_downloads_.find(download_id);
726 // A cancel at the right time could remove the download from the 761 // A cancel at the right time could remove the download from the
727 // |active_downloads_| map before we get here. 762 // |active_downloads_| map before we get here.
728 if (it == active_downloads_.end()) 763 if (it == active_downloads_.end())
729 return; 764 return;
730 765
731 DownloadItem* download = it->second; 766 DownloadItem* download = it->second;
732 767
733 VLOG(20) << "Error " << os_error << " at offset " 768 VLOG(20) << __FUNCTION__ << "()" << " Error " << os_error
734 << download->received_bytes() << " for download = " 769 << " at offset " << download->received_bytes()
735 << download->DebugString(true); 770 << " for download = " << download->DebugString(true);
771
772 download->Interrupted(size, os_error);
736 773
737 // TODO(ahendrickson) - Remove this when we add resuming of interrupted 774 // TODO(ahendrickson) - Remove this when we add resuming of interrupted
738 // downloads, as we will keep the download item around in that case. 775 // downloads, as we will keep the download item around in that case.
739 // 776 //
740 // Clean up will happen when the history system create callback runs if we 777 // Clean up will happen when the history system create callback runs if we
741 // don't have a valid db_handle yet. 778 // don't have a valid db_handle yet.
742 if (download->db_handle() != DownloadHistory::kUninitializedHandle) { 779 if (download->db_handle() != DownloadHistory::kUninitializedHandle) {
743 in_progress_.erase(download_id); 780 in_progress_.erase(download_id);
744 active_downloads_.erase(download_id); 781 active_downloads_.erase(download_id);
745 UpdateAppIcon(); // Reflect removal from in_progress_. 782 UpdateAppIcon(); // Reflect removal from in_progress_.
746 download_history_->UpdateEntry(download); 783 download_history_->UpdateEntry(download);
747 } 784 }
748 785
749 download->Interrupted(size, os_error);
750
751 BrowserThread::PostTask( 786 BrowserThread::PostTask(
752 BrowserThread::FILE, FROM_HERE, 787 BrowserThread::FILE, FROM_HERE,
753 NewRunnableMethod( 788 NewRunnableMethod(
754 file_manager_, &DownloadFileManager::CancelDownload, download_id)); 789 file_manager_, &DownloadFileManager::CancelDownload, download_id));
755 } 790 }
756 791
757 void DownloadManager::PauseDownload(int32 download_id, bool pause) { 792 void DownloadManager::PauseDownload(int32 download_id, bool pause) {
758 DownloadMap::iterator it = in_progress_.find(download_id); 793 DownloadMap::iterator it = in_progress_.find(download_id);
759 if (it == in_progress_.end()) 794 if (it == in_progress_.end())
760 return; 795 return;
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
957 int64 total_bytes = 0; 992 int64 total_bytes = 0;
958 for (DownloadMap::iterator i = in_progress_.begin(); 993 for (DownloadMap::iterator i = in_progress_.begin();
959 i != in_progress_.end(); ++i) { 994 i != in_progress_.end(); ++i) {
960 total_bytes += i->second->total_bytes(); 995 total_bytes += i->second->total_bytes();
961 } 996 }
962 return total_bytes; 997 return total_bytes;
963 } 998 }
964 999
965 void DownloadManager::FileSelected(const FilePath& path, 1000 void DownloadManager::FileSelected(const FilePath& path,
966 int index, void* params) { 1001 int index, void* params) {
967 DownloadCreateInfo* info = reinterpret_cast<DownloadCreateInfo*>(params); 1002 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
968 if (info->prompt_user_for_save_location) 1003
1004 int32* id_ptr = reinterpret_cast<int32 *>(params);
1005 DCHECK(id_ptr != NULL);
1006 int32 download_id = *id_ptr;
1007 delete id_ptr;
1008 DCHECK_EQ(index, download_id);
1009
1010 DownloadItem* download = GetActiveDownloadItem(download_id);
1011 if (!download)
1012 return;
1013 VLOG(20) << __FUNCTION__ << "()" << " path = \"" << path.value() << "\""
1014 << " download = " << download->DebugString(true);
1015
1016 if (download->save_as())
969 last_download_path_ = path.DirName(); 1017 last_download_path_ = path.DirName();
970 1018
971 info->path = path; 1019 // Make sure the initial file name is set only once.
972 AttachDownloadItem(info); 1020 ContinueDownloadWithPath(download_id, path);
973 } 1021 }
974 1022
975 void DownloadManager::FileSelectionCanceled(void* params) { 1023 void DownloadManager::FileSelectionCanceled(void* params) {
976 // The user didn't pick a place to save the file, so need to cancel the 1024 // The user didn't pick a place to save the file, so need to cancel the
977 // download that's already in progress to the temporary location. 1025 // download that's already in progress to the temporary location.
978 DownloadCreateInfo* info = reinterpret_cast<DownloadCreateInfo*>(params); 1026 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
979 DownloadCancelledInternal(info->download_id, info->process_handle); 1027 int32* id_ptr = reinterpret_cast<int32 *>(params);
1028 DCHECK(id_ptr != NULL);
1029 int32 download_id = *id_ptr;
1030 delete id_ptr;
1031
1032 DownloadItem* download = GetActiveDownloadItem(download_id);
1033 if (!download)
1034 return;
1035
1036 VLOG(20) << __FUNCTION__ << "()"
1037 << " download = " << download->DebugString(true);
1038
1039 DownloadCancelledInternal(download_id, download->process_handle());
980 } 1040 }
981 1041
982 void DownloadManager::DangerousDownloadValidated(DownloadItem* download) { 1042 void DownloadManager::DangerousDownloadValidated(DownloadItem* download) {
983 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1043 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
984 DCHECK_EQ(DownloadItem::DANGEROUS, download->safety_state()); 1044 DCHECK_EQ(DownloadItem::DANGEROUS, download->safety_state());
985 download->set_safety_state(DownloadItem::DANGEROUS_BUT_VALIDATED); 1045 download->set_safety_state(DownloadItem::DANGEROUS_BUT_VALIDATED);
986 download->UpdateObservers(); 1046 download->UpdateObservers();
987 1047
988 MaybeCompleteDownload(download); 1048 MaybeCompleteDownload(download);
989 } 1049 }
990 1050
991 // Operations posted to us from the history service ---------------------------- 1051 // Operations posted to us from the history service ----------------------------
992 1052
993 // The history service has retrieved all download entries. 'entries' contains 1053 // The history service has retrieved all download entries. 'entries' contains
994 // 'DownloadCreateInfo's in sorted order (by ascending start_time). 1054 // 'DownloadHistoryInfo's in sorted order (by ascending start_time).
995 void DownloadManager::OnQueryDownloadEntriesComplete( 1055 void DownloadManager::OnQueryDownloadEntriesComplete(
996 std::vector<DownloadCreateInfo>* entries) { 1056 std::vector<DownloadHistoryInfo>* entries) {
997 for (size_t i = 0; i < entries->size(); ++i) { 1057 for (size_t i = 0; i < entries->size(); ++i) {
998 DownloadItem* download = new DownloadItem(this, entries->at(i)); 1058 DownloadItem* download = new DownloadItem(this, entries->at(i));
999 DCHECK(!ContainsKey(history_downloads_, download->db_handle())); 1059 DCHECK(!ContainsKey(history_downloads_, download->db_handle()));
1000 downloads_.insert(download); 1060 downloads_.insert(download);
1001 history_downloads_[download->db_handle()] = download; 1061 history_downloads_[download->db_handle()] = download;
1002 VLOG(20) << __FUNCTION__ << "()" << i << ">" 1062 VLOG(20) << __FUNCTION__ << "()" << i << ">"
1003 << " download = " << download->DebugString(true); 1063 << " download = " << download->DebugString(true);
1004 } 1064 }
1005 NotifyModelChanged(); 1065 NotifyModelChanged();
1006 } 1066 }
1007 1067
1008 // Once the new DownloadItem's creation info has been committed to the history 1068 // Once the new DownloadItem's creation info has been committed to the history
1009 // service, we associate the DownloadItem with the db handle, update our 1069 // service, we associate the DownloadItem with the db handle, update our
1010 // 'history_downloads_' map and inform observers. 1070 // 'history_downloads_' map and inform observers.
1011 void DownloadManager::OnCreateDownloadEntryComplete( 1071 void DownloadManager::OnCreateDownloadEntryComplete(int32 download_id,
1012 DownloadCreateInfo info, 1072 int64 db_handle) {
1013 int64 db_handle) {
1014 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1073 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1015 DownloadMap::iterator it = in_progress_.find(info.download_id); 1074 DownloadItem* download = GetActiveDownloadItem(download_id);
1016 DCHECK(it != in_progress_.end()); 1075 if (!download)
1076 return;
1017 1077
1018 DownloadItem* download = it->second;
1019 VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << db_handle 1078 VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << db_handle
1020 << " download_id = " << info.download_id 1079 << " download_id = " << download_id
1021 << " download = " << download->DebugString(true); 1080 << " download = " << download->DebugString(true);
1022 1081
1023 // It's not immediately obvious, but HistoryBackend::CreateDownload() can 1082 // It's not immediately obvious, but HistoryBackend::CreateDownload() can
1024 // call this function with an invalid |db_handle|. For instance, this can 1083 // call this function with an invalid |db_handle|. For instance, this can
1025 // happen when the history database is offline. We cannot have multiple 1084 // happen when the history database is offline. We cannot have multiple
1026 // DownloadItems with the same invalid db_handle, so we need to assign a 1085 // DownloadItems with the same invalid db_handle, so we need to assign a
1027 // unique |db_handle| here. 1086 // unique |db_handle| here.
1028 if (db_handle == DownloadHistory::kUninitializedHandle) 1087 if (db_handle == DownloadHistory::kUninitializedHandle)
1029 db_handle = download_history_->GetNextFakeDbHandle(); 1088 db_handle = download_history_->GetNextFakeDbHandle();
1030 1089
1031 DCHECK(download->db_handle() == DownloadHistory::kUninitializedHandle); 1090 DCHECK(download->db_handle() == DownloadHistory::kUninitializedHandle);
1032 download->set_db_handle(db_handle); 1091 download->set_db_handle(db_handle);
1033 1092
1034 DCHECK(!ContainsKey(history_downloads_, download->db_handle())); 1093 DCHECK(!ContainsKey(history_downloads_, download->db_handle()));
1035 history_downloads_[download->db_handle()] = download; 1094 history_downloads_[download->db_handle()] = download;
1036 1095
1037 // Show in the appropriate browser UI. 1096 // Show in the appropriate browser UI.
1038 // This includes buttons to save or cancel, for a dangerous download. 1097 // This includes buttons to save or cancel, for a dangerous download.
1039 ShowDownloadInBrowser(&info.process_handle, download); 1098 ShowDownloadInBrowser(download);
1040 1099
1041 // Inform interested objects about the new download. 1100 // Inform interested objects about the new download.
1042 NotifyModelChanged(); 1101 NotifyModelChanged();
1043 1102
1044 // If the download is still in progress, try to complete it. 1103 // If the download is still in progress, try to complete it.
1045 // 1104 //
1046 // Otherwise, download has been cancelled or interrupted before we've 1105 // Otherwise, download has been cancelled or interrupted before we've
1047 // received the DB handle. We post one final message to the history 1106 // received the DB handle. We post one final message to the history
1048 // service so that it can be properly in sync with the DownloadItem's 1107 // service so that it can be properly in sync with the DownloadItem's
1049 // completion status, and also inform any observers so that they get 1108 // completion status, and also inform any observers so that they get
1050 // more than just the start notification. 1109 // more than just the start notification.
1051 if (download->IsInProgress()) { 1110 if (download->IsInProgress()) {
1052 MaybeCompleteDownload(download); 1111 MaybeCompleteDownload(download);
1053 } else { 1112 } else {
1054 DCHECK(download->IsCancelled()) 1113 DCHECK(download->IsCancelled())
1055 << " download = " << download->DebugString(true); 1114 << " download = " << download->DebugString(true);
1056 in_progress_.erase(it); 1115 in_progress_.erase(download_id);
1057 active_downloads_.erase(info.download_id); 1116 active_downloads_.erase(download_id);
1058 download_history_->UpdateEntry(download); 1117 download_history_->UpdateEntry(download);
1059 download->UpdateObservers(); 1118 download->UpdateObservers();
1060 } 1119 }
1061 } 1120 }
1062 1121
1063 void DownloadManager::ShowDownloadInBrowser( 1122 void DownloadManager::ShowDownloadInBrowser(DownloadItem* download) {
1064 DownloadProcessHandle* process_handle, DownloadItem* download) {
1065 if (!process_handle)
1066 return;
1067 1123
1068 // The 'contents' may no longer exist if the user closed the tab before we 1124 // The 'contents' may no longer exist if the user closed the tab before we
1069 // get this start completion event. If it does, tell the origin TabContents 1125 // get this start completion event. If it does, tell the origin TabContents
1070 // to display its download shelf. 1126 // to display its download shelf.
1071 TabContents* contents = process_handle->GetTabContents(); 1127 DownloadProcessHandle process_handle = download->process_handle();
1128 TabContents* contents = process_handle.GetTabContents();
1072 1129
1073 // If the contents no longer exists, we start the download in the last active 1130 // If the contents no longer exists, we start the download in the last active
1074 // browser. This is not ideal but better than fully hiding the download from 1131 // browser. This is not ideal but better than fully hiding the download from
1075 // the user. 1132 // the user.
1076 if (!contents) { 1133 if (!contents) {
1077 Browser* last_active = BrowserList::GetLastActive(); 1134 Browser* last_active = BrowserList::GetLastActive();
1078 if (last_active) 1135 if (last_active)
1079 contents = last_active->GetSelectedTabContents(); 1136 contents = last_active->GetSelectedTabContents();
1080 } 1137 }
1081 1138
1082 if (!contents) 1139 if (!contents)
1083 return; 1140 return;
1084 1141
1085 contents->OnStartDownload(download); 1142 contents->OnStartDownload(download);
1086 } 1143 }
1087 1144
1088 // Clears the last download path, used to initialize "save as" dialogs. 1145 // Clears the last download path, used to initialize "save as" dialogs.
1089 void DownloadManager::ClearLastDownloadPath() { 1146 void DownloadManager::ClearLastDownloadPath() {
1090 last_download_path_ = FilePath(); 1147 last_download_path_ = FilePath();
1091 } 1148 }
1092 1149
1093 void DownloadManager::NotifyModelChanged() { 1150 void DownloadManager::NotifyModelChanged() {
1094 FOR_EACH_OBSERVER(Observer, observers_, ModelChanged()); 1151 FOR_EACH_OBSERVER(Observer, observers_, ModelChanged());
1095 } 1152 }
1096 1153
1097 DownloadItem* DownloadManager::GetDownloadItem(int id) { 1154 DownloadItem* DownloadManager::GetDownloadItem(int download_id) {
1098 for (DownloadMap::iterator it = history_downloads_.begin(); 1155 for (DownloadMap::iterator it = history_downloads_.begin();
1099 it != history_downloads_.end(); ++it) { 1156 it != history_downloads_.end(); ++it) {
1100 DownloadItem* item = it->second; 1157 DownloadItem* item = it->second;
1101 if (item->id() == id) 1158 if (item->id() == download_id)
1102 return item; 1159 return item;
1103 } 1160 }
1104 return NULL; 1161 return NULL;
1105 } 1162 }
1106 1163
1164 DownloadItem* DownloadManager::GetActiveDownloadItem(int download_id) {
1165 DCHECK(ContainsKey(active_downloads_, download_id));
1166 DownloadItem* download = active_downloads_[download_id];
1167 DCHECK(download != NULL);
1168 return download;
1169 }
1170
1107 // Confirm that everything in all maps is also in |downloads_|, and that 1171 // Confirm that everything in all maps is also in |downloads_|, and that
1108 // everything in |downloads_| is also in some other map. 1172 // everything in |downloads_| is also in some other map.
1109 void DownloadManager::AssertContainersConsistent() const { 1173 void DownloadManager::AssertContainersConsistent() const {
1110 #if !defined(NDEBUG) 1174 #if !defined(NDEBUG)
1111 // Turn everything into sets. 1175 // Turn everything into sets.
1112 DownloadSet active_set, history_set; 1176 DownloadSet active_set, history_set;
1113 const DownloadMap* input_maps[] = {&active_downloads_, &history_downloads_}; 1177 const DownloadMap* input_maps[] = {&active_downloads_, &history_downloads_};
1114 DownloadSet* local_sets[] = {&active_set, &history_set}; 1178 DownloadSet* local_sets[] = {&active_set, &history_set};
1115 DCHECK_EQ(ARRAYSIZE_UNSAFE(input_maps), ARRAYSIZE_UNSAFE(local_sets)); 1179 DCHECK_EQ(ARRAYSIZE_UNSAFE(input_maps), ARRAYSIZE_UNSAFE(local_sets));
1116 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input_maps); i++) { 1180 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input_maps); i++) {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1170 observed_download_manager_->RemoveObserver(this); 1234 observed_download_manager_->RemoveObserver(this);
1171 } 1235 }
1172 1236
1173 void DownloadManager::OtherDownloadManagerObserver::ModelChanged() { 1237 void DownloadManager::OtherDownloadManagerObserver::ModelChanged() {
1174 observing_download_manager_->NotifyModelChanged(); 1238 observing_download_manager_->NotifyModelChanged();
1175 } 1239 }
1176 1240
1177 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() { 1241 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() {
1178 observed_download_manager_ = NULL; 1242 observed_download_manager_ = NULL;
1179 } 1243 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698