diff options
author | xiyuan@chromium.org <xiyuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-29 22:03:57 +0000 |
---|---|---|
committer | xiyuan@chromium.org <xiyuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-29 22:03:57 +0000 |
commit | 274e42bf367cc47931bdac85837cfc2c8259f8a1 (patch) | |
tree | 75dc09021e2b1e85d416928773b351de33b7fae3 /chrome/browser/views/select_file_dialog.cc | |
parent | a9aca52ac15959a2c71a4ee22539a2392d3ee06b (diff) | |
download | chromium_src-274e42bf367cc47931bdac85837cfc2c8259f8a1.zip chromium_src-274e42bf367cc47931bdac85837cfc2c8259f8a1.tar.gz chromium_src-274e42bf367cc47931bdac85837cfc2c8259f8a1.tar.bz2 |
Replace GtkFileChooser with file browser for ChromeOS
- Remove dialogs_gtk.cc and add select_file_dialog.cc for chrome os build;
- select_file_dialog.cc provides a SelectFileDialogImpl that serves file
browse html via HTMLDialogUI;
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/543137
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@37547 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/views/select_file_dialog.cc')
-rw-r--r-- | chrome/browser/views/select_file_dialog.cc | 390 |
1 files changed, 390 insertions, 0 deletions
diff --git a/chrome/browser/views/select_file_dialog.cc b/chrome/browser/views/select_file_dialog.cc new file mode 100644 index 0000000..375e224 --- /dev/null +++ b/chrome/browser/views/select_file_dialog.cc @@ -0,0 +1,390 @@ +// Copyright (c) 2010 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/shell_dialogs.h" + +#include "app/l10n_util.h" +#include "base/file_path.h" +#include "base/json/json_reader.h" +#include "base/scoped_ptr.h" +#include "base/string_util.h" +#include "base/utf_string_conversions.h" +#include "base/values.h" +#include "chrome/browser/browser.h" +#include "chrome/browser/browser_list.h" +#include "chrome/browser/chrome_thread.h" +#include "chrome/browser/dom_ui/html_dialog_ui.h" +#include "chrome/browser/shell_dialogs.h" +#include "chrome/common/url_constants.h" +#include "grit/generated_resources.h" + +namespace { + +static const wchar_t* kKeyNamePath = L"path"; + +}; // namespace + +// Implementation of SelectFileDialog that shows an UI for choosing a file +// or folder using FileBrowseUI. +class SelectFileDialogImpl : public SelectFileDialog { + public: + explicit SelectFileDialogImpl(Listener* listener); + + // BaseShellDialog implementation. + virtual bool IsRunning(gfx::NativeWindow parent_window) const; + virtual void ListenerDestroyed(); + + // SelectFileDialog implementation. + // |params| is user data we pass back via the Listener interface. + virtual void SelectFile(Type type, + const string16& title, + const FilePath& default_path, + const FileTypeInfo* file_types, + int file_type_index, + const FilePath::StringType& default_extension, + gfx::NativeWindow owning_window, + void* params); + + private: + virtual ~SelectFileDialogImpl(); + + class FileBrowseDelegate : public HtmlDialogUIDelegate { + public: + FileBrowseDelegate(SelectFileDialogImpl* owner, + Type type, + const std::wstring& title, + const FilePath& default_path, + const FileTypeInfo* file_types, + int file_type_index, + const FilePath::StringType& default_extension, + gfx::NativeWindow parent, + void* params); + + // Owner of this FileBrowseDelegate. + SelectFileDialogImpl* owner_; + + // Parent window. + gfx::NativeWindow parent_; + + // The type of dialog we are showing the user. + Type type_; + + // The dialog title. + std::wstring title_; + + // Default path of the file dialog. + FilePath default_path_; + + // The file filters. + FileTypeInfo file_types_; + + // The index of the default selected file filter. + // Note: This starts from 1, not 0. + size_t file_type_index_; + + // Default extension to be added to file if user does not type one. + FilePath::StringType default_extension_; + + // Associated user data. + void* params_; + + private: + ~FileBrowseDelegate(); + + // Overridden from HtmlDialogUI::Delegate: + virtual bool IsDialogModal() const; + virtual std::wstring GetDialogTitle() const; + virtual GURL GetDialogContentURL() const; + virtual void GetDOMMessageHandlers( + std::vector<DOMMessageHandler*>* handlers) const; + virtual void GetDialogSize(gfx::Size* size) const; + virtual std::string GetDialogArgs() const; + virtual void OnDialogClosed(const std::string& json_retval); + + DISALLOW_COPY_AND_ASSIGN(FileBrowseDelegate); + }; + + // Notification from FileBrowseDelegate when file browse UI is dismissed. + void OnDialogClosed(FileBrowseDelegate* delegate, const std::string& json); + + // The set of all parent windows for which we are currently running dialogs. + std::set<gfx::NativeWindow> parents_; + + // The set of all FileBrowseDelegate that we are currently running. + std::set<FileBrowseDelegate*> delegates_; + + // The listener to be notified of selection completion. + Listener* listener_; + + DISALLOW_COPY_AND_ASSIGN(SelectFileDialogImpl); +}; + +// static +SelectFileDialog* SelectFileDialog::Create(Listener* listener) { + DCHECK(!ChromeThread::CurrentlyOn(ChromeThread::IO)); + DCHECK(!ChromeThread::CurrentlyOn(ChromeThread::FILE)); + return new SelectFileDialogImpl(listener); +} + +SelectFileDialogImpl::SelectFileDialogImpl(Listener* listener) + : listener_(listener) { +} + +SelectFileDialogImpl::~SelectFileDialogImpl() { + // All dialogs should be dismissed by now. + DCHECK(parents_.empty() && delegates_.empty()); +} + +bool SelectFileDialogImpl::IsRunning(gfx::NativeWindow parent_window) const { + return parent_window && parents_.find(parent_window) != parents_.end(); +} + +void SelectFileDialogImpl::ListenerDestroyed() { + listener_ = NULL; +} + +void SelectFileDialogImpl::SelectFile( + Type type, + const string16& title, + const FilePath& default_path, + const FileTypeInfo* file_types, + int file_type_index, + const FilePath::StringType& default_extension, + gfx::NativeWindow owning_window, + void* params) { + std::wstring title_string; + if (title.empty()) { + int string_id; + switch (type) { + case SELECT_FOLDER: + string_id = IDS_SELECT_FOLDER_DIALOG_TITLE; + break; + case SELECT_OPEN_FILE: + case SELECT_OPEN_MULTI_FILE: + string_id = IDS_OPEN_FILE_DIALOG_TITLE; + break; + case SELECT_SAVEAS_FILE: + string_id = IDS_SAVE_AS_DIALOG_TITLE; + break; + default: + NOTREACHED(); + return; + } + title_string = l10n_util::GetString(string_id); + } else { + title_string = UTF16ToWide(title); + } + + if (owning_window) + parents_.insert(owning_window); + + FileBrowseDelegate* file_browse_delegate = new FileBrowseDelegate(this, + type, title_string, default_path, file_types, file_type_index, + default_extension, owning_window, params); + delegates_.insert(file_browse_delegate); + + Browser* browser = BrowserList::GetLastActive(); + DCHECK(browser); + browser->BrowserShowHtmlDialog(file_browse_delegate, owning_window); +} + +void SelectFileDialogImpl::OnDialogClosed(FileBrowseDelegate* delegate, + const std::string& json) { + // Nothing to do if listener_ is gone. + + if (!listener_) + return; + + bool notification_fired = false; + + if (!json.empty()) { + scoped_ptr<Value> value(base::JSONReader::Read(json, false)); + if (!value.get() || !value->IsType(Value::TYPE_DICTIONARY)) { + // Bad json value returned. + NOTREACHED(); + } else { + const DictionaryValue* dict = static_cast<DictionaryValue*>(value.get()); + if (delegate->type_ == SELECT_OPEN_FILE || + delegate->type_ == SELECT_SAVEAS_FILE || + delegate->type_ == SELECT_FOLDER) { + std::wstring path_string; + if (dict->HasKey(kKeyNamePath) && + dict->GetString(kKeyNamePath, &path_string)) { + FilePath path = FilePath::FromWStringHack(path_string); + + listener_->FileSelected(path, 0, delegate->params_); + notification_fired = true; + } + } else if (delegate->type_ == SELECT_OPEN_MULTI_FILE) { + ListValue* paths_value = NULL; + if (dict->HasKey(kKeyNamePath) && + dict->GetList(kKeyNamePath, &paths_value) && + paths_value) { + std::vector<FilePath> paths; + paths.reserve(paths_value->GetSize()); + for (size_t i = 0; i < paths_value->GetSize(); ++i) { + std::wstring path_string; + if (paths_value->GetString(i, &path_string) && + !path_string.empty()) { + paths.push_back(FilePath::FromWStringHack(path_string)); + } + } + + listener_->MultiFilesSelected(paths, delegate->params_); + notification_fired = true; + } + } else { + NOTREACHED(); + } + } + } + + // Always notify listener when dialog is dismissed. + if (!notification_fired) + listener_->FileSelectionCanceled(delegate->params_); + + parents_.erase(delegate->parent_); + delegates_.erase(delegate); +} + +SelectFileDialogImpl::FileBrowseDelegate::FileBrowseDelegate( + SelectFileDialogImpl* owner, + Type type, + const std::wstring& title, + const FilePath& default_path, + const FileTypeInfo* file_types, + int file_type_index, + const FilePath::StringType& default_extension, + gfx::NativeWindow parent, + void* params) + : owner_(owner), + parent_(parent), + type_(type), + title_(title), + default_path_(default_path), + file_type_index_(file_type_index), + default_extension_(default_extension), + params_(params) { + if (file_types) + file_types_ = *file_types; + else + file_types_.include_all_files = true; +} + +SelectFileDialogImpl::FileBrowseDelegate::~FileBrowseDelegate() { +} + +bool SelectFileDialogImpl::FileBrowseDelegate::IsDialogModal() const { + return true; +} + +std::wstring SelectFileDialogImpl::FileBrowseDelegate::GetDialogTitle() const { + return title_; +} + +GURL SelectFileDialogImpl::FileBrowseDelegate::GetDialogContentURL() const { + std::string url_string(chrome::kChromeUIFileBrowseURL); + + return GURL(url_string); +} + +void SelectFileDialogImpl::FileBrowseDelegate::GetDOMMessageHandlers( + std::vector<DOMMessageHandler*>* handlers) const { + return; +} + +void SelectFileDialogImpl::FileBrowseDelegate::GetDialogSize( + gfx::Size* size) const { + size->SetSize(320, 240); +} + +std::string SelectFileDialogImpl::FileBrowseDelegate::GetDialogArgs() const { + // SelectFile inputs as json. + // { + // "type" : "open", // (or "open_multiple", "save", "folder" + // "all_files" : true, + // "file_types" : { + // "exts" : [ ["htm", "html"], ["txt"] ], + // "desc" : [ "HTML files", "Text files" ], + // }, + // "file_type_index" : 1, // 1-based file type index. + // } + // See browser/shell_dialogs.h for more details. + + std::string type_string; + switch (type_) { + case SELECT_FOLDER: + type_string = "folder"; + break; + case SELECT_OPEN_FILE: + type_string = "open"; + break; + case SELECT_OPEN_MULTI_FILE: + type_string = "open_multiple"; + break; + case SELECT_SAVEAS_FILE: + type_string = "save"; + break; + default: + NOTREACHED(); + return std::string(); + } + + std::string exts_list; + std::string desc_list; + for (size_t i = 0; i < file_types_.extensions.size(); ++i) { + DCHECK(!file_types_.extensions[i].empty()); + + std::string exts; + for (size_t j = 0; j < file_types_.extensions[i].size(); ++j) { + if (!exts.empty()) + exts.append(","); + StringAppendF(&exts, "\"%s\"", file_types_.extensions[i][j].c_str()); + } + + if (!exts_list.empty()) + exts_list.append(","); + StringAppendF(&exts_list, "[%s]", exts.c_str()); + + std::string desc; + if (i < file_types_.extension_description_overrides.size()) { + desc = UTF16ToUTF8(file_types_.extension_description_overrides[i]); + } else { +#if defined(OS_WIN) + desc = WideToUTF8(file_types_.extensions[i][0]); +#elif defined(OS_POSIX) + desc = file_types_.extensions[i][0]; +#else + NOTIMPLEMENTED(); +#endif + } + + if (!desc_list.empty()) + desc_list.append(","); + StringAppendF(&desc_list, "\"%s\"", desc.c_str()); + } + + std::string filename = default_path_.BaseName().value(); + + return StringPrintf("{" + "\"type\":\"%s\"," + "\"all_files\":%s," + "\"current_file\":\"%s\"," + "\"file_types\":{\"exts\":[%s],\"desc\":[%s]}," + "\"file_type_index\":%d" + "}", + type_string.c_str(), + file_types_.include_all_files ? "true" : "false", + filename.c_str(), + exts_list.c_str(), + desc_list.c_str(), + file_type_index_); +} + +void SelectFileDialogImpl::FileBrowseDelegate::OnDialogClosed( + const std::string& json_retval) { + owner_->OnDialogClosed(this, json_retval); + delete this; + return; +} |