// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/download/download_file_picker.h" #include "base/metrics/histogram.h" #include "chrome/browser/download/download_prefs.h" #include "chrome/browser/platform_util.h" #include "chrome/browser/ui/chrome_select_file_policy.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/download_item.h" #include "content/public/browser/download_manager.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_view.h" #include "grit/generated_resources.h" #include "ui/base/l10n/l10n_util.h" using content::DownloadItem; using content::DownloadManager; using content::WebContents; namespace { enum FilePickerResult { FILE_PICKER_SAME, FILE_PICKER_DIFFERENT_DIR, FILE_PICKER_DIFFERENT_NAME, FILE_PICKER_CANCEL, FILE_PICKER_MAX, }; // Record how the File Picker was used during a download. This UMA is only // recorded for profiles that do not always prompt for save locations on // downloads. void RecordFilePickerResult(const base::FilePath& suggested_path, const base::FilePath& actual_path) { FilePickerResult result; if (suggested_path == actual_path) result = FILE_PICKER_SAME; else if (actual_path.empty()) result = FILE_PICKER_CANCEL; else if (suggested_path.DirName() != actual_path.DirName()) result = FILE_PICKER_DIFFERENT_DIR; else result = FILE_PICKER_DIFFERENT_NAME; UMA_HISTOGRAM_ENUMERATION("Download.FilePickerResult", result, FILE_PICKER_MAX); } } // namespace DownloadFilePicker::DownloadFilePicker( DownloadItem* item, const base::FilePath& suggested_path, const FileSelectedCallback& callback) : suggested_path_(suggested_path), file_selected_callback_(callback), should_record_file_picker_result_(false) { const DownloadPrefs* prefs = DownloadPrefs::FromBrowserContext(item->GetBrowserContext()); DCHECK(prefs); // Only record UMA if we aren't prompting the user for all downloads. should_record_file_picker_result_ = !prefs->PromptForDownload(); WebContents* web_contents = item->GetWebContents(); select_file_dialog_ = ui::SelectFileDialog::Create( this, new ChromeSelectFilePolicy(web_contents)); ui::SelectFileDialog::FileTypeInfo file_type_info; // Platform file pickers, notably on Mac and Windows, tend to break // with double extensions like .tar.gz, so only pass in normal ones. base::FilePath::StringType extension = suggested_path_.FinalExtension(); if (!extension.empty()) { extension.erase(extension.begin()); // drop the . file_type_info.extensions.resize(1); file_type_info.extensions[0].push_back(extension); } file_type_info.include_all_files = true; file_type_info.support_drive = true; gfx::NativeWindow owning_window = web_contents ? platform_util::GetTopLevel(web_contents->GetView()->GetNativeView()) : NULL; select_file_dialog_->SelectFile(ui::SelectFileDialog::SELECT_SAVEAS_FILE, base::string16(), suggested_path_, &file_type_info, 0, base::FilePath::StringType(), owning_window, NULL); } DownloadFilePicker::~DownloadFilePicker() { } void DownloadFilePicker::OnFileSelected(const base::FilePath& path) { if (should_record_file_picker_result_) RecordFilePickerResult(suggested_path_, path); file_selected_callback_.Run(path); delete this; } void DownloadFilePicker::FileSelected(const base::FilePath& path, int index, void* params) { OnFileSelected(path); // Deletes |this| } void DownloadFilePicker::FileSelectionCanceled(void* params) { OnFileSelected(base::FilePath()); // Deletes |this| } // static void DownloadFilePicker::ShowFilePicker(DownloadItem* item, const base::FilePath& suggested_path, const FileSelectedCallback& callback) { new DownloadFilePicker(item, suggested_path, callback); // DownloadFilePicker deletes itself. }