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" | |
| 33 #include "chrome/browser/extensions/crx_installer.h" | 31 #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" | 32 #include "chrome/browser/platform_util.h" |
| 39 #include "chrome/browser/profiles/profile.h" | 33 #include "chrome/browser/profiles/profile.h" |
| 40 #include "chrome/browser/safe_browsing/safe_browsing_service.h" | 34 #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" | 35 #include "chrome/common/chrome_notification_types.h" |
| 44 #include "chrome/common/extensions/feature_switch.h" | 36 #include "chrome/common/extensions/extension.h" |
| 45 #include "chrome/common/extensions/user_script.h" | |
| 46 #include "chrome/common/pref_names.h" | 37 #include "chrome/common/pref_names.h" |
| 47 #include "components/user_prefs/pref_registry_syncable.h" | 38 #include "components/user_prefs/pref_registry_syncable.h" |
| 48 #include "content/public/browser/download_item.h" | 39 #include "content/public/browser/download_item.h" |
| 49 #include "content/public/browser/download_manager.h" | 40 #include "content/public/browser/download_manager.h" |
| 50 #include "content/public/browser/notification_source.h" | 41 #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 | 42 |
| 57 #if defined(OS_CHROMEOS) | 43 #if defined(OS_CHROMEOS) |
| 58 #include "chrome/browser/chromeos/drive/drive_download_handler.h" | 44 #include "chrome/browser/chromeos/drive/drive_download_handler.h" |
| 59 #include "chrome/browser/chromeos/drive/drive_file_system_util.h" | 45 #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" | 46 #include "chrome/browser/download/save_package_file_picker_chromeos.h" |
| 62 #endif | 47 #endif |
| 63 | 48 |
| 64 using content::BrowserContext; | 49 using content::BrowserContext; |
| 65 using content::BrowserThread; | 50 using content::BrowserThread; |
| 66 using content::DownloadId; | 51 using content::DownloadId; |
| 67 using content::DownloadItem; | 52 using content::DownloadItem; |
| 68 using content::DownloadManager; | 53 using content::DownloadManager; |
| 69 using content::WebContents; | |
| 70 using safe_browsing::DownloadProtectionService; | 54 using safe_browsing::DownloadProtectionService; |
| 71 | 55 |
| 72 namespace { | 56 namespace { |
| 73 | 57 |
| 74 // String pointer used for identifying safebrowing data associated with | 58 // String pointer used for identifying safebrowing data associated with |
| 75 // a download item. | 59 // a download item. |
| 76 static const char safe_browsing_id[] = "Safe Browsing ID"; | 60 static const char safe_browsing_id[] = "Safe Browsing ID"; |
| 77 | 61 |
| 78 // The state of a safebrowsing check. | 62 // The state of a safebrowsing check. |
| 79 class SafeBrowsingState : public DownloadCompletionBlocker { | 63 class SafeBrowsingState : public DownloadCompletionBlocker { |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 96 } | 80 } |
| 97 | 81 |
| 98 private: | 82 private: |
| 99 DownloadProtectionService::DownloadCheckResult verdict_; | 83 DownloadProtectionService::DownloadCheckResult verdict_; |
| 100 | 84 |
| 101 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingState); | 85 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingState); |
| 102 }; | 86 }; |
| 103 | 87 |
| 104 SafeBrowsingState::~SafeBrowsingState() {} | 88 SafeBrowsingState::~SafeBrowsingState() {} |
| 105 | 89 |
| 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 | 90 // Returns a file path in the form that is expected by |
| 169 // platform_util::OpenItem/ShowItemInFolder, including any transformation | 91 // platform_util::OpenItem/ShowItemInFolder, including any transformation |
| 170 // required for download abstractions layered on top of the core system, | 92 // required for download abstractions layered on top of the core system, |
| 171 // e.g. download to Drive. | 93 // e.g. download to Drive. |
| 172 base::FilePath GetPlatformDownloadPath(Profile* profile, | 94 base::FilePath GetPlatformDownloadPath(Profile* profile, |
| 173 const DownloadItem* download) { | 95 const DownloadItem* download) { |
| 174 #if defined(OS_CHROMEOS) | 96 #if defined(OS_CHROMEOS) |
| 175 drive::DriveDownloadHandler* drive_download_handler = | 97 drive::DriveDownloadHandler* drive_download_handler = |
| 176 drive::DriveDownloadHandler::GetForProfile(profile); | 98 drive::DriveDownloadHandler::GetForProfile(profile); |
| 177 if (drive_download_handler && | 99 if (drive_download_handler && |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 214 if (!profile_->IsOffTheRecord()) | 136 if (!profile_->IsOffTheRecord()) |
| 215 return DownloadId(this, next_download_id_++); | 137 return DownloadId(this, next_download_id_++); |
| 216 | 138 |
| 217 return BrowserContext::GetDownloadManager(profile_->GetOriginalProfile())-> | 139 return BrowserContext::GetDownloadManager(profile_->GetOriginalProfile())-> |
| 218 GetDelegate()->GetNextId(); | 140 GetDelegate()->GetNextId(); |
| 219 } | 141 } |
| 220 | 142 |
| 221 bool ChromeDownloadManagerDelegate::DetermineDownloadTarget( | 143 bool ChromeDownloadManagerDelegate::DetermineDownloadTarget( |
| 222 DownloadItem* download, | 144 DownloadItem* download, |
| 223 const content::DownloadTargetCallback& callback) { | 145 const content::DownloadTargetCallback& callback) { |
| 224 #if defined(FULL_SAFE_BROWSING) | 146 DownloadTargetDeterminer::CompletionCallback destination_callback = |
| 225 DownloadProtectionService* service = GetDownloadProtectionService(); | 147 base::Bind(&ChromeDownloadManagerDelegate::OnDetermineDownloadTargetDone, |
| 226 if (service) { | 148 this, callback); |
| 227 VLOG(2) << __FUNCTION__ << "() Start SB URL check for download = " | 149 DownloadTargetDeterminer::Start(download, |
| 228 << download->DebugString(false); | 150 download_prefs_.get(), |
| 229 service->CheckDownloadUrl( | 151 last_download_path_, |
| 230 *download, | 152 this, |
| 231 base::Bind( | 153 destination_callback); |
| 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; | 154 return true; |
| 242 } | 155 } |
| 243 | 156 |
| 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( | 157 bool ChromeDownloadManagerDelegate::ShouldOpenFileBasedOnExtension( |
| 260 const base::FilePath& path) { | 158 const base::FilePath& path) { |
| 261 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 159 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 262 base::FilePath::StringType extension = path.Extension(); | 160 if (path.Extension().empty()) |
| 263 if (extension.empty()) | |
| 264 return false; | 161 return false; |
| 162 // TODO(asanka): This determination is done based on |path|, while elsewhere | |
|
benjhayden
2013/04/09 15:46:32
Where else?
asanka
2013/04/16 20:34:01
Updated comment.
| |
| 163 // an extension download is recognized based on characteristics of the | |
| 164 // DownloadItem other than the path. Reconcile this. | |
| 265 if (extensions::Extension::IsExtension(path)) | 165 if (extensions::Extension::IsExtension(path)) |
| 266 return false; | 166 return false; |
| 267 DCHECK(extension[0] == base::FilePath::kExtensionSeparator); | 167 return download_prefs_->IsAutoOpenEnabledBasedOnExtension(path); |
| 268 extension.erase(0, 1); | |
| 269 return download_prefs_->IsAutoOpenEnabledForExtension(extension); | |
| 270 } | 168 } |
| 271 | 169 |
| 272 // static | 170 // static |
| 273 void ChromeDownloadManagerDelegate::DisableSafeBrowsing(DownloadItem* item) { | 171 void ChromeDownloadManagerDelegate::DisableSafeBrowsing(DownloadItem* item) { |
| 274 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 172 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 275 #if defined(FULL_SAFE_BROWSING) | 173 #if defined(FULL_SAFE_BROWSING) |
| 276 SafeBrowsingState* state = static_cast<SafeBrowsingState*>( | 174 SafeBrowsingState* state = static_cast<SafeBrowsingState*>( |
| 277 item->GetUserData(&safe_browsing_id)); | 175 item->GetUserData(&safe_browsing_id)); |
| 278 if (!state) { | 176 if (!state) { |
| 279 state = new SafeBrowsingState(); | 177 state = new SafeBrowsingState(); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 394 | 292 |
| 395 *download_save_dir = prefs->GetFilePath(prefs::kDownloadDefaultDirectory); | 293 *download_save_dir = prefs->GetFilePath(prefs::kDownloadDefaultDirectory); |
| 396 | 294 |
| 397 *skip_dir_check = false; | 295 *skip_dir_check = false; |
| 398 #if defined(OS_CHROMEOS) | 296 #if defined(OS_CHROMEOS) |
| 399 *skip_dir_check = drive::util::IsUnderDriveMountPoint(*website_save_dir); | 297 *skip_dir_check = drive::util::IsUnderDriveMountPoint(*website_save_dir); |
| 400 #endif | 298 #endif |
| 401 } | 299 } |
| 402 | 300 |
| 403 void ChromeDownloadManagerDelegate::ChooseSavePath( | 301 void ChromeDownloadManagerDelegate::ChooseSavePath( |
| 404 WebContents* web_contents, | 302 content::WebContents* web_contents, |
| 405 const base::FilePath& suggested_path, | 303 const base::FilePath& suggested_path, |
| 406 const base::FilePath::StringType& default_extension, | 304 const base::FilePath::StringType& default_extension, |
| 407 bool can_save_as_complete, | 305 bool can_save_as_complete, |
| 408 const content::SavePackagePathPickedCallback& callback) { | 306 const content::SavePackagePathPickedCallback& callback) { |
| 409 // Deletes itself. | 307 // Deletes itself. |
| 410 #if defined(OS_CHROMEOS) | 308 #if defined(OS_CHROMEOS) |
| 411 new SavePackageFilePickerChromeOS( | 309 new SavePackageFilePickerChromeOS( |
| 412 web_contents, | 310 web_contents, |
| 413 suggested_path, | 311 suggested_path, |
| 414 can_save_as_complete, | 312 can_save_as_complete, |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 450 download->GetFullPath()), | 348 download->GetFullPath()), |
| 451 callback); | 349 callback); |
| 452 } | 350 } |
| 453 | 351 |
| 454 void ChromeDownloadManagerDelegate::ClearLastDownloadPath() { | 352 void ChromeDownloadManagerDelegate::ClearLastDownloadPath() { |
| 455 last_download_path_.clear(); | 353 last_download_path_.clear(); |
| 456 } | 354 } |
| 457 | 355 |
| 458 DownloadProtectionService* | 356 DownloadProtectionService* |
| 459 ChromeDownloadManagerDelegate::GetDownloadProtectionService() { | 357 ChromeDownloadManagerDelegate::GetDownloadProtectionService() { |
| 358 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 460 #if defined(FULL_SAFE_BROWSING) | 359 #if defined(FULL_SAFE_BROWSING) |
| 461 SafeBrowsingService* sb_service = g_browser_process->safe_browsing_service(); | 360 SafeBrowsingService* sb_service = g_browser_process->safe_browsing_service(); |
| 462 if (sb_service && sb_service->download_protection_service() && | 361 if (sb_service && sb_service->download_protection_service() && |
| 463 profile_->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled)) { | 362 profile_->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled)) { |
| 464 return sb_service->download_protection_service(); | 363 return sb_service->download_protection_service(); |
| 465 } | 364 } |
| 466 #endif | 365 #endif |
| 467 return NULL; | 366 return NULL; |
| 468 } | 367 } |
| 469 | 368 |
| 470 // TODO(phajdan.jr): This is apparently not being exercised in tests. | 369 void ChromeDownloadManagerDelegate::PromptUserForDownloadPath( |
| 471 bool ChromeDownloadManagerDelegate::IsDangerousFile( | 370 DownloadItem* download, |
| 472 const DownloadItem& download, | |
| 473 const base::FilePath& suggested_path, | 371 const base::FilePath& suggested_path, |
| 474 bool visited_referrer_before) { | 372 const DownloadTargetDeterminerDelegate::FileSelectedCallback& callback) { |
| 475 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 373 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 476 const bool is_extension_download = | 374 DownloadFilePicker::ShowFilePicker( |
| 477 download_crx_util::IsExtensionDownload(download); | 375 download, |
| 478 | 376 suggested_path, |
| 479 // User-initiated extension downloads from pref-whitelisted sources are not | 377 base::Bind(&ChromeDownloadManagerDelegate::OnDownloadPathSelected, |
| 480 // considered dangerous. | 378 this, |
| 481 if (download.HasUserGesture() && | 379 callback)); |
| 482 is_extension_download && | |
| 483 download_crx_util::OffStoreInstallAllowedByPrefs(profile_, download)) { | |
| 484 return false; | |
| 485 } | |
| 486 | |
| 487 // Extensions that are not from the gallery are considered dangerous. | |
| 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 } | 380 } |
| 515 | 381 |
| 516 void ChromeDownloadManagerDelegate::GetReservedPath( | 382 ExtensionDownloadsEventRouter* |
| 517 DownloadItem& download, | 383 ChromeDownloadManagerDelegate::GetExtensionEventRouter() { |
| 518 const base::FilePath& target_path, | 384 return DownloadServiceFactory::GetForProfile(profile_)-> |
| 519 const base::FilePath& default_download_path, | 385 GetExtensionEventRouter(); |
| 520 bool should_uniquify_path, | |
| 521 const DownloadPathReservationTracker::ReservedPathCallback& callback) { | |
| 522 DownloadPathReservationTracker::GetReservedPath( | |
| 523 download, target_path, default_download_path, should_uniquify_path, | |
| 524 callback); | |
| 525 } | 386 } |
| 526 | 387 |
| 527 void ChromeDownloadManagerDelegate::CheckDownloadUrlDone( | 388 void ChromeDownloadManagerDelegate::DetermineLocalPath( |
| 528 int32 download_id, | 389 DownloadItem* download, |
| 529 const content::DownloadTargetCallback& callback, | 390 const base::FilePath& virtual_path, |
| 530 DownloadProtectionService::DownloadCheckResult result) { | 391 const DownloadTargetDeterminerDelegate::LocalPathCallback& callback) { |
| 531 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 392 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 532 DownloadItem* download = download_manager_->GetDownload(download_id); | 393 #if defined(OS_CHROMEOS) |
| 533 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS)) | 394 drive::DriveDownloadHandler* drive_download_handler = |
| 534 return; | 395 drive::DriveDownloadHandler::GetForProfile(GetProfile()); |
| 535 | 396 if (drive_download_handler) { |
| 536 VLOG(2) << __FUNCTION__ << "() download = " << download->DebugString(false) | 397 drive_download_handler->SubstituteDriveDownloadPath( |
| 537 << " verdict = " << result; | 398 virtual_path_, download_, |
| 538 content::DownloadDangerType danger_type = download->GetDangerType(); | 399 base::Bind( |
| 539 if (result != DownloadProtectionService::SAFE) | 400 &DownloadTargetDeterminer::DetermineLocalPathDone, |
| 540 danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL; | 401 weak_ptr_factory_.GetWeakPtr())); |
| 541 | |
| 542 // HistoryServiceFactory redirects incognito profiles to on-record profiles. | |
| 543 HistoryService* history = HistoryServiceFactory::GetForProfile( | |
| 544 profile_, Profile::EXPLICIT_ACCESS); | |
| 545 if (!history || !download->GetReferrerUrl().is_valid()) { | |
| 546 // If the original profile doesn't have a HistoryService or the referrer url | |
| 547 // is invalid, then give up and assume the referrer has not been visited | |
| 548 // before. There's no history for on-record profiles in unit_tests, for | |
| 549 // example. | |
| 550 CheckVisitedReferrerBeforeDone(download_id, callback, danger_type, false); | |
| 551 return; | 402 return; |
| 552 } | 403 } |
| 553 history->GetVisibleVisitCountToHost( | 404 #endif |
| 554 download->GetReferrerUrl(), &history_consumer_, | 405 callback.Run(virtual_path); |
| 555 base::Bind(&VisitCountsToVisitedBefore, base::Bind( | 406 } |
| 556 &ChromeDownloadManagerDelegate::CheckVisitedReferrerBeforeDone, | 407 |
| 557 this, download_id, callback, danger_type))); | 408 void ChromeDownloadManagerDelegate::ReserveVirtualPath( |
| 409 content::DownloadItem* download, | |
| 410 const base::FilePath& virtual_path, | |
| 411 bool should_uniquify_path, | |
| 412 const DownloadTargetDeterminerDelegate::ReservedPathCallback& callback) { | |
| 413 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 414 DCHECK(!virtual_path.empty()); | |
| 415 #if defined(OS_CHROMEOS) | |
| 416 // TODO(asanka): Handle path reservations for virtual paths as well. | |
| 417 // http://crbug.com/151618 | |
| 418 if (drive::util::IsUnderDriveMountPoint(virtual_path)) { | |
| 419 callback.Run(virtual_path, true); | |
| 420 return; | |
| 421 } | |
| 422 #endif | |
| 423 DownloadPathReservationTracker::GetReservedPath( | |
| 424 *download, virtual_path, download_prefs_->DownloadPath(), | |
| 425 should_uniquify_path, callback); | |
| 426 } | |
| 427 | |
| 428 void ChromeDownloadManagerDelegate::OnDownloadPathSelected( | |
| 429 const DownloadTargetDeterminerDelegate::FileSelectedCallback& callback, | |
| 430 const base::FilePath& virtual_path, | |
| 431 const base::FilePath& local_path) { | |
| 432 if (!virtual_path.empty()) | |
| 433 last_download_path_ = virtual_path.DirName(); | |
| 434 callback.Run(virtual_path, local_path); | |
| 435 } | |
| 436 | |
| 437 void ChromeDownloadManagerDelegate::OnDetermineDownloadTargetDone( | |
| 438 const content::DownloadTargetCallback& callback, | |
| 439 const base::FilePath& virtual_path, | |
|
benjhayden
2013/04/09 15:46:32
I spent a few seconds looking for where this was u
| |
| 440 const base::FilePath& local_path, | |
| 441 const base::FilePath& intermediate_path, | |
| 442 content::DownloadItem::TargetDisposition target_disposition, | |
| 443 content::DownloadDangerType danger_type) { | |
| 444 callback.Run(local_path, target_disposition, danger_type, intermediate_path); | |
| 558 } | 445 } |
| 559 | 446 |
| 560 void ChromeDownloadManagerDelegate::CheckClientDownloadDone( | 447 void ChromeDownloadManagerDelegate::CheckClientDownloadDone( |
| 561 int32 download_id, | 448 int32 download_id, |
| 562 DownloadProtectionService::DownloadCheckResult result) { | 449 DownloadProtectionService::DownloadCheckResult result) { |
| 563 DownloadItem* item = download_manager_->GetDownload(download_id); | 450 DownloadItem* item = download_manager_->GetDownload(download_id); |
| 564 if (!item || (item->GetState() != DownloadItem::IN_PROGRESS)) | 451 if (!item || (item->GetState() != DownloadItem::IN_PROGRESS)) |
| 565 return; | 452 return; |
| 566 | 453 |
| 567 VLOG(2) << __FUNCTION__ << "() download = " << item->DebugString(false) | 454 VLOG(2) << __FUNCTION__ << "() download = " << item->DebugString(false) |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 605 registrar_.Remove(this, | 492 registrar_.Remove(this, |
| 606 chrome::NOTIFICATION_CRX_INSTALLER_DONE, | 493 chrome::NOTIFICATION_CRX_INSTALLER_DONE, |
| 607 source); | 494 source); |
| 608 | 495 |
| 609 scoped_refptr<extensions::CrxInstaller> installer = | 496 scoped_refptr<extensions::CrxInstaller> installer = |
| 610 content::Source<extensions::CrxInstaller>(source).ptr(); | 497 content::Source<extensions::CrxInstaller>(source).ptr(); |
| 611 content::DownloadOpenDelayedCallback callback = crx_installers_[installer]; | 498 content::DownloadOpenDelayedCallback callback = crx_installers_[installer]; |
| 612 crx_installers_.erase(installer.get()); | 499 crx_installers_.erase(installer.get()); |
| 613 callback.Run(installer->did_handle_successfully()); | 500 callback.Run(installer->did_handle_successfully()); |
| 614 } | 501 } |
| 615 | |
| 616 struct ChromeDownloadManagerDelegate::ContinueFilenameDeterminationInfo { | |
| 617 ContinueFilenameDeterminationInfo(); | |
| 618 ~ContinueFilenameDeterminationInfo(); | |
| 619 | |
| 620 int32 download_id; | |
| 621 content::DownloadTargetCallback callback; | |
| 622 content::DownloadDangerType danger_type; | |
| 623 bool visited_referrer_before; | |
| 624 bool should_prompt; | |
| 625 }; | |
| 626 | |
| 627 ChromeDownloadManagerDelegate::ContinueFilenameDeterminationInfo:: | |
| 628 ContinueFilenameDeterminationInfo() {} | |
| 629 ChromeDownloadManagerDelegate::ContinueFilenameDeterminationInfo:: | |
| 630 ~ContinueFilenameDeterminationInfo() {} | |
| 631 | |
| 632 void ChromeDownloadManagerDelegate::CheckVisitedReferrerBeforeDone( | |
| 633 int32 download_id, | |
| 634 const content::DownloadTargetCallback& callback, | |
| 635 content::DownloadDangerType danger_type, | |
| 636 bool visited_referrer_before) { | |
| 637 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 638 | |
| 639 DownloadItem* download = | |
| 640 download_manager_->GetDownload(download_id); | |
| 641 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS)) | |
| 642 return; | |
| 643 | |
| 644 bool should_prompt = (download->GetTargetDisposition() == | |
| 645 DownloadItem::TARGET_DISPOSITION_PROMPT); | |
| 646 bool is_forced_path = !download->GetForcedFilePath().empty(); | |
| 647 base::FilePath generated_name; | |
| 648 base::FilePath suggested_path; | |
| 649 | |
| 650 // Check whether this download is for an extension install or not. | |
| 651 // Allow extensions to be explicitly saved. | |
| 652 if (!is_forced_path) { | |
| 653 GenerateFileNameFromRequest( | |
| 654 *download, | |
| 655 &generated_name, | |
| 656 profile_->GetPrefs()->GetString(prefs::kDefaultCharset)); | |
| 657 | |
| 658 // Freeze the user's preference for showing a Save As dialog. We're going | |
| 659 // to bounce around a bunch of threads and we don't want to worry about race | |
| 660 // conditions where the user changes this pref out from under us. | |
| 661 if (download_prefs_->PromptForDownload()) { | |
| 662 // But ignore the user's preference for the following scenarios: | |
| 663 // 1) Extension installation. Note that we only care here about the case | |
| 664 // where an extension is installed, not when one is downloaded with | |
| 665 // "save as...". | |
| 666 // 2) Filetypes marked "always open." If the user just wants this file | |
| 667 // opened, don't bother asking where to keep it. | |
| 668 if (!download_crx_util::IsExtensionDownload(*download) && | |
| 669 !ShouldOpenFileBasedOnExtension(generated_name)) | |
| 670 should_prompt = true; | |
| 671 } | |
| 672 if (download_prefs_->IsDownloadPathManaged()) | |
| 673 should_prompt = false; | |
| 674 | |
| 675 // Determine the proper path for a download, by either one of the following: | |
| 676 // 1) using the default download directory. | |
| 677 // 2) prompting the user. | |
| 678 base::FilePath target_directory; | |
| 679 if (should_prompt && !last_download_path_.empty()) | |
| 680 target_directory = last_download_path_; | |
| 681 else | |
| 682 target_directory = download_prefs_->DownloadPath(); | |
| 683 suggested_path = target_directory.Append(generated_name); | |
| 684 } else { | |
| 685 DCHECK(!should_prompt); | |
| 686 suggested_path = download->GetForcedFilePath(); | |
| 687 } | |
| 688 | |
| 689 ContinueFilenameDeterminationInfo continue_info; | |
| 690 continue_info.download_id = download_id; | |
| 691 continue_info.callback = callback; | |
| 692 continue_info.danger_type = danger_type; | |
| 693 continue_info.visited_referrer_before = visited_referrer_before; | |
| 694 continue_info.should_prompt = should_prompt; | |
| 695 | |
| 696 base::Closure filename_determined = base::Bind( | |
| 697 &ChromeDownloadManagerDelegate::ContinueDeterminingFilename, | |
| 698 this, continue_info, suggested_path, is_forced_path); | |
| 699 #if defined(OS_ANDROID) | |
| 700 filename_determined.Run(); | |
| 701 #else | |
| 702 if (is_forced_path || | |
| 703 !DownloadServiceFactory::GetForProfile(profile_) | |
| 704 ->GetExtensionEventRouter()) { | |
| 705 filename_determined.Run(); | |
| 706 } else { | |
| 707 DownloadService* service = DownloadServiceFactory::GetForProfile(profile_); | |
| 708 ExtensionDownloadsEventRouter* router = service->GetExtensionEventRouter(); | |
| 709 ExtensionDownloadsEventRouter::FilenameChangedCallback overriding = | |
| 710 base::Bind(&ChromeDownloadManagerDelegate::OnExtensionOverridingFilename, | |
| 711 this, continue_info); | |
| 712 router->OnDeterminingFilename( | |
| 713 download, generated_name, filename_determined, overriding); | |
| 714 } | |
| 715 #endif | |
| 716 } | |
| 717 | |
| 718 void ChromeDownloadManagerDelegate::OnExtensionOverridingFilename( | |
| 719 const ContinueFilenameDeterminationInfo& continue_info, | |
| 720 const base::FilePath& changed_filename, | |
| 721 bool overwrite) { | |
| 722 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 723 DownloadItem* download = | |
| 724 download_manager_->GetDownload(continue_info.download_id); | |
| 725 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS)) | |
| 726 return; | |
| 727 // If an extension overrides the filename, then the target directory will be | |
| 728 // forced to download_prefs_->DownloadPath() since extensions cannot place | |
| 729 // downloaded files anywhere except there. This prevents subdirectories from | |
| 730 // accumulating: if an extension is allowed to say that a file should go in | |
| 731 // last_download_path/music/foo.mp3, then last_download_path will accumulate | |
| 732 // the subdirectory /music/ so that the next download may end up in | |
| 733 // Downloads/music/music/music/bar.mp3. | |
| 734 base::FilePath temp_filename(download_prefs_->DownloadPath().Append( | |
| 735 changed_filename).NormalizePathSeparators()); | |
| 736 // Do not pass a mime type to GenerateSafeFileName so that it does not force | |
| 737 // the filename to have an extension if the (chrome) extension does not | |
| 738 // suggest it. | |
| 739 net::GenerateSafeFileName(std::string(), false, &temp_filename); | |
| 740 // If |is_forced_path| were true, then extensions would not have been | |
| 741 // consulted, so use |overwrite| instead of |is_forced_path|. This does NOT | |
| 742 // set DownloadItem::GetForcedFilePath()! | |
| 743 ContinueDeterminingFilename(continue_info, temp_filename, overwrite); | |
| 744 } | |
| 745 | |
| 746 void ChromeDownloadManagerDelegate::ContinueDeterminingFilename( | |
| 747 const ContinueFilenameDeterminationInfo& continue_info, | |
| 748 const base::FilePath& suggested_path, | |
| 749 bool is_forced_path) { | |
| 750 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 751 int32 download_id = continue_info.download_id; | |
| 752 const content::DownloadTargetCallback& callback = continue_info.callback; | |
| 753 content::DownloadDangerType danger_type = continue_info.danger_type; | |
| 754 bool visited_referrer_before = continue_info.visited_referrer_before; | |
| 755 bool should_prompt = continue_info.should_prompt; | |
| 756 DownloadItem* download = | |
| 757 download_manager_->GetDownload(download_id); | |
| 758 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS)) | |
| 759 return; | |
| 760 | |
| 761 // If the download hasn't already been marked dangerous (could be | |
| 762 // DANGEROUS_URL), check if it is a dangerous file. | |
| 763 if (danger_type == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) { | |
| 764 if (!should_prompt && !is_forced_path && | |
| 765 IsDangerousFile(*download, suggested_path, visited_referrer_before)) { | |
| 766 danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE; | |
| 767 } | |
| 768 | |
| 769 #if defined(FULL_SAFE_BROWSING) | |
| 770 DownloadProtectionService* service = GetDownloadProtectionService(); | |
| 771 // If this type of files is handled by the enhanced SafeBrowsing download | |
| 772 // protection, mark it as potentially dangerous content until we are done | |
| 773 // with scanning it. | |
| 774 if (service && service->enabled()) { | |
| 775 // TODO(noelutz): if the user changes the extension name in the UI to | |
| 776 // something like .exe SafeBrowsing will currently *not* check if the | |
| 777 // download is malicious. | |
| 778 if (service->IsSupportedDownload(*download, suggested_path)) | |
| 779 danger_type = content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT; | |
| 780 } | |
| 781 #endif | |
| 782 } else { | |
| 783 // Currently we only expect this case. | |
| 784 DCHECK_EQ(content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL, danger_type); | |
| 785 } | |
| 786 | |
| 787 #if defined (OS_CHROMEOS) | |
| 788 drive::DriveDownloadHandler* drive_download_handler = | |
| 789 drive::DriveDownloadHandler::GetForProfile(profile_); | |
| 790 if (drive_download_handler) { | |
| 791 drive_download_handler->SubstituteDriveDownloadPath( | |
| 792 suggested_path, download, | |
| 793 base::Bind( | |
| 794 &ChromeDownloadManagerDelegate::SubstituteDriveDownloadPathCallback, | |
| 795 this, download->GetId(), callback, should_prompt, is_forced_path, | |
| 796 danger_type)); | |
| 797 return; | |
| 798 } | |
| 799 #endif | |
| 800 GetReservedPath( | |
| 801 *download, suggested_path, download_prefs_->DownloadPath(), | |
| 802 !is_forced_path, | |
| 803 base::Bind(&ChromeDownloadManagerDelegate::OnPathReservationAvailable, | |
| 804 this, download->GetId(), callback, should_prompt, | |
| 805 danger_type)); | |
| 806 } | |
| 807 | |
| 808 #if defined (OS_CHROMEOS) | |
| 809 // TODO(asanka): Merge this logic with the logic in DownloadFilePickerChromeOS. | |
| 810 void ChromeDownloadManagerDelegate::SubstituteDriveDownloadPathCallback( | |
| 811 int32 download_id, | |
| 812 const content::DownloadTargetCallback& callback, | |
| 813 bool should_prompt, | |
| 814 bool is_forced_path, | |
| 815 content::DownloadDangerType danger_type, | |
| 816 const base::FilePath& suggested_path) { | |
| 817 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 818 DownloadItem* download = | |
| 819 download_manager_->GetDownload(download_id); | |
| 820 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS)) | |
| 821 return; | |
| 822 | |
| 823 if (suggested_path.empty()) { | |
| 824 // Substitution failed. | |
| 825 callback.Run(base::FilePath(), | |
| 826 DownloadItem::TARGET_DISPOSITION_OVERWRITE, | |
| 827 danger_type, | |
| 828 base::FilePath()); | |
| 829 return; | |
| 830 } | |
| 831 | |
| 832 GetReservedPath( | |
| 833 *download, suggested_path, download_prefs_->DownloadPath(), | |
| 834 !is_forced_path, | |
| 835 base::Bind(&ChromeDownloadManagerDelegate::OnPathReservationAvailable, | |
| 836 this, download->GetId(), callback, should_prompt, | |
| 837 danger_type)); | |
| 838 } | |
| 839 #endif | |
| 840 | |
| 841 void ChromeDownloadManagerDelegate::OnPathReservationAvailable( | |
| 842 int32 download_id, | |
| 843 const content::DownloadTargetCallback& callback, | |
| 844 bool should_prompt, | |
| 845 content::DownloadDangerType danger_type, | |
| 846 const base::FilePath& reserved_path, | |
| 847 bool reserved_path_verified) { | |
| 848 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 849 DownloadItem* download = | |
| 850 download_manager_->GetDownload(download_id); | |
| 851 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS)) | |
| 852 return; | |
| 853 if (should_prompt || !reserved_path_verified) { | |
| 854 // If the target path could not be verified then the path was non-existant, | |
| 855 // non writeable or could not be uniquified. Prompt the user. | |
| 856 ChooseDownloadPath( | |
| 857 download, reserved_path, | |
| 858 base::Bind(&ChromeDownloadManagerDelegate::OnTargetPathDetermined, | |
| 859 this, download_id, callback, | |
| 860 DownloadItem::TARGET_DISPOSITION_PROMPT, danger_type)); | |
| 861 } else { | |
| 862 OnTargetPathDetermined(download_id, callback, | |
| 863 DownloadItem::TARGET_DISPOSITION_OVERWRITE, | |
| 864 danger_type, reserved_path); | |
| 865 } | |
| 866 } | |
| 867 | |
| 868 void ChromeDownloadManagerDelegate::OnTargetPathDetermined( | |
| 869 int32 download_id, | |
| 870 const content::DownloadTargetCallback& callback, | |
| 871 DownloadItem::TargetDisposition disposition, | |
| 872 content::DownloadDangerType danger_type, | |
| 873 const base::FilePath& target_path) { | |
| 874 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 875 base::FilePath intermediate_path; | |
| 876 DownloadItem* download = | |
| 877 download_manager_->GetDownload(download_id); | |
| 878 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS)) | |
| 879 return; | |
| 880 | |
| 881 // If |target_path| is empty, then that means that the user wants to cancel | |
| 882 // the download. | |
| 883 if (!target_path.empty()) { | |
| 884 intermediate_path = GetIntermediatePath( | |
| 885 target_path, danger_type, !download->GetForcedFilePath().empty()); | |
| 886 | |
| 887 // Retain the last directory. Exclude temporary downloads since the path | |
| 888 // likely points at the location of a temporary file. | |
| 889 // TODO(asanka): This logic is a hack. DownloadFilePicker should give us a | |
| 890 // directory to persist. Or perhaps, if the Drive path | |
| 891 // substitution logic is moved here, then we would have a | |
| 892 // persistable path after the DownloadFilePicker is done. | |
| 893 if (disposition == DownloadItem::TARGET_DISPOSITION_PROMPT && | |
| 894 !download->IsTemporary()) | |
| 895 last_download_path_ = target_path.DirName(); | |
| 896 } | |
| 897 callback.Run(target_path, disposition, danger_type, intermediate_path); | |
| 898 } | |
| OLD | NEW |