| Index: chrome/browser/download/download_manager.cc
|
| ===================================================================
|
| --- chrome/browser/download/download_manager.cc (revision 35459)
|
| +++ chrome/browser/download/download_manager.cc (working copy)
|
| @@ -135,7 +135,10 @@
|
| auto_opened_(false),
|
| original_name_(info.original_name),
|
| render_process_id_(-1),
|
| - request_id_(-1) {
|
| + request_id_(-1),
|
| + save_as_(false),
|
| + name_finalized_(false),
|
| + is_temporary_(false) {
|
| if (state_ == IN_PROGRESS)
|
| state_ = CANCELLED;
|
| Init(false /* don't start progress timer */);
|
| @@ -155,7 +158,8 @@
|
| int request_id,
|
| bool is_dangerous,
|
| bool save_as,
|
| - bool is_extension_install)
|
| + bool is_extension_install,
|
| + bool is_temporary)
|
| : id_(download_id),
|
| full_path_(path),
|
| path_uniquifier_(path_uniquifier),
|
| @@ -177,7 +181,9 @@
|
| render_process_id_(render_process_id),
|
| request_id_(request_id),
|
| save_as_(save_as),
|
| - is_extension_install_(is_extension_install) {
|
| + is_extension_install_(is_extension_install),
|
| + name_finalized_(false),
|
| + is_temporary_(is_temporary) {
|
| Init(true /* start progress timer */);
|
| }
|
|
|
| @@ -204,6 +210,10 @@
|
| FOR_EACH_OBSERVER(Observer, observers_, OnDownloadUpdated(this));
|
| }
|
|
|
| +void DownloadItem::NotifyObserversDownloadFileCompleted() {
|
| + FOR_EACH_OBSERVER(Observer, observers_, OnDownloadFileCompleted(this));
|
| +}
|
| +
|
| void DownloadItem::NotifyObserversDownloadOpened() {
|
| FOR_EACH_OBSERVER(Observer, observers_, OnDownloadOpened(this));
|
| }
|
| @@ -470,6 +480,22 @@
|
| }
|
| }
|
|
|
| +void DownloadManager::GetTemporaryDownloads(Observer* observer,
|
| + const FilePath& dir_path) {
|
| + DCHECK(observer);
|
| +
|
| + std::vector<DownloadItem*> download_copy;
|
| +
|
| + for (DownloadMap::iterator it = downloads_.begin();
|
| + it != downloads_.end(); ++it) {
|
| + if (it->second->is_temporary() &&
|
| + it->second->full_path().DirName() == dir_path)
|
| + download_copy.push_back(it->second);
|
| + }
|
| +
|
| + observer->SetDownloads(download_copy);
|
| +}
|
| +
|
| // Query the history service for information about all persisted downloads.
|
| bool DownloadManager::Init(Profile* profile) {
|
| DCHECK(profile);
|
| @@ -507,9 +533,6 @@
|
| ChromeThread::FILE, FROM_HERE,
|
| NewRunnableFunction(&file_util::CreateDirectory, download_path()));
|
|
|
| - // We use this to determine possibly dangerous downloads.
|
| - download_util::InitializeExeTypes(&exe_types_);
|
| -
|
| // We store any file extension that should be opened automatically at
|
| // download completion in this pref.
|
| std::wstring extensions_to_open =
|
| @@ -563,17 +586,21 @@
|
| info->save_as = true;
|
| }
|
|
|
| - // Determine the proper path for a download, by choosing either the default
|
| - // download directory, or prompting the user.
|
| + // Determine the proper path for a download, by either one of the following:
|
| + // 1) using the provided save file path.
|
| + // 2) using the default download directory.
|
| + // 3) prompting the user.
|
| FilePath generated_name;
|
| - GenerateFilename(info, &generated_name);
|
| - if (info->save_as && !last_download_path_.empty())
|
| + GenerateFileNameFromInfo(info, &generated_name);
|
| + if (!info->save_file_path.empty())
|
| + info->suggested_path = info->save_file_path;
|
| + else if (info->save_as && !last_download_path_.empty())
|
| info->suggested_path = last_download_path_;
|
| else
|
| info->suggested_path = download_path();
|
| info->suggested_path = info->suggested_path.Append(generated_name);
|
|
|
| - if (!info->save_as) {
|
| + if (!info->save_as && info->save_file_path.empty()) {
|
| // Downloads can be marked as dangerous for two reasons:
|
| // a) They have a dangerous-looking filename
|
| // b) They are an extension that is not from the gallery
|
| @@ -703,7 +730,8 @@
|
| info->request_id,
|
| info->is_dangerous,
|
| info->save_as,
|
| - info->is_extension_install);
|
| + info->is_extension_install,
|
| + !info->save_file_path.empty());
|
| download->set_manager(this);
|
| in_progress_[info->download_id] = download;
|
| } else {
|
| @@ -731,11 +759,13 @@
|
| // Do not store the download in the history database for a few special cases:
|
| // - incognito mode (that is the point of this mode)
|
| // - extensions (users don't think of extension installation as 'downloading')
|
| + // - temporary download, like in drag-and-drop
|
| // We have to make sure that these handles don't collide with normal db
|
| // handles, so we use a negative value. Eventually, they could overlap, but
|
| // you'd have to do enough downloading that your ISP would likely stab you in
|
| // the neck first. YMMV.
|
| - if (profile_->IsOffTheRecord() || download->is_extension_install()) {
|
| + if (profile_->IsOffTheRecord() || download->is_extension_install() ||
|
| + download->is_temporary()) {
|
| static int64 fake_db_handle = kUninitializedHandle - 1;
|
| OnCreateDownloadEntryComplete(*info, fake_db_handle--);
|
| } else {
|
| @@ -848,6 +878,21 @@
|
|
|
| void DownloadManager::DownloadRenamedToFinalName(int download_id,
|
| const FilePath& full_path) {
|
| + DownloadMap::iterator it = downloads_.begin();
|
| + while (it != downloads_.end()) {
|
| + DownloadItem* download = it->second;
|
| + if (download->id() == download_id) {
|
| + // The download file is meant to be completed if both the filename is
|
| + // finalized and the file data is downloaded. The ordering of these two
|
| + // actions is indeterministic. Thus, if we are still in downloading the
|
| + // file, delay the notification.
|
| + download->set_name_finalized(true);
|
| + if (download->state() == DownloadItem::COMPLETE)
|
| + download->NotifyObserversDownloadFileCompleted();
|
| + return;
|
| + }
|
| + it++;
|
| + }
|
| }
|
|
|
| void DownloadManager::ContinueDownloadFinished(DownloadItem* download) {
|
| @@ -863,14 +908,26 @@
|
| download->referrer_url());
|
| download->set_auto_opened(true);
|
| } else if (download->open_when_complete() ||
|
| - ShouldOpenFileBasedOnExtension(download->full_path())) {
|
| - OpenDownloadInShell(download, NULL);
|
| + ShouldOpenFileBasedOnExtension(download->full_path()) ||
|
| + download->is_temporary()) {
|
| + // If the download is temporary, like in drag-and-drop, do not open it but
|
| + // we still need to set it auto-opened so that it can be removed from the
|
| + // download shelf.
|
| + if (!download->is_temporary())
|
| + OpenDownloadInShell(download, NULL);
|
| download->set_auto_opened(true);
|
| }
|
|
|
| // Notify our observers that we are complete (the call to Finished() set the
|
| // state to complete but did not notify).
|
| download->UpdateObservers();
|
| +
|
| + // The download file is meant to be completed if both the filename is
|
| + // finalized and the file data is downloaded. The ordering of these two
|
| + // actions is indeterministic. Thus, if the filename is not finalized yet,
|
| + // delay the notification.
|
| + if (download->name_finalized())
|
| + download->NotifyObserversDownloadFileCompleted();
|
| }
|
|
|
| // Called on the file thread. Renames the downloaded file to its original name.
|
| @@ -1097,10 +1154,25 @@
|
| const GURL& referrer,
|
| const std::string& referrer_charset,
|
| TabContents* tab_contents) {
|
| + file_manager_->DownloadUrl(url,
|
| + referrer,
|
| + referrer_charset,
|
| + FilePath(),
|
| + tab_contents->process()->id(),
|
| + tab_contents->render_view_host()->routing_id(),
|
| + request_context_getter_);
|
| +}
|
| +
|
| +void DownloadManager::DownloadUrlToFile(const GURL& url,
|
| + const GURL& referrer,
|
| + const std::string& referrer_charset,
|
| + const FilePath& save_file_path,
|
| + TabContents* tab_contents) {
|
| DCHECK(tab_contents);
|
| file_manager_->DownloadUrl(url,
|
| referrer,
|
| referrer_charset,
|
| + save_file_path,
|
| tab_contents->process()->id(),
|
| tab_contents->render_view_host()->routing_id(),
|
| request_context_getter_);
|
| @@ -1189,7 +1261,19 @@
|
| generated_extension->swap(extension);
|
| }
|
|
|
| -void DownloadManager::GenerateFilename(DownloadCreateInfo* info,
|
| +void DownloadManager::GenerateFileNameFromInfo(DownloadCreateInfo* info,
|
| + FilePath* generated_name) {
|
| + GenerateFileName(GURL(info->url),
|
| + info->content_disposition,
|
| + info->referrer_charset,
|
| + info->mime_type,
|
| + generated_name);
|
| +}
|
| +
|
| +void DownloadManager::GenerateFileName(const GURL& url,
|
| + const std::string& content_disposition,
|
| + const std::string& referrer_charset,
|
| + const std::string& mime_type,
|
| FilePath* generated_name) {
|
| std::wstring default_name =
|
| l10n_util::GetString(IDS_DEFAULT_DOWNLOAD_FILENAME);
|
| @@ -1199,14 +1283,14 @@
|
| FilePath default_file_path(base::SysWideToNativeMB(default_name));
|
| #endif
|
|
|
| - *generated_name = net::GetSuggestedFilename(GURL(info->url),
|
| - info->content_disposition,
|
| - info->referrer_charset,
|
| + *generated_name = net::GetSuggestedFilename(GURL(url),
|
| + content_disposition,
|
| + referrer_charset,
|
| default_file_path);
|
|
|
| DCHECK(!generated_name->empty());
|
|
|
| - GenerateSafeFilename(info->mime_type, generated_name);
|
| + GenerateSafeFileName(mime_type, generated_name);
|
| }
|
|
|
| void DownloadManager::AddObserver(Observer* observer) {
|
| @@ -1363,7 +1447,7 @@
|
| }
|
|
|
| bool DownloadManager::IsExecutableExtension(
|
| - const FilePath::StringType& extension) const {
|
| + const FilePath::StringType& extension) {
|
| if (extension.empty())
|
| return false;
|
| if (!IsStringASCII(extension))
|
| @@ -1373,13 +1457,12 @@
|
| #elif defined(OS_POSIX)
|
| std::string ascii_extension = extension;
|
| #endif
|
| - StringToLowerASCII(&ascii_extension);
|
|
|
| // Strip out leading dot if it's still there
|
| if (ascii_extension[0] == FilePath::kExtensionSeparator)
|
| ascii_extension.erase(0, 1);
|
|
|
| - return exe_types_.find(ascii_extension) != exe_types_.end();
|
| + return download_util::IsExecutableExtension(ascii_extension);
|
| }
|
|
|
| void DownloadManager::ResetAutoOpenFiles() {
|
| @@ -1455,7 +1538,7 @@
|
| download->original_name()));
|
| }
|
|
|
| -void DownloadManager::GenerateSafeFilename(const std::string& mime_type,
|
| +void DownloadManager::GenerateSafeFileName(const std::string& mime_type,
|
| FilePath* file_name) {
|
| // Make sure we get the right file extension
|
| FilePath::StringType extension;
|
|
|