Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/chrome_download_manager_delegate.h" | 5 #include "chrome/browser/download/chrome_download_manager_delegate.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| 11 #include "base/callback.h" | 11 #include "base/callback.h" |
| 12 #include "base/file_util.h" | 12 #include "base/file_util.h" |
| 13 #include "base/prefs/pref_member.h" | 13 #include "base/prefs/pref_member.h" |
| 14 #include "base/prefs/pref_service.h" | 14 #include "base/prefs/pref_service.h" |
| 15 #include "base/rand_util.h" | 15 #include "base/rand_util.h" |
| 16 #include "base/stringprintf.h" | 16 #include "base/stringprintf.h" |
| 17 #include "base/time.h" | 17 #include "base/time.h" |
| 18 #include "base/utf_string_conversions.h" | 18 #include "base/utf_string_conversions.h" |
| 19 #include "chrome/browser/browser_process.h" | 19 #include "chrome/browser/browser_process.h" |
| 20 #include "chrome/browser/download/download_completion_blocker.h" | 20 #include "chrome/browser/download/download_completion_blocker.h" |
| 21 #include "chrome/browser/download/download_crx_util.h" | 21 #include "chrome/browser/download/download_crx_util.h" |
| 22 #include "chrome/browser/download/download_extensions.h" | |
| 23 #include "chrome/browser/download/download_file_picker.h" | 22 #include "chrome/browser/download/download_file_picker.h" |
| 24 #include "chrome/browser/download/download_history.h" | 23 #include "chrome/browser/download/download_history.h" |
| 25 #include "chrome/browser/download/download_path_reservation_tracker.h" | 24 #include "chrome/browser/download/download_path_reservation_tracker.h" |
| 26 #include "chrome/browser/download/download_prefs.h" | 25 #include "chrome/browser/download/download_prefs.h" |
| 27 #include "chrome/browser/download/download_service.h" | 26 #include "chrome/browser/download/download_service.h" |
| 28 #include "chrome/browser/download/download_service_factory.h" | 27 #include "chrome/browser/download/download_service_factory.h" |
| 29 #include "chrome/browser/download/download_status_updater.h" | 28 #include "chrome/browser/download/download_target_determiner.h" |
| 30 #include "chrome/browser/download/download_util.h" | 29 #include "chrome/browser/download/download_util.h" |
| 31 #include "chrome/browser/download/save_package_file_picker.h" | 30 #include "chrome/browser/download/save_package_file_picker.h" |
| 32 #include "chrome/browser/extensions/api/downloads/downloads_api.h" | 31 #include "chrome/browser/extensions/api/downloads/downloads_api.h" |
| 33 #include "chrome/browser/extensions/crx_installer.h" | 32 #include "chrome/browser/extensions/crx_installer.h" |
| 34 #include "chrome/browser/extensions/extension_service.h" | |
| 35 #include "chrome/browser/extensions/extension_system.h" | |
| 36 #include "chrome/browser/history/history_service.h" | |
| 37 #include "chrome/browser/history/history_service_factory.h" | |
| 38 #include "chrome/browser/platform_util.h" | 33 #include "chrome/browser/platform_util.h" |
| 39 #include "chrome/browser/profiles/profile.h" | 34 #include "chrome/browser/profiles/profile.h" |
| 40 #include "chrome/browser/safe_browsing/safe_browsing_service.h" | 35 #include "chrome/browser/safe_browsing/safe_browsing_service.h" |
| 41 #include "chrome/browser/ui/host_desktop.h" | |
| 42 #include "chrome/browser/ui/tabs/tab_strip_model.h" | |
| 43 #include "chrome/common/chrome_notification_types.h" | 36 #include "chrome/common/chrome_notification_types.h" |
| 44 #include "chrome/common/extensions/feature_switch.h" | 37 #include "chrome/common/extensions/extension.h" |
| 45 #include "chrome/common/extensions/user_script.h" | |
| 46 #include "chrome/common/pref_names.h" | 38 #include "chrome/common/pref_names.h" |
| 47 #include "components/user_prefs/pref_registry_syncable.h" | 39 #include "components/user_prefs/pref_registry_syncable.h" |
| 48 #include "content/public/browser/download_item.h" | 40 #include "content/public/browser/download_item.h" |
| 49 #include "content/public/browser/download_manager.h" | 41 #include "content/public/browser/download_manager.h" |
| 50 #include "content/public/browser/notification_source.h" | 42 #include "content/public/browser/notification_source.h" |
| 51 #include "content/public/browser/web_contents.h" | |
| 52 #include "content/public/browser/web_contents_delegate.h" | |
| 53 #include "grit/generated_resources.h" | |
| 54 #include "net/base/net_util.h" | |
| 55 #include "ui/base/l10n/l10n_util.h" | |
| 56 | 43 |
| 57 #if defined(OS_CHROMEOS) | 44 #if defined(OS_CHROMEOS) |
| 58 #include "chrome/browser/chromeos/drive/drive_download_handler.h" | 45 #include "chrome/browser/chromeos/drive/drive_download_handler.h" |
| 59 #include "chrome/browser/chromeos/drive/drive_file_system_util.h" | 46 #include "chrome/browser/chromeos/drive/drive_file_system_util.h" |
| 60 #include "chrome/browser/download/download_file_picker_chromeos.h" | |
| 61 #include "chrome/browser/download/save_package_file_picker_chromeos.h" | 47 #include "chrome/browser/download/save_package_file_picker_chromeos.h" |
| 62 #endif | 48 #endif |
| 63 | 49 |
| 64 using content::BrowserContext; | 50 using content::BrowserContext; |
| 65 using content::BrowserThread; | 51 using content::BrowserThread; |
| 66 using content::DownloadId; | 52 using content::DownloadId; |
| 67 using content::DownloadItem; | 53 using content::DownloadItem; |
| 68 using content::DownloadManager; | 54 using content::DownloadManager; |
| 69 using content::WebContents; | |
| 70 using safe_browsing::DownloadProtectionService; | 55 using safe_browsing::DownloadProtectionService; |
| 71 | 56 |
| 72 namespace { | 57 namespace { |
| 73 | 58 |
| 74 // String pointer used for identifying safebrowing data associated with | 59 // String pointer used for identifying safebrowing data associated with |
| 75 // a download item. | 60 // a download item. |
| 76 static const char safe_browsing_id[] = "Safe Browsing ID"; | 61 static const char safe_browsing_id[] = "Safe Browsing ID"; |
| 77 | 62 |
| 78 // The state of a safebrowsing check. | 63 // The state of a safebrowsing check. |
| 79 class SafeBrowsingState : public DownloadCompletionBlocker { | 64 class SafeBrowsingState : public DownloadCompletionBlocker { |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 96 } | 81 } |
| 97 | 82 |
| 98 private: | 83 private: |
| 99 DownloadProtectionService::DownloadCheckResult verdict_; | 84 DownloadProtectionService::DownloadCheckResult verdict_; |
| 100 | 85 |
| 101 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingState); | 86 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingState); |
| 102 }; | 87 }; |
| 103 | 88 |
| 104 SafeBrowsingState::~SafeBrowsingState() {} | 89 SafeBrowsingState::~SafeBrowsingState() {} |
| 105 | 90 |
| 106 // Generate a filename based on the response from the server. Similar | |
| 107 // in operation to net::GenerateFileName(), but uses a localized | |
| 108 // default name. | |
| 109 void GenerateFileNameFromRequest(const DownloadItem& download_item, | |
| 110 base::FilePath* generated_name, | |
| 111 std::string referrer_charset) { | |
| 112 std::string default_file_name( | |
| 113 l10n_util::GetStringUTF8(IDS_DEFAULT_DOWNLOAD_FILENAME)); | |
| 114 | |
| 115 *generated_name = net::GenerateFileName(download_item.GetURL(), | |
| 116 download_item.GetContentDisposition(), | |
| 117 referrer_charset, | |
| 118 download_item.GetSuggestedFilename(), | |
| 119 download_item.GetMimeType(), | |
| 120 default_file_name); | |
| 121 } | |
| 122 | |
| 123 typedef base::Callback<void(bool)> VisitedBeforeCallback; | |
| 124 | |
| 125 // Condenses the results from HistoryService::GetVisibleVisitCountToHost() to a | |
| 126 // single bool so that VisitedBeforeCallback can curry up to 5 other parameters | |
| 127 // without a struct. | |
| 128 void VisitCountsToVisitedBefore( | |
| 129 const VisitedBeforeCallback& callback, | |
| 130 HistoryService::Handle unused_handle, | |
| 131 bool found_visits, | |
| 132 int count, | |
| 133 base::Time first_visit) { | |
| 134 callback.Run(found_visits && count && | |
| 135 (first_visit.LocalMidnight() < base::Time::Now().LocalMidnight())); | |
| 136 } | |
| 137 | |
| 138 base::FilePath GetIntermediatePath(const base::FilePath& target_path, | |
| 139 content::DownloadDangerType danger_type, | |
| 140 bool is_forced_path) { | |
| 141 // If the download is not dangerous, just append .crdownload to the target | |
| 142 // path. | |
| 143 if (danger_type == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) { | |
| 144 if (is_forced_path) | |
| 145 return target_path; | |
| 146 return download_util::GetCrDownloadPath(target_path); | |
| 147 } | |
| 148 | |
| 149 // If the download is potentially dangerous we create a filename of the form | |
| 150 // 'Unconfirmed <random>.crdownload'. | |
| 151 base::FilePath::StringType file_name; | |
| 152 base::FilePath dir = target_path.DirName(); | |
| 153 #if defined(OS_WIN) | |
| 154 string16 unconfirmed_prefix = | |
| 155 l10n_util::GetStringUTF16(IDS_DOWNLOAD_UNCONFIRMED_PREFIX); | |
| 156 #else | |
| 157 std::string unconfirmed_prefix = | |
| 158 l10n_util::GetStringUTF8(IDS_DOWNLOAD_UNCONFIRMED_PREFIX); | |
| 159 #endif | |
| 160 base::SStringPrintf( | |
| 161 &file_name, | |
| 162 unconfirmed_prefix.append( | |
| 163 FILE_PATH_LITERAL(" %d.crdownload")).c_str(), | |
| 164 base::RandInt(0, 1000000)); | |
| 165 return dir.Append(file_name); | |
| 166 } | |
| 167 | |
| 168 // Returns a file path in the form that is expected by | 91 // Returns a file path in the form that is expected by |
| 169 // platform_util::OpenItem/ShowItemInFolder, including any transformation | 92 // platform_util::OpenItem/ShowItemInFolder, including any transformation |
| 170 // required for download abstractions layered on top of the core system, | 93 // required for download abstractions layered on top of the core system, |
| 171 // e.g. download to Drive. | 94 // e.g. download to Drive. |
| 172 base::FilePath GetPlatformDownloadPath(Profile* profile, | 95 base::FilePath GetPlatformDownloadPath(Profile* profile, |
| 173 const DownloadItem* download) { | 96 const DownloadItem* download) { |
| 174 #if defined(OS_CHROMEOS) | 97 #if defined(OS_CHROMEOS) |
| 175 drive::DriveDownloadHandler* drive_download_handler = | 98 drive::DriveDownloadHandler* drive_download_handler = |
| 176 drive::DriveDownloadHandler::GetForProfile(profile); | 99 drive::DriveDownloadHandler::GetForProfile(profile); |
| 177 if (drive_download_handler && | 100 if (drive_download_handler && |
| 178 drive_download_handler->IsDriveDownload(download)) | 101 drive_download_handler->IsDriveDownload(download)) |
| 179 return drive_download_handler->GetTargetPath(download); | 102 return drive_download_handler->GetTargetPath(download); |
| 180 #endif | 103 #endif |
| 181 return download->GetFullPath(); | 104 return download->GetFullPath(); |
| 182 } | 105 } |
| 183 | 106 |
| 107 // Callback invoked by DownloadProtectionService::CheckClientDownload. | |
| 108 // |is_content_check_supported| is true if the SB service supports scanning the | |
| 109 // download for malicious content. | |
| 110 // |callback| is invoked with a danger type determined as follows: | |
| 111 // | |
| 112 // Danger type is (in order of preference): | |
| 113 // * DANGEROUS_URL, if the URL is a known malware site. | |
| 114 // * MAYBE_DANGEROUS_CONTENT, if the content will be scanned for | |
| 115 // malware. I.e. |is_content_check_supported| is true. | |
| 116 // * NOT_DANGEROUS. | |
| 117 void CheckDownloadUrlDone( | |
| 118 const DownloadTargetDeterminerDelegate::CheckDownloadUrlCallback& callback, | |
| 119 bool is_content_check_supported, | |
| 120 DownloadProtectionService::DownloadCheckResult result) { | |
| 121 content::DownloadDangerType danger_type; | |
| 122 if (result == DownloadProtectionService::SAFE) { | |
| 123 // If this type of files is handled by the enhanced SafeBrowsing download | |
| 124 // protection, mark it as potentially dangerous content until we are done | |
| 125 // with scanning it. | |
| 126 if (is_content_check_supported) | |
| 127 danger_type = content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT; | |
| 128 else | |
| 129 danger_type = content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS; | |
| 130 } else { | |
| 131 // If the URL is malicious, we'll use that as the danger type. The results | |
| 132 // of the content check, if one is performed, will be ignored. | |
| 133 danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL; | |
| 134 } | |
| 135 callback.Run(danger_type); | |
| 136 } | |
| 137 | |
| 184 } // namespace | 138 } // namespace |
| 185 | 139 |
| 186 // static | 140 // static |
| 187 void ChromeDownloadManagerDelegate::RegisterUserPrefs( | 141 void ChromeDownloadManagerDelegate::RegisterUserPrefs( |
| 188 PrefRegistrySyncable* registry) { | 142 PrefRegistrySyncable* registry) { |
| 189 const base::FilePath& default_download_path = | 143 const base::FilePath& default_download_path = |
| 190 download_util::GetDefaultDownloadDirectory(); | 144 download_util::GetDefaultDownloadDirectory(); |
| 191 registry->RegisterFilePathPref(prefs::kSaveFileDefaultDirectory, | 145 registry->RegisterFilePathPref(prefs::kSaveFileDefaultDirectory, |
| 192 default_download_path, | 146 default_download_path, |
| 193 PrefRegistrySyncable::UNSYNCABLE_PREF); | 147 PrefRegistrySyncable::UNSYNCABLE_PREF); |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 214 if (!profile_->IsOffTheRecord()) | 168 if (!profile_->IsOffTheRecord()) |
| 215 return DownloadId(this, next_download_id_++); | 169 return DownloadId(this, next_download_id_++); |
| 216 | 170 |
| 217 return BrowserContext::GetDownloadManager(profile_->GetOriginalProfile())-> | 171 return BrowserContext::GetDownloadManager(profile_->GetOriginalProfile())-> |
| 218 GetDelegate()->GetNextId(); | 172 GetDelegate()->GetNextId(); |
| 219 } | 173 } |
| 220 | 174 |
| 221 bool ChromeDownloadManagerDelegate::DetermineDownloadTarget( | 175 bool ChromeDownloadManagerDelegate::DetermineDownloadTarget( |
| 222 DownloadItem* download, | 176 DownloadItem* download, |
| 223 const content::DownloadTargetCallback& callback) { | 177 const content::DownloadTargetCallback& callback) { |
| 224 #if defined(FULL_SAFE_BROWSING) | 178 DownloadTargetDeterminer::Start(download, |
| 225 DownloadProtectionService* service = GetDownloadProtectionService(); | 179 download_prefs_.get(), |
| 226 if (service) { | 180 last_download_path_, |
| 227 VLOG(2) << __FUNCTION__ << "() Start SB URL check for download = " | 181 this, |
| 228 << download->DebugString(false); | 182 callback); |
| 229 service->CheckDownloadUrl( | |
| 230 *download, | |
| 231 base::Bind( | |
| 232 &ChromeDownloadManagerDelegate::CheckDownloadUrlDone, | |
| 233 this, | |
| 234 download->GetId(), | |
| 235 callback)); | |
| 236 return true; | |
| 237 } | |
| 238 #endif | |
| 239 CheckDownloadUrlDone(download->GetId(), callback, | |
| 240 DownloadProtectionService::SAFE); | |
| 241 return true; | 183 return true; |
| 242 } | 184 } |
| 243 | 185 |
| 244 void ChromeDownloadManagerDelegate::ChooseDownloadPath( | |
| 245 DownloadItem* item, | |
| 246 const base::FilePath& suggested_path, | |
| 247 const FileSelectedCallback& file_selected_callback) { | |
| 248 // Deletes itself. | |
| 249 DownloadFilePicker* file_picker = | |
| 250 #if defined(OS_CHROMEOS) | |
| 251 new DownloadFilePickerChromeOS(); | |
| 252 #else | |
| 253 new DownloadFilePicker(); | |
| 254 #endif | |
| 255 file_picker->Init(download_manager_, item, suggested_path, | |
| 256 file_selected_callback); | |
| 257 } | |
| 258 | |
| 259 bool ChromeDownloadManagerDelegate::ShouldOpenFileBasedOnExtension( | 186 bool ChromeDownloadManagerDelegate::ShouldOpenFileBasedOnExtension( |
| 260 const base::FilePath& path) { | 187 const base::FilePath& path) { |
| 261 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 188 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 262 base::FilePath::StringType extension = path.Extension(); | 189 if (path.Extension().empty()) |
| 263 if (extension.empty()) | |
| 264 return false; | 190 return false; |
| 191 // TODO(asanka): This determination is done based on |path|, while | |
| 192 // ShouldOpenDownload() detects extension downloads based on the | |
| 193 // characteristics of the download. Reconcile this. http://crbug.com/167702 | |
| 265 if (extensions::Extension::IsExtension(path)) | 194 if (extensions::Extension::IsExtension(path)) |
| 266 return false; | 195 return false; |
| 267 DCHECK(extension[0] == base::FilePath::kExtensionSeparator); | 196 return download_prefs_->IsAutoOpenEnabledBasedOnExtension(path); |
| 268 extension.erase(0, 1); | |
| 269 return download_prefs_->IsAutoOpenEnabledForExtension(extension); | |
| 270 } | 197 } |
| 271 | 198 |
| 272 // static | 199 // static |
| 273 void ChromeDownloadManagerDelegate::DisableSafeBrowsing(DownloadItem* item) { | 200 void ChromeDownloadManagerDelegate::DisableSafeBrowsing(DownloadItem* item) { |
| 274 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 201 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 275 #if defined(FULL_SAFE_BROWSING) | 202 #if defined(FULL_SAFE_BROWSING) |
| 276 SafeBrowsingState* state = static_cast<SafeBrowsingState*>( | 203 SafeBrowsingState* state = static_cast<SafeBrowsingState*>( |
| 277 item->GetUserData(&safe_browsing_id)); | 204 item->GetUserData(&safe_browsing_id)); |
| 278 if (!state) { | 205 if (!state) { |
| 279 state = new SafeBrowsingState(); | 206 state = new SafeBrowsingState(); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 394 | 321 |
| 395 *download_save_dir = prefs->GetFilePath(prefs::kDownloadDefaultDirectory); | 322 *download_save_dir = prefs->GetFilePath(prefs::kDownloadDefaultDirectory); |
| 396 | 323 |
| 397 *skip_dir_check = false; | 324 *skip_dir_check = false; |
| 398 #if defined(OS_CHROMEOS) | 325 #if defined(OS_CHROMEOS) |
| 399 *skip_dir_check = drive::util::IsUnderDriveMountPoint(*website_save_dir); | 326 *skip_dir_check = drive::util::IsUnderDriveMountPoint(*website_save_dir); |
| 400 #endif | 327 #endif |
| 401 } | 328 } |
| 402 | 329 |
| 403 void ChromeDownloadManagerDelegate::ChooseSavePath( | 330 void ChromeDownloadManagerDelegate::ChooseSavePath( |
| 404 WebContents* web_contents, | 331 content::WebContents* web_contents, |
| 405 const base::FilePath& suggested_path, | 332 const base::FilePath& suggested_path, |
| 406 const base::FilePath::StringType& default_extension, | 333 const base::FilePath::StringType& default_extension, |
| 407 bool can_save_as_complete, | 334 bool can_save_as_complete, |
| 408 const content::SavePackagePathPickedCallback& callback) { | 335 const content::SavePackagePathPickedCallback& callback) { |
| 409 // Deletes itself. | 336 // Deletes itself. |
| 410 #if defined(OS_CHROMEOS) | 337 #if defined(OS_CHROMEOS) |
| 411 new SavePackageFilePickerChromeOS( | 338 new SavePackageFilePickerChromeOS( |
| 412 web_contents, | 339 web_contents, |
| 413 suggested_path, | 340 suggested_path, |
| 414 can_save_as_complete, | 341 can_save_as_complete, |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 450 download->GetFullPath()), | 377 download->GetFullPath()), |
| 451 callback); | 378 callback); |
| 452 } | 379 } |
| 453 | 380 |
| 454 void ChromeDownloadManagerDelegate::ClearLastDownloadPath() { | 381 void ChromeDownloadManagerDelegate::ClearLastDownloadPath() { |
| 455 last_download_path_.clear(); | 382 last_download_path_.clear(); |
| 456 } | 383 } |
| 457 | 384 |
| 458 DownloadProtectionService* | 385 DownloadProtectionService* |
| 459 ChromeDownloadManagerDelegate::GetDownloadProtectionService() { | 386 ChromeDownloadManagerDelegate::GetDownloadProtectionService() { |
| 387 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 460 #if defined(FULL_SAFE_BROWSING) | 388 #if defined(FULL_SAFE_BROWSING) |
| 461 SafeBrowsingService* sb_service = g_browser_process->safe_browsing_service(); | 389 SafeBrowsingService* sb_service = g_browser_process->safe_browsing_service(); |
| 462 if (sb_service && sb_service->download_protection_service() && | 390 if (sb_service && sb_service->download_protection_service() && |
| 463 profile_->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled)) { | 391 profile_->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled)) { |
| 464 return sb_service->download_protection_service(); | 392 return sb_service->download_protection_service(); |
| 465 } | 393 } |
| 466 #endif | 394 #endif |
| 467 return NULL; | 395 return NULL; |
| 468 } | 396 } |
| 469 | 397 |
| 470 // TODO(phajdan.jr): This is apparently not being exercised in tests. | 398 void ChromeDownloadManagerDelegate::NotifyExtensions( |
| 471 bool ChromeDownloadManagerDelegate::IsDangerousFile( | 399 DownloadItem* download, |
| 472 const DownloadItem& download, | 400 const base::FilePath& virtual_path, |
| 473 const base::FilePath& suggested_path, | 401 const NotifyExtensionsCallback& callback) { |
| 474 bool visited_referrer_before) { | |
| 475 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 402 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 476 const bool is_extension_download = | 403 #if !defined(OS_ANDROID) |
| 477 download_crx_util::IsExtensionDownload(download); | 404 ExtensionDownloadsEventRouter* router = |
| 478 | 405 DownloadServiceFactory::GetForProfile(profile_)-> |
| 479 // User-initiated extension downloads from pref-whitelisted sources are not | 406 GetExtensionEventRouter(); |
| 480 // considered dangerous. | 407 if (router) { |
| 481 if (download.HasUserGesture() && | 408 base::Closure original_path_callback = |
| 482 is_extension_download && | 409 base::Bind(callback, base::FilePath(), |
| 483 download_crx_util::OffStoreInstallAllowedByPrefs(profile_, download)) { | 410 DownloadPathReservationTracker::UNIQUIFY); |
| 484 return false; | 411 router->OnDeterminingFilename(download, virtual_path.BaseName(), |
| 412 original_path_callback, | |
| 413 callback); | |
| 414 return; | |
| 485 } | 415 } |
| 486 | 416 #endif |
| 487 // Extensions that are not from the gallery are considered dangerous. | 417 callback.Run(base::FilePath(), DownloadPathReservationTracker::UNIQUIFY); |
| 488 // When off-store install is disabled we skip this, since in this case, we | |
| 489 // will not offer to install the extension. | |
| 490 if (extensions::FeatureSwitch::easy_off_store_install()->IsEnabled() && | |
| 491 is_extension_download && | |
| 492 !extensions::WebstoreInstaller::GetAssociatedApproval(download)) { | |
| 493 return true; | |
| 494 } | |
| 495 | |
| 496 // Anything the user has marked auto-open is OK if it's user-initiated. | |
| 497 if (ShouldOpenFileBasedOnExtension(suggested_path) && | |
| 498 download.HasUserGesture()) | |
| 499 return false; | |
| 500 | |
| 501 // "Allow on user gesture" is OK when we have a user gesture and the hosting | |
| 502 // page has been visited before today. | |
| 503 download_util::DownloadDangerLevel danger_level = | |
| 504 download_util::GetFileDangerLevel(suggested_path.BaseName()); | |
| 505 if (danger_level == download_util::AllowOnUserGesture) { | |
| 506 if (download.GetTransitionType() & | |
| 507 content::PAGE_TRANSITION_FROM_ADDRESS_BAR) { | |
| 508 return false; | |
| 509 } | |
| 510 return !download.HasUserGesture() || !visited_referrer_before; | |
| 511 } | |
| 512 | |
| 513 return danger_level == download_util::Dangerous; | |
| 514 } | 418 } |
| 515 | 419 |
| 516 void ChromeDownloadManagerDelegate::GetReservedPath( | 420 void ChromeDownloadManagerDelegate::ReserveVirtualPath( |
| 517 DownloadItem& download, | 421 content::DownloadItem* download, |
| 518 const base::FilePath& target_path, | 422 const base::FilePath& virtual_path, |
| 519 const base::FilePath& default_download_path, | |
| 520 DownloadPathReservationTracker::FilenameConflictAction conflict_action, | 423 DownloadPathReservationTracker::FilenameConflictAction conflict_action, |
| 521 const DownloadPathReservationTracker::ReservedPathCallback& callback) { | 424 const DownloadTargetDeterminerDelegate::ReservedPathCallback& callback) { |
| 425 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 426 DCHECK(!virtual_path.empty()); | |
| 427 #if defined(OS_CHROMEOS) | |
| 428 // TODO(asanka): Handle path reservations for virtual paths as well. | |
| 429 // http://crbug.com/151618 | |
| 430 if (drive::util::IsUnderDriveMountPoint(virtual_path)) { | |
| 431 callback.Run(virtual_path, true); | |
| 432 return; | |
| 433 } | |
| 434 #endif | |
| 522 DownloadPathReservationTracker::GetReservedPath( | 435 DownloadPathReservationTracker::GetReservedPath( |
| 523 download, target_path, default_download_path, conflict_action, callback); | 436 *download, virtual_path, download_prefs_->DownloadPath(), |
| 437 conflict_action, callback); | |
| 524 } | 438 } |
| 525 | 439 |
| 526 void ChromeDownloadManagerDelegate::CheckDownloadUrlDone( | 440 void ChromeDownloadManagerDelegate::PromptUserForDownloadPath( |
| 527 int32 download_id, | 441 DownloadItem* download, |
| 528 const content::DownloadTargetCallback& callback, | 442 const base::FilePath& suggested_path, |
| 529 DownloadProtectionService::DownloadCheckResult result) { | 443 const DownloadTargetDeterminerDelegate::FileSelectedCallback& callback) { |
| 530 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 444 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 531 DownloadItem* download = download_manager_->GetDownload(download_id); | 445 DownloadFilePicker::ShowFilePicker( |
| 532 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS)) | 446 download, |
| 533 return; | 447 suggested_path, |
| 448 base::Bind(&ChromeDownloadManagerDelegate::OnDownloadPathSelected, | |
| 449 this, | |
| 450 callback)); | |
| 451 } | |
| 534 | 452 |
| 535 VLOG(2) << __FUNCTION__ << "() download = " << download->DebugString(false) | 453 void ChromeDownloadManagerDelegate::DetermineLocalPath( |
| 536 << " verdict = " << result; | 454 DownloadItem* download, |
| 537 content::DownloadDangerType danger_type = download->GetDangerType(); | 455 const base::FilePath& virtual_path, |
| 538 if (result != DownloadProtectionService::SAFE) | 456 const DownloadTargetDeterminerDelegate::LocalPathCallback& callback) { |
| 539 danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL; | 457 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 540 | 458 #if defined(OS_CHROMEOS) |
| 541 // HistoryServiceFactory redirects incognito profiles to on-record profiles. | 459 drive::DriveDownloadHandler* drive_download_handler = |
| 542 HistoryService* history = HistoryServiceFactory::GetForProfile( | 460 drive::DriveDownloadHandler::GetForProfile(profile_); |
| 543 profile_, Profile::EXPLICIT_ACCESS); | 461 if (drive_download_handler) { |
| 544 if (!history || !download->GetReferrerUrl().is_valid()) { | 462 drive_download_handler->SubstituteDriveDownloadPath( |
| 545 // If the original profile doesn't have a HistoryService or the referrer url | 463 virtual_path, download, callback); |
| 546 // is invalid, then give up and assume the referrer has not been visited | |
| 547 // before. There's no history for on-record profiles in unit_tests, for | |
| 548 // example. | |
| 549 CheckVisitedReferrerBeforeDone(download_id, callback, danger_type, false); | |
| 550 return; | 464 return; |
| 551 } | 465 } |
| 552 history->GetVisibleVisitCountToHost( | 466 #endif |
| 553 download->GetReferrerUrl(), &history_consumer_, | 467 callback.Run(virtual_path); |
| 554 base::Bind(&VisitCountsToVisitedBefore, base::Bind( | 468 } |
| 555 &ChromeDownloadManagerDelegate::CheckVisitedReferrerBeforeDone, | 469 |
| 556 this, download_id, callback, danger_type))); | 470 void ChromeDownloadManagerDelegate::CheckDownloadUrl( |
| 471 DownloadItem* download, | |
| 472 const base::FilePath& suggested_path, | |
| 473 const CheckDownloadUrlCallback& callback) { | |
| 474 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 475 | |
| 476 #if defined(FULL_SAFE_BROWSING) | |
| 477 safe_browsing::DownloadProtectionService* service = | |
| 478 GetDownloadProtectionService(); | |
| 479 if (service) { | |
| 480 bool is_content_check_supported = | |
| 481 service->IsSupportedDownload(*download, suggested_path); | |
| 482 VLOG(2) << __FUNCTION__ << "() Start SB URL check for download = " | |
| 483 << download->DebugString(false); | |
| 484 service->CheckDownloadUrl(*download, | |
| 485 base::Bind(&CheckDownloadUrlDone, | |
| 486 callback, | |
| 487 is_content_check_supported)); | |
| 488 return; | |
| 489 } | |
| 490 #endif | |
| 491 callback.Run(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS); | |
| 492 } | |
| 493 | |
| 494 void ChromeDownloadManagerDelegate::OnDownloadPathSelected( | |
|
Randy Smith (Not in Mondays)
2013/04/26 19:05:46
Any reason not to put this next to PromptUserForDo
asanka
2013/04/29 18:43:20
Moved it next to PromptUserForDownloadPath(). I or
| |
| 495 const DownloadTargetDeterminerDelegate::FileSelectedCallback& callback, | |
| 496 const base::FilePath& virtual_path) { | |
| 497 if (!virtual_path.empty()) | |
| 498 last_download_path_ = virtual_path.DirName(); | |
| 499 callback.Run(virtual_path); | |
| 557 } | 500 } |
| 558 | 501 |
| 559 void ChromeDownloadManagerDelegate::CheckClientDownloadDone( | 502 void ChromeDownloadManagerDelegate::CheckClientDownloadDone( |
| 560 int32 download_id, | 503 int32 download_id, |
| 561 DownloadProtectionService::DownloadCheckResult result) { | 504 DownloadProtectionService::DownloadCheckResult result) { |
| 562 DownloadItem* item = download_manager_->GetDownload(download_id); | 505 DownloadItem* item = download_manager_->GetDownload(download_id); |
| 563 if (!item || (item->GetState() != DownloadItem::IN_PROGRESS)) | 506 if (!item || (item->GetState() != DownloadItem::IN_PROGRESS)) |
| 564 return; | 507 return; |
| 565 | 508 |
| 566 VLOG(2) << __FUNCTION__ << "() download = " << item->DebugString(false) | 509 VLOG(2) << __FUNCTION__ << "() download = " << item->DebugString(false) |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 604 registrar_.Remove(this, | 547 registrar_.Remove(this, |
| 605 chrome::NOTIFICATION_CRX_INSTALLER_DONE, | 548 chrome::NOTIFICATION_CRX_INSTALLER_DONE, |
| 606 source); | 549 source); |
| 607 | 550 |
| 608 scoped_refptr<extensions::CrxInstaller> installer = | 551 scoped_refptr<extensions::CrxInstaller> installer = |
| 609 content::Source<extensions::CrxInstaller>(source).ptr(); | 552 content::Source<extensions::CrxInstaller>(source).ptr(); |
| 610 content::DownloadOpenDelayedCallback callback = crx_installers_[installer]; | 553 content::DownloadOpenDelayedCallback callback = crx_installers_[installer]; |
| 611 crx_installers_.erase(installer.get()); | 554 crx_installers_.erase(installer.get()); |
| 612 callback.Run(installer->did_handle_successfully()); | 555 callback.Run(installer->did_handle_successfully()); |
| 613 } | 556 } |
| 614 | |
| 615 struct ChromeDownloadManagerDelegate::ContinueFilenameDeterminationInfo { | |
| 616 ContinueFilenameDeterminationInfo(); | |
| 617 ~ContinueFilenameDeterminationInfo(); | |
| 618 | |
| 619 int32 download_id; | |
| 620 content::DownloadTargetCallback callback; | |
| 621 content::DownloadDangerType danger_type; | |
| 622 bool visited_referrer_before; | |
| 623 bool should_prompt; | |
| 624 }; | |
| 625 | |
| 626 ChromeDownloadManagerDelegate::ContinueFilenameDeterminationInfo:: | |
| 627 ContinueFilenameDeterminationInfo() {} | |
| 628 ChromeDownloadManagerDelegate::ContinueFilenameDeterminationInfo:: | |
| 629 ~ContinueFilenameDeterminationInfo() {} | |
| 630 | |
| 631 void ChromeDownloadManagerDelegate::CheckVisitedReferrerBeforeDone( | |
| 632 int32 download_id, | |
| 633 const content::DownloadTargetCallback& callback, | |
| 634 content::DownloadDangerType danger_type, | |
| 635 bool visited_referrer_before) { | |
| 636 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 637 | |
| 638 DownloadItem* download = | |
| 639 download_manager_->GetDownload(download_id); | |
| 640 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS)) | |
| 641 return; | |
| 642 | |
| 643 bool should_prompt = (download->GetTargetDisposition() == | |
| 644 DownloadItem::TARGET_DISPOSITION_PROMPT); | |
| 645 bool is_forced_path = !download->GetForcedFilePath().empty(); | |
| 646 base::FilePath generated_name; | |
| 647 base::FilePath suggested_path; | |
| 648 | |
| 649 // Check whether this download is for an extension install or not. | |
| 650 // Allow extensions to be explicitly saved. | |
| 651 if (!is_forced_path) { | |
| 652 GenerateFileNameFromRequest( | |
| 653 *download, | |
| 654 &generated_name, | |
| 655 profile_->GetPrefs()->GetString(prefs::kDefaultCharset)); | |
| 656 | |
| 657 // Freeze the user's preference for showing a Save As dialog. We're going | |
| 658 // to bounce around a bunch of threads and we don't want to worry about race | |
| 659 // conditions where the user changes this pref out from under us. | |
| 660 if (download_prefs_->PromptForDownload()) { | |
| 661 // But ignore the user's preference for the following scenarios: | |
| 662 // 1) Extension installation. Note that we only care here about the case | |
| 663 // where an extension is installed, not when one is downloaded with | |
| 664 // "save as...". | |
| 665 // 2) Filetypes marked "always open." If the user just wants this file | |
| 666 // opened, don't bother asking where to keep it. | |
| 667 if (!download_crx_util::IsExtensionDownload(*download) && | |
| 668 !ShouldOpenFileBasedOnExtension(generated_name)) | |
| 669 should_prompt = true; | |
| 670 } | |
| 671 if (download_prefs_->IsDownloadPathManaged()) | |
| 672 should_prompt = false; | |
| 673 | |
| 674 // Determine the proper path for a download, by either one of the following: | |
| 675 // 1) using the default download directory. | |
| 676 // 2) prompting the user. | |
| 677 base::FilePath target_directory; | |
| 678 if (should_prompt && !last_download_path_.empty()) | |
| 679 target_directory = last_download_path_; | |
| 680 else | |
| 681 target_directory = download_prefs_->DownloadPath(); | |
| 682 suggested_path = target_directory.Append(generated_name); | |
| 683 } else { | |
| 684 DCHECK(!should_prompt); | |
| 685 suggested_path = download->GetForcedFilePath(); | |
| 686 } | |
| 687 | |
| 688 ContinueFilenameDeterminationInfo continue_info; | |
| 689 continue_info.download_id = download_id; | |
| 690 continue_info.callback = callback; | |
| 691 continue_info.danger_type = danger_type; | |
| 692 continue_info.visited_referrer_before = visited_referrer_before; | |
| 693 continue_info.should_prompt = should_prompt; | |
| 694 | |
| 695 DownloadPathReservationTracker::FilenameConflictAction conflict_action = ( | |
| 696 is_forced_path ? | |
| 697 DownloadPathReservationTracker::OVERWRITE : | |
| 698 DownloadPathReservationTracker::UNIQUIFY); | |
| 699 base::Closure filename_determined = base::Bind( | |
| 700 &ChromeDownloadManagerDelegate::ContinueDeterminingFilename, | |
| 701 this, continue_info, suggested_path, conflict_action); | |
| 702 #if defined(OS_ANDROID) | |
| 703 filename_determined.Run(); | |
| 704 #else | |
| 705 if (is_forced_path || | |
| 706 !DownloadServiceFactory::GetForProfile(profile_) | |
| 707 ->GetExtensionEventRouter()) { | |
| 708 filename_determined.Run(); | |
| 709 } else { | |
| 710 DownloadService* service = DownloadServiceFactory::GetForProfile(profile_); | |
| 711 ExtensionDownloadsEventRouter* router = service->GetExtensionEventRouter(); | |
| 712 ExtensionDownloadsEventRouter::FilenameChangedCallback overriding = | |
| 713 base::Bind(&ChromeDownloadManagerDelegate::OnExtensionOverridingFilename, | |
| 714 this, continue_info); | |
| 715 router->OnDeterminingFilename( | |
| 716 download, generated_name, filename_determined, overriding); | |
| 717 } | |
| 718 #endif | |
| 719 } | |
| 720 | |
| 721 void ChromeDownloadManagerDelegate::OnExtensionOverridingFilename( | |
| 722 const ContinueFilenameDeterminationInfo& continue_info, | |
| 723 const base::FilePath& changed_filename, | |
| 724 DownloadPathReservationTracker::FilenameConflictAction conflict_action) { | |
| 725 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 726 DownloadItem* download = | |
| 727 download_manager_->GetDownload(continue_info.download_id); | |
| 728 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS)) | |
| 729 return; | |
| 730 | |
| 731 // If an extension overrides the filename, then the target directory will be | |
| 732 // forced to download_prefs_->DownloadPath() since extensions cannot place | |
| 733 // downloaded files anywhere except there. This prevents subdirectories from | |
| 734 // accumulating: if an extension is allowed to say that a file should go in | |
| 735 // last_download_path/music/foo.mp3, then last_download_path will accumulate | |
| 736 // the subdirectory /music/ so that the next download may end up in | |
| 737 // Downloads/music/music/music/bar.mp3. | |
| 738 base::FilePath temp_filename(download_prefs_->DownloadPath().Append( | |
| 739 changed_filename).NormalizePathSeparators()); | |
| 740 // Do not pass a mime type to GenerateSafeFileName so that it does not force | |
| 741 // the filename to have an extension if the (chrome) extension does not | |
| 742 // suggest it. | |
| 743 net::GenerateSafeFileName(std::string(), false, &temp_filename); | |
| 744 | |
| 745 ContinueDeterminingFilename(continue_info, temp_filename, conflict_action); | |
| 746 } | |
| 747 | |
| 748 void ChromeDownloadManagerDelegate::ContinueDeterminingFilename( | |
| 749 const ContinueFilenameDeterminationInfo& continue_info, | |
| 750 const base::FilePath& suggested_path, | |
| 751 DownloadPathReservationTracker::FilenameConflictAction conflict_action) { | |
| 752 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 753 int32 download_id = continue_info.download_id; | |
| 754 const content::DownloadTargetCallback& callback = continue_info.callback; | |
| 755 content::DownloadDangerType danger_type = continue_info.danger_type; | |
| 756 bool visited_referrer_before = continue_info.visited_referrer_before; | |
| 757 bool should_prompt = continue_info.should_prompt; | |
| 758 DownloadItem* download = | |
| 759 download_manager_->GetDownload(download_id); | |
| 760 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS)) | |
| 761 return; | |
| 762 | |
| 763 // If the download hasn't already been marked dangerous (could be | |
| 764 // DANGEROUS_URL), check if it is a dangerous file. | |
| 765 if (danger_type == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) { | |
| 766 if (!should_prompt && | |
| 767 download->GetForcedFilePath().empty() && | |
| 768 IsDangerousFile(*download, suggested_path, visited_referrer_before)) { | |
| 769 danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE; | |
| 770 } | |
| 771 | |
| 772 #if defined(FULL_SAFE_BROWSING) | |
| 773 DownloadProtectionService* service = GetDownloadProtectionService(); | |
| 774 // If this type of files is handled by the enhanced SafeBrowsing download | |
| 775 // protection, mark it as potentially dangerous content until we are done | |
| 776 // with scanning it. | |
| 777 if (service && service->enabled()) { | |
| 778 // TODO(noelutz): if the user changes the extension name in the UI to | |
| 779 // something like .exe SafeBrowsing will currently *not* check if the | |
| 780 // download is malicious. | |
| 781 if (service->IsSupportedDownload(*download, suggested_path)) | |
| 782 danger_type = content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT; | |
| 783 } | |
| 784 #endif | |
| 785 } else { | |
| 786 // Currently we only expect this case. | |
| 787 DCHECK_EQ(content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL, danger_type); | |
| 788 } | |
| 789 | |
| 790 #if defined (OS_CHROMEOS) | |
| 791 drive::DriveDownloadHandler* drive_download_handler = | |
| 792 drive::DriveDownloadHandler::GetForProfile(profile_); | |
| 793 if (drive_download_handler) { | |
| 794 drive_download_handler->SubstituteDriveDownloadPath( | |
| 795 suggested_path, download, | |
| 796 base::Bind( | |
| 797 &ChromeDownloadManagerDelegate::SubstituteDriveDownloadPathCallback, | |
| 798 this, download->GetId(), callback, should_prompt, conflict_action, | |
| 799 danger_type)); | |
| 800 return; | |
| 801 } | |
| 802 #endif | |
| 803 GetReservedPath( | |
| 804 *download, suggested_path, download_prefs_->DownloadPath(), | |
| 805 conflict_action, | |
| 806 base::Bind(&ChromeDownloadManagerDelegate::OnPathReservationAvailable, | |
| 807 this, download->GetId(), callback, should_prompt, | |
| 808 danger_type)); | |
| 809 } | |
| 810 | |
| 811 #if defined (OS_CHROMEOS) | |
| 812 // TODO(asanka): Merge this logic with the logic in DownloadFilePickerChromeOS. | |
| 813 void ChromeDownloadManagerDelegate::SubstituteDriveDownloadPathCallback( | |
| 814 int32 download_id, | |
| 815 const content::DownloadTargetCallback& callback, | |
| 816 bool should_prompt, | |
| 817 DownloadPathReservationTracker::FilenameConflictAction conflict_action, | |
| 818 content::DownloadDangerType danger_type, | |
| 819 const base::FilePath& suggested_path) { | |
| 820 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 821 DownloadItem* download = | |
| 822 download_manager_->GetDownload(download_id); | |
| 823 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS)) | |
| 824 return; | |
| 825 | |
| 826 if (suggested_path.empty()) { | |
| 827 // Substitution failed. | |
| 828 callback.Run(base::FilePath(), | |
| 829 DownloadItem::TARGET_DISPOSITION_OVERWRITE, | |
| 830 danger_type, | |
| 831 base::FilePath()); | |
| 832 return; | |
| 833 } | |
| 834 | |
| 835 GetReservedPath( | |
| 836 *download, suggested_path, download_prefs_->DownloadPath(), | |
| 837 conflict_action, | |
| 838 base::Bind(&ChromeDownloadManagerDelegate::OnPathReservationAvailable, | |
| 839 this, download->GetId(), callback, should_prompt, | |
| 840 danger_type)); | |
| 841 } | |
| 842 #endif | |
| 843 | |
| 844 void ChromeDownloadManagerDelegate::OnPathReservationAvailable( | |
| 845 int32 download_id, | |
| 846 const content::DownloadTargetCallback& callback, | |
| 847 bool should_prompt, | |
| 848 content::DownloadDangerType danger_type, | |
| 849 const base::FilePath& reserved_path, | |
| 850 bool reserved_path_verified) { | |
| 851 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 852 DownloadItem* download = | |
| 853 download_manager_->GetDownload(download_id); | |
| 854 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS)) | |
| 855 return; | |
| 856 if (should_prompt || !reserved_path_verified) { | |
| 857 // If the target path could not be verified then the path was non-existant, | |
| 858 // non writeable or could not be uniquified. Prompt the user. | |
| 859 ChooseDownloadPath( | |
| 860 download, reserved_path, | |
| 861 base::Bind(&ChromeDownloadManagerDelegate::OnTargetPathDetermined, | |
| 862 this, download_id, callback, | |
| 863 DownloadItem::TARGET_DISPOSITION_PROMPT, danger_type)); | |
| 864 } else { | |
| 865 OnTargetPathDetermined(download_id, callback, | |
| 866 DownloadItem::TARGET_DISPOSITION_OVERWRITE, | |
| 867 danger_type, reserved_path); | |
| 868 } | |
| 869 } | |
| 870 | |
| 871 void ChromeDownloadManagerDelegate::OnTargetPathDetermined( | |
| 872 int32 download_id, | |
| 873 const content::DownloadTargetCallback& callback, | |
| 874 DownloadItem::TargetDisposition disposition, | |
| 875 content::DownloadDangerType danger_type, | |
| 876 const base::FilePath& target_path) { | |
| 877 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 878 base::FilePath intermediate_path; | |
| 879 DownloadItem* download = | |
| 880 download_manager_->GetDownload(download_id); | |
| 881 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS)) | |
| 882 return; | |
| 883 | |
| 884 // If |target_path| is empty, then that means that the user wants to cancel | |
| 885 // the download. | |
| 886 if (!target_path.empty()) { | |
| 887 intermediate_path = GetIntermediatePath( | |
| 888 target_path, danger_type, !download->GetForcedFilePath().empty()); | |
| 889 | |
| 890 // Retain the last directory. Exclude temporary downloads since the path | |
| 891 // likely points at the location of a temporary file. | |
| 892 // TODO(asanka): This logic is a hack. DownloadFilePicker should give us a | |
| 893 // directory to persist. Or perhaps, if the Drive path | |
| 894 // substitution logic is moved here, then we would have a | |
| 895 // persistable path after the DownloadFilePicker is done. | |
| 896 if (disposition == DownloadItem::TARGET_DISPOSITION_PROMPT && | |
| 897 !download->IsTemporary()) | |
| 898 last_download_path_ = target_path.DirName(); | |
| 899 } | |
| 900 callback.Run(target_path, disposition, danger_type, intermediate_path); | |
| 901 } | |
| OLD | NEW |