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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/download/chrome_download_manager_delegate.h" 6 7 #include <string> 8 9 #include "base/basictypes.h" 10 #include "base/bind.h" 11 #include "base/bind_helpers.h" 12 #include "base/callback.h" 13 #include "base/file_util.h" 14 #include "base/prefs/pref_member.h" 15 #include "base/prefs/pref_service.h" 16 #include "base/rand_util.h" 17 #include "base/strings/stringprintf.h" 18 #include "base/strings/utf_string_conversions.h" 19 #include "base/task_runner.h" 20 #include "base/threading/sequenced_worker_pool.h" 21 #include "base/time/time.h" 22 #include "chrome/browser/browser_process.h" 23 #include "chrome/browser/chrome_notification_types.h" 24 #include "chrome/browser/download/download_completion_blocker.h" 25 #include "chrome/browser/download/download_crx_util.h" 26 #include "chrome/browser/download/download_file_picker.h" 27 #include "chrome/browser/download/download_history.h" 28 #include "chrome/browser/download/download_item_model.h" 29 #include "chrome/browser/download/download_path_reservation_tracker.h" 30 #include "chrome/browser/download/download_prefs.h" 31 #include "chrome/browser/download/download_service.h" 32 #include "chrome/browser/download/download_service_factory.h" 33 #include "chrome/browser/download/download_stats.h" 34 #include "chrome/browser/download/download_target_determiner.h" 35 #include "chrome/browser/download/save_package_file_picker.h" 36 #include "chrome/browser/extensions/api/downloads/downloads_api.h" 37 #include "chrome/browser/extensions/crx_installer.h" 38 #include "chrome/browser/platform_util.h" 39 #include "chrome/browser/profiles/profile.h" 40 #include "chrome/browser/safe_browsing/safe_browsing_service.h" 41 #include "chrome/browser/ui/browser.h" 42 #include "chrome/browser/ui/browser_finder.h" 43 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h" 44 #include "chrome/common/chrome_constants.h" 45 #include "chrome/common/pref_names.h" 46 #include "components/user_prefs/pref_registry_syncable.h" 47 #include "content/public/browser/download_item.h" 48 #include "content/public/browser/download_manager.h" 49 #include "content/public/browser/notification_source.h" 50 #include "content/public/browser/page_navigator.h" 51 #include "extensions/common/constants.h" 52 #include "net/base/mime_util.h" 53 #include "net/base/net_util.h" 54 55 #if defined(OS_CHROMEOS) 56 #include "chrome/browser/chromeos/drive/download_handler.h" 57 #include "chrome/browser/chromeos/drive/file_system_util.h" 58 #endif 59 60 using content::BrowserThread; 61 using content::DownloadItem; 62 using content::DownloadManager; 63 using safe_browsing::DownloadProtectionService; 64 65 namespace { 66 67 #if defined(FULL_SAFE_BROWSING) 68 69 // String pointer used for identifying safebrowing data associated with 70 // a download item. 71 const char kSafeBrowsingUserDataKey[] = "Safe Browsing ID"; 72 73 // The state of a safebrowsing check. 74 class SafeBrowsingState : public DownloadCompletionBlocker { 75 public: 76 SafeBrowsingState() 77 : verdict_(DownloadProtectionService::SAFE) { 78 } 79 80 virtual ~SafeBrowsingState(); 81 82 // The verdict that we got from calling CheckClientDownload. Only valid to 83 // call if |is_complete()|. 84 DownloadProtectionService::DownloadCheckResult verdict() const { 85 return verdict_; 86 } 87 88 void SetVerdict(DownloadProtectionService::DownloadCheckResult result) { 89 verdict_ = result; 90 CompleteDownload(); 91 } 92 93 private: 94 DownloadProtectionService::DownloadCheckResult verdict_; 95 96 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingState); 97 }; 98 99 SafeBrowsingState::~SafeBrowsingState() {} 100 101 #endif // FULL_SAFE_BROWSING 102 103 // Used with GetPlatformDownloadPath() to indicate which platform path to 104 // return. 105 enum PlatformDownloadPathType { 106 // Return the platform specific target path. 107 PLATFORM_TARGET_PATH, 108 109 // Return the platform specific current path. If the download is in-progress 110 // and the download location is a local filesystem path, then 111 // GetPlatformDownloadPath will return the path to the intermediate file. 112 PLATFORM_CURRENT_PATH 113 }; 114 115 // Returns a path in the form that that is expected by platform_util::OpenItem / 116 // platform_util::ShowItemInFolder / DownloadTargetDeterminer. 117 // 118 // DownloadItems corresponding to Drive downloads use a temporary file as the 119 // target path. The paths returned by DownloadItem::GetFullPath() / 120 // GetTargetFilePath() refer to this temporary file. This function looks up the 121 // corresponding path in Drive for these downloads. 122 // 123 // How the platform path is determined is based on PlatformDownloadPathType. 124 base::FilePath GetPlatformDownloadPath(Profile* profile, 125 const DownloadItem* download, 126 PlatformDownloadPathType path_type) { 127 #if defined(OS_CHROMEOS) 128 // Drive downloads always return the target path for all types. 129 drive::DownloadHandler* drive_download_handler = 130 drive::DownloadHandler::GetForProfile(profile); 131 if (drive_download_handler && 132 drive_download_handler->IsDriveDownload(download)) 133 return drive_download_handler->GetTargetPath(download); 134 #endif 135 136 if (path_type == PLATFORM_TARGET_PATH) 137 return download->GetTargetFilePath(); 138 return download->GetFullPath(); 139 } 140 141 #if defined(FULL_SAFE_BROWSING) 142 // Callback invoked by DownloadProtectionService::CheckClientDownload. 143 // |is_content_check_supported| is true if the SB service supports scanning the 144 // download for malicious content. 145 // |callback| is invoked with a danger type determined as follows: 146 // 147 // Danger type is (in order of preference): 148 // * DANGEROUS_URL, if the URL is a known malware site. 149 // * MAYBE_DANGEROUS_CONTENT, if the content will be scanned for 150 // malware. I.e. |is_content_check_supported| is true. 151 // * NOT_DANGEROUS. 152 void CheckDownloadUrlDone( 153 const DownloadTargetDeterminerDelegate::CheckDownloadUrlCallback& callback, 154 bool is_content_check_supported, 155 DownloadProtectionService::DownloadCheckResult result) { 156 content::DownloadDangerType danger_type; 157 if (result == DownloadProtectionService::SAFE) { 158 // If this type of files is handled by the enhanced SafeBrowsing download 159 // protection, mark it as potentially dangerous content until we are done 160 // with scanning it. 161 if (is_content_check_supported) 162 danger_type = content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT; 163 else 164 danger_type = content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS; 165 } else { 166 // If the URL is malicious, we'll use that as the danger type. The results 167 // of the content check, if one is performed, will be ignored. 168 danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL; 169 } 170 callback.Run(danger_type); 171 } 172 173 #endif // FULL_SAFE_BROWSING 174 175 // Called on the blocking pool to determine the MIME type for |path|. 176 void GetMimeTypeAndReplyOnUIThread( 177 const base::FilePath& path, 178 const base::Callback<void(const std::string&)>& callback) { 179 std::string mime_type; 180 net::GetMimeTypeFromFile(path, &mime_type); 181 BrowserThread::PostTask( 182 BrowserThread::UI, FROM_HERE, base::Bind(callback, mime_type)); 183 } 184 185 bool IsOpenInBrowserPreferreredForFile(const base::FilePath& path) { 186 // On Android, always prefer opening with an external app. On ChromeOS, there 187 // are no external apps so just allow all opens to be handled by the "System." 188 #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) && defined(ENABLE_PLUGINS) 189 // TODO(asanka): Consider other file types and MIME types. 190 // http://crbug.com/323561 191 if (path.MatchesExtension(FILE_PATH_LITERAL(".pdf")) || 192 path.MatchesExtension(FILE_PATH_LITERAL(".htm")) || 193 path.MatchesExtension(FILE_PATH_LITERAL(".html")) || 194 path.MatchesExtension(FILE_PATH_LITERAL(".shtm")) || 195 path.MatchesExtension(FILE_PATH_LITERAL(".shtml")) || 196 path.MatchesExtension(FILE_PATH_LITERAL(".svg")) || 197 path.MatchesExtension(FILE_PATH_LITERAL(".xht")) || 198 path.MatchesExtension(FILE_PATH_LITERAL(".xhtm")) || 199 path.MatchesExtension(FILE_PATH_LITERAL(".xhtml")) || 200 path.MatchesExtension(FILE_PATH_LITERAL(".xml")) || 201 path.MatchesExtension(FILE_PATH_LITERAL(".xsl")) || 202 path.MatchesExtension(FILE_PATH_LITERAL(".xslt"))) { 203 return true; 204 } 205 #endif 206 return false; 207 } 208 209 } // namespace 210 211 ChromeDownloadManagerDelegate::ChromeDownloadManagerDelegate(Profile* profile) 212 : profile_(profile), 213 next_download_id_(content::DownloadItem::kInvalidId), 214 download_prefs_(new DownloadPrefs(profile)), 215 weak_ptr_factory_(this) { 216 } 217 218 ChromeDownloadManagerDelegate::~ChromeDownloadManagerDelegate() { 219 // If a DownloadManager was set for this, Shutdown() must be called. 220 DCHECK(!download_manager_); 221 } 222 223 void ChromeDownloadManagerDelegate::SetDownloadManager(DownloadManager* dm) { 224 download_manager_ = dm; 225 } 226 227 void ChromeDownloadManagerDelegate::Shutdown() { 228 download_prefs_.reset(); 229 weak_ptr_factory_.InvalidateWeakPtrs(); 230 download_manager_ = NULL; 231 } 232 233 content::DownloadIdCallback 234 ChromeDownloadManagerDelegate::GetDownloadIdReceiverCallback() { 235 return base::Bind(&ChromeDownloadManagerDelegate::SetNextId, 236 weak_ptr_factory_.GetWeakPtr()); 237 } 238 239 void ChromeDownloadManagerDelegate::SetNextId(uint32 next_id) { 240 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 241 DCHECK(!profile_->IsOffTheRecord()); 242 DCHECK_NE(content::DownloadItem::kInvalidId, next_id); 243 next_download_id_ = next_id; 244 245 IdCallbackVector callbacks; 246 id_callbacks_.swap(callbacks); 247 for (IdCallbackVector::const_iterator it = callbacks.begin(); 248 it != callbacks.end(); ++it) { 249 ReturnNextId(*it); 250 } 251 } 252 253 void ChromeDownloadManagerDelegate::GetNextId( 254 const content::DownloadIdCallback& callback) { 255 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 256 if (profile_->IsOffTheRecord()) { 257 content::BrowserContext::GetDownloadManager( 258 profile_->GetOriginalProfile())->GetDelegate()->GetNextId(callback); 259 return; 260 } 261 if (next_download_id_ == content::DownloadItem::kInvalidId) { 262 id_callbacks_.push_back(callback); 263 return; 264 } 265 ReturnNextId(callback); 266 } 267 268 void ChromeDownloadManagerDelegate::ReturnNextId( 269 const content::DownloadIdCallback& callback) { 270 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 271 DCHECK(!profile_->IsOffTheRecord()); 272 DCHECK_NE(content::DownloadItem::kInvalidId, next_download_id_); 273 callback.Run(next_download_id_++); 274 } 275 276 bool ChromeDownloadManagerDelegate::DetermineDownloadTarget( 277 DownloadItem* download, 278 const content::DownloadTargetCallback& callback) { 279 DownloadTargetDeterminer::CompletionCallback target_determined_callback = 280 base::Bind(&ChromeDownloadManagerDelegate::OnDownloadTargetDetermined, 281 weak_ptr_factory_.GetWeakPtr(), 282 download->GetId(), 283 callback); 284 DownloadTargetDeterminer::Start( 285 download, 286 GetPlatformDownloadPath(profile_, download, PLATFORM_TARGET_PATH), 287 download_prefs_.get(), 288 this, 289 target_determined_callback); 290 return true; 291 } 292 293 bool ChromeDownloadManagerDelegate::ShouldOpenFileBasedOnExtension( 294 const base::FilePath& path) { 295 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 296 if (path.Extension().empty()) 297 return false; 298 // TODO(asanka): This determination is done based on |path|, while 299 // ShouldOpenDownload() detects extension downloads based on the 300 // characteristics of the download. Reconcile this. http://crbug.com/167702 301 if (path.MatchesExtension(extensions::kExtensionFileExtension)) 302 return false; 303 return download_prefs_->IsAutoOpenEnabledBasedOnExtension(path); 304 } 305 306 // static 307 void ChromeDownloadManagerDelegate::DisableSafeBrowsing(DownloadItem* item) { 308 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 309 #if defined(FULL_SAFE_BROWSING) 310 SafeBrowsingState* state = static_cast<SafeBrowsingState*>( 311 item->GetUserData(&kSafeBrowsingUserDataKey)); 312 if (!state) { 313 state = new SafeBrowsingState(); 314 item->SetUserData(&kSafeBrowsingUserDataKey, state); 315 } 316 state->SetVerdict(DownloadProtectionService::SAFE); 317 #endif 318 } 319 320 bool ChromeDownloadManagerDelegate::IsDownloadReadyForCompletion( 321 DownloadItem* item, 322 const base::Closure& internal_complete_callback) { 323 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 324 #if defined(FULL_SAFE_BROWSING) 325 SafeBrowsingState* state = static_cast<SafeBrowsingState*>( 326 item->GetUserData(&kSafeBrowsingUserDataKey)); 327 if (!state) { 328 // Begin the safe browsing download protection check. 329 DownloadProtectionService* service = GetDownloadProtectionService(); 330 if (service) { 331 VLOG(2) << __FUNCTION__ << "() Start SB download check for download = " 332 << item->DebugString(false); 333 state = new SafeBrowsingState(); 334 state->set_callback(internal_complete_callback); 335 item->SetUserData(&kSafeBrowsingUserDataKey, state); 336 service->CheckClientDownload( 337 item, 338 base::Bind( 339 &ChromeDownloadManagerDelegate::CheckClientDownloadDone, 340 weak_ptr_factory_.GetWeakPtr(), 341 item->GetId())); 342 return false; 343 } 344 } else if (!state->is_complete()) { 345 // Don't complete the download until we have an answer. 346 state->set_callback(internal_complete_callback); 347 return false; 348 } 349 #endif 350 return true; 351 } 352 353 void ChromeDownloadManagerDelegate::ShouldCompleteDownloadInternal( 354 uint32 download_id, 355 const base::Closure& user_complete_callback) { 356 DownloadItem* item = download_manager_->GetDownload(download_id); 357 if (!item) 358 return; 359 if (ShouldCompleteDownload(item, user_complete_callback)) 360 user_complete_callback.Run(); 361 } 362 363 bool ChromeDownloadManagerDelegate::ShouldCompleteDownload( 364 DownloadItem* item, 365 const base::Closure& user_complete_callback) { 366 return IsDownloadReadyForCompletion(item, base::Bind( 367 &ChromeDownloadManagerDelegate::ShouldCompleteDownloadInternal, 368 weak_ptr_factory_.GetWeakPtr(), item->GetId(), user_complete_callback)); 369 } 370 371 bool ChromeDownloadManagerDelegate::ShouldOpenDownload( 372 DownloadItem* item, const content::DownloadOpenDelayedCallback& callback) { 373 if (download_crx_util::IsExtensionDownload(*item)) { 374 scoped_refptr<extensions::CrxInstaller> crx_installer = 375 download_crx_util::OpenChromeExtension(profile_, *item); 376 377 // CRX_INSTALLER_DONE will fire when the install completes. At that 378 // time, Observe() will call the passed callback. 379 registrar_.Add( 380 this, 381 chrome::NOTIFICATION_CRX_INSTALLER_DONE, 382 content::Source<extensions::CrxInstaller>(crx_installer.get())); 383 384 crx_installers_[crx_installer.get()] = callback; 385 // The status text and percent complete indicator will change now 386 // that we are installing a CRX. Update observers so that they pick 387 // up the change. 388 item->UpdateObservers(); 389 return false; 390 } 391 392 return true; 393 } 394 395 bool ChromeDownloadManagerDelegate::GenerateFileHash() { 396 #if defined(FULL_SAFE_BROWSING) 397 return profile_->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled) && 398 g_browser_process->safe_browsing_service()->DownloadBinHashNeeded(); 399 #else 400 return false; 401 #endif 402 } 403 404 void ChromeDownloadManagerDelegate::GetSaveDir( 405 content::BrowserContext* browser_context, 406 base::FilePath* website_save_dir, 407 base::FilePath* download_save_dir, 408 bool* skip_dir_check) { 409 *website_save_dir = download_prefs_->SaveFilePath(); 410 DCHECK(!website_save_dir->empty()); 411 *download_save_dir = download_prefs_->DownloadPath(); 412 *skip_dir_check = false; 413 #if defined(OS_CHROMEOS) 414 *skip_dir_check = drive::util::IsUnderDriveMountPoint(*website_save_dir); 415 #endif 416 } 417 418 void ChromeDownloadManagerDelegate::ChooseSavePath( 419 content::WebContents* web_contents, 420 const base::FilePath& suggested_path, 421 const base::FilePath::StringType& default_extension, 422 bool can_save_as_complete, 423 const content::SavePackagePathPickedCallback& callback) { 424 // Deletes itself. 425 new SavePackageFilePicker( 426 web_contents, 427 suggested_path, 428 default_extension, 429 can_save_as_complete, 430 download_prefs_.get(), 431 callback); 432 } 433 434 void ChromeDownloadManagerDelegate::OpenDownloadUsingPlatformHandler( 435 DownloadItem* download) { 436 base::FilePath platform_path( 437 GetPlatformDownloadPath(profile_, download, PLATFORM_TARGET_PATH)); 438 DCHECK(!platform_path.empty()); 439 platform_util::OpenItem(profile_, platform_path); 440 } 441 442 void ChromeDownloadManagerDelegate::OpenDownload(DownloadItem* download) { 443 DCHECK_EQ(DownloadItem::COMPLETE, download->GetState()); 444 DCHECK(!download->GetTargetFilePath().empty()); 445 if (!download->CanOpenDownload()) 446 return; 447 448 if (!DownloadItemModel(download).ShouldPreferOpeningInBrowser()) { 449 RecordDownloadOpenMethod(DOWNLOAD_OPEN_METHOD_DEFAULT_PLATFORM); 450 OpenDownloadUsingPlatformHandler(download); 451 return; 452 } 453 454 #if !defined(OS_ANDROID) 455 content::WebContents* web_contents = download->GetWebContents(); 456 Browser* browser = 457 web_contents ? chrome::FindBrowserWithWebContents(web_contents) : NULL; 458 scoped_ptr<chrome::ScopedTabbedBrowserDisplayer> browser_displayer; 459 if (!browser || 460 !browser->CanSupportWindowFeature(Browser::FEATURE_TABSTRIP)) { 461 browser_displayer.reset(new chrome::ScopedTabbedBrowserDisplayer( 462 profile_, chrome::GetActiveDesktop())); 463 browser = browser_displayer->browser(); 464 } 465 content::OpenURLParams params( 466 net::FilePathToFileURL(download->GetTargetFilePath()), 467 content::Referrer(), 468 NEW_FOREGROUND_TAB, 469 content::PAGE_TRANSITION_LINK, 470 false); 471 browser->OpenURL(params); 472 RecordDownloadOpenMethod(DOWNLOAD_OPEN_METHOD_DEFAULT_BROWSER); 473 #else 474 // ShouldPreferOpeningInBrowser() should never be true on Android. 475 NOTREACHED(); 476 #endif 477 } 478 479 void ChromeDownloadManagerDelegate::ShowDownloadInShell( 480 DownloadItem* download) { 481 if (!download->CanShowInFolder()) 482 return; 483 base::FilePath platform_path( 484 GetPlatformDownloadPath(profile_, download, PLATFORM_CURRENT_PATH)); 485 DCHECK(!platform_path.empty()); 486 platform_util::ShowItemInFolder(profile_, platform_path); 487 } 488 489 void ChromeDownloadManagerDelegate::CheckForFileExistence( 490 DownloadItem* download, 491 const content::CheckForFileExistenceCallback& callback) { 492 #if defined(OS_CHROMEOS) 493 drive::DownloadHandler* drive_download_handler = 494 drive::DownloadHandler::GetForProfile(profile_); 495 if (drive_download_handler && 496 drive_download_handler->IsDriveDownload(download)) { 497 drive_download_handler->CheckForFileExistence(download, callback); 498 return; 499 } 500 #endif 501 static const char kSequenceToken[] = "ChromeDMD-FileExistenceChecker"; 502 base::SequencedWorkerPool* worker_pool = BrowserThread::GetBlockingPool(); 503 scoped_refptr<base::SequencedTaskRunner> task_runner = 504 worker_pool->GetSequencedTaskRunnerWithShutdownBehavior( 505 worker_pool->GetNamedSequenceToken(kSequenceToken), 506 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); 507 base::PostTaskAndReplyWithResult( 508 task_runner.get(), 509 FROM_HERE, 510 base::Bind(&base::PathExists, download->GetTargetFilePath()), 511 callback); 512 } 513 514 std::string 515 ChromeDownloadManagerDelegate::ApplicationClientIdForFileScanning() const { 516 return std::string(chrome::kApplicationClientIDStringForAVScanning); 517 } 518 519 DownloadProtectionService* 520 ChromeDownloadManagerDelegate::GetDownloadProtectionService() { 521 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 522 #if defined(FULL_SAFE_BROWSING) 523 SafeBrowsingService* sb_service = g_browser_process->safe_browsing_service(); 524 if (sb_service && sb_service->download_protection_service() && 525 profile_->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled)) { 526 return sb_service->download_protection_service(); 527 } 528 #endif 529 return NULL; 530 } 531 532 void ChromeDownloadManagerDelegate::NotifyExtensions( 533 DownloadItem* download, 534 const base::FilePath& virtual_path, 535 const NotifyExtensionsCallback& callback) { 536 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 537 #if !defined(OS_ANDROID) 538 ExtensionDownloadsEventRouter* router = 539 DownloadServiceFactory::GetForBrowserContext(profile_)-> 540 GetExtensionEventRouter(); 541 if (router) { 542 base::Closure original_path_callback = 543 base::Bind(callback, base::FilePath(), 544 DownloadPathReservationTracker::UNIQUIFY); 545 router->OnDeterminingFilename(download, virtual_path.BaseName(), 546 original_path_callback, 547 callback); 548 return; 549 } 550 #endif 551 callback.Run(base::FilePath(), DownloadPathReservationTracker::UNIQUIFY); 552 } 553 554 void ChromeDownloadManagerDelegate::ReserveVirtualPath( 555 content::DownloadItem* download, 556 const base::FilePath& virtual_path, 557 bool create_directory, 558 DownloadPathReservationTracker::FilenameConflictAction conflict_action, 559 const DownloadTargetDeterminerDelegate::ReservedPathCallback& callback) { 560 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 561 DCHECK(!virtual_path.empty()); 562 #if defined(OS_CHROMEOS) 563 // TODO(asanka): Handle path reservations for virtual paths as well. 564 // http://crbug.com/151618 565 if (drive::util::IsUnderDriveMountPoint(virtual_path)) { 566 callback.Run(virtual_path, true); 567 return; 568 } 569 #endif 570 DownloadPathReservationTracker::GetReservedPath( 571 download, 572 virtual_path, 573 download_prefs_->DownloadPath(), 574 create_directory, 575 conflict_action, 576 callback); 577 } 578 579 void ChromeDownloadManagerDelegate::PromptUserForDownloadPath( 580 DownloadItem* download, 581 const base::FilePath& suggested_path, 582 const DownloadTargetDeterminerDelegate::FileSelectedCallback& callback) { 583 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 584 DownloadFilePicker::ShowFilePicker(download, suggested_path, callback); 585 } 586 587 void ChromeDownloadManagerDelegate::DetermineLocalPath( 588 DownloadItem* download, 589 const base::FilePath& virtual_path, 590 const DownloadTargetDeterminerDelegate::LocalPathCallback& callback) { 591 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 592 #if defined(OS_CHROMEOS) 593 drive::DownloadHandler* drive_download_handler = 594 drive::DownloadHandler::GetForProfile(profile_); 595 if (drive_download_handler) { 596 drive_download_handler->SubstituteDriveDownloadPath( 597 virtual_path, download, callback); 598 return; 599 } 600 #endif 601 callback.Run(virtual_path); 602 } 603 604 void ChromeDownloadManagerDelegate::CheckDownloadUrl( 605 DownloadItem* download, 606 const base::FilePath& suggested_path, 607 const CheckDownloadUrlCallback& callback) { 608 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 609 610 #if defined(FULL_SAFE_BROWSING) 611 safe_browsing::DownloadProtectionService* service = 612 GetDownloadProtectionService(); 613 if (service) { 614 bool is_content_check_supported = 615 service->IsSupportedDownload(*download, suggested_path); 616 VLOG(2) << __FUNCTION__ << "() Start SB URL check for download = " 617 << download->DebugString(false); 618 service->CheckDownloadUrl(*download, 619 base::Bind(&CheckDownloadUrlDone, 620 callback, 621 is_content_check_supported)); 622 return; 623 } 624 #endif 625 callback.Run(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS); 626 } 627 628 void ChromeDownloadManagerDelegate::GetFileMimeType( 629 const base::FilePath& path, 630 const GetFileMimeTypeCallback& callback) { 631 BrowserThread::PostBlockingPoolTask( 632 FROM_HERE, 633 base::Bind(&GetMimeTypeAndReplyOnUIThread, path, callback)); 634 } 635 636 #if defined(FULL_SAFE_BROWSING) 637 void ChromeDownloadManagerDelegate::CheckClientDownloadDone( 638 uint32 download_id, 639 DownloadProtectionService::DownloadCheckResult result) { 640 DownloadItem* item = download_manager_->GetDownload(download_id); 641 if (!item || (item->GetState() != DownloadItem::IN_PROGRESS)) 642 return; 643 644 VLOG(2) << __FUNCTION__ << "() download = " << item->DebugString(false) 645 << " verdict = " << result; 646 // We only mark the content as being dangerous if the download's safety state 647 // has not been set to DANGEROUS yet. We don't want to show two warnings. 648 if (item->GetDangerType() == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS || 649 item->GetDangerType() == 650 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT) { 651 content::DownloadDangerType danger_type = 652 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS; 653 switch (result) { 654 case DownloadProtectionService::SAFE: 655 // Do nothing. 656 break; 657 case DownloadProtectionService::DANGEROUS: 658 danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT; 659 break; 660 case DownloadProtectionService::UNCOMMON: 661 danger_type = content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT; 662 break; 663 case DownloadProtectionService::DANGEROUS_HOST: 664 danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST; 665 break; 666 case DownloadProtectionService::POTENTIALLY_UNWANTED: 667 danger_type = content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED; 668 break; 669 } 670 671 if (danger_type != content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) 672 item->OnContentCheckCompleted(danger_type); 673 } 674 675 SafeBrowsingState* state = static_cast<SafeBrowsingState*>( 676 item->GetUserData(&kSafeBrowsingUserDataKey)); 677 state->SetVerdict(result); 678 } 679 #endif // FULL_SAFE_BROWSING 680 681 // content::NotificationObserver implementation. 682 void ChromeDownloadManagerDelegate::Observe( 683 int type, 684 const content::NotificationSource& source, 685 const content::NotificationDetails& details) { 686 DCHECK(type == chrome::NOTIFICATION_CRX_INSTALLER_DONE); 687 688 registrar_.Remove(this, 689 chrome::NOTIFICATION_CRX_INSTALLER_DONE, 690 source); 691 692 scoped_refptr<extensions::CrxInstaller> installer = 693 content::Source<extensions::CrxInstaller>(source).ptr(); 694 content::DownloadOpenDelayedCallback callback = 695 crx_installers_[installer.get()]; 696 crx_installers_.erase(installer.get()); 697 callback.Run(installer->did_handle_successfully()); 698 } 699 700 void ChromeDownloadManagerDelegate::OnDownloadTargetDetermined( 701 int32 download_id, 702 const content::DownloadTargetCallback& callback, 703 scoped_ptr<DownloadTargetInfo> target_info) { 704 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 705 DownloadItem* item = download_manager_->GetDownload(download_id); 706 if (!target_info->target_path.empty() && item && 707 IsOpenInBrowserPreferreredForFile(target_info->target_path) && 708 target_info->is_filetype_handled_securely) 709 DownloadItemModel(item).SetShouldPreferOpeningInBrowser(true); 710 callback.Run(target_info->target_path, 711 target_info->target_disposition, 712 target_info->danger_type, 713 target_info->intermediate_path); 714 } 715