| OLD | NEW |
| 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_manager.h" | 5 #include "chrome/browser/download/download_manager.h" |
| 6 | 6 |
| 7 #include "app/l10n_util.h" | 7 #include "app/l10n_util.h" |
| 8 #include "app/resource_bundle.h" | 8 #include "app/resource_bundle.h" |
| 9 #include "base/callback.h" | 9 #include "base/callback.h" |
| 10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
| (...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 397 // history system of a new download. Since this method can be called while the | 397 // history system of a new download. Since this method can be called while the |
| 398 // history service thread is still reading the persistent state, we do not | 398 // history service thread is still reading the persistent state, we do not |
| 399 // insert the new DownloadItem into 'downloads_' or inform our observers at this | 399 // insert the new DownloadItem into 'downloads_' or inform our observers at this |
| 400 // point. OnCreateDatabaseEntryComplete() handles that finalization of the the | 400 // point. OnCreateDatabaseEntryComplete() handles that finalization of the the |
| 401 // download creation as a callback from the history thread. | 401 // download creation as a callback from the history thread. |
| 402 void DownloadManager::StartDownload(DownloadCreateInfo* info) { | 402 void DownloadManager::StartDownload(DownloadCreateInfo* info) { |
| 403 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 403 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
| 404 DCHECK(info); | 404 DCHECK(info); |
| 405 | 405 |
| 406 // Check whether this download is for an extension install or not. | 406 // Check whether this download is for an extension install or not. |
| 407 // Allow extensions to be explicitly saved. | 407 if (!info->save_as) { // Allow extensions to be explicitly saved. |
| 408 if (!info->prompt_user_for_save_location) { | |
| 409 if (UserScript::HasUserScriptFileExtension(info->url) || | 408 if (UserScript::HasUserScriptFileExtension(info->url) || |
| 410 info->mime_type == Extension::kMimeType) | 409 info->mime_type == Extension::kMimeType) |
| 411 info->is_extension_install = true; | 410 info->is_extension_install = true; |
| 412 } | 411 } |
| 413 | 412 |
| 414 if (info->save_info.file_path.empty()) { | 413 if (info->save_info.file_path.empty()) { |
| 415 FilePath generated_name; | 414 FilePath generated_name; |
| 416 GenerateFileNameFromInfo(info, &generated_name); | 415 GenerateFileNameFromInfo(info, &generated_name); |
| 417 | 416 |
| 418 // Freeze the user's preference for showing a Save As dialog. We're going | 417 // Freeze the user's preference for showing a Save As dialog. We're going |
| 419 // to bounce around a bunch of threads and we don't want to worry about race | 418 // to bounce around a bunch of threads and we don't want to worry about race |
| 420 // conditions where the user changes this pref out from under us. | 419 // conditions where the user changes this pref out from under us. |
| 421 if (*prompt_for_download_) { | 420 if (*prompt_for_download_) { |
| 422 // But ignore the user's preference for the following scenarios: | 421 // But ignore the user's preference for the following scenarios: |
| 423 // 1) Extension installation. Note that we only care here about the case | 422 // 1) Extension installation. Note that we only care here about the case |
| 424 // where an extension is installed, not when one is downloaded with | 423 // where an extension is installed, not when one is downloaded with |
| 425 // "save as...". | 424 // "save as...". |
| 426 // 2) Filetypes marked "always open." If the user just wants this file | 425 // 2) Filetypes marked "always open." If the user just wants this file |
| 427 // opened, don't bother asking where to keep it. | 426 // opened, don't bother asking where to keep it. |
| 428 if (!info->is_extension_install && | 427 if (!info->is_extension_install && |
| 429 !ShouldOpenFileBasedOnExtension(generated_name)) | 428 !ShouldOpenFileBasedOnExtension(generated_name)) |
| 430 info->prompt_user_for_save_location = true; | 429 info->save_as = true; |
| 431 } | 430 } |
| 432 | 431 |
| 433 // Determine the proper path for a download, by either one of the following: | 432 // Determine the proper path for a download, by either one of the following: |
| 434 // 1) using the default download directory. | 433 // 1) using the default download directory. |
| 435 // 2) prompting the user. | 434 // 2) prompting the user. |
| 436 if (info->prompt_user_for_save_location && !last_download_path_.empty()) | 435 if (info->save_as && !last_download_path_.empty()) |
| 437 info->suggested_path = last_download_path_; | 436 info->suggested_path = last_download_path_; |
| 438 else | 437 else |
| 439 info->suggested_path = download_path(); | 438 info->suggested_path = download_path(); |
| 440 info->suggested_path = info->suggested_path.Append(generated_name); | 439 info->suggested_path = info->suggested_path.Append(generated_name); |
| 441 } else { | 440 } else { |
| 442 info->suggested_path = info->save_info.file_path; | 441 info->suggested_path = info->save_info.file_path; |
| 443 } | 442 } |
| 444 | 443 |
| 445 if (!info->prompt_user_for_save_location && | 444 if (!info->save_as && info->save_info.file_path.empty()) { |
| 446 info->save_info.file_path.empty()) { | |
| 447 // Downloads can be marked as dangerous for two reasons: | 445 // Downloads can be marked as dangerous for two reasons: |
| 448 // a) They have a dangerous-looking filename | 446 // a) They have a dangerous-looking filename |
| 449 // b) They are an extension that is not from the gallery | 447 // b) They are an extension that is not from the gallery |
| 450 if (IsDangerous(info->suggested_path.BaseName())) | 448 if (IsDangerous(info->suggested_path.BaseName())) |
| 451 info->is_dangerous = true; | 449 info->is_dangerous = true; |
| 452 else if (info->is_extension_install && | 450 else if (info->is_extension_install && |
| 453 !ExtensionsService::IsDownloadFromGallery(info->url, | 451 !ExtensionsService::IsDownloadFromGallery(info->url, |
| 454 info->referrer_url)) { | 452 info->referrer_url)) { |
| 455 info->is_dangerous = true; | 453 info->is_dangerous = true; |
| 456 } | 454 } |
| 457 } | 455 } |
| 458 | 456 |
| 459 // We need to move over to the download thread because we don't want to stat | 457 // We need to move over to the download thread because we don't want to stat |
| 460 // the suggested path on the UI thread. | 458 // the suggested path on the UI thread. |
| 461 ChromeThread::PostTask( | 459 ChromeThread::PostTask( |
| 462 ChromeThread::FILE, FROM_HERE, | 460 ChromeThread::FILE, FROM_HERE, |
| 463 NewRunnableMethod( | 461 NewRunnableMethod( |
| 464 this, &DownloadManager::CheckIfSuggestedPathExists, info)); | 462 this, &DownloadManager::CheckIfSuggestedPathExists, info)); |
| 465 } | 463 } |
| 466 | 464 |
| 467 void DownloadManager::CheckIfSuggestedPathExists(DownloadCreateInfo* info) { | 465 void DownloadManager::CheckIfSuggestedPathExists(DownloadCreateInfo* info) { |
| 468 DCHECK(info); | 466 DCHECK(info); |
| 469 | 467 |
| 470 // Check writability of the suggested path. If we can't write to it, default | 468 // Check writability of the suggested path. If we can't write to it, default |
| 471 // to the user's "My Documents" directory. We'll prompt them in this case. | 469 // to the user's "My Documents" directory. We'll prompt them in this case. |
| 472 FilePath dir = info->suggested_path.DirName(); | 470 FilePath dir = info->suggested_path.DirName(); |
| 473 FilePath filename = info->suggested_path.BaseName(); | 471 FilePath filename = info->suggested_path.BaseName(); |
| 474 if (!file_util::PathIsWritable(dir)) { | 472 if (!file_util::PathIsWritable(dir)) { |
| 475 info->prompt_user_for_save_location = true; | 473 info->save_as = true; |
| 476 PathService::Get(chrome::DIR_USER_DOCUMENTS, &info->suggested_path); | 474 PathService::Get(chrome::DIR_USER_DOCUMENTS, &info->suggested_path); |
| 477 info->suggested_path = info->suggested_path.Append(filename); | 475 info->suggested_path = info->suggested_path.Append(filename); |
| 478 } | 476 } |
| 479 | 477 |
| 480 // Do not add the path uniquifier if we are saving to a specific path as in | 478 // Do not add the path uniquifier if we are saving to a specific path as in |
| 481 // the drag-out case. | 479 // the drag-out case. |
| 482 if (info->save_info.file_path.empty()) { | 480 if (info->save_info.file_path.empty()) { |
| 483 info->path_uniquifier = download_util::GetUniquePathNumber( | 481 info->path_uniquifier = download_util::GetUniquePathNumber( |
| 484 info->suggested_path); | 482 info->suggested_path); |
| 485 } | 483 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 502 } else { | 500 } else { |
| 503 // We know the final path, build it if necessary. | 501 // We know the final path, build it if necessary. |
| 504 if (info->path_uniquifier > 0) { | 502 if (info->path_uniquifier > 0) { |
| 505 download_util::AppendNumberToPath(&(info->suggested_path), | 503 download_util::AppendNumberToPath(&(info->suggested_path), |
| 506 info->path_uniquifier); | 504 info->path_uniquifier); |
| 507 // Setting path_uniquifier to 0 to make sure we don't try to unique it | 505 // Setting path_uniquifier to 0 to make sure we don't try to unique it |
| 508 // later on. | 506 // later on. |
| 509 info->path_uniquifier = 0; | 507 info->path_uniquifier = 0; |
| 510 } else if (info->path_uniquifier == -1) { | 508 } else if (info->path_uniquifier == -1) { |
| 511 // We failed to find a unique path. We have to prompt the user. | 509 // We failed to find a unique path. We have to prompt the user. |
| 512 info->prompt_user_for_save_location = true; | 510 info->save_as = true; |
| 513 } | 511 } |
| 514 } | 512 } |
| 515 | 513 |
| 516 if (!info->prompt_user_for_save_location && | 514 if (!info->save_as && info->save_info.file_path.empty()) { |
| 517 info->save_info.file_path.empty()) { | |
| 518 // Create an empty file at the suggested path so that we don't allocate the | 515 // Create an empty file at the suggested path so that we don't allocate the |
| 519 // same "non-existant" path to multiple downloads. | 516 // same "non-existant" path to multiple downloads. |
| 520 // See: http://code.google.com/p/chromium/issues/detail?id=3662 | 517 // See: http://code.google.com/p/chromium/issues/detail?id=3662 |
| 521 file_util::WriteFile(info->suggested_path, "", 0); | 518 file_util::WriteFile(info->suggested_path, "", 0); |
| 522 } | 519 } |
| 523 | 520 |
| 524 // Now we return to the UI thread. | 521 // Now we return to the UI thread. |
| 525 ChromeThread::PostTask( | 522 ChromeThread::PostTask( |
| 526 ChromeThread::UI, FROM_HERE, | 523 ChromeThread::UI, FROM_HERE, |
| 527 NewRunnableMethod(this, | 524 NewRunnableMethod(this, |
| 528 &DownloadManager::OnPathExistenceAvailable, | 525 &DownloadManager::OnPathExistenceAvailable, |
| 529 info)); | 526 info)); |
| 530 } | 527 } |
| 531 | 528 |
| 532 void DownloadManager::OnPathExistenceAvailable(DownloadCreateInfo* info) { | 529 void DownloadManager::OnPathExistenceAvailable(DownloadCreateInfo* info) { |
| 533 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 530 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
| 534 DCHECK(info); | 531 DCHECK(info); |
| 535 | 532 |
| 536 if (info->prompt_user_for_save_location) { | 533 if (info->save_as) { |
| 537 // We must ask the user for the place to put the download. | 534 // We must ask the user for the place to put the download. |
| 538 if (!select_file_dialog_.get()) | 535 if (!select_file_dialog_.get()) |
| 539 select_file_dialog_ = SelectFileDialog::Create(this); | 536 select_file_dialog_ = SelectFileDialog::Create(this); |
| 540 | 537 |
| 541 TabContents* contents = tab_util::GetTabContentsByID(info->child_id, | 538 TabContents* contents = tab_util::GetTabContentsByID(info->child_id, |
| 542 info->render_view_id); | 539 info->render_view_id); |
| 543 SelectFileDialog::FileTypeInfo file_type_info; | 540 SelectFileDialog::FileTypeInfo file_type_info; |
| 544 file_type_info.extensions.resize(1); | 541 file_type_info.extensions.resize(1); |
| 545 file_type_info.extensions[0].push_back(info->suggested_path.Extension()); | 542 file_type_info.extensions[0].push_back(info->suggested_path.Extension()); |
| 546 if (!file_type_info.extensions[0][0].empty()) | 543 if (!file_type_info.extensions[0][0].empty()) |
| (...skipping 26 matching lines...) Expand all Loading... |
| 573 info->url, | 570 info->url, |
| 574 info->referrer_url, | 571 info->referrer_url, |
| 575 info->mime_type, | 572 info->mime_type, |
| 576 info->original_mime_type, | 573 info->original_mime_type, |
| 577 info->original_name, | 574 info->original_name, |
| 578 info->start_time, | 575 info->start_time, |
| 579 info->total_bytes, | 576 info->total_bytes, |
| 580 info->child_id, | 577 info->child_id, |
| 581 info->request_id, | 578 info->request_id, |
| 582 info->is_dangerous, | 579 info->is_dangerous, |
| 583 info->prompt_user_for_save_location, | 580 info->save_as, |
| 584 profile_->IsOffTheRecord(), | 581 profile_->IsOffTheRecord(), |
| 585 info->is_extension_install, | 582 info->is_extension_install, |
| 586 !info->save_info.file_path.empty()); | 583 !info->save_info.file_path.empty()); |
| 587 download->set_manager(this); | 584 download->set_manager(this); |
| 588 in_progress_[info->download_id] = download; | 585 in_progress_[info->download_id] = download; |
| 589 } else { | 586 } else { |
| 590 NOTREACHED(); // Should not exist! | 587 NOTREACHED(); // Should not exist! |
| 591 return; | 588 return; |
| 592 } | 589 } |
| 593 | 590 |
| (...skipping 812 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1406 if (!extensions.empty()) | 1403 if (!extensions.empty()) |
| 1407 extensions.erase(extensions.size() - 1); | 1404 extensions.erase(extensions.size() - 1); |
| 1408 | 1405 |
| 1409 prefs->SetString(prefs::kDownloadExtensionsToOpen, extensions); | 1406 prefs->SetString(prefs::kDownloadExtensionsToOpen, extensions); |
| 1410 } | 1407 } |
| 1411 } | 1408 } |
| 1412 | 1409 |
| 1413 void DownloadManager::FileSelected(const FilePath& path, | 1410 void DownloadManager::FileSelected(const FilePath& path, |
| 1414 int index, void* params) { | 1411 int index, void* params) { |
| 1415 DownloadCreateInfo* info = reinterpret_cast<DownloadCreateInfo*>(params); | 1412 DownloadCreateInfo* info = reinterpret_cast<DownloadCreateInfo*>(params); |
| 1416 if (info->prompt_user_for_save_location) | 1413 if (info->save_as) |
| 1417 last_download_path_ = path.DirName(); | 1414 last_download_path_ = path.DirName(); |
| 1418 ContinueStartDownload(info, path); | 1415 ContinueStartDownload(info, path); |
| 1419 } | 1416 } |
| 1420 | 1417 |
| 1421 void DownloadManager::FileSelectionCanceled(void* params) { | 1418 void DownloadManager::FileSelectionCanceled(void* params) { |
| 1422 // The user didn't pick a place to save the file, so need to cancel the | 1419 // The user didn't pick a place to save the file, so need to cancel the |
| 1423 // download that's already in progress to the temporary location. | 1420 // download that's already in progress to the temporary location. |
| 1424 DownloadCreateInfo* info = reinterpret_cast<DownloadCreateInfo*>(params); | 1421 DownloadCreateInfo* info = reinterpret_cast<DownloadCreateInfo*>(params); |
| 1425 DownloadCancelledInternal(info->download_id, | 1422 DownloadCancelledInternal(info->download_id, |
| 1426 info->child_id, | 1423 info->child_id, |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1608 observing_download_manager_->NotifyModelChanged(); | 1605 observing_download_manager_->NotifyModelChanged(); |
| 1609 } | 1606 } |
| 1610 | 1607 |
| 1611 void DownloadManager::OtherDownloadManagerObserver::SetDownloads( | 1608 void DownloadManager::OtherDownloadManagerObserver::SetDownloads( |
| 1612 std::vector<DownloadItem*>& downloads) { | 1609 std::vector<DownloadItem*>& downloads) { |
| 1613 } | 1610 } |
| 1614 | 1611 |
| 1615 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() { | 1612 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() { |
| 1616 observed_download_manager_ = NULL; | 1613 observed_download_manager_ = NULL; |
| 1617 } | 1614 } |
| OLD | NEW |