Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / download / chrome_download_manager_delegate.cc
blob4ff4ebf400c4a8046b229a3c74ccb1da813862ee
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/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"
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
60 using content::BrowserThread;
61 using content::DownloadItem;
62 using content::DownloadManager;
63 using safe_browsing::DownloadProtectionService;
65 namespace {
67 #if defined(FULL_SAFE_BROWSING)
69 // String pointer used for identifying safebrowing data associated with
70 // a download item.
71 const char kSafeBrowsingUserDataKey[] = "Safe Browsing ID";
73 // The state of a safebrowsing check.
74 class SafeBrowsingState : public DownloadCompletionBlocker {
75 public:
76 SafeBrowsingState()
77 : verdict_(DownloadProtectionService::SAFE) {
80 virtual ~SafeBrowsingState();
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_;
88 void SetVerdict(DownloadProtectionService::DownloadCheckResult result) {
89 verdict_ = result;
90 CompleteDownload();
93 private:
94 DownloadProtectionService::DownloadCheckResult verdict_;
96 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingState);
99 SafeBrowsingState::~SafeBrowsingState() {}
101 #endif // FULL_SAFE_BROWSING
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,
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
115 // Returns a path in the form that that is expected by platform_util::OpenItem /
116 // platform_util::ShowItemInFolder / DownloadTargetDeterminer.
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.
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
136 if (path_type == PLATFORM_TARGET_PATH)
137 return download->GetTargetFilePath();
138 return download->GetFullPath();
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:
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;
170 callback.Run(danger_type);
173 #endif // FULL_SAFE_BROWSING
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));
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;
205 #endif
206 return false;
209 } // namespace
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) {
218 ChromeDownloadManagerDelegate::~ChromeDownloadManagerDelegate() {
219 // If a DownloadManager was set for this, Shutdown() must be called.
220 DCHECK(!download_manager_);
223 void ChromeDownloadManagerDelegate::SetDownloadManager(DownloadManager* dm) {
224 download_manager_ = dm;
227 void ChromeDownloadManagerDelegate::Shutdown() {
228 download_prefs_.reset();
229 weak_ptr_factory_.InvalidateWeakPtrs();
230 download_manager_ = NULL;
233 content::DownloadIdCallback
234 ChromeDownloadManagerDelegate::GetDownloadIdReceiverCallback() {
235 return base::Bind(&ChromeDownloadManagerDelegate::SetNextId,
236 weak_ptr_factory_.GetWeakPtr());
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;
245 IdCallbackVector callbacks;
246 id_callbacks_.swap(callbacks);
247 for (IdCallbackVector::const_iterator it = callbacks.begin();
248 it != callbacks.end(); ++it) {
249 ReturnNextId(*it);
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;
261 if (next_download_id_ == content::DownloadItem::kInvalidId) {
262 id_callbacks_.push_back(callback);
263 return;
265 ReturnNextId(callback);
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_++);
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;
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);
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);
316 state->SetVerdict(DownloadProtectionService::SAFE);
317 #endif
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;
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;
349 #endif
350 return true;
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();
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));
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);
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()));
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;
392 return true;
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
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
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);
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);
442 void ChromeDownloadManagerDelegate::OpenDownload(DownloadItem* download) {
443 DCHECK_EQ(DownloadItem::COMPLETE, download->GetState());
444 DCHECK(!download->GetTargetFilePath().empty());
445 if (!download->CanOpenDownload())
446 return;
448 if (!DownloadItemModel(download).ShouldPreferOpeningInBrowser()) {
449 RecordDownloadOpenMethod(DOWNLOAD_OPEN_METHOD_DEFAULT_PLATFORM);
450 OpenDownloadUsingPlatformHandler(download);
451 return;
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();
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
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);
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;
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);
514 std::string
515 ChromeDownloadManagerDelegate::ApplicationClientIdForFileScanning() const {
516 return std::string(chrome::kApplicationClientIDStringForAVScanning);
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();
528 #endif
529 return NULL;
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;
550 #endif
551 callback.Run(base::FilePath(), DownloadPathReservationTracker::UNIQUIFY);
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;
569 #endif
570 DownloadPathReservationTracker::GetReservedPath(
571 download,
572 virtual_path,
573 download_prefs_->DownloadPath(),
574 create_directory,
575 conflict_action,
576 callback);
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);
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;
600 #endif
601 callback.Run(virtual_path);
604 void ChromeDownloadManagerDelegate::CheckDownloadUrl(
605 DownloadItem* download,
606 const base::FilePath& suggested_path,
607 const CheckDownloadUrlCallback& callback) {
608 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
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;
624 #endif
625 callback.Run(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
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));
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;
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;
671 if (danger_type != content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS)
672 item->OnContentCheckCompleted(danger_type);
675 SafeBrowsingState* state = static_cast<SafeBrowsingState*>(
676 item->GetUserData(&kSafeBrowsingUserDataKey));
677 state->SetVerdict(result);
679 #endif // FULL_SAFE_BROWSING
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);
688 registrar_.Remove(this,
689 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
690 source);
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());
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_safely)
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);