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.
5 #include "chrome/browser/download/chrome_download_manager_delegate.h"
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/task_runner_util.h"
21 #include "base/threading/sequenced_worker_pool.h"
22 #include "base/time/time.h"
23 #include "chrome/browser/browser_process.h"
24 #include "chrome/browser/chrome_notification_types.h"
25 #include "chrome/browser/download/download_completion_blocker.h"
26 #include "chrome/browser/download/download_crx_util.h"
27 #include "chrome/browser/download/download_file_picker.h"
28 #include "chrome/browser/download/download_history.h"
29 #include "chrome/browser/download/download_item_model.h"
30 #include "chrome/browser/download/download_path_reservation_tracker.h"
31 #include "chrome/browser/download/download_prefs.h"
32 #include "chrome/browser/download/download_service.h"
33 #include "chrome/browser/download/download_service_factory.h"
34 #include "chrome/browser/download/download_stats.h"
35 #include "chrome/browser/download/download_target_determiner.h"
36 #include "chrome/browser/download/save_package_file_picker.h"
37 #include "chrome/browser/platform_util.h"
38 #include "chrome/browser/profiles/profile.h"
39 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
40 #include "chrome/browser/ui/browser.h"
41 #include "chrome/browser/ui/browser_finder.h"
42 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
43 #include "chrome/common/chrome_constants.h"
44 #include "chrome/common/pref_names.h"
45 #include "components/pref_registry/pref_registry_syncable.h"
46 #include "content/public/browser/download_item.h"
47 #include "content/public/browser/download_manager.h"
48 #include "content/public/browser/notification_source.h"
49 #include "content/public/browser/page_navigator.h"
50 #include "net/base/filename_util.h"
51 #include "net/base/mime_util.h"
53 #if defined(OS_CHROMEOS)
54 #include "chrome/browser/chromeos/drive/download_handler.h"
55 #include "chrome/browser/chromeos/drive/file_system_util.h"
58 #if defined(ENABLE_EXTENSIONS)
59 #include "chrome/browser/extensions/api/downloads/downloads_api.h"
60 #include "chrome/browser/extensions/crx_installer.h"
61 #include "chrome/browser/extensions/webstore_installer.h"
62 #include "extensions/common/constants.h"
65 using content::BrowserThread;
66 using content::DownloadItem;
67 using content::DownloadManager;
68 using safe_browsing::DownloadProtectionService;
72 #if defined(FULL_SAFE_BROWSING)
74 // String pointer used for identifying safebrowing data associated with
76 const char kSafeBrowsingUserDataKey[] = "Safe Browsing ID";
78 // The state of a safebrowsing check.
79 class SafeBrowsingState : public DownloadCompletionBlocker {
82 : verdict_(DownloadProtectionService::SAFE) {
85 virtual ~SafeBrowsingState();
87 // The verdict that we got from calling CheckClientDownload. Only valid to
88 // call if |is_complete()|.
89 DownloadProtectionService::DownloadCheckResult verdict() const {
93 void SetVerdict(DownloadProtectionService::DownloadCheckResult result) {
99 DownloadProtectionService::DownloadCheckResult verdict_;
101 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingState);
104 SafeBrowsingState::~SafeBrowsingState() {}
106 #endif // FULL_SAFE_BROWSING
108 // Used with GetPlatformDownloadPath() to indicate which platform path to
110 enum PlatformDownloadPathType {
111 // Return the platform specific target path.
112 PLATFORM_TARGET_PATH,
114 // Return the platform specific current path. If the download is in-progress
115 // and the download location is a local filesystem path, then
116 // GetPlatformDownloadPath will return the path to the intermediate file.
117 PLATFORM_CURRENT_PATH
120 // Returns a path in the form that that is expected by platform_util::OpenItem /
121 // platform_util::ShowItemInFolder / DownloadTargetDeterminer.
123 // DownloadItems corresponding to Drive downloads use a temporary file as the
124 // target path. The paths returned by DownloadItem::GetFullPath() /
125 // GetTargetFilePath() refer to this temporary file. This function looks up the
126 // corresponding path in Drive for these downloads.
128 // How the platform path is determined is based on PlatformDownloadPathType.
129 base::FilePath GetPlatformDownloadPath(Profile* profile,
130 const DownloadItem* download,
131 PlatformDownloadPathType path_type) {
132 #if defined(OS_CHROMEOS)
133 // Drive downloads always return the target path for all types.
134 drive::DownloadHandler* drive_download_handler =
135 drive::DownloadHandler::GetForProfile(profile);
136 if (drive_download_handler &&
137 drive_download_handler->IsDriveDownload(download))
138 return drive_download_handler->GetTargetPath(download);
141 if (path_type == PLATFORM_TARGET_PATH)
142 return download->GetTargetFilePath();
143 return download->GetFullPath();
146 #if defined(FULL_SAFE_BROWSING)
147 // Callback invoked by DownloadProtectionService::CheckClientDownload.
148 // |is_content_check_supported| is true if the SB service supports scanning the
149 // download for malicious content.
150 // |callback| is invoked with a danger type determined as follows:
152 // Danger type is (in order of preference):
153 // * DANGEROUS_URL, if the URL is a known malware site.
154 // * MAYBE_DANGEROUS_CONTENT, if the content will be scanned for
155 // malware. I.e. |is_content_check_supported| is true.
157 void CheckDownloadUrlDone(
158 const DownloadTargetDeterminerDelegate::CheckDownloadUrlCallback& callback,
159 bool is_content_check_supported,
160 DownloadProtectionService::DownloadCheckResult result) {
161 content::DownloadDangerType danger_type;
162 if (result == DownloadProtectionService::SAFE) {
163 // If this type of files is handled by the enhanced SafeBrowsing download
164 // protection, mark it as potentially dangerous content until we are done
166 if (is_content_check_supported)
167 danger_type = content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT;
169 danger_type = content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS;
171 // If the URL is malicious, we'll use that as the danger type. The results
172 // of the content check, if one is performed, will be ignored.
173 danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL;
175 callback.Run(danger_type);
178 #endif // FULL_SAFE_BROWSING
180 // Called on the blocking pool to determine the MIME type for |path|.
181 std::string GetMimeType(const base::FilePath& path) {
182 std::string mime_type;
183 net::GetMimeTypeFromFile(path, &mime_type);
187 bool IsOpenInBrowserPreferreredForFile(const base::FilePath& path) {
188 // On Android, always prefer opening with an external app. On ChromeOS, there
189 // are no external apps so just allow all opens to be handled by the "System."
190 #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) && defined(ENABLE_PLUGINS)
191 // TODO(asanka): Consider other file types and MIME types.
192 // http://crbug.com/323561
193 if (path.MatchesExtension(FILE_PATH_LITERAL(".pdf")) ||
194 path.MatchesExtension(FILE_PATH_LITERAL(".htm")) ||
195 path.MatchesExtension(FILE_PATH_LITERAL(".html")) ||
196 path.MatchesExtension(FILE_PATH_LITERAL(".shtm")) ||
197 path.MatchesExtension(FILE_PATH_LITERAL(".shtml")) ||
198 path.MatchesExtension(FILE_PATH_LITERAL(".svg")) ||
199 path.MatchesExtension(FILE_PATH_LITERAL(".xht")) ||
200 path.MatchesExtension(FILE_PATH_LITERAL(".xhtm")) ||
201 path.MatchesExtension(FILE_PATH_LITERAL(".xhtml")) ||
202 path.MatchesExtension(FILE_PATH_LITERAL(".xsl")) ||
203 path.MatchesExtension(FILE_PATH_LITERAL(".xslt"))) {
212 ChromeDownloadManagerDelegate::ChromeDownloadManagerDelegate(Profile* profile)
214 next_download_id_(content::DownloadItem::kInvalidId),
215 download_prefs_(new DownloadPrefs(profile)),
216 weak_ptr_factory_(this) {
219 ChromeDownloadManagerDelegate::~ChromeDownloadManagerDelegate() {
220 // If a DownloadManager was set for this, Shutdown() must be called.
221 DCHECK(!download_manager_);
224 void ChromeDownloadManagerDelegate::SetDownloadManager(DownloadManager* dm) {
225 download_manager_ = dm;
228 void ChromeDownloadManagerDelegate::Shutdown() {
229 download_prefs_.reset();
230 weak_ptr_factory_.InvalidateWeakPtrs();
231 download_manager_ = NULL;
234 content::DownloadIdCallback
235 ChromeDownloadManagerDelegate::GetDownloadIdReceiverCallback() {
236 return base::Bind(&ChromeDownloadManagerDelegate::SetNextId,
237 weak_ptr_factory_.GetWeakPtr());
240 void ChromeDownloadManagerDelegate::SetNextId(uint32 next_id) {
241 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
242 DCHECK(!profile_->IsOffTheRecord());
243 DCHECK_NE(content::DownloadItem::kInvalidId, next_id);
244 next_download_id_ = next_id;
246 IdCallbackVector callbacks;
247 id_callbacks_.swap(callbacks);
248 for (IdCallbackVector::const_iterator it = callbacks.begin();
249 it != callbacks.end(); ++it) {
254 void ChromeDownloadManagerDelegate::GetNextId(
255 const content::DownloadIdCallback& callback) {
256 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
257 if (profile_->IsOffTheRecord()) {
258 content::BrowserContext::GetDownloadManager(
259 profile_->GetOriginalProfile())->GetDelegate()->GetNextId(callback);
262 if (next_download_id_ == content::DownloadItem::kInvalidId) {
263 id_callbacks_.push_back(callback);
266 ReturnNextId(callback);
269 void ChromeDownloadManagerDelegate::ReturnNextId(
270 const content::DownloadIdCallback& callback) {
271 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
272 DCHECK(!profile_->IsOffTheRecord());
273 DCHECK_NE(content::DownloadItem::kInvalidId, next_download_id_);
274 callback.Run(next_download_id_++);
277 bool ChromeDownloadManagerDelegate::DetermineDownloadTarget(
278 DownloadItem* download,
279 const content::DownloadTargetCallback& callback) {
280 DownloadTargetDeterminer::CompletionCallback target_determined_callback =
281 base::Bind(&ChromeDownloadManagerDelegate::OnDownloadTargetDetermined,
282 weak_ptr_factory_.GetWeakPtr(),
285 DownloadTargetDeterminer::Start(
287 GetPlatformDownloadPath(profile_, download, PLATFORM_TARGET_PATH),
288 download_prefs_.get(),
290 target_determined_callback);
294 bool ChromeDownloadManagerDelegate::ShouldOpenFileBasedOnExtension(
295 const base::FilePath& path) {
296 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
297 if (path.Extension().empty())
299 #if defined(ENABLE_EXTENSIONS)
300 // TODO(asanka): This determination is done based on |path|, while
301 // ShouldOpenDownload() detects extension downloads based on the
302 // characteristics of the download. Reconcile this. http://crbug.com/167702
303 if (path.MatchesExtension(extensions::kExtensionFileExtension))
306 return download_prefs_->IsAutoOpenEnabledBasedOnExtension(path);
310 void ChromeDownloadManagerDelegate::DisableSafeBrowsing(DownloadItem* item) {
311 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
312 #if defined(FULL_SAFE_BROWSING)
313 SafeBrowsingState* state = static_cast<SafeBrowsingState*>(
314 item->GetUserData(&kSafeBrowsingUserDataKey));
316 state = new SafeBrowsingState();
317 item->SetUserData(&kSafeBrowsingUserDataKey, state);
319 state->SetVerdict(DownloadProtectionService::SAFE);
323 bool ChromeDownloadManagerDelegate::IsDownloadReadyForCompletion(
325 const base::Closure& internal_complete_callback) {
326 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
327 #if defined(FULL_SAFE_BROWSING)
328 SafeBrowsingState* state = static_cast<SafeBrowsingState*>(
329 item->GetUserData(&kSafeBrowsingUserDataKey));
331 // Begin the safe browsing download protection check.
332 DownloadProtectionService* service = GetDownloadProtectionService();
334 VLOG(2) << __FUNCTION__ << "() Start SB download check for download = "
335 << item->DebugString(false);
336 state = new SafeBrowsingState();
337 state->set_callback(internal_complete_callback);
338 item->SetUserData(&kSafeBrowsingUserDataKey, state);
339 service->CheckClientDownload(
342 &ChromeDownloadManagerDelegate::CheckClientDownloadDone,
343 weak_ptr_factory_.GetWeakPtr(),
347 } else if (!state->is_complete()) {
348 // Don't complete the download until we have an answer.
349 state->set_callback(internal_complete_callback);
356 void ChromeDownloadManagerDelegate::ShouldCompleteDownloadInternal(
358 const base::Closure& user_complete_callback) {
359 DownloadItem* item = download_manager_->GetDownload(download_id);
362 if (ShouldCompleteDownload(item, user_complete_callback))
363 user_complete_callback.Run();
366 bool ChromeDownloadManagerDelegate::ShouldCompleteDownload(
368 const base::Closure& user_complete_callback) {
369 return IsDownloadReadyForCompletion(item, base::Bind(
370 &ChromeDownloadManagerDelegate::ShouldCompleteDownloadInternal,
371 weak_ptr_factory_.GetWeakPtr(), item->GetId(), user_complete_callback));
374 bool ChromeDownloadManagerDelegate::ShouldOpenDownload(
375 DownloadItem* item, const content::DownloadOpenDelayedCallback& callback) {
376 #if defined(ENABLE_EXTENSIONS)
377 if (download_crx_util::IsExtensionDownload(*item) &&
378 !extensions::WebstoreInstaller::GetAssociatedApproval(*item)) {
379 scoped_refptr<extensions::CrxInstaller> crx_installer =
380 download_crx_util::OpenChromeExtension(profile_, *item);
382 // CRX_INSTALLER_DONE will fire when the install completes. At that
383 // time, Observe() will call the passed callback.
386 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
387 content::Source<extensions::CrxInstaller>(crx_installer.get()));
389 crx_installers_[crx_installer.get()] = callback;
390 // The status text and percent complete indicator will change now
391 // that we are installing a CRX. Update observers so that they pick
393 item->UpdateObservers();
401 bool ChromeDownloadManagerDelegate::GenerateFileHash() {
402 #if defined(FULL_SAFE_BROWSING)
403 return profile_->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled) &&
404 g_browser_process->safe_browsing_service()->DownloadBinHashNeeded();
410 void ChromeDownloadManagerDelegate::GetSaveDir(
411 content::BrowserContext* browser_context,
412 base::FilePath* website_save_dir,
413 base::FilePath* download_save_dir,
414 bool* skip_dir_check) {
415 *website_save_dir = download_prefs_->SaveFilePath();
416 DCHECK(!website_save_dir->empty());
417 *download_save_dir = download_prefs_->DownloadPath();
418 *skip_dir_check = false;
419 #if defined(OS_CHROMEOS)
420 *skip_dir_check = drive::util::IsUnderDriveMountPoint(*website_save_dir);
424 void ChromeDownloadManagerDelegate::ChooseSavePath(
425 content::WebContents* web_contents,
426 const base::FilePath& suggested_path,
427 const base::FilePath::StringType& default_extension,
428 bool can_save_as_complete,
429 const content::SavePackagePathPickedCallback& callback) {
431 new SavePackageFilePicker(
435 can_save_as_complete,
436 download_prefs_.get(),
440 void ChromeDownloadManagerDelegate::OpenDownloadUsingPlatformHandler(
441 DownloadItem* download) {
442 base::FilePath platform_path(
443 GetPlatformDownloadPath(profile_, download, PLATFORM_TARGET_PATH));
444 DCHECK(!platform_path.empty());
445 platform_util::OpenItem(profile_, platform_path);
448 void ChromeDownloadManagerDelegate::OpenDownload(DownloadItem* download) {
449 DCHECK_EQ(DownloadItem::COMPLETE, download->GetState());
450 DCHECK(!download->GetTargetFilePath().empty());
451 if (!download->CanOpenDownload())
454 if (!DownloadItemModel(download).ShouldPreferOpeningInBrowser()) {
455 RecordDownloadOpenMethod(DOWNLOAD_OPEN_METHOD_DEFAULT_PLATFORM);
456 OpenDownloadUsingPlatformHandler(download);
460 #if !defined(OS_ANDROID)
461 content::WebContents* web_contents = download->GetWebContents();
463 web_contents ? chrome::FindBrowserWithWebContents(web_contents) : NULL;
464 scoped_ptr<chrome::ScopedTabbedBrowserDisplayer> browser_displayer;
466 !browser->CanSupportWindowFeature(Browser::FEATURE_TABSTRIP)) {
467 browser_displayer.reset(new chrome::ScopedTabbedBrowserDisplayer(
468 profile_, chrome::GetActiveDesktop()));
469 browser = browser_displayer->browser();
471 content::OpenURLParams params(
472 net::FilePathToFileURL(download->GetTargetFilePath()),
475 content::PAGE_TRANSITION_LINK,
477 browser->OpenURL(params);
478 RecordDownloadOpenMethod(DOWNLOAD_OPEN_METHOD_DEFAULT_BROWSER);
480 // ShouldPreferOpeningInBrowser() should never be true on Android.
485 void ChromeDownloadManagerDelegate::ShowDownloadInShell(
486 DownloadItem* download) {
487 if (!download->CanShowInFolder())
489 base::FilePath platform_path(
490 GetPlatformDownloadPath(profile_, download, PLATFORM_CURRENT_PATH));
491 DCHECK(!platform_path.empty());
492 platform_util::ShowItemInFolder(profile_, platform_path);
495 void ChromeDownloadManagerDelegate::CheckForFileExistence(
496 DownloadItem* download,
497 const content::CheckForFileExistenceCallback& callback) {
498 #if defined(OS_CHROMEOS)
499 drive::DownloadHandler* drive_download_handler =
500 drive::DownloadHandler::GetForProfile(profile_);
501 if (drive_download_handler &&
502 drive_download_handler->IsDriveDownload(download)) {
503 drive_download_handler->CheckForFileExistence(download, callback);
507 static const char kSequenceToken[] = "ChromeDMD-FileExistenceChecker";
508 base::SequencedWorkerPool* worker_pool = BrowserThread::GetBlockingPool();
509 scoped_refptr<base::SequencedTaskRunner> task_runner =
510 worker_pool->GetSequencedTaskRunnerWithShutdownBehavior(
511 worker_pool->GetNamedSequenceToken(kSequenceToken),
512 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
513 base::PostTaskAndReplyWithResult(
516 base::Bind(&base::PathExists, download->GetTargetFilePath()),
521 ChromeDownloadManagerDelegate::ApplicationClientIdForFileScanning() const {
522 return std::string(chrome::kApplicationClientIDStringForAVScanning);
525 DownloadProtectionService*
526 ChromeDownloadManagerDelegate::GetDownloadProtectionService() {
527 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
528 #if defined(FULL_SAFE_BROWSING)
529 SafeBrowsingService* sb_service = g_browser_process->safe_browsing_service();
530 if (sb_service && sb_service->download_protection_service() &&
531 profile_->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled)) {
532 return sb_service->download_protection_service();
538 void ChromeDownloadManagerDelegate::NotifyExtensions(
539 DownloadItem* download,
540 const base::FilePath& virtual_path,
541 const NotifyExtensionsCallback& callback) {
542 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
543 #if defined(ENABLE_EXTENSIONS)
544 extensions::ExtensionDownloadsEventRouter* router =
545 DownloadServiceFactory::GetForBrowserContext(profile_)
546 ->GetExtensionEventRouter();
548 base::Closure original_path_callback =
549 base::Bind(callback, base::FilePath(),
550 DownloadPathReservationTracker::UNIQUIFY);
551 router->OnDeterminingFilename(download, virtual_path.BaseName(),
552 original_path_callback,
557 callback.Run(base::FilePath(), DownloadPathReservationTracker::UNIQUIFY);
560 void ChromeDownloadManagerDelegate::ReserveVirtualPath(
561 content::DownloadItem* download,
562 const base::FilePath& virtual_path,
563 bool create_directory,
564 DownloadPathReservationTracker::FilenameConflictAction conflict_action,
565 const DownloadTargetDeterminerDelegate::ReservedPathCallback& callback) {
566 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
567 DCHECK(!virtual_path.empty());
568 #if defined(OS_CHROMEOS)
569 // TODO(asanka): Handle path reservations for virtual paths as well.
570 // http://crbug.com/151618
571 if (drive::util::IsUnderDriveMountPoint(virtual_path)) {
572 callback.Run(virtual_path, true);
576 DownloadPathReservationTracker::GetReservedPath(
579 download_prefs_->DownloadPath(),
585 void ChromeDownloadManagerDelegate::PromptUserForDownloadPath(
586 DownloadItem* download,
587 const base::FilePath& suggested_path,
588 const DownloadTargetDeterminerDelegate::FileSelectedCallback& callback) {
589 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
590 DownloadFilePicker::ShowFilePicker(download, suggested_path, callback);
593 void ChromeDownloadManagerDelegate::DetermineLocalPath(
594 DownloadItem* download,
595 const base::FilePath& virtual_path,
596 const DownloadTargetDeterminerDelegate::LocalPathCallback& callback) {
597 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
598 #if defined(OS_CHROMEOS)
599 drive::DownloadHandler* drive_download_handler =
600 drive::DownloadHandler::GetForProfile(profile_);
601 if (drive_download_handler) {
602 drive_download_handler->SubstituteDriveDownloadPath(
603 virtual_path, download, callback);
607 callback.Run(virtual_path);
610 void ChromeDownloadManagerDelegate::CheckDownloadUrl(
611 DownloadItem* download,
612 const base::FilePath& suggested_path,
613 const CheckDownloadUrlCallback& callback) {
614 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
616 #if defined(FULL_SAFE_BROWSING)
617 safe_browsing::DownloadProtectionService* service =
618 GetDownloadProtectionService();
620 bool is_content_check_supported =
621 service->IsSupportedDownload(*download, suggested_path);
622 VLOG(2) << __FUNCTION__ << "() Start SB URL check for download = "
623 << download->DebugString(false);
624 service->CheckDownloadUrl(*download,
625 base::Bind(&CheckDownloadUrlDone,
627 is_content_check_supported));
631 callback.Run(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
634 void ChromeDownloadManagerDelegate::GetFileMimeType(
635 const base::FilePath& path,
636 const GetFileMimeTypeCallback& callback) {
637 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
638 base::PostTaskAndReplyWithResult(BrowserThread::GetBlockingPool(),
640 base::Bind(&GetMimeType, path),
644 #if defined(FULL_SAFE_BROWSING)
645 void ChromeDownloadManagerDelegate::CheckClientDownloadDone(
647 DownloadProtectionService::DownloadCheckResult result) {
648 DownloadItem* item = download_manager_->GetDownload(download_id);
649 if (!item || (item->GetState() != DownloadItem::IN_PROGRESS))
652 VLOG(2) << __FUNCTION__ << "() download = " << item->DebugString(false)
653 << " verdict = " << result;
654 // We only mark the content as being dangerous if the download's safety state
655 // has not been set to DANGEROUS yet. We don't want to show two warnings.
656 if (item->GetDangerType() == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS ||
657 item->GetDangerType() ==
658 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT) {
659 content::DownloadDangerType danger_type =
660 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS;
662 case DownloadProtectionService::SAFE:
665 case DownloadProtectionService::DANGEROUS:
666 danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT;
668 case DownloadProtectionService::UNCOMMON:
669 danger_type = content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT;
671 case DownloadProtectionService::DANGEROUS_HOST:
672 danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST;
674 case DownloadProtectionService::POTENTIALLY_UNWANTED:
675 danger_type = content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED;
679 if (danger_type != content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS)
680 item->OnContentCheckCompleted(danger_type);
683 SafeBrowsingState* state = static_cast<SafeBrowsingState*>(
684 item->GetUserData(&kSafeBrowsingUserDataKey));
685 state->SetVerdict(result);
687 #endif // FULL_SAFE_BROWSING
689 // content::NotificationObserver implementation.
690 void ChromeDownloadManagerDelegate::Observe(
692 const content::NotificationSource& source,
693 const content::NotificationDetails& details) {
694 #if defined(ENABLE_EXTENSIONS)
695 DCHECK(type == chrome::NOTIFICATION_CRX_INSTALLER_DONE);
697 registrar_.Remove(this,
698 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
701 scoped_refptr<extensions::CrxInstaller> installer =
702 content::Source<extensions::CrxInstaller>(source).ptr();
703 content::DownloadOpenDelayedCallback callback =
704 crx_installers_[installer.get()];
705 crx_installers_.erase(installer.get());
706 callback.Run(installer->did_handle_successfully());
710 void ChromeDownloadManagerDelegate::OnDownloadTargetDetermined(
712 const content::DownloadTargetCallback& callback,
713 scoped_ptr<DownloadTargetInfo> target_info) {
714 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
715 DownloadItem* item = download_manager_->GetDownload(download_id);
716 if (!target_info->target_path.empty() && item &&
717 IsOpenInBrowserPreferreredForFile(target_info->target_path) &&
718 target_info->is_filetype_handled_safely)
719 DownloadItemModel(item).SetShouldPreferOpeningInBrowser(true);
720 callback.Run(target_info->target_path,
721 target_info->target_disposition,
722 target_info->danger_type,
723 target_info->intermediate_path);