Home | History | Annotate | Download | only in download
      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/download_file_picker.h"
      6 
      7 #include "base/metrics/histogram.h"
      8 #include "chrome/browser/download/download_prefs.h"
      9 #include "chrome/browser/platform_util.h"
     10 #include "chrome/browser/ui/chrome_select_file_policy.h"
     11 #include "content/public/browser/browser_context.h"
     12 #include "content/public/browser/download_item.h"
     13 #include "content/public/browser/download_manager.h"
     14 #include "content/public/browser/web_contents.h"
     15 #include "content/public/browser/web_contents_view.h"
     16 #include "grit/generated_resources.h"
     17 #include "ui/base/l10n/l10n_util.h"
     18 
     19 using content::DownloadItem;
     20 using content::DownloadManager;
     21 using content::WebContents;
     22 
     23 namespace {
     24 
     25 enum FilePickerResult {
     26   FILE_PICKER_SAME,
     27   FILE_PICKER_DIFFERENT_DIR,
     28   FILE_PICKER_DIFFERENT_NAME,
     29   FILE_PICKER_CANCEL,
     30   FILE_PICKER_MAX,
     31 };
     32 
     33 // Record how the File Picker was used during a download. This UMA is only
     34 // recorded for profiles that do not always prompt for save locations on
     35 // downloads.
     36 void RecordFilePickerResult(const base::FilePath& suggested_path,
     37                             const base::FilePath& actual_path) {
     38   FilePickerResult result;
     39   if (suggested_path == actual_path)
     40     result = FILE_PICKER_SAME;
     41   else if (actual_path.empty())
     42     result = FILE_PICKER_CANCEL;
     43   else if (suggested_path.DirName() != actual_path.DirName())
     44     result = FILE_PICKER_DIFFERENT_DIR;
     45   else
     46     result = FILE_PICKER_DIFFERENT_NAME;
     47 
     48   UMA_HISTOGRAM_ENUMERATION("Download.FilePickerResult",
     49                             result,
     50                             FILE_PICKER_MAX);
     51 }
     52 
     53 }  // namespace
     54 
     55 DownloadFilePicker::DownloadFilePicker(
     56     DownloadItem* item,
     57     const base::FilePath& suggested_path,
     58     const FileSelectedCallback& callback)
     59     : suggested_path_(suggested_path),
     60       file_selected_callback_(callback),
     61       should_record_file_picker_result_(false) {
     62   const DownloadPrefs* prefs =
     63       DownloadPrefs::FromBrowserContext(item->GetBrowserContext());
     64   DCHECK(prefs);
     65   // Only record UMA if we aren't prompting the user for all downloads.
     66   should_record_file_picker_result_ = !prefs->PromptForDownload();
     67 
     68   WebContents* web_contents = item->GetWebContents();
     69   select_file_dialog_ = ui::SelectFileDialog::Create(
     70       this, new ChromeSelectFilePolicy(web_contents));
     71   ui::SelectFileDialog::FileTypeInfo file_type_info;
     72   base::FilePath::StringType extension = suggested_path_.Extension();
     73   if (!extension.empty()) {
     74     extension.erase(extension.begin());  // drop the .
     75     file_type_info.extensions.resize(1);
     76     file_type_info.extensions[0].push_back(extension);
     77   }
     78   file_type_info.include_all_files = true;
     79   file_type_info.support_drive = true;
     80   gfx::NativeWindow owning_window = web_contents ?
     81       platform_util::GetTopLevel(web_contents->GetView()->GetNativeView()) :
     82       NULL;
     83 
     84   select_file_dialog_->SelectFile(ui::SelectFileDialog::SELECT_SAVEAS_FILE,
     85                                   string16(),
     86                                   suggested_path_,
     87                                   &file_type_info,
     88                                   0,
     89                                   base::FilePath::StringType(),
     90                                   owning_window,
     91                                   NULL);
     92 }
     93 
     94 DownloadFilePicker::~DownloadFilePicker() {
     95 }
     96 
     97 void DownloadFilePicker::OnFileSelected(const base::FilePath& path) {
     98   if (should_record_file_picker_result_)
     99     RecordFilePickerResult(suggested_path_, path);
    100   file_selected_callback_.Run(path);
    101   delete this;
    102 }
    103 
    104 void DownloadFilePicker::FileSelected(const base::FilePath& path,
    105                                       int index,
    106                                       void* params) {
    107   OnFileSelected(path);
    108   // Deletes |this|
    109 }
    110 
    111 void DownloadFilePicker::FileSelectionCanceled(void* params) {
    112   OnFileSelected(base::FilePath());
    113   // Deletes |this|
    114 }
    115 
    116 // static
    117 void DownloadFilePicker::ShowFilePicker(DownloadItem* item,
    118                                         const base::FilePath& suggested_path,
    119                                         const FileSelectedCallback& callback) {
    120   new DownloadFilePicker(item, suggested_path, callback);
    121   // DownloadFilePicker deletes itself.
    122 }
    123