Upstream version 7.36.149.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/extensions/webstore_installer.h"
39 #include "chrome/browser/platform_util.h"
40 #include "chrome/browser/profiles/profile.h"
41 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
42 #include "chrome/browser/ui/browser.h"
43 #include "chrome/browser/ui/browser_finder.h"
44 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
45 #include "chrome/common/chrome_constants.h"
46 #include "chrome/common/pref_names.h"
47 #include "components/user_prefs/pref_registry_syncable.h"
48 #include "content/public/browser/download_item.h"
49 #include "content/public/browser/download_manager.h"
50 #include "content/public/browser/notification_source.h"
51 #include "content/public/browser/page_navigator.h"
52 #include "extensions/common/constants.h"
53 #include "net/base/filename_util.h"
54 #include "net/base/mime_util.h"
55
56 #if defined(OS_CHROMEOS)
57 #include "chrome/browser/chromeos/drive/download_handler.h"
58 #include "chrome/browser/chromeos/drive/file_system_util.h"
59 #endif
60
61 using content::BrowserThread;
62 using content::DownloadItem;
63 using content::DownloadManager;
64 using safe_browsing::DownloadProtectionService;
65
66 namespace {
67
68 #if defined(FULL_SAFE_BROWSING)
69
70 // String pointer used for identifying safebrowing data associated with
71 // a download item.
72 const char kSafeBrowsingUserDataKey[] = "Safe Browsing ID";
73
74 // The state of a safebrowsing check.
75 class SafeBrowsingState : public DownloadCompletionBlocker {
76  public:
77   SafeBrowsingState()
78     : verdict_(DownloadProtectionService::SAFE) {
79   }
80
81   virtual ~SafeBrowsingState();
82
83   // The verdict that we got from calling CheckClientDownload. Only valid to
84   // call if |is_complete()|.
85   DownloadProtectionService::DownloadCheckResult verdict() const {
86     return verdict_;
87   }
88
89   void SetVerdict(DownloadProtectionService::DownloadCheckResult result) {
90     verdict_ = result;
91     CompleteDownload();
92   }
93
94  private:
95   DownloadProtectionService::DownloadCheckResult verdict_;
96
97   DISALLOW_COPY_AND_ASSIGN(SafeBrowsingState);
98 };
99
100 SafeBrowsingState::~SafeBrowsingState() {}
101
102 #endif  // FULL_SAFE_BROWSING
103
104 // Used with GetPlatformDownloadPath() to indicate which platform path to
105 // return.
106 enum PlatformDownloadPathType {
107   // Return the platform specific target path.
108   PLATFORM_TARGET_PATH,
109
110   // Return the platform specific current path. If the download is in-progress
111   // and the download location is a local filesystem path, then
112   // GetPlatformDownloadPath will return the path to the intermediate file.
113   PLATFORM_CURRENT_PATH
114 };
115
116 // Returns a path in the form that that is expected by platform_util::OpenItem /
117 // platform_util::ShowItemInFolder / DownloadTargetDeterminer.
118 //
119 // DownloadItems corresponding to Drive downloads use a temporary file as the
120 // target path. The paths returned by DownloadItem::GetFullPath() /
121 // GetTargetFilePath() refer to this temporary file. This function looks up the
122 // corresponding path in Drive for these downloads.
123 //
124 // How the platform path is determined is based on PlatformDownloadPathType.
125 base::FilePath GetPlatformDownloadPath(Profile* profile,
126                                        const DownloadItem* download,
127                                        PlatformDownloadPathType path_type) {
128 #if defined(OS_CHROMEOS)
129   // Drive downloads always return the target path for all types.
130   drive::DownloadHandler* drive_download_handler =
131       drive::DownloadHandler::GetForProfile(profile);
132   if (drive_download_handler &&
133       drive_download_handler->IsDriveDownload(download))
134     return drive_download_handler->GetTargetPath(download);
135 #endif
136
137   if (path_type == PLATFORM_TARGET_PATH)
138     return download->GetTargetFilePath();
139   return download->GetFullPath();
140 }
141
142 #if defined(FULL_SAFE_BROWSING)
143 // Callback invoked by DownloadProtectionService::CheckClientDownload.
144 // |is_content_check_supported| is true if the SB service supports scanning the
145 // download for malicious content.
146 // |callback| is invoked with a danger type determined as follows:
147 //
148 // Danger type is (in order of preference):
149 //   * DANGEROUS_URL, if the URL is a known malware site.
150 //   * MAYBE_DANGEROUS_CONTENT, if the content will be scanned for
151 //         malware. I.e. |is_content_check_supported| is true.
152 //   * NOT_DANGEROUS.
153 void CheckDownloadUrlDone(
154     const DownloadTargetDeterminerDelegate::CheckDownloadUrlCallback& callback,
155     bool is_content_check_supported,
156     DownloadProtectionService::DownloadCheckResult result) {
157   content::DownloadDangerType danger_type;
158   if (result == DownloadProtectionService::SAFE) {
159     // If this type of files is handled by the enhanced SafeBrowsing download
160     // protection, mark it as potentially dangerous content until we are done
161     // with scanning it.
162     if (is_content_check_supported)
163       danger_type = content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT;
164     else
165       danger_type = content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS;
166   } else {
167     // If the URL is malicious, we'll use that as the danger type. The results
168     // of the content check, if one is performed, will be ignored.
169     danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL;
170   }
171   callback.Run(danger_type);
172 }
173
174 #endif  // FULL_SAFE_BROWSING
175
176 // Called on the blocking pool to determine the MIME type for |path|.
177 void GetMimeTypeAndReplyOnUIThread(
178     const base::FilePath& path,
179     const base::Callback<void(const std::string&)>& callback) {
180   std::string mime_type;
181   net::GetMimeTypeFromFile(path, &mime_type);
182   BrowserThread::PostTask(
183       BrowserThread::UI, FROM_HERE, base::Bind(callback, mime_type));
184 }
185
186 bool IsOpenInBrowserPreferreredForFile(const base::FilePath& path) {
187   // On Android, always prefer opening with an external app. On ChromeOS, there
188   // are no external apps so just allow all opens to be handled by the "System."
189 #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) && defined(ENABLE_PLUGINS)
190   // TODO(asanka): Consider other file types and MIME types.
191   // http://crbug.com/323561
192   if (path.MatchesExtension(FILE_PATH_LITERAL(".pdf")) ||
193       path.MatchesExtension(FILE_PATH_LITERAL(".htm")) ||
194       path.MatchesExtension(FILE_PATH_LITERAL(".html")) ||
195       path.MatchesExtension(FILE_PATH_LITERAL(".shtm")) ||
196       path.MatchesExtension(FILE_PATH_LITERAL(".shtml")) ||
197       path.MatchesExtension(FILE_PATH_LITERAL(".svg")) ||
198       path.MatchesExtension(FILE_PATH_LITERAL(".xht")) ||
199       path.MatchesExtension(FILE_PATH_LITERAL(".xhtm")) ||
200       path.MatchesExtension(FILE_PATH_LITERAL(".xhtml")) ||
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       !extensions::WebstoreInstaller::GetAssociatedApproval(*item)) {
375     scoped_refptr<extensions::CrxInstaller> crx_installer =
376         download_crx_util::OpenChromeExtension(profile_, *item);
377
378     // CRX_INSTALLER_DONE will fire when the install completes.  At that
379     // time, Observe() will call the passed callback.
380     registrar_.Add(
381         this,
382         chrome::NOTIFICATION_CRX_INSTALLER_DONE,
383         content::Source<extensions::CrxInstaller>(crx_installer.get()));
384
385     crx_installers_[crx_installer.get()] = callback;
386     // The status text and percent complete indicator will change now
387     // that we are installing a CRX.  Update observers so that they pick
388     // up the change.
389     item->UpdateObservers();
390     return false;
391   }
392
393   return true;
394 }
395
396 bool ChromeDownloadManagerDelegate::GenerateFileHash() {
397 #if defined(FULL_SAFE_BROWSING)
398   return profile_->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled) &&
399       g_browser_process->safe_browsing_service()->DownloadBinHashNeeded();
400 #else
401   return false;
402 #endif
403 }
404
405 void ChromeDownloadManagerDelegate::GetSaveDir(
406     content::BrowserContext* browser_context,
407     base::FilePath* website_save_dir,
408     base::FilePath* download_save_dir,
409     bool* skip_dir_check) {
410   *website_save_dir = download_prefs_->SaveFilePath();
411   DCHECK(!website_save_dir->empty());
412   *download_save_dir = download_prefs_->DownloadPath();
413   *skip_dir_check = false;
414 #if defined(OS_CHROMEOS)
415   *skip_dir_check = drive::util::IsUnderDriveMountPoint(*website_save_dir);
416 #endif
417 }
418
419 void ChromeDownloadManagerDelegate::ChooseSavePath(
420     content::WebContents* web_contents,
421     const base::FilePath& suggested_path,
422     const base::FilePath::StringType& default_extension,
423     bool can_save_as_complete,
424     const content::SavePackagePathPickedCallback& callback) {
425   // Deletes itself.
426   new SavePackageFilePicker(
427       web_contents,
428       suggested_path,
429       default_extension,
430       can_save_as_complete,
431       download_prefs_.get(),
432       callback);
433 }
434
435 void ChromeDownloadManagerDelegate::OpenDownloadUsingPlatformHandler(
436     DownloadItem* download) {
437   base::FilePath platform_path(
438       GetPlatformDownloadPath(profile_, download, PLATFORM_TARGET_PATH));
439   DCHECK(!platform_path.empty());
440   platform_util::OpenItem(profile_, platform_path);
441 }
442
443 void ChromeDownloadManagerDelegate::OpenDownload(DownloadItem* download) {
444   DCHECK_EQ(DownloadItem::COMPLETE, download->GetState());
445   DCHECK(!download->GetTargetFilePath().empty());
446   if (!download->CanOpenDownload())
447     return;
448
449   if (!DownloadItemModel(download).ShouldPreferOpeningInBrowser()) {
450     RecordDownloadOpenMethod(DOWNLOAD_OPEN_METHOD_DEFAULT_PLATFORM);
451     OpenDownloadUsingPlatformHandler(download);
452     return;
453   }
454
455 #if !defined(OS_ANDROID)
456   content::WebContents* web_contents = download->GetWebContents();
457   Browser* browser =
458       web_contents ? chrome::FindBrowserWithWebContents(web_contents) : NULL;
459   scoped_ptr<chrome::ScopedTabbedBrowserDisplayer> browser_displayer;
460   if (!browser ||
461       !browser->CanSupportWindowFeature(Browser::FEATURE_TABSTRIP)) {
462     browser_displayer.reset(new chrome::ScopedTabbedBrowserDisplayer(
463         profile_, chrome::GetActiveDesktop()));
464     browser = browser_displayer->browser();
465   }
466   content::OpenURLParams params(
467       net::FilePathToFileURL(download->GetTargetFilePath()),
468       content::Referrer(),
469       NEW_FOREGROUND_TAB,
470       content::PAGE_TRANSITION_LINK,
471       false);
472   browser->OpenURL(params);
473   RecordDownloadOpenMethod(DOWNLOAD_OPEN_METHOD_DEFAULT_BROWSER);
474 #else
475   // ShouldPreferOpeningInBrowser() should never be true on Android.
476   NOTREACHED();
477 #endif
478 }
479
480 void ChromeDownloadManagerDelegate::ShowDownloadInShell(
481     DownloadItem* download) {
482   if (!download->CanShowInFolder())
483     return;
484   base::FilePath platform_path(
485       GetPlatformDownloadPath(profile_, download, PLATFORM_CURRENT_PATH));
486   DCHECK(!platform_path.empty());
487   platform_util::ShowItemInFolder(profile_, platform_path);
488 }
489
490 void ChromeDownloadManagerDelegate::CheckForFileExistence(
491     DownloadItem* download,
492     const content::CheckForFileExistenceCallback& callback) {
493 #if defined(OS_CHROMEOS)
494   drive::DownloadHandler* drive_download_handler =
495       drive::DownloadHandler::GetForProfile(profile_);
496   if (drive_download_handler &&
497       drive_download_handler->IsDriveDownload(download)) {
498     drive_download_handler->CheckForFileExistence(download, callback);
499     return;
500   }
501 #endif
502   static const char kSequenceToken[] = "ChromeDMD-FileExistenceChecker";
503   base::SequencedWorkerPool* worker_pool = BrowserThread::GetBlockingPool();
504   scoped_refptr<base::SequencedTaskRunner> task_runner =
505       worker_pool->GetSequencedTaskRunnerWithShutdownBehavior(
506           worker_pool->GetNamedSequenceToken(kSequenceToken),
507           base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
508   base::PostTaskAndReplyWithResult(
509       task_runner.get(),
510       FROM_HERE,
511       base::Bind(&base::PathExists, download->GetTargetFilePath()),
512       callback);
513 }
514
515 std::string
516 ChromeDownloadManagerDelegate::ApplicationClientIdForFileScanning() const {
517   return std::string(chrome::kApplicationClientIDStringForAVScanning);
518 }
519
520 DownloadProtectionService*
521     ChromeDownloadManagerDelegate::GetDownloadProtectionService() {
522   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
523 #if defined(FULL_SAFE_BROWSING)
524   SafeBrowsingService* sb_service = g_browser_process->safe_browsing_service();
525   if (sb_service && sb_service->download_protection_service() &&
526       profile_->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled)) {
527     return sb_service->download_protection_service();
528   }
529 #endif
530   return NULL;
531 }
532
533 void ChromeDownloadManagerDelegate::NotifyExtensions(
534     DownloadItem* download,
535     const base::FilePath& virtual_path,
536     const NotifyExtensionsCallback& callback) {
537   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
538 #if !defined(OS_ANDROID)
539   extensions::ExtensionDownloadsEventRouter* router =
540       DownloadServiceFactory::GetForBrowserContext(profile_)
541           ->GetExtensionEventRouter();
542   if (router) {
543     base::Closure original_path_callback =
544         base::Bind(callback, base::FilePath(),
545                    DownloadPathReservationTracker::UNIQUIFY);
546     router->OnDeterminingFilename(download, virtual_path.BaseName(),
547                                   original_path_callback,
548                                   callback);
549     return;
550   }
551 #endif
552   callback.Run(base::FilePath(), DownloadPathReservationTracker::UNIQUIFY);
553 }
554
555 void ChromeDownloadManagerDelegate::ReserveVirtualPath(
556     content::DownloadItem* download,
557     const base::FilePath& virtual_path,
558     bool create_directory,
559     DownloadPathReservationTracker::FilenameConflictAction conflict_action,
560     const DownloadTargetDeterminerDelegate::ReservedPathCallback& callback) {
561   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
562   DCHECK(!virtual_path.empty());
563 #if defined(OS_CHROMEOS)
564   // TODO(asanka): Handle path reservations for virtual paths as well.
565   //               http://crbug.com/151618
566   if (drive::util::IsUnderDriveMountPoint(virtual_path)) {
567     callback.Run(virtual_path, true);
568     return;
569   }
570 #endif
571   DownloadPathReservationTracker::GetReservedPath(
572       download,
573       virtual_path,
574       download_prefs_->DownloadPath(),
575       create_directory,
576       conflict_action,
577       callback);
578 }
579
580 void ChromeDownloadManagerDelegate::PromptUserForDownloadPath(
581     DownloadItem* download,
582     const base::FilePath& suggested_path,
583     const DownloadTargetDeterminerDelegate::FileSelectedCallback& callback) {
584   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
585   DownloadFilePicker::ShowFilePicker(download, suggested_path, callback);
586 }
587
588 void ChromeDownloadManagerDelegate::DetermineLocalPath(
589     DownloadItem* download,
590     const base::FilePath& virtual_path,
591     const DownloadTargetDeterminerDelegate::LocalPathCallback& callback) {
592   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
593 #if defined(OS_CHROMEOS)
594   drive::DownloadHandler* drive_download_handler =
595       drive::DownloadHandler::GetForProfile(profile_);
596   if (drive_download_handler) {
597     drive_download_handler->SubstituteDriveDownloadPath(
598         virtual_path, download, callback);
599     return;
600   }
601 #endif
602   callback.Run(virtual_path);
603 }
604
605 void ChromeDownloadManagerDelegate::CheckDownloadUrl(
606     DownloadItem* download,
607     const base::FilePath& suggested_path,
608     const CheckDownloadUrlCallback& callback) {
609   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
610
611 #if defined(FULL_SAFE_BROWSING)
612   safe_browsing::DownloadProtectionService* service =
613       GetDownloadProtectionService();
614   if (service) {
615     bool is_content_check_supported =
616         service->IsSupportedDownload(*download, suggested_path);
617     VLOG(2) << __FUNCTION__ << "() Start SB URL check for download = "
618             << download->DebugString(false);
619     service->CheckDownloadUrl(*download,
620                               base::Bind(&CheckDownloadUrlDone,
621                                          callback,
622                                          is_content_check_supported));
623     return;
624   }
625 #endif
626   callback.Run(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
627 }
628
629 void ChromeDownloadManagerDelegate::GetFileMimeType(
630     const base::FilePath& path,
631     const GetFileMimeTypeCallback& callback) {
632   BrowserThread::PostBlockingPoolTask(
633       FROM_HERE,
634       base::Bind(&GetMimeTypeAndReplyOnUIThread, path, callback));
635 }
636
637 #if defined(FULL_SAFE_BROWSING)
638 void ChromeDownloadManagerDelegate::CheckClientDownloadDone(
639     uint32 download_id,
640     DownloadProtectionService::DownloadCheckResult result) {
641   DownloadItem* item = download_manager_->GetDownload(download_id);
642   if (!item || (item->GetState() != DownloadItem::IN_PROGRESS))
643     return;
644
645   VLOG(2) << __FUNCTION__ << "() download = " << item->DebugString(false)
646           << " verdict = " << result;
647   // We only mark the content as being dangerous if the download's safety state
648   // has not been set to DANGEROUS yet.  We don't want to show two warnings.
649   if (item->GetDangerType() == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS ||
650       item->GetDangerType() ==
651       content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT) {
652     content::DownloadDangerType danger_type =
653         content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS;
654     switch (result) {
655       case DownloadProtectionService::SAFE:
656         // Do nothing.
657         break;
658       case DownloadProtectionService::DANGEROUS:
659         danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT;
660         break;
661       case DownloadProtectionService::UNCOMMON:
662         danger_type = content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT;
663         break;
664       case DownloadProtectionService::DANGEROUS_HOST:
665         danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST;
666         break;
667       case DownloadProtectionService::POTENTIALLY_UNWANTED:
668         danger_type = content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED;
669         break;
670     }
671
672     if (danger_type != content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS)
673       item->OnContentCheckCompleted(danger_type);
674   }
675
676   SafeBrowsingState* state = static_cast<SafeBrowsingState*>(
677       item->GetUserData(&kSafeBrowsingUserDataKey));
678   state->SetVerdict(result);
679 }
680 #endif  // FULL_SAFE_BROWSING
681
682 // content::NotificationObserver implementation.
683 void ChromeDownloadManagerDelegate::Observe(
684     int type,
685     const content::NotificationSource& source,
686     const content::NotificationDetails& details) {
687   DCHECK(type == chrome::NOTIFICATION_CRX_INSTALLER_DONE);
688
689   registrar_.Remove(this,
690                     chrome::NOTIFICATION_CRX_INSTALLER_DONE,
691                     source);
692
693   scoped_refptr<extensions::CrxInstaller> installer =
694       content::Source<extensions::CrxInstaller>(source).ptr();
695   content::DownloadOpenDelayedCallback callback =
696       crx_installers_[installer.get()];
697   crx_installers_.erase(installer.get());
698   callback.Run(installer->did_handle_successfully());
699 }
700
701 void ChromeDownloadManagerDelegate::OnDownloadTargetDetermined(
702     int32 download_id,
703     const content::DownloadTargetCallback& callback,
704     scoped_ptr<DownloadTargetInfo> target_info) {
705   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
706   DownloadItem* item = download_manager_->GetDownload(download_id);
707   if (!target_info->target_path.empty() && item &&
708       IsOpenInBrowserPreferreredForFile(target_info->target_path) &&
709       target_info->is_filetype_handled_safely)
710     DownloadItemModel(item).SetShouldPreferOpeningInBrowser(true);
711   callback.Run(target_info->target_path,
712                target_info->target_disposition,
713                target_info->danger_type,
714                target_info->intermediate_path);
715 }