Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / download / chrome_download_manager_delegate.cc
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_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);
714 }