2a8d6c6f1e2343e7d46b7e9f8e78873e3a16b15e
[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/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"
52
53 #if defined(OS_CHROMEOS)
54 #include "chrome/browser/chromeos/drive/download_handler.h"
55 #include "chrome/browser/chromeos/drive/file_system_util.h"
56 #endif
57
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"
63 #endif
64
65 using content::BrowserThread;
66 using content::DownloadItem;
67 using content::DownloadManager;
68 using safe_browsing::DownloadProtectionService;
69
70 namespace {
71
72 #if defined(FULL_SAFE_BROWSING)
73
74 // String pointer used for identifying safebrowing data associated with
75 // a download item.
76 const char kSafeBrowsingUserDataKey[] = "Safe Browsing ID";
77
78 // The state of a safebrowsing check.
79 class SafeBrowsingState : public DownloadCompletionBlocker {
80  public:
81   SafeBrowsingState()
82     : verdict_(DownloadProtectionService::SAFE) {
83   }
84
85   virtual ~SafeBrowsingState();
86
87   // The verdict that we got from calling CheckClientDownload. Only valid to
88   // call if |is_complete()|.
89   DownloadProtectionService::DownloadCheckResult verdict() const {
90     return verdict_;
91   }
92
93   void SetVerdict(DownloadProtectionService::DownloadCheckResult result) {
94     verdict_ = result;
95     CompleteDownload();
96   }
97
98  private:
99   DownloadProtectionService::DownloadCheckResult verdict_;
100
101   DISALLOW_COPY_AND_ASSIGN(SafeBrowsingState);
102 };
103
104 SafeBrowsingState::~SafeBrowsingState() {}
105
106 #endif  // FULL_SAFE_BROWSING
107
108 // Used with GetPlatformDownloadPath() to indicate which platform path to
109 // return.
110 enum PlatformDownloadPathType {
111   // Return the platform specific target path.
112   PLATFORM_TARGET_PATH,
113
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
118 };
119
120 // Returns a path in the form that that is expected by platform_util::OpenItem /
121 // platform_util::ShowItemInFolder / DownloadTargetDeterminer.
122 //
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.
127 //
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);
139 #endif
140
141   if (path_type == PLATFORM_TARGET_PATH)
142     return download->GetTargetFilePath();
143   return download->GetFullPath();
144 }
145
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:
151 //
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.
156 //   * NOT_DANGEROUS.
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
165     // with scanning it.
166     if (is_content_check_supported)
167       danger_type = content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT;
168     else
169       danger_type = content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS;
170   } else {
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;
174   }
175   callback.Run(danger_type);
176 }
177
178 #endif  // FULL_SAFE_BROWSING
179
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);
184   return mime_type;
185 }
186
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"))) {
204     return true;
205   }
206 #endif
207   return false;
208 }
209
210 }  // namespace
211
212 ChromeDownloadManagerDelegate::ChromeDownloadManagerDelegate(Profile* profile)
213     : profile_(profile),
214       next_download_id_(content::DownloadItem::kInvalidId),
215       download_prefs_(new DownloadPrefs(profile)),
216       weak_ptr_factory_(this) {
217 }
218
219 ChromeDownloadManagerDelegate::~ChromeDownloadManagerDelegate() {
220   // If a DownloadManager was set for this, Shutdown() must be called.
221   DCHECK(!download_manager_);
222 }
223
224 void ChromeDownloadManagerDelegate::SetDownloadManager(DownloadManager* dm) {
225   download_manager_ = dm;
226 }
227
228 void ChromeDownloadManagerDelegate::Shutdown() {
229   download_prefs_.reset();
230   weak_ptr_factory_.InvalidateWeakPtrs();
231   download_manager_ = NULL;
232 }
233
234 content::DownloadIdCallback
235 ChromeDownloadManagerDelegate::GetDownloadIdReceiverCallback() {
236   return base::Bind(&ChromeDownloadManagerDelegate::SetNextId,
237                     weak_ptr_factory_.GetWeakPtr());
238 }
239
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;
245
246   IdCallbackVector callbacks;
247   id_callbacks_.swap(callbacks);
248   for (IdCallbackVector::const_iterator it = callbacks.begin();
249        it != callbacks.end(); ++it) {
250     ReturnNextId(*it);
251   }
252 }
253
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);
260     return;
261   }
262   if (next_download_id_ == content::DownloadItem::kInvalidId) {
263     id_callbacks_.push_back(callback);
264     return;
265   }
266   ReturnNextId(callback);
267 }
268
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_++);
275 }
276
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(),
283                  download->GetId(),
284                  callback);
285   DownloadTargetDeterminer::Start(
286       download,
287       GetPlatformDownloadPath(profile_, download, PLATFORM_TARGET_PATH),
288       download_prefs_.get(),
289       this,
290       target_determined_callback);
291   return true;
292 }
293
294 bool ChromeDownloadManagerDelegate::ShouldOpenFileBasedOnExtension(
295     const base::FilePath& path) {
296   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
297   if (path.Extension().empty())
298     return false;
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))
304     return false;
305 #endif
306   return download_prefs_->IsAutoOpenEnabledBasedOnExtension(path);
307 }
308
309 // static
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));
315   if (!state) {
316     state = new SafeBrowsingState();
317     item->SetUserData(&kSafeBrowsingUserDataKey, state);
318   }
319   state->SetVerdict(DownloadProtectionService::SAFE);
320 #endif
321 }
322
323 bool ChromeDownloadManagerDelegate::IsDownloadReadyForCompletion(
324     DownloadItem* item,
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));
330   if (!state) {
331     // Begin the safe browsing download protection check.
332     DownloadProtectionService* service = GetDownloadProtectionService();
333     if (service) {
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(
340           item,
341           base::Bind(
342               &ChromeDownloadManagerDelegate::CheckClientDownloadDone,
343               weak_ptr_factory_.GetWeakPtr(),
344               item->GetId()));
345       return false;
346     }
347   } else if (!state->is_complete()) {
348     // Don't complete the download until we have an answer.
349     state->set_callback(internal_complete_callback);
350     return false;
351   }
352 #endif
353   return true;
354 }
355
356 void ChromeDownloadManagerDelegate::ShouldCompleteDownloadInternal(
357     uint32 download_id,
358     const base::Closure& user_complete_callback) {
359   DownloadItem* item = download_manager_->GetDownload(download_id);
360   if (!item)
361     return;
362   if (ShouldCompleteDownload(item, user_complete_callback))
363     user_complete_callback.Run();
364 }
365
366 bool ChromeDownloadManagerDelegate::ShouldCompleteDownload(
367     DownloadItem* item,
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));
372 }
373
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);
381
382     // CRX_INSTALLER_DONE will fire when the install completes.  At that
383     // time, Observe() will call the passed callback.
384     registrar_.Add(
385         this,
386         chrome::NOTIFICATION_CRX_INSTALLER_DONE,
387         content::Source<extensions::CrxInstaller>(crx_installer.get()));
388
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
392     // up the change.
393     item->UpdateObservers();
394     return false;
395   }
396 #endif
397
398   return true;
399 }
400
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();
405 #else
406   return false;
407 #endif
408 }
409
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);
421 #endif
422 }
423
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) {
430   // Deletes itself.
431   new SavePackageFilePicker(
432       web_contents,
433       suggested_path,
434       default_extension,
435       can_save_as_complete,
436       download_prefs_.get(),
437       callback);
438 }
439
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);
446 }
447
448 void ChromeDownloadManagerDelegate::OpenDownload(DownloadItem* download) {
449   DCHECK_EQ(DownloadItem::COMPLETE, download->GetState());
450   DCHECK(!download->GetTargetFilePath().empty());
451   if (!download->CanOpenDownload())
452     return;
453
454   if (!DownloadItemModel(download).ShouldPreferOpeningInBrowser()) {
455     RecordDownloadOpenMethod(DOWNLOAD_OPEN_METHOD_DEFAULT_PLATFORM);
456     OpenDownloadUsingPlatformHandler(download);
457     return;
458   }
459
460 #if !defined(OS_ANDROID)
461   content::WebContents* web_contents = download->GetWebContents();
462   Browser* browser =
463       web_contents ? chrome::FindBrowserWithWebContents(web_contents) : NULL;
464   scoped_ptr<chrome::ScopedTabbedBrowserDisplayer> browser_displayer;
465   if (!browser ||
466       !browser->CanSupportWindowFeature(Browser::FEATURE_TABSTRIP)) {
467     browser_displayer.reset(new chrome::ScopedTabbedBrowserDisplayer(
468         profile_, chrome::GetActiveDesktop()));
469     browser = browser_displayer->browser();
470   }
471   content::OpenURLParams params(
472       net::FilePathToFileURL(download->GetTargetFilePath()),
473       content::Referrer(),
474       NEW_FOREGROUND_TAB,
475       content::PAGE_TRANSITION_LINK,
476       false);
477   browser->OpenURL(params);
478   RecordDownloadOpenMethod(DOWNLOAD_OPEN_METHOD_DEFAULT_BROWSER);
479 #else
480   // ShouldPreferOpeningInBrowser() should never be true on Android.
481   NOTREACHED();
482 #endif
483 }
484
485 void ChromeDownloadManagerDelegate::ShowDownloadInShell(
486     DownloadItem* download) {
487   if (!download->CanShowInFolder())
488     return;
489   base::FilePath platform_path(
490       GetPlatformDownloadPath(profile_, download, PLATFORM_CURRENT_PATH));
491   DCHECK(!platform_path.empty());
492   platform_util::ShowItemInFolder(profile_, platform_path);
493 }
494
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);
504     return;
505   }
506 #endif
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(
514       task_runner.get(),
515       FROM_HERE,
516       base::Bind(&base::PathExists, download->GetTargetFilePath()),
517       callback);
518 }
519
520 std::string
521 ChromeDownloadManagerDelegate::ApplicationClientIdForFileScanning() const {
522   return std::string(chrome::kApplicationClientIDStringForAVScanning);
523 }
524
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();
533   }
534 #endif
535   return NULL;
536 }
537
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();
547   if (router) {
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,
553                                   callback);
554     return;
555   }
556 #endif
557   callback.Run(base::FilePath(), DownloadPathReservationTracker::UNIQUIFY);
558 }
559
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);
573     return;
574   }
575 #endif
576   DownloadPathReservationTracker::GetReservedPath(
577       download,
578       virtual_path,
579       download_prefs_->DownloadPath(),
580       create_directory,
581       conflict_action,
582       callback);
583 }
584
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);
591 }
592
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);
604     return;
605   }
606 #endif
607   callback.Run(virtual_path);
608 }
609
610 void ChromeDownloadManagerDelegate::CheckDownloadUrl(
611     DownloadItem* download,
612     const base::FilePath& suggested_path,
613     const CheckDownloadUrlCallback& callback) {
614   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
615
616 #if defined(FULL_SAFE_BROWSING)
617   safe_browsing::DownloadProtectionService* service =
618       GetDownloadProtectionService();
619   if (service) {
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,
626                                          callback,
627                                          is_content_check_supported));
628     return;
629   }
630 #endif
631   callback.Run(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
632 }
633
634 void ChromeDownloadManagerDelegate::GetFileMimeType(
635     const base::FilePath& path,
636     const GetFileMimeTypeCallback& callback) {
637   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
638   base::PostTaskAndReplyWithResult(BrowserThread::GetBlockingPool(),
639                                    FROM_HERE,
640                                    base::Bind(&GetMimeType, path),
641                                    callback);
642 }
643
644 #if defined(FULL_SAFE_BROWSING)
645 void ChromeDownloadManagerDelegate::CheckClientDownloadDone(
646     uint32 download_id,
647     DownloadProtectionService::DownloadCheckResult result) {
648   DownloadItem* item = download_manager_->GetDownload(download_id);
649   if (!item || (item->GetState() != DownloadItem::IN_PROGRESS))
650     return;
651
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;
661     switch (result) {
662       case DownloadProtectionService::SAFE:
663         // Do nothing.
664         break;
665       case DownloadProtectionService::DANGEROUS:
666         danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT;
667         break;
668       case DownloadProtectionService::UNCOMMON:
669         danger_type = content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT;
670         break;
671       case DownloadProtectionService::DANGEROUS_HOST:
672         danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST;
673         break;
674       case DownloadProtectionService::POTENTIALLY_UNWANTED:
675         danger_type = content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED;
676         break;
677     }
678
679     if (danger_type != content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS)
680       item->OnContentCheckCompleted(danger_type);
681   }
682
683   SafeBrowsingState* state = static_cast<SafeBrowsingState*>(
684       item->GetUserData(&kSafeBrowsingUserDataKey));
685   state->SetVerdict(result);
686 }
687 #endif  // FULL_SAFE_BROWSING
688
689 // content::NotificationObserver implementation.
690 void ChromeDownloadManagerDelegate::Observe(
691     int type,
692     const content::NotificationSource& source,
693     const content::NotificationDetails& details) {
694 #if defined(ENABLE_EXTENSIONS)
695   DCHECK(type == chrome::NOTIFICATION_CRX_INSTALLER_DONE);
696
697   registrar_.Remove(this,
698                     chrome::NOTIFICATION_CRX_INSTALLER_DONE,
699                     source);
700
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());
707 #endif
708 }
709
710 void ChromeDownloadManagerDelegate::OnDownloadTargetDetermined(
711     int32 download_id,
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);
724 }