Add ICU message format support
[chromium-blink-merge.git] / chrome / browser / download / chrome_download_manager_delegate.cc
blob29adec1cda4b841f3d090674f7c736e8efac73dd
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"
7 #include <string>
9 #include "base/basictypes.h"
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/callback.h"
13 #include "base/files/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/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/platform_util.h"
37 #include "chrome/browser/profiles/profile.h"
38 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
39 #include "chrome/browser/ui/browser.h"
40 #include "chrome/browser/ui/browser_finder.h"
41 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
42 #include "chrome/common/chrome_constants.h"
43 #include "chrome/common/pref_names.h"
44 #include "components/pref_registry/pref_registry_syncable.h"
45 #include "content/public/browser/download_item.h"
46 #include "content/public/browser/download_manager.h"
47 #include "content/public/browser/notification_source.h"
48 #include "content/public/browser/page_navigator.h"
49 #include "net/base/filename_util.h"
50 #include "net/base/mime_util.h"
52 #if defined(OS_ANDROID)
53 #include "chrome/browser/android/download/chrome_download_manager_overwrite_infobar_delegate.h"
54 #include "chrome/browser/infobars/infobar_service.h"
55 #endif
57 #if defined(OS_CHROMEOS)
58 #include "chrome/browser/chromeos/drive/download_handler.h"
59 #include "chrome/browser/chromeos/drive/file_system_core_util.h"
60 #endif
62 #if defined(ENABLE_EXTENSIONS)
63 #include "chrome/browser/extensions/api/downloads/downloads_api.h"
64 #include "chrome/browser/extensions/crx_installer.h"
65 #include "chrome/browser/extensions/webstore_installer.h"
66 #include "extensions/browser/notification_types.h"
67 #include "extensions/common/constants.h"
68 #endif
70 using content::BrowserThread;
71 using content::DownloadItem;
72 using content::DownloadManager;
73 using safe_browsing::DownloadProtectionService;
75 namespace {
77 #if defined(FULL_SAFE_BROWSING)
79 // String pointer used for identifying safebrowing data associated with
80 // a download item.
81 const char kSafeBrowsingUserDataKey[] = "Safe Browsing ID";
83 // The state of a safebrowsing check.
84 class SafeBrowsingState : public DownloadCompletionBlocker {
85 public:
86 SafeBrowsingState() {}
87 ~SafeBrowsingState() override;
89 private:
90 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingState);
93 SafeBrowsingState::~SafeBrowsingState() {}
95 #endif // FULL_SAFE_BROWSING
97 // Used with GetPlatformDownloadPath() to indicate which platform path to
98 // return.
99 enum PlatformDownloadPathType {
100 // Return the platform specific target path.
101 PLATFORM_TARGET_PATH,
103 // Return the platform specific current path. If the download is in-progress
104 // and the download location is a local filesystem path, then
105 // GetPlatformDownloadPath will return the path to the intermediate file.
106 PLATFORM_CURRENT_PATH
109 // Returns a path in the form that that is expected by platform_util::OpenItem /
110 // platform_util::ShowItemInFolder / DownloadTargetDeterminer.
112 // DownloadItems corresponding to Drive downloads use a temporary file as the
113 // target path. The paths returned by DownloadItem::GetFullPath() /
114 // GetTargetFilePath() refer to this temporary file. This function looks up the
115 // corresponding path in Drive for these downloads.
117 // How the platform path is determined is based on PlatformDownloadPathType.
118 base::FilePath GetPlatformDownloadPath(Profile* profile,
119 const DownloadItem* download,
120 PlatformDownloadPathType path_type) {
121 #if defined(OS_CHROMEOS)
122 // Drive downloads always return the target path for all types.
123 drive::DownloadHandler* drive_download_handler =
124 drive::DownloadHandler::GetForProfile(profile);
125 if (drive_download_handler &&
126 drive_download_handler->IsDriveDownload(download))
127 return drive_download_handler->GetTargetPath(download);
128 #endif
130 if (path_type == PLATFORM_TARGET_PATH)
131 return download->GetTargetFilePath();
132 return download->GetFullPath();
135 #if defined(FULL_SAFE_BROWSING)
136 // Callback invoked by DownloadProtectionService::CheckClientDownload.
137 // |is_content_check_supported| is true if the SB service supports scanning the
138 // download for malicious content.
139 // |callback| is invoked with a danger type determined as follows:
141 // Danger type is (in order of preference):
142 // * DANGEROUS_URL, if the URL is a known malware site.
143 // * MAYBE_DANGEROUS_CONTENT, if the content will be scanned for
144 // malware. I.e. |is_content_check_supported| is true.
145 // * NOT_DANGEROUS.
146 void CheckDownloadUrlDone(
147 const DownloadTargetDeterminerDelegate::CheckDownloadUrlCallback& callback,
148 bool is_content_check_supported,
149 DownloadProtectionService::DownloadCheckResult result) {
150 content::DownloadDangerType danger_type;
151 if (result == DownloadProtectionService::SAFE ||
152 result == DownloadProtectionService::UNKNOWN) {
153 // If this type of files is handled by the enhanced SafeBrowsing download
154 // protection, mark it as potentially dangerous content until we are done
155 // with scanning it.
156 if (is_content_check_supported)
157 danger_type = content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT;
158 else
159 danger_type = content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS;
160 } else {
161 // If the URL is malicious, we'll use that as the danger type. The results
162 // of the content check, if one is performed, will be ignored.
163 danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL;
165 callback.Run(danger_type);
168 #endif // FULL_SAFE_BROWSING
170 // Called on the blocking pool to determine the MIME type for |path|.
171 std::string GetMimeType(const base::FilePath& path) {
172 std::string mime_type;
173 net::GetMimeTypeFromFile(path, &mime_type);
174 return mime_type;
177 } // namespace
179 ChromeDownloadManagerDelegate::ChromeDownloadManagerDelegate(Profile* profile)
180 : profile_(profile),
181 next_download_id_(content::DownloadItem::kInvalidId),
182 download_prefs_(new DownloadPrefs(profile)),
183 weak_ptr_factory_(this) {
186 ChromeDownloadManagerDelegate::~ChromeDownloadManagerDelegate() {
187 // If a DownloadManager was set for this, Shutdown() must be called.
188 DCHECK(!download_manager_);
191 void ChromeDownloadManagerDelegate::SetDownloadManager(DownloadManager* dm) {
192 download_manager_ = dm;
194 #if defined(FULL_SAFE_BROWSING) || defined(MOBILE_SAFE_BROWSING)
195 SafeBrowsingService* sb_service = g_browser_process->safe_browsing_service();
196 if (sb_service && !profile_->IsOffTheRecord()) {
197 // Include this download manager in the set monitored by safe browsing.
198 sb_service->AddDownloadManager(dm);
200 #endif
203 void ChromeDownloadManagerDelegate::Shutdown() {
204 download_prefs_.reset();
205 weak_ptr_factory_.InvalidateWeakPtrs();
206 download_manager_ = NULL;
209 content::DownloadIdCallback
210 ChromeDownloadManagerDelegate::GetDownloadIdReceiverCallback() {
211 return base::Bind(&ChromeDownloadManagerDelegate::SetNextId,
212 weak_ptr_factory_.GetWeakPtr());
215 void ChromeDownloadManagerDelegate::SetNextId(uint32 next_id) {
216 DCHECK_CURRENTLY_ON(BrowserThread::UI);
217 DCHECK(!profile_->IsOffTheRecord());
218 DCHECK_NE(content::DownloadItem::kInvalidId, next_id);
219 next_download_id_ = next_id;
221 IdCallbackVector callbacks;
222 id_callbacks_.swap(callbacks);
223 for (IdCallbackVector::const_iterator it = callbacks.begin();
224 it != callbacks.end(); ++it) {
225 ReturnNextId(*it);
229 void ChromeDownloadManagerDelegate::GetNextId(
230 const content::DownloadIdCallback& callback) {
231 DCHECK_CURRENTLY_ON(BrowserThread::UI);
232 if (profile_->IsOffTheRecord()) {
233 content::BrowserContext::GetDownloadManager(
234 profile_->GetOriginalProfile())->GetDelegate()->GetNextId(callback);
235 return;
237 if (next_download_id_ == content::DownloadItem::kInvalidId) {
238 id_callbacks_.push_back(callback);
239 return;
241 ReturnNextId(callback);
244 void ChromeDownloadManagerDelegate::ReturnNextId(
245 const content::DownloadIdCallback& callback) {
246 DCHECK_CURRENTLY_ON(BrowserThread::UI);
247 DCHECK(!profile_->IsOffTheRecord());
248 DCHECK_NE(content::DownloadItem::kInvalidId, next_download_id_);
249 callback.Run(next_download_id_++);
252 bool ChromeDownloadManagerDelegate::DetermineDownloadTarget(
253 DownloadItem* download,
254 const content::DownloadTargetCallback& callback) {
255 DownloadTargetDeterminer::CompletionCallback target_determined_callback =
256 base::Bind(&ChromeDownloadManagerDelegate::OnDownloadTargetDetermined,
257 weak_ptr_factory_.GetWeakPtr(),
258 download->GetId(),
259 callback);
260 DownloadTargetDeterminer::Start(
261 download,
262 GetPlatformDownloadPath(profile_, download, PLATFORM_TARGET_PATH),
263 download_prefs_.get(),
264 this,
265 target_determined_callback);
266 return true;
269 bool ChromeDownloadManagerDelegate::ShouldOpenFileBasedOnExtension(
270 const base::FilePath& path) {
271 DCHECK_CURRENTLY_ON(BrowserThread::UI);
272 if (path.Extension().empty())
273 return false;
274 #if defined(ENABLE_EXTENSIONS)
275 // TODO(asanka): This determination is done based on |path|, while
276 // ShouldOpenDownload() detects extension downloads based on the
277 // characteristics of the download. Reconcile this. http://crbug.com/167702
278 if (path.MatchesExtension(extensions::kExtensionFileExtension))
279 return false;
280 #endif
281 return download_prefs_->IsAutoOpenEnabledBasedOnExtension(path);
284 // static
285 void ChromeDownloadManagerDelegate::DisableSafeBrowsing(DownloadItem* item) {
286 DCHECK_CURRENTLY_ON(BrowserThread::UI);
287 #if defined(FULL_SAFE_BROWSING)
288 SafeBrowsingState* state = static_cast<SafeBrowsingState*>(
289 item->GetUserData(&kSafeBrowsingUserDataKey));
290 if (!state) {
291 state = new SafeBrowsingState();
292 item->SetUserData(&kSafeBrowsingUserDataKey, state);
294 state->CompleteDownload();
295 #endif
298 bool ChromeDownloadManagerDelegate::IsDownloadReadyForCompletion(
299 DownloadItem* item,
300 const base::Closure& internal_complete_callback) {
301 DCHECK_CURRENTLY_ON(BrowserThread::UI);
302 #if defined(FULL_SAFE_BROWSING)
303 SafeBrowsingState* state = static_cast<SafeBrowsingState*>(
304 item->GetUserData(&kSafeBrowsingUserDataKey));
305 if (!state) {
306 // Begin the safe browsing download protection check.
307 DownloadProtectionService* service = GetDownloadProtectionService();
308 if (service) {
309 DVLOG(2) << __FUNCTION__ << "() Start SB download check for download = "
310 << item->DebugString(false);
311 state = new SafeBrowsingState();
312 state->set_callback(internal_complete_callback);
313 item->SetUserData(&kSafeBrowsingUserDataKey, state);
314 service->CheckClientDownload(
315 item,
316 base::Bind(&ChromeDownloadManagerDelegate::CheckClientDownloadDone,
317 weak_ptr_factory_.GetWeakPtr(),
318 item->GetId()));
319 return false;
322 // In case the service was disabled between the download starting and now,
323 // we need to restore the danger state.
324 content::DownloadDangerType danger_type = item->GetDangerType();
325 if (DownloadItemModel(item).IsDangerousFileBasedOnType() &&
326 (danger_type == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS ||
327 danger_type ==
328 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT)) {
329 DVLOG(2) << __FUNCTION__
330 << "() SB service disabled. Marking download as DANGEROUS FILE";
331 item->OnContentCheckCompleted(
332 content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE);
333 content::BrowserThread::PostTask(
334 content::BrowserThread::UI, FROM_HERE, internal_complete_callback);
335 return false;
337 } else if (!state->is_complete()) {
338 // Don't complete the download until we have an answer.
339 state->set_callback(internal_complete_callback);
340 return false;
343 #endif
344 return true;
347 void ChromeDownloadManagerDelegate::ShouldCompleteDownloadInternal(
348 uint32 download_id,
349 const base::Closure& user_complete_callback) {
350 DownloadItem* item = download_manager_->GetDownload(download_id);
351 if (!item)
352 return;
353 if (ShouldCompleteDownload(item, user_complete_callback))
354 user_complete_callback.Run();
357 bool ChromeDownloadManagerDelegate::ShouldCompleteDownload(
358 DownloadItem* item,
359 const base::Closure& user_complete_callback) {
360 return IsDownloadReadyForCompletion(item, base::Bind(
361 &ChromeDownloadManagerDelegate::ShouldCompleteDownloadInternal,
362 weak_ptr_factory_.GetWeakPtr(), item->GetId(), user_complete_callback));
365 bool ChromeDownloadManagerDelegate::ShouldOpenDownload(
366 DownloadItem* item, const content::DownloadOpenDelayedCallback& callback) {
367 #if defined(ENABLE_EXTENSIONS)
368 if (download_crx_util::IsExtensionDownload(*item) &&
369 !extensions::WebstoreInstaller::GetAssociatedApproval(*item)) {
370 scoped_refptr<extensions::CrxInstaller> crx_installer =
371 download_crx_util::OpenChromeExtension(profile_, *item);
373 // CRX_INSTALLER_DONE will fire when the install completes. At that
374 // time, Observe() will call the passed callback.
375 registrar_.Add(
376 this,
377 extensions::NOTIFICATION_CRX_INSTALLER_DONE,
378 content::Source<extensions::CrxInstaller>(crx_installer.get()));
380 crx_installers_[crx_installer.get()] = callback;
381 // The status text and percent complete indicator will change now
382 // that we are installing a CRX. Update observers so that they pick
383 // up the change.
384 item->UpdateObservers();
385 return false;
387 #endif
389 return true;
392 bool ChromeDownloadManagerDelegate::GenerateFileHash() {
393 #if defined(FULL_SAFE_BROWSING)
394 return profile_->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled) &&
395 g_browser_process->safe_browsing_service()->DownloadBinHashNeeded();
396 #else
397 return false;
398 #endif
401 void ChromeDownloadManagerDelegate::GetSaveDir(
402 content::BrowserContext* browser_context,
403 base::FilePath* website_save_dir,
404 base::FilePath* download_save_dir,
405 bool* skip_dir_check) {
406 *website_save_dir = download_prefs_->SaveFilePath();
407 DCHECK(!website_save_dir->empty());
408 *download_save_dir = download_prefs_->DownloadPath();
409 *skip_dir_check = false;
410 #if defined(OS_CHROMEOS)
411 *skip_dir_check = drive::util::IsUnderDriveMountPoint(*website_save_dir);
412 #endif
415 void ChromeDownloadManagerDelegate::ChooseSavePath(
416 content::WebContents* web_contents,
417 const base::FilePath& suggested_path,
418 const base::FilePath::StringType& default_extension,
419 bool can_save_as_complete,
420 const content::SavePackagePathPickedCallback& callback) {
421 // Deletes itself.
422 new SavePackageFilePicker(
423 web_contents,
424 suggested_path,
425 default_extension,
426 can_save_as_complete,
427 download_prefs_.get(),
428 callback);
431 void ChromeDownloadManagerDelegate::OpenDownloadUsingPlatformHandler(
432 DownloadItem* download) {
433 base::FilePath platform_path(
434 GetPlatformDownloadPath(profile_, download, PLATFORM_TARGET_PATH));
435 DCHECK(!platform_path.empty());
436 platform_util::OpenItem(profile_, platform_path, platform_util::OPEN_FILE,
437 platform_util::OpenOperationCallback());
440 void ChromeDownloadManagerDelegate::OpenDownload(DownloadItem* download) {
441 DCHECK_EQ(DownloadItem::COMPLETE, download->GetState());
442 DCHECK(!download->GetTargetFilePath().empty());
443 if (!download->CanOpenDownload())
444 return;
446 if (!DownloadItemModel(download).ShouldPreferOpeningInBrowser()) {
447 RecordDownloadOpenMethod(DOWNLOAD_OPEN_METHOD_DEFAULT_PLATFORM);
448 OpenDownloadUsingPlatformHandler(download);
449 return;
452 #if !defined(OS_ANDROID)
453 content::WebContents* web_contents = download->GetWebContents();
454 Browser* browser =
455 web_contents ? chrome::FindBrowserWithWebContents(web_contents) : NULL;
456 scoped_ptr<chrome::ScopedTabbedBrowserDisplayer> browser_displayer;
457 if (!browser ||
458 !browser->CanSupportWindowFeature(Browser::FEATURE_TABSTRIP)) {
459 browser_displayer.reset(new chrome::ScopedTabbedBrowserDisplayer(
460 profile_, chrome::GetActiveDesktop()));
461 browser = browser_displayer->browser();
463 content::OpenURLParams params(
464 net::FilePathToFileURL(download->GetTargetFilePath()),
465 content::Referrer(),
466 NEW_FOREGROUND_TAB,
467 ui::PAGE_TRANSITION_LINK,
468 false);
469 browser->OpenURL(params);
470 RecordDownloadOpenMethod(DOWNLOAD_OPEN_METHOD_DEFAULT_BROWSER);
471 #else
472 // ShouldPreferOpeningInBrowser() should never be true on Android.
473 NOTREACHED();
474 #endif
477 void ChromeDownloadManagerDelegate::ShowDownloadInShell(
478 DownloadItem* download) {
479 if (!download->CanShowInFolder())
480 return;
481 base::FilePath platform_path(
482 GetPlatformDownloadPath(profile_, download, PLATFORM_CURRENT_PATH));
483 DCHECK(!platform_path.empty());
484 platform_util::ShowItemInFolder(profile_, platform_path);
487 void ChromeDownloadManagerDelegate::CheckForFileExistence(
488 DownloadItem* download,
489 const content::CheckForFileExistenceCallback& callback) {
490 #if defined(OS_CHROMEOS)
491 drive::DownloadHandler* drive_download_handler =
492 drive::DownloadHandler::GetForProfile(profile_);
493 if (drive_download_handler &&
494 drive_download_handler->IsDriveDownload(download)) {
495 drive_download_handler->CheckForFileExistence(download, callback);
496 return;
498 #endif
499 static const char kSequenceToken[] = "ChromeDMD-FileExistenceChecker";
500 base::SequencedWorkerPool* worker_pool = BrowserThread::GetBlockingPool();
501 scoped_refptr<base::SequencedTaskRunner> task_runner =
502 worker_pool->GetSequencedTaskRunnerWithShutdownBehavior(
503 worker_pool->GetNamedSequenceToken(kSequenceToken),
504 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
505 base::PostTaskAndReplyWithResult(
506 task_runner.get(),
507 FROM_HERE,
508 base::Bind(&base::PathExists, download->GetTargetFilePath()),
509 callback);
512 std::string
513 ChromeDownloadManagerDelegate::ApplicationClientIdForFileScanning() const {
514 return std::string(chrome::kApplicationClientIDStringForAVScanning);
517 DownloadProtectionService*
518 ChromeDownloadManagerDelegate::GetDownloadProtectionService() {
519 DCHECK_CURRENTLY_ON(BrowserThread::UI);
520 #if defined(FULL_SAFE_BROWSING)
521 SafeBrowsingService* sb_service = g_browser_process->safe_browsing_service();
522 if (sb_service && sb_service->download_protection_service() &&
523 profile_->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled)) {
524 return sb_service->download_protection_service();
526 #endif
527 return NULL;
530 void ChromeDownloadManagerDelegate::NotifyExtensions(
531 DownloadItem* download,
532 const base::FilePath& virtual_path,
533 const NotifyExtensionsCallback& callback) {
534 DCHECK_CURRENTLY_ON(BrowserThread::UI);
535 #if defined(ENABLE_EXTENSIONS)
536 extensions::ExtensionDownloadsEventRouter* router =
537 DownloadServiceFactory::GetForBrowserContext(profile_)
538 ->GetExtensionEventRouter();
539 if (router) {
540 base::Closure original_path_callback =
541 base::Bind(callback, base::FilePath(),
542 DownloadPathReservationTracker::UNIQUIFY);
543 router->OnDeterminingFilename(download, virtual_path.BaseName(),
544 original_path_callback,
545 callback);
546 return;
548 #endif
549 callback.Run(base::FilePath(), DownloadPathReservationTracker::UNIQUIFY);
552 void ChromeDownloadManagerDelegate::ReserveVirtualPath(
553 content::DownloadItem* download,
554 const base::FilePath& virtual_path,
555 bool create_directory,
556 DownloadPathReservationTracker::FilenameConflictAction conflict_action,
557 const DownloadTargetDeterminerDelegate::ReservedPathCallback& callback) {
558 DCHECK_CURRENTLY_ON(BrowserThread::UI);
559 DCHECK(!virtual_path.empty());
560 #if defined(OS_CHROMEOS)
561 // TODO(asanka): Handle path reservations for virtual paths as well.
562 // http://crbug.com/151618
563 if (drive::util::IsUnderDriveMountPoint(virtual_path)) {
564 callback.Run(virtual_path, true);
565 return;
567 #endif
568 DownloadPathReservationTracker::GetReservedPath(
569 download,
570 virtual_path,
571 download_prefs_->DownloadPath(),
572 create_directory,
573 conflict_action,
574 callback);
577 void ChromeDownloadManagerDelegate::PromptUserForDownloadPath(
578 DownloadItem* download,
579 const base::FilePath& suggested_path,
580 const DownloadTargetDeterminerDelegate::FileSelectedCallback& callback) {
581 DCHECK_CURRENTLY_ON(BrowserThread::UI);
582 #if defined(OS_ANDROID)
583 chrome::android::ChromeDownloadManagerOverwriteInfoBarDelegate::Create(
584 InfoBarService::FromWebContents(download->GetWebContents()),
585 suggested_path, callback);
586 #else
587 DownloadFilePicker::ShowFilePicker(download, suggested_path, callback);
588 #endif
591 void ChromeDownloadManagerDelegate::DetermineLocalPath(
592 DownloadItem* download,
593 const base::FilePath& virtual_path,
594 const DownloadTargetDeterminerDelegate::LocalPathCallback& callback) {
595 DCHECK_CURRENTLY_ON(BrowserThread::UI);
596 #if defined(OS_CHROMEOS)
597 drive::DownloadHandler* drive_download_handler =
598 drive::DownloadHandler::GetForProfile(profile_);
599 if (drive_download_handler) {
600 drive_download_handler->SubstituteDriveDownloadPath(
601 virtual_path, download, callback);
602 return;
604 #endif
605 callback.Run(virtual_path);
608 void ChromeDownloadManagerDelegate::CheckDownloadUrl(
609 DownloadItem* download,
610 const base::FilePath& suggested_path,
611 const CheckDownloadUrlCallback& callback) {
612 DCHECK_CURRENTLY_ON(BrowserThread::UI);
614 #if defined(FULL_SAFE_BROWSING)
615 safe_browsing::DownloadProtectionService* service =
616 GetDownloadProtectionService();
617 if (service) {
618 bool is_content_check_supported =
619 service->IsSupportedDownload(*download, suggested_path);
620 DVLOG(2) << __FUNCTION__ << "() Start SB URL check for download = "
621 << download->DebugString(false);
622 service->CheckDownloadUrl(*download,
623 base::Bind(&CheckDownloadUrlDone,
624 callback,
625 is_content_check_supported));
626 return;
628 #endif
629 callback.Run(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
632 void ChromeDownloadManagerDelegate::GetFileMimeType(
633 const base::FilePath& path,
634 const GetFileMimeTypeCallback& callback) {
635 DCHECK_CURRENTLY_ON(BrowserThread::UI);
636 base::PostTaskAndReplyWithResult(BrowserThread::GetBlockingPool(),
637 FROM_HERE,
638 base::Bind(&GetMimeType, path),
639 callback);
642 #if defined(FULL_SAFE_BROWSING)
643 void ChromeDownloadManagerDelegate::CheckClientDownloadDone(
644 uint32 download_id,
645 DownloadProtectionService::DownloadCheckResult result) {
646 DownloadItem* item = download_manager_->GetDownload(download_id);
647 if (!item || (item->GetState() != DownloadItem::IN_PROGRESS))
648 return;
650 DVLOG(2) << __FUNCTION__ << "() download = " << item->DebugString(false)
651 << " verdict = " << result;
652 // We only mark the content as being dangerous if the download's safety state
653 // has not been set to DANGEROUS yet. We don't want to show two warnings.
654 if (item->GetDangerType() == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS ||
655 item->GetDangerType() ==
656 content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT) {
657 content::DownloadDangerType danger_type =
658 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS;
659 switch (result) {
660 case DownloadProtectionService::UNKNOWN:
661 // The check failed or was inconclusive.
662 if (DownloadItemModel(item).IsDangerousFileBasedOnType())
663 danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE;
664 break;
665 case DownloadProtectionService::SAFE:
666 // Do nothing.
667 break;
668 case DownloadProtectionService::DANGEROUS:
669 danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT;
670 break;
671 case DownloadProtectionService::UNCOMMON:
672 danger_type = content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT;
673 break;
674 case DownloadProtectionService::DANGEROUS_HOST:
675 danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST;
676 break;
677 case DownloadProtectionService::POTENTIALLY_UNWANTED:
678 danger_type = content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED;
679 break;
682 if (danger_type != content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS)
683 item->OnContentCheckCompleted(danger_type);
686 SafeBrowsingState* state = static_cast<SafeBrowsingState*>(
687 item->GetUserData(&kSafeBrowsingUserDataKey));
688 state->CompleteDownload();
690 #endif // FULL_SAFE_BROWSING
692 // content::NotificationObserver implementation.
693 void ChromeDownloadManagerDelegate::Observe(
694 int type,
695 const content::NotificationSource& source,
696 const content::NotificationDetails& details) {
697 #if defined(ENABLE_EXTENSIONS)
698 DCHECK(type == extensions::NOTIFICATION_CRX_INSTALLER_DONE);
700 registrar_.Remove(this, extensions::NOTIFICATION_CRX_INSTALLER_DONE, source);
702 scoped_refptr<extensions::CrxInstaller> installer =
703 content::Source<extensions::CrxInstaller>(source).ptr();
704 content::DownloadOpenDelayedCallback callback =
705 crx_installers_[installer.get()];
706 crx_installers_.erase(installer.get());
707 callback.Run(installer->did_handle_successfully());
708 #endif
711 void ChromeDownloadManagerDelegate::OnDownloadTargetDetermined(
712 int32 download_id,
713 const content::DownloadTargetCallback& callback,
714 scoped_ptr<DownloadTargetInfo> target_info) {
715 DCHECK_CURRENTLY_ON(BrowserThread::UI);
716 DownloadItem* item = download_manager_->GetDownload(download_id);
717 if (item) {
718 if (!target_info->target_path.empty() &&
719 IsOpenInBrowserPreferreredForFile(target_info->target_path) &&
720 target_info->is_filetype_handled_safely)
721 DownloadItemModel(item).SetShouldPreferOpeningInBrowser(true);
723 if (target_info->is_dangerous_file)
724 DownloadItemModel(item).SetIsDangerousFileBasedOnType(true);
726 callback.Run(target_info->target_path,
727 target_info->target_disposition,
728 target_info->danger_type,
729 target_info->intermediate_path);
732 bool ChromeDownloadManagerDelegate::IsOpenInBrowserPreferreredForFile(
733 const base::FilePath& path) {
734 #if defined(OS_WIN) || defined(OS_LINUX) || \
735 (defined(OS_MACOSX) && !defined(OS_IOS))
736 if (path.MatchesExtension(FILE_PATH_LITERAL(".pdf"))) {
737 return !download_prefs_->ShouldOpenPdfInSystemReader();
739 #endif
741 // On Android, always prefer opening with an external app. On ChromeOS, there
742 // are no external apps so just allow all opens to be handled by the "System."
743 #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) && defined(ENABLE_PLUGINS)
744 // TODO(asanka): Consider other file types and MIME types.
745 // http://crbug.com/323561
746 if (path.MatchesExtension(FILE_PATH_LITERAL(".pdf")) ||
747 path.MatchesExtension(FILE_PATH_LITERAL(".htm")) ||
748 path.MatchesExtension(FILE_PATH_LITERAL(".html")) ||
749 path.MatchesExtension(FILE_PATH_LITERAL(".shtm")) ||
750 path.MatchesExtension(FILE_PATH_LITERAL(".shtml")) ||
751 path.MatchesExtension(FILE_PATH_LITERAL(".svg")) ||
752 path.MatchesExtension(FILE_PATH_LITERAL(".xht")) ||
753 path.MatchesExtension(FILE_PATH_LITERAL(".xhtm")) ||
754 path.MatchesExtension(FILE_PATH_LITERAL(".xhtml")) ||
755 path.MatchesExtension(FILE_PATH_LITERAL(".xsl")) ||
756 path.MatchesExtension(FILE_PATH_LITERAL(".xslt"))) {
757 return true;
759 #endif
760 return false;