| OLD | NEW |
| 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" |
| 11 #include "base/path_service.h" | |
| 12 #include "base/rand_util.h" | 11 #include "base/rand_util.h" |
| 13 #include "base/stl_util-inl.h" | 12 #include "base/stl_util-inl.h" |
| 14 #include "base/stringprintf.h" | 13 #include "base/stringprintf.h" |
| 15 #include "base/sys_string_conversions.h" | 14 #include "base/sys_string_conversions.h" |
| 16 #include "base/task.h" | 15 #include "base/task.h" |
| 17 #include "base/utf_string_conversions.h" | 16 #include "base/utf_string_conversions.h" |
| 18 #include "build/build_config.h" | 17 #include "build/build_config.h" |
| 19 #include "chrome/browser/browser_process.h" | 18 #include "chrome/browser/browser_process.h" |
| 20 #include "chrome/browser/download/download_create_info.h" | 19 #include "chrome/browser/download/download_create_info.h" |
| 21 #include "chrome/browser/download/download_extensions.h" | 20 #include "chrome/browser/download/download_extensions.h" |
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 358 // the suggested path on the UI thread. | 357 // the suggested path on the UI thread. |
| 359 // We can only access preferences on the UI thread, so check the download path | 358 // We can only access preferences on the UI thread, so check the download path |
| 360 // now and pass the value to the FILE thread. | 359 // now and pass the value to the FILE thread. |
| 361 BrowserThread::PostTask( | 360 BrowserThread::PostTask( |
| 362 BrowserThread::FILE, FROM_HERE, | 361 BrowserThread::FILE, FROM_HERE, |
| 363 NewRunnableMethod( | 362 NewRunnableMethod( |
| 364 this, | 363 this, |
| 365 &DownloadManager::CheckIfSuggestedPathExists, | 364 &DownloadManager::CheckIfSuggestedPathExists, |
| 366 download->id(), | 365 download->id(), |
| 367 state, | 366 state, |
| 368 download_prefs()->download_path())); | 367 download_prefs()->download_path(), |
| 368 download_prefs()->GetDefaultDownloadDirectory())); |
| 369 } | 369 } |
| 370 | 370 |
| 371 void DownloadManager::CheckIfSuggestedPathExists(int32 download_id, | 371 void DownloadManager::CheckIfSuggestedPathExists( |
| 372 DownloadStateInfo state, | 372 int32 download_id, |
| 373 const FilePath& default_path) { | 373 DownloadStateInfo state, |
| 374 const FilePath& download_save_dir, |
| 375 const FilePath& default_download_dir) { |
| 374 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 376 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 375 | 377 |
| 376 // Make sure the default download directory exists. | 378 FilePath save_dir; |
| 377 // TODO(phajdan.jr): only create the directory when we're sure the user | 379 if (ChooseSavableDirectory( |
| 378 // is going to save there and not to another directory of his choice. | 380 FilePath(), download_save_dir, default_download_dir, &save_dir)) |
| 379 file_util::CreateDirectory(default_path); | |
| 380 | |
| 381 // Check writability of the suggested path. If we can't write to it, default | |
| 382 // to the user's "My Documents" directory. We'll prompt them in this case. | |
| 383 FilePath dir = state.suggested_path.DirName(); | |
| 384 FilePath filename = state.suggested_path.BaseName(); | |
| 385 if (!file_util::PathIsWritable(dir)) { | |
| 386 VLOG(1) << "Unable to write to directory \"" << dir.value() << "\""; | |
| 387 state.prompt_user_for_save_location = true; | 381 state.prompt_user_for_save_location = true; |
| 388 PathService::Get(chrome::DIR_USER_DOCUMENTS, &state.suggested_path); | 382 state.suggested_path = save_dir.Append(state.suggested_path.BaseName()); |
| 389 state.suggested_path = state.suggested_path.Append(filename); | |
| 390 } | |
| 391 | 383 |
| 392 // If the download is deemed dangerous, we'll use a temporary name for it. | 384 // If the download is deemed dangerous, we'll use a temporary name for it. |
| 393 if (state.IsDangerous()) { | 385 if (state.IsDangerous()) { |
| 394 state.target_name = FilePath(state.suggested_path).BaseName(); | 386 state.target_name = state.suggested_path.BaseName(); |
| 395 // Create a temporary file to hold the file until the user approves its | 387 // Create a temporary file to hold the file until the user approves its |
| 396 // download. | 388 // download. |
| 397 FilePath::StringType file_name; | 389 FilePath::StringType file_name; |
| 398 FilePath path; | 390 FilePath path; |
| 399 #if defined(OS_WIN) | 391 #if defined(OS_WIN) |
| 400 string16 unconfirmed_prefix = | 392 string16 unconfirmed_prefix = |
| 401 l10n_util::GetStringUTF16(IDS_DOWNLOAD_UNCONFIRMED_PREFIX); | 393 l10n_util::GetStringUTF16(IDS_DOWNLOAD_UNCONFIRMED_PREFIX); |
| 402 #else | 394 #else |
| 403 std::string unconfirmed_prefix = | 395 std::string unconfirmed_prefix = |
| 404 l10n_util::GetStringUTF8(IDS_DOWNLOAD_UNCONFIRMED_PREFIX); | 396 l10n_util::GetStringUTF8(IDS_DOWNLOAD_UNCONFIRMED_PREFIX); |
| 405 #endif | 397 #endif |
| 406 | 398 |
| 407 while (path.empty()) { | 399 while (path.empty()) { |
| 408 base::SStringPrintf( | 400 base::SStringPrintf( |
| 409 &file_name, | 401 &file_name, |
| 410 unconfirmed_prefix.append( | 402 unconfirmed_prefix.append( |
| 411 FILE_PATH_LITERAL(" %d.crdownload")).c_str(), | 403 FILE_PATH_LITERAL(" %d.crdownload")).c_str(), |
| 412 base::RandInt(0, 100000)); | 404 base::RandInt(0, 100000)); |
| 413 path = dir.Append(file_name); | 405 path = state.suggested_path.DirName().Append(file_name); |
| 414 if (file_util::PathExists(path)) | 406 if (file_util::PathExists(path)) |
| 415 path = FilePath(); | 407 path = FilePath(); |
| 416 } | 408 } |
| 417 state.suggested_path = path; | 409 state.suggested_path = path; |
| 418 } else { | 410 } else { |
| 419 // Do not add the path uniquifier if we are saving to a specific path as in | 411 // Do not add the path uniquifier if we are saving to a specific path as in |
| 420 // the drag-out case. | 412 // the drag-out case. |
| 421 if (state.force_file_name.empty()) { | 413 if (state.force_file_name.empty()) { |
| 422 state.path_uniquifier = download_util::GetUniquePathNumberWithCrDownload( | 414 state.path_uniquifier = download_util::GetUniquePathNumberWithCrDownload( |
| 423 state.suggested_path); | 415 state.suggested_path); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 493 // FileSelectionCancelled(). | 485 // FileSelectionCancelled(). |
| 494 int32* id_ptr = new int32; | 486 int32* id_ptr = new int32; |
| 495 *id_ptr = download_id; | 487 *id_ptr = download_id; |
| 496 select_file_dialog_->SelectFile(SelectFileDialog::SELECT_SAVEAS_FILE, | 488 select_file_dialog_->SelectFile(SelectFileDialog::SELECT_SAVEAS_FILE, |
| 497 string16(), | 489 string16(), |
| 498 suggested_path, | 490 suggested_path, |
| 499 &file_type_info, 0, FILE_PATH_LITERAL(""), | 491 &file_type_info, 0, FILE_PATH_LITERAL(""), |
| 500 contents, owning_window, | 492 contents, owning_window, |
| 501 reinterpret_cast<void*>(id_ptr)); | 493 reinterpret_cast<void*>(id_ptr)); |
| 502 FOR_EACH_OBSERVER(Observer, observers_, | 494 FOR_EACH_OBSERVER(Observer, observers_, |
| 503 SelectFileDialogDisplayed(download_id)); | 495 SelectFileDialogDisplayed(download_id, suggested_path)); |
| 504 } else { | 496 } else { |
| 505 // No prompting for download, just continue with the suggested name. | 497 // No prompting for download, just continue with the suggested name. |
| 506 ContinueDownloadWithPath(download, suggested_path); | 498 ContinueDownloadWithPath(download, suggested_path); |
| 507 } | 499 } |
| 508 } | 500 } |
| 509 | 501 |
| 510 void DownloadManager::CreateDownloadItem(DownloadCreateInfo* info) { | 502 void DownloadManager::CreateDownloadItem(DownloadCreateInfo* info) { |
| 511 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 503 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 512 | 504 |
| 513 DownloadItem* download = new DownloadItem(this, *info, | 505 DownloadItem* download = new DownloadItem(this, *info, |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 645 } | 637 } |
| 646 | 638 |
| 647 void DownloadManager::AssertNotInQueues(DownloadItem* download) { | 639 void DownloadManager::AssertNotInQueues(DownloadItem* download) { |
| 648 // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved. | 640 // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved. |
| 649 CHECK(!ContainsKey(downloads_, download)); | 641 CHECK(!ContainsKey(downloads_, download)); |
| 650 CHECK(!ContainsKey(active_downloads_, download->id())); | 642 CHECK(!ContainsKey(active_downloads_, download->id())); |
| 651 CHECK(!ContainsKey(in_progress_, download->id())); | 643 CHECK(!ContainsKey(in_progress_, download->id())); |
| 652 CHECK(!ContainsKey(history_downloads_, download->db_handle())); | 644 CHECK(!ContainsKey(history_downloads_, download->db_handle())); |
| 653 } | 645 } |
| 654 | 646 |
| 647 // static |
| 648 bool DownloadManager::ChooseSavableDirectory( |
| 649 const FilePath& website_save_dir, |
| 650 const FilePath& download_save_dir, |
| 651 const FilePath& default_download_dir, |
| 652 FilePath* save_dir) { |
| 653 bool prompt_dialog = false; |
| 654 if (file_util::PathIsWritable(website_save_dir)) { |
| 655 // If the default html/websites save folder exists, |
| 656 // then use the default h5Btml/websites save folder. |
| 657 *save_dir = website_save_dir; |
| 658 } else if (file_util::PathIsWritable(download_save_dir)) { |
| 659 // If the default html/websites save folder does not exist |
| 660 // but the default download folder exists, |
| 661 // then use the default download folder. |
| 662 *save_dir = download_save_dir; |
| 663 } else { |
| 664 // If both the above folders do not exist, |
| 665 // use the user's "Downloads" folder. |
| 666 *save_dir = default_download_dir; |
| 667 prompt_dialog = true; |
| 668 if (!file_util::PathIsWritable(*save_dir)) { |
| 669 VLOG(1) << "Cannot find the user's writable \"Downloads\" folder."; |
| 670 // Create the |download_save_dir| folder if we cannot get |
| 671 // the user's writable "Downloads" folder (This will be a rare case). |
| 672 *save_dir = download_save_dir; |
| 673 } |
| 674 // Make sure that the folder does exist. |
| 675 if (!file_util::CreateDirectory(*save_dir)) |
| 676 LOG(ERROR) << "Failed to create " << (*save_dir).value(); |
| 677 } |
| 678 return prompt_dialog; |
| 679 } |
| 680 |
| 655 bool DownloadManager::IsDownloadReadyForCompletion(DownloadItem* download) { | 681 bool DownloadManager::IsDownloadReadyForCompletion(DownloadItem* download) { |
| 656 // If we don't have all the data, the download is not ready for | 682 // If we don't have all the data, the download is not ready for |
| 657 // completion. | 683 // completion. |
| 658 if (!download->all_data_saved()) | 684 if (!download->all_data_saved()) |
| 659 return false; | 685 return false; |
| 660 | 686 |
| 661 // If the download is dangerous, but not yet validated, it's not ready for | 687 // If the download is dangerous, but not yet validated, it's not ready for |
| 662 // completion. | 688 // completion. |
| 663 if (download->safety_state() == DownloadItem::DANGEROUS) | 689 if (download->safety_state() == DownloadItem::DANGEROUS) |
| 664 return false; | 690 return false; |
| (...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1261 observed_download_manager_->RemoveObserver(this); | 1287 observed_download_manager_->RemoveObserver(this); |
| 1262 } | 1288 } |
| 1263 | 1289 |
| 1264 void DownloadManager::OtherDownloadManagerObserver::ModelChanged() { | 1290 void DownloadManager::OtherDownloadManagerObserver::ModelChanged() { |
| 1265 observing_download_manager_->NotifyModelChanged(); | 1291 observing_download_manager_->NotifyModelChanged(); |
| 1266 } | 1292 } |
| 1267 | 1293 |
| 1268 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() { | 1294 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() { |
| 1269 observed_download_manager_ = NULL; | 1295 observed_download_manager_ = NULL; |
| 1270 } | 1296 } |
| OLD | NEW |