diff options
author | avi@chromium.org <avi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-12 20:03:08 +0000 |
---|---|---|
committer | avi@chromium.org <avi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-12 20:03:08 +0000 |
commit | b949f1110dea9e220706cbe72ede4118d78308f0 (patch) | |
tree | 16627db33014921df4287548a54caac852dd76eb /chrome | |
parent | 3e1302168c2b16d744486172b55dc48114baac7e (diff) | |
download | chromium_src-b949f1110dea9e220706cbe72ede4118d78308f0.zip chromium_src-b949f1110dea9e220706cbe72ede4118d78308f0.tar.gz chromium_src-b949f1110dea9e220706cbe72ede4118d78308f0.tar.bz2 |
Refactoring; switch the |filter| parameter into something that is more amenable to cross-platform implementation.
BUG=9852
Review URL: http://codereview.chromium.org/63093
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@13573 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
21 files changed, 227 insertions, 216 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index c28c691..33cbe02 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -3288,8 +3288,11 @@ each locale. --> </message> <!-- Saving Page--> - <message name="IDS_SAVE_PAGE_FILTER" desc="Filter string for save page. \0's are required separators and additional two \0's should be appended when using this."> - Web Page, HTML Only\0*.htm\0Web Page, Complete\0*.htm + <message name="IDS_SAVE_PAGE_DESC_HTML_ONLY" desc="In the Save Page dialog, the description of saving only the HTML of a web page."> + Web Page, HTML Only + </message> + <message name="IDS_SAVE_PAGE_DESC_COMPLETE" desc="In the Save Page dialog, the description of saving both the HTML and all shown resources."> + Web Page, Complete </message> <message name="IDS_SAVE_PAGE_STATUS_COMPLETED" desc="Save page status: completed"> Completed diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc index 5c5c581..1963361 100644 --- a/chrome/browser/browser.cc +++ b/chrome/browser/browser.cc @@ -993,7 +993,7 @@ void Browser::OpenFile() { gfx::NativeWindow parent_window = window_->GetNativeHandle(); select_file_dialog_->SelectFile(SelectFileDialog::SELECT_OPEN_FILE, string16(), FilePath(), - std::wstring(), 0, FILE_PATH_LITERAL(""), + NULL, 0, FILE_PATH_LITERAL(""), parent_window, NULL); } #endif diff --git a/chrome/browser/download/download_manager.cc b/chrome/browser/download/download_manager.cc index 3b68cfa..43954a7 100644 --- a/chrome/browser/download/download_manager.cc +++ b/chrome/browser/download/download_manager.cc @@ -640,18 +640,16 @@ void DownloadManager::OnPathExistenceAvailable(DownloadCreateInfo* info) { WebContents* contents = tab_util::GetWebContentsByID( info->render_process_id, info->render_view_id); -#if defined(OS_WIN) - std::wstring filter = - win_util::GetFileFilterFromPath(info->suggested_path.value()); -#elif defined(OS_LINUX) - std::wstring filter; -#endif + SelectFileDialog::FileTypeInfo file_type_info; + file_type_info.extensions.resize(1); + file_type_info.extensions[0].push_back(info->suggested_path.Extension()); + file_type_info.include_all_files = true; gfx::NativeWindow owning_window = contents ? platform_util::GetTopLevel(contents->GetNativeView()) : NULL; select_file_dialog_->SelectFile(SelectFileDialog::SELECT_SAVEAS_FILE, string16(), info->suggested_path, - filter, 0, FILE_PATH_LITERAL(""), + &file_type_info, 0, FILE_PATH_LITERAL(""), owning_window, info); } else { // No prompting for download, just continue with the suggested name. diff --git a/chrome/browser/download/save_package.cc b/chrome/browser/download/save_package.cc index 23bb704..01a1b26 100644 --- a/chrome/browser/download/save_package.cc +++ b/chrome/browser/download/save_package.cc @@ -995,8 +995,8 @@ FilePath SavePackage::GetSuggestNameForSaveAs(PrefService* prefs, void SavePackage::GetSaveInfo() { // Use "Web Page, Complete" option as default choice of saving page. - int filter_index = 2; - std::wstring filter; + int file_type_index = 2; + SelectFileDialog::FileTypeInfo file_type_info; FilePath::StringType default_extension; FilePath title = FilePath::FromWStringHack(UTF16ToWideHack(web_contents_->GetTitle())); @@ -1009,22 +1009,22 @@ void SavePackage::GetSaveInfo() { // If the contents can not be saved as complete-HTML, do not show the // file filters. if (CanSaveAsComplete(save_params->current_tab_mime_type)) { - filter = l10n_util::GetString(IDS_SAVE_PAGE_FILTER); - filter.resize(filter.size() + 2); - filter[filter.size() - 1] = L'\0'; - filter[filter.size() - 2] = L'\0'; + file_type_info.extensions.resize(2); + file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("htm")); + file_type_info.extension_description_overrides.push_back( + WideToUTF16(l10n_util::GetString(IDS_SAVE_PAGE_DESC_HTML_ONLY))); + file_type_info.extensions[1].push_back(FILE_PATH_LITERAL("htm")); + file_type_info.extension_description_overrides.push_back( + WideToUTF16(l10n_util::GetString(IDS_SAVE_PAGE_DESC_COMPLETE))); + file_type_info.include_all_files = false; default_extension = FILE_PATH_LITERAL("htm"); } else { -#if defined(OS_WIN) - filter = win_util::GetFileFilterFromPath(suggested_path.ToWStringHack()); -#else - // TODO(port): implement this. - NOTIMPLEMENTED(); -#endif - filter_index = 1; + file_type_info.extensions.resize(1); + file_type_info.extensions[0].push_back(suggested_path.Extension()); + file_type_info.include_all_files = true; + file_type_index = 1; } - #if defined(OS_LINUX) || defined(OS_WIN) if (g_should_prompt_for_filename) { if (!select_file_dialog_.get()) @@ -1032,8 +1032,8 @@ void SavePackage::GetSaveInfo() { select_file_dialog_->SelectFile(SelectFileDialog::SELECT_SAVEAS_FILE, string16(), suggested_path, - filter, - filter_index, + &file_type_info, + file_type_index, default_extension, platform_util::GetTopLevel( web_contents_->GetNativeView()), @@ -1042,7 +1042,7 @@ void SavePackage::GetSaveInfo() { #endif // defined(OS_LINUX) || defined(OS_WIN) { // Just use 'suggested_path' instead of opening the dialog prompt. - ContinueSave(save_params, suggested_path, filter_index); + ContinueSave(save_params, suggested_path, file_type_index); delete save_params; } } diff --git a/chrome/browser/gtk/dialogs_gtk.cc b/chrome/browser/gtk/dialogs_gtk.cc index d7b6350..113edb2 100644 --- a/chrome/browser/gtk/dialogs_gtk.cc +++ b/chrome/browser/gtk/dialogs_gtk.cc @@ -30,12 +30,13 @@ class SelectFileDialogImpl : public SelectFileDialog { // SelectFileDialog implementation. // |params| is user data we pass back via the Listener interface. - virtual void SelectFile(Type type, const string16& title, + virtual void SelectFile(Type type, + const string16& title, const FilePath& default_path, - const std::wstring& filter, - int filter_index, + const FileTypeInfo* file_types, + int file_type_index, const FilePath::StringType& default_extension, - gfx::NativeWindow parent_window, + gfx::NativeWindow owning_window, void* params); private: @@ -114,21 +115,21 @@ void SelectFileDialogImpl::ListenerDestroyed() { listener_ = NULL; } -// We ignore |filter| and |default_extension|. -// TODO(estade): use |filter|. +// We ignore |file_types| and |default_extension|. +// TODO(estade): use |file_types|. void SelectFileDialogImpl::SelectFile( Type type, const string16& title, const FilePath& default_path, - const std::wstring& filter, - int filter_index, + const FileTypeInfo* file_types, + int file_type_index, const FilePath::StringType& default_extension, - gfx::NativeWindow parent_window, + gfx::NativeWindow owning_window, void* params) { // TODO(estade): on windows, parent_window may be null. But I'm not sure when // that's used and how to deal with it here. For now, don't allow it. - DCHECK(parent_window); - parents_.insert(parent_window); + DCHECK(owning_window); + parents_.insert(owning_window); std::string title_string = UTF16ToUTF8(title); @@ -136,14 +137,14 @@ void SelectFileDialogImpl::SelectFile( switch (type) { case SELECT_OPEN_FILE: DCHECK(default_path.empty()); - dialog = CreateFileOpenDialog(title_string, parent_window); + dialog = CreateFileOpenDialog(title_string, owning_window); break; case SELECT_OPEN_MULTI_FILE: DCHECK(default_path.empty()); - dialog = CreateMultiFileOpenDialog(title_string, parent_window); + dialog = CreateMultiFileOpenDialog(title_string, owning_window); break; case SELECT_SAVEAS_FILE: - dialog = CreateSaveAsDialog(title_string, default_path, parent_window); + dialog = CreateSaveAsDialog(title_string, default_path, owning_window); break; default: NOTIMPLEMENTED() << "Dialog type " << type << " not implemented."; diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc index ef6ea8d..e50c032 100644 --- a/chrome/browser/renderer_host/render_view_host.cc +++ b/chrome/browser/renderer_host/render_view_host.cc @@ -1126,12 +1126,9 @@ void RenderViewHost::OnMsgPasteFromSelectionClipboard() { } void RenderViewHost::OnMsgRunFileChooser(bool multiple_files, - const std::wstring& title, - const std::wstring& default_file, - const std::wstring& filter) { - std::wstring real_filter = filter; - std::replace(real_filter.begin(), real_filter.end(), '|', '\0'); - delegate_->RunFileChooser(multiple_files, title, default_file, real_filter); + const string16& title, + const FilePath& default_file) { + delegate_->RunFileChooser(multiple_files, title, default_file); } void RenderViewHost::OnMsgRunJavaScriptMessage( diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h index 8d82ba3..e6e7ad11 100644 --- a/chrome/browser/renderer_host/render_view_host.h +++ b/chrome/browser/renderer_host/render_view_host.h @@ -511,9 +511,8 @@ class RenderViewHost : public RenderWidgetHost { void OnMsgSelectionChanged(const std::string& text); void OnMsgPasteFromSelectionClipboard(); void OnMsgRunFileChooser(bool multiple_files, - const std::wstring& title, - const std::wstring& default_file, - const std::wstring& filter); + const string16& title, + const FilePath& default_file); void OnMsgRunJavaScriptMessage(const std::wstring& message, const std::wstring& default_prompt, const GURL& frame_url, diff --git a/chrome/browser/renderer_host/render_view_host_delegate.h b/chrome/browser/renderer_host/render_view_host_delegate.h index 7a9a94b..ebe8df1 100644 --- a/chrome/browser/renderer_host/render_view_host_delegate.h +++ b/chrome/browser/renderer_host/render_view_host_delegate.h @@ -283,9 +283,8 @@ class RenderViewHostDelegate { // A file chooser should be shown. virtual void RunFileChooser(bool multiple_files, - const std::wstring& title, - const std::wstring& default_file, - const std::wstring& filter) { } + const string16& title, + const FilePath& default_file) { } // A javascript message, confirmation or prompt should be shown. virtual void RunJavaScriptMessage(const std::wstring& message, diff --git a/chrome/browser/shell_dialogs.h b/chrome/browser/shell_dialogs.h index 4975395..4285364 100644 --- a/chrome/browser/shell_dialogs.h +++ b/chrome/browser/shell_dialogs.h @@ -15,9 +15,6 @@ class ChromeFont; -// Helpers to show certain types of Windows shell dialogs in a way that doesn't -// block the UI of the entire app. - // A base class for shell dialogs. class BaseShellDialog { public: @@ -71,36 +68,50 @@ class SelectFileDialog // object will have no reference (refcount is 0). static SelectFileDialog* Create(Listener* listener); + // Holds information about allowed extensions on a file save dialog. + // |extensions| is a list of allowed extensions. For example, it might be + // { { "htm", "html" }, { "txt" } }. Only pass more than one extension + // in the inner vector if the extensions are equivalent. Do NOT include + // leading periods. + // |extension_description_overrides| overrides the system descriptions of the + // specified extensions. Entries correspond to |extensions|; if left blank + // the system descriptions will be used. + // |include_all_files| specifies whether all files (e.g. *.*) will be allowed + // in the file filtering. + struct FileTypeInfo { + std::vector<std::vector<FilePath::StringType> > extensions; + std::vector<string16> extension_description_overrides; + bool include_all_files; + }; + // Selects a file. This will start displaying the dialog box. This will also // block the calling window until the dialog box is complete. The listener // associated with this object will be notified when the selection is // complete. // |type| is the type of file dialog to be shown, see Type enumeration above. // |title| is the title to be displayed in the dialog. If this string is - // empty, the default title is used. + // empty, the default title is used. // |default_path| is the default path and suggested file name to be shown in - // the dialog. This only works for SELECT_SAVEAS_FILE and SELECT_OPEN_FILE. - // Can be an empty string to indicate Windows should choose the default to - // show. - // |filter| is a null (\0) separated list of alternating filter description - // and filters and terminated with two nulls. - // |filter_index| is the 1-based index into the filter list in |filter|. - // Specify 0 if you don't need filters, or if you only need the default - // (first filter) behavior. - // |owning_window| is the window the dialog is modal to, or NULL for a - // modeless dialog. + // the dialog. This only works for SELECT_SAVEAS_FILE and SELECT_OPEN_FILE. + // Can be an empty string to indicate the platform default. + // |file_types| holds the infomation about the file types allowed. Pass NULL + // to get no special behavior + // |file_type_index| is the 1-based index into the file type list in + // |file_types|. Specify 0 if you don't need to specify extension behavior. // |default_extension| is the default extension to add to the file if the - // user doesn't type one. This should NOT include the '.'. If you specify - // this you must also specify a filter. + // user doesn't type one. This should NOT include the '.'. On Windows, if + // you specify this you must also specify |file_types|. + // |owning_window| is the window the dialog is modal to, or NULL for a + // modeless dialog. // |params| is data from the calling context which will be passed through to - // the listener. Can be NULL. + // the listener. Can be NULL. // NOTE: only one instance of any shell dialog can be shown per owning_window // at a time (for obvious reasons). virtual void SelectFile(Type type, const string16& title, const FilePath& default_path, - const std::wstring& filter, - int filter_index, + const FileTypeInfo* file_types, + int file_type_index, const FilePath::StringType& default_extension, gfx::NativeWindow owning_window, void* params) = 0; diff --git a/chrome/browser/tab_contents/web_contents.cc b/chrome/browser/tab_contents/web_contents.cc index eaf181e..b58d7b3 100644 --- a/chrome/browser/tab_contents/web_contents.cc +++ b/chrome/browser/tab_contents/web_contents.cc @@ -1145,15 +1145,14 @@ void WebContents::GetHistoryListCount(int* back_list_count, void WebContents::RunFileChooser(bool multiple_files, const string16& title, - const FilePath& default_file, - const std::wstring& filter) { + const FilePath& default_file) { if (!select_file_dialog_.get()) select_file_dialog_ = SelectFileDialog::Create(this); SelectFileDialog::Type dialog_type = multiple_files ? SelectFileDialog::SELECT_OPEN_MULTI_FILE : SelectFileDialog::SELECT_OPEN_FILE; select_file_dialog_->SelectFile(dialog_type, title, default_file, - filter, 0, FILE_PATH_LITERAL(""), + NULL, 0, FILE_PATH_LITERAL(""), view_->GetTopLevelNativeWindow(), NULL); } diff --git a/chrome/browser/tab_contents/web_contents.h b/chrome/browser/tab_contents/web_contents.h index be0fe27..6164ddb 100644 --- a/chrome/browser/tab_contents/web_contents.h +++ b/chrome/browser/tab_contents/web_contents.h @@ -370,8 +370,7 @@ class WebContents : public TabContents, int* forward_list_count); virtual void RunFileChooser(bool multiple_files, const string16& title, - const FilePath& default_file, - const std::wstring& filter); + const FilePath& default_file); virtual void RunJavaScriptMessage(const std::wstring& message, const std::wstring& default_prompt, const GURL& frame_url, diff --git a/chrome/browser/views/bookmark_manager_view.cc b/chrome/browser/views/bookmark_manager_view.cc index 12150c6..585f6a4 100644 --- a/chrome/browser/views/bookmark_manager_view.cc +++ b/chrome/browser/views/bookmark_manager_view.cc @@ -716,14 +716,16 @@ void BookmarkManagerView::ShowImportBookmarksFileChooser() { if (select_file_dialog_.get()) select_file_dialog_->ListenerDestroyed(); - std::wstring filter_string = - win_util::GetFileFilterFromExtensions(L"*.html;*.htm", true); + SelectFileDialog::FileTypeInfo file_type_info; + file_type_info.extensions.resize(1); + file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("html")); + file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("htm")); + file_type_info.include_all_files = true; select_file_dialog_ = SelectFileDialog::Create(this); select_file_dialog_->SelectFile( SelectFileDialog::SELECT_OPEN_FILE, std::wstring(), - FilePath(FILE_PATH_LITERAL("bookmarks.html")), filter_string, 0, - std::wstring(), - GetWidget()->GetNativeView(), + FilePath(FILE_PATH_LITERAL("bookmarks.html")), &file_type_info, 0, + std::wstring(), GetWidget()->GetNativeView(), reinterpret_cast<void*>(IDS_BOOKMARK_MANAGER_IMPORT_MENU)); } @@ -731,11 +733,14 @@ void BookmarkManagerView::ShowExportBookmarksFileChooser() { if (select_file_dialog_.get()) select_file_dialog_->ListenerDestroyed(); + SelectFileDialog::FileTypeInfo file_type_info; + file_type_info.extensions.resize(1); + file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("html")); + file_type_info.include_all_files = true; select_file_dialog_ = SelectFileDialog::Create(this); select_file_dialog_->SelectFile( SelectFileDialog::SELECT_SAVEAS_FILE, std::wstring(), - FilePath(FILE_PATH_LITERAL("bookmarks.html")), - win_util::GetFileFilterFromPath(L"bookmarks.html"), 0, L"html", - GetWidget()->GetNativeView(), + FilePath(FILE_PATH_LITERAL("bookmarks.html")), &file_type_info, 0, + L"html", GetWidget()->GetNativeView(), reinterpret_cast<void*>(IDS_BOOKMARK_MANAGER_EXPORT_MENU)); } diff --git a/chrome/browser/views/options/content_page_view.cc b/chrome/browser/views/options/content_page_view.cc index e6966e0..10feabc9 100644 --- a/chrome/browser/views/options/content_page_view.cc +++ b/chrome/browser/views/options/content_page_view.cc @@ -217,7 +217,7 @@ void ContentPageView::ButtonPressed(views::Button* sender) { FilePath::FromWStringHack( profile()->GetPrefs()->GetString( prefs::kDownloadDefaultDirectory)), - std::wstring(), 0, std::wstring(), + NULL, 0, std::wstring(), GetRootWindow(), NULL); } else if (sender == download_ask_for_save_location_checkbox_) { diff --git a/chrome/browser/views/shell_dialogs_win.cc b/chrome/browser/views/shell_dialogs_win.cc index 0c3abcf..69ee892 100644 --- a/chrome/browser/views/shell_dialogs_win.cc +++ b/chrome/browser/views/shell_dialogs_win.cc @@ -22,6 +22,9 @@ #include "chrome/common/win_util.h" #include "grit/generated_resources.h" +// Helpers to show certain types of Windows shell dialogs in a way that doesn't +// block the UI of the entire app. + class ShellDialogThread : public base::Thread { public: ShellDialogThread() : base::Thread("Chrome_ShellDialogThread") { } @@ -192,12 +195,13 @@ class SelectFileDialogImpl : public SelectFileDialog, virtual ~SelectFileDialogImpl(); // SelectFileDialog implementation: - virtual void SelectFile(Type type, const string16& title, + virtual void SelectFile(Type type, + const string16& title, const FilePath& default_path, - const std::wstring& filter, - int filter_index, + const FileTypeInfo* file_types, + int file_type_index, const FilePath::StringType& default_extension, - HWND owning_hwnd, + gfx::NativeWindow owning_window, void* params); virtual bool IsRunning(HWND owning_hwnd) const; virtual void ListenerDestroyed(); @@ -208,21 +212,31 @@ class SelectFileDialogImpl : public SelectFileDialog, ExecuteSelectParams(Type type, const std::wstring& title, const FilePath& default_path, - const std::wstring& filter, - int filter_index, + const FileTypeInfo* file_types, + int file_type_index, const std::wstring& default_extension, RunState run_state, HWND owner, void* params) - : type(type), title(title), default_path(default_path), filter(filter), - filter_index(filter_index), default_extension(default_extension), - run_state(run_state), owner(owner), params(params) { + : type(type), + title(title), + default_path(default_path), + file_type_index(file_type_index), + default_extension(default_extension), + run_state(run_state), + owner(owner), + params(params) { + if (file_types) { + this->file_types = *file_types; + } else { + this->file_types.include_all_files = true; + } } SelectFileDialog::Type type; std::wstring title; FilePath default_path; - std::wstring filter; - int filter_index; + FileTypeInfo file_types; + int file_type_index; std::wstring default_extension; RunState run_state; HWND owner; @@ -291,14 +305,15 @@ void SelectFileDialogImpl::SelectFile( Type type, const string16& title, const FilePath& default_path, - const std::wstring& filter, - int filter_index, + const FileTypeInfo* file_types, + int file_type_index, const FilePath::StringType& default_extension, - HWND owner, + gfx::NativeWindow owning_window, void* params) { ExecuteSelectParams execute_params(type, UTF16ToWide(title), default_path, - filter, filter_index, default_extension, - BeginRun(owner), owner, params); + file_types, file_type_index, + default_extension, BeginRun(owning_window), + owning_window, params); execute_params.run_state.dialog_thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this, &SelectFileDialogImpl::ExecuteSelectFile, execute_params)); @@ -316,9 +331,27 @@ void SelectFileDialogImpl::ListenerDestroyed() { void SelectFileDialogImpl::ExecuteSelectFile( const ExecuteSelectParams& params) { + std::vector<std::wstring> exts; + for (size_t i=0; i<params.file_types.extensions.size(); ++i) { + const std::vector<std::wstring>& inner_exts = + params.file_types.extensions[i]; + std::wstring ext_string; + for (size_t j=0; j<inner_exts.size(); ++j) { + if (!ext_string.empty()) + ext_string.push_back(L';'); + ext_string.push_back(L'.'); + ext_string.append(inner_exts[j]); + } + exts.push_back(ext_string); + } + std::wstring filter = win_util::FormatFilterForExtensions( + exts, + params.file_types.extension_description_overrides, + params.file_types.include_all_files); + FilePath path = params.default_path; bool success = false; - unsigned filter_index = params.filter_index; + unsigned filter_index = params.file_type_index; if (params.type == SELECT_FOLDER) { success = RunSelectFolderDialog(params.title, params.run_state.owner, @@ -326,18 +359,18 @@ void SelectFileDialogImpl::ExecuteSelectFile( } else if (params.type == SELECT_SAVEAS_FILE) { std::wstring path_as_wstring = path.ToWStringHack(); success = win_util::SaveFileAsWithFilter(params.run_state.owner, - params.default_path.ToWStringHack(), params.filter, + params.default_path.ToWStringHack(), filter, params.default_extension, false, &filter_index, &path_as_wstring); if(success) { path = FilePath::FromWStringHack(path_as_wstring); } DisableOwner(params.run_state.owner); } else if (params.type == SELECT_OPEN_FILE) { - success = RunOpenFileDialog(params.title, params.filter, + success = RunOpenFileDialog(params.title, filter, params.run_state.owner, &path); } else if (params.type == SELECT_OPEN_MULTI_FILE) { std::vector<FilePath> paths; - if (RunOpenMultiFileDialog(params.title, params.filter, + if (RunOpenMultiFileDialog(params.title, filter, params.run_state.owner, &paths)) { ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, &SelectFileDialogImpl::MultiFilesSelected, @@ -425,7 +458,7 @@ bool SelectFileDialogImpl::RunSelectFolderDialog(const std::wstring& title, HRESULT hr = shell_folder->GetDisplayNameOf(list, SHGDN_FORPARSING, &out_dir_buffer); if (SUCCEEDED(hr) && out_dir_buffer.uType == STRRET_WSTR) { - *path = FilePath::FromWStringHack(out_dir_buffer.pOleStr); + *path = FilePath(out_dir_buffer.pOleStr); CoTaskMemFree(out_dir_buffer.pOleStr); result = true; } @@ -433,7 +466,7 @@ bool SelectFileDialogImpl::RunSelectFolderDialog(const std::wstring& title, // Use old way if we don't get what we want. wchar_t old_out_dir_buffer[MAX_PATH + 1]; if (SHGetPathFromIDList(list, old_out_dir_buffer)) { - *path = FilePath::FromWStringHack(old_out_dir_buffer); + *path = FilePath(old_out_dir_buffer); result = true; } } diff --git a/chrome/browser/views/user_data_dir_dialog.cc b/chrome/browser/views/user_data_dir_dialog.cc index 958e4ce..3598950 100644 --- a/chrome/browser/views/user_data_dir_dialog.cc +++ b/chrome/browser/views/user_data_dir_dialog.cc @@ -73,7 +73,7 @@ bool UserDataDirDialog::Accept() { HWND owning_hwnd = GetAncestor(message_box_view_->GetWidget()->GetNativeView(), GA_ROOT); select_file_dialog_->SelectFile(SelectFileDialog::SELECT_FOLDER, - dialog_title, FilePath(), std::wstring(), + dialog_title, FilePath(), NULL, 0, std::wstring(), owning_hwnd, NULL); return false; } diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index 6e2b3eb..06170ed 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -928,11 +928,10 @@ IPC_BEGIN_MESSAGES(ViewHost) // Asks the browser to display the file chooser. The result is returned in a // ViewHost_RunFileChooserResponse message. - IPC_MESSAGE_ROUTED4(ViewHostMsg_RunFileChooser, + IPC_MESSAGE_ROUTED3(ViewHostMsg_RunFileChooser, bool /* multiple_files */, - std::wstring /* title */, - std::wstring /* Default file name */, - std::wstring /* filter */) + string16 /* title */, + FilePath /* Default file name */) // Notification that password forms have been seen that are candidates for // filling/submitting by the password manager diff --git a/chrome/common/temp_scaffolding_stubs.h b/chrome/common/temp_scaffolding_stubs.h index f73eb3f..69bdbbb 100644 --- a/chrome/common/temp_scaffolding_stubs.h +++ b/chrome/common/temp_scaffolding_stubs.h @@ -373,9 +373,14 @@ class SelectFileDialog : public base::RefCountedThreadSafe<SelectFileDialog> { class Listener { public: }; + struct FileTypeInfo { + std::vector<std::vector<FilePath::StringType> > extensions; + std::vector<string16> extension_description_overrides; + bool include_all_files; + }; void ListenerDestroyed() { NOTIMPLEMENTED(); } void SelectFile(Type, const string16&, const FilePath&, - const std::wstring&, int, const FilePath::StringType&, + const FileTypeInfo*, int, const FilePath::StringType&, gfx::NativeWindow, void*) { NOTIMPLEMENTED(); } static SelectFileDialog* Create(WebContents*) { NOTIMPLEMENTED(); diff --git a/chrome/common/win_util.cc b/chrome/common/win_util.cc index 62e3015..bf96cfb 100644 --- a/chrome/common/win_util.cc +++ b/chrome/common/win_util.cc @@ -219,107 +219,63 @@ static bool GetRegistryDescriptionFromExtension(const std::wstring& file_ext, return false; } -// Set up a filter for a Save/Open dialog, which will consist of 'file_ext' -// file extension, 'ext_desc' as the text description of the 'file_ext' type, -// and (optionally) the default 'All Files' view. The purpose of the filter is -// to show only files of a particular type in a Windows Save/Open dialog box. -// The resulting filter is stored in 'buffer', which is a vector since multiple -// NULLs are embedded. The filters created here are: -// 1. only files that have 'file_ext' as their extension -// 2. all files (only added if 'include_all_files' is true) -// Example: -// file_ext: ".txt" -// ext_desc: "Text Document" -// returned (in buffer): "Text Document\0*.txt\0All Files\0*.*\0\0" -// This is painful to build, as you will soon see. -static void FormatFilterForExtension(const std::wstring& file_ext, - const std::wstring& ext_desc, - bool include_all_files, - std::vector<wchar_t>* buffer) { - DCHECK(buffer); - - // Force something reasonable to appear in the dialog box if there is no - // description provided. - if (file_ext.empty() || ext_desc.empty()) - include_all_files = true; - - size_t size; - size_t offset = 0; +std::wstring FormatFilterForExtensions( + const std::vector<std::wstring>& file_ext, + const std::vector<std::wstring>& ext_desc, + bool include_all_files) { const std::wstring all_ext = L"*.*"; const std::wstring all_desc = l10n_util::GetString(IDS_SAVEAS_ALL_FILES); - // Includes 2 internal NULLs + "*". - const size_t ext_size = ext_desc.length() + file_ext.length() + 3; - // Includes 2 internal NULLs. - const size_t all_size = all_desc.length() + all_ext.length() + 2; - // Includes double terminating NULL. - const size_t buf_size = (!ext_desc.empty() ? ext_size : 0) + - (include_all_files ? all_size : 0) + 1; - buffer->resize(buf_size); - - if (!file_ext.empty() && !ext_desc.empty()) { - // Copy in the text description ("JPEG Image") + NULL. - size = ext_desc.length() + 1; - memcpy(&(*buffer)[offset], ext_desc.c_str(), size * sizeof(wchar_t)); - offset += size; - - // Copy in the file type ("*.jpg") + NULL. - const std::wstring wildcard_ext = L"*" + file_ext; - size = wildcard_ext.length() + 1; - memcpy(&(*buffer)[offset], wildcard_ext.c_str(), size * sizeof(wchar_t)); - offset += size; - } + DCHECK(file_ext.size()>=ext_desc.size()); - if (include_all_files) { - // Copy in the default description ("All Files") + NULL. - size = all_desc.length() + 1; - memcpy(&(*buffer)[offset], all_desc.c_str(), size * sizeof(wchar_t)); - offset += size; - - // Copy in the default file extension ("*.*") + NULL. - size = all_ext.length() + 1; - memcpy(&(*buffer)[offset], all_ext.c_str(), size * sizeof(wchar_t)); - offset += size; - } + std::wstring result; - (*buffer)[offset] = L'\0'; // Double NULL required. -} + for (size_t i=0; i<file_ext.size(); ++i) { + std::wstring ext = file_ext[i]; + std::wstring desc; + if (i<ext_desc.size()) + desc = ext_desc[i]; + + if (ext.empty()) { + // Force something reasonable to appear in the dialog box if there is no + // extension provided. + include_all_files = true; + continue; + } -std::wstring GetFileFilterFromPath(const std::wstring& file_name) { - std::wstring reg_description; - std::wstring file_ext = file_util::GetFileExtensionFromPath(file_name); - if (!file_ext.empty()) { - file_ext = L"." + file_ext; - GetRegistryDescriptionFromExtension(file_ext, ®_description); + if (desc.empty()) { + DCHECK(ext.find(L'.') != std::wstring::npos); + std::wstring first_extension = ext.substr(ext.find(L'.')); + size_t first_separator_index = first_extension.find(L';'); + if (first_separator_index != std::wstring::npos) + first_extension = first_extension.substr(0, first_separator_index); + GetRegistryDescriptionFromExtension(first_extension, &desc); + if (desc.empty()) + desc = L"*." + first_extension; + } + + result.append(desc.c_str(), desc.size()+1); // Append NULL too. + result.append(ext.c_str(), ext.size()+1); } - std::vector<wchar_t> filter; - FormatFilterForExtension(file_ext, reg_description, true, &filter); - return std::wstring(&filter[0], filter.size()); -} + if (include_all_files) { + result.append(all_desc.c_str(), all_desc.size()+1); + result.append(all_ext.c_str(), all_ext.size()+1); + } -std::wstring GetFileFilterFromExtensions(const std::wstring& extensions, - bool include_all_files) { - DCHECK(extensions.find(L'.') != std::wstring::npos); - std::wstring first_extension = extensions.substr(extensions.find(L'.')); - size_t first_separator_index = first_extension.find(L';'); - if (first_separator_index != std::wstring::npos) - first_extension = first_extension.substr(0, first_separator_index); - - std::wstring description; - GetRegistryDescriptionFromExtension(first_extension, &description); - if (description.empty()) - description = L"*." + first_extension; - - std::vector<wchar_t> filter; - FormatFilterForExtension(extensions, description, true, &filter); - return std::wstring(&filter[0], filter.size()); + result.append(1, '\0'); // Double NULL required. + return result; } bool SaveFileAs(HWND owner, const std::wstring& suggested_name, std::wstring* final_name) { - std::wstring filter = GetFileFilterFromPath(suggested_name); + std::wstring file_ext = file_util::GetFileExtensionFromPath(suggested_name); + file_ext.insert(L'.', 0); + std::wstring filter = FormatFilterForExtensions( + std::vector<std::wstring>(1, file_ext), + std::vector<std::wstring>(), + true); unsigned index = 1; return SaveFileAsWithFilter(owner, suggested_name, diff --git a/chrome/common/win_util.h b/chrome/common/win_util.h index 8884960..b30ef5c 100644 --- a/chrome/common/win_util.h +++ b/chrome/common/win_util.h @@ -133,14 +133,23 @@ bool OpenItemViaShellNoZoneCheck(const FilePath& full_path, // Returns 'true' on successful open, 'false' otherwise. bool OpenItemWithExternalApp(const std::wstring& full_path); -std::wstring GetFileFilterFromPath(const std::wstring& file_name); - -// Returns a file filter whose description comes from the OS for the first file -// extension in |extensions|. |extensions| is a semicolon separated list of -// extensions. Each extension is specified as '*.foo' where foo is the -// extension. -std::wstring GetFileFilterFromExtensions(const std::wstring& extensions, - bool include_all_files); +// Set up a filter for a Save/Open dialog, which will consist of |file_ext| file +// extensions (internally separated by semicolons), |ext_desc| as the text +// descriptions of the |file_ext| types (optional), and (optionally) the default +// 'All Files' view. The purpose of the filter is to show only files of a +// particular type in a Windows Save/Open dialog box. The resulting filter is +// returned. The filters created here are: +// 1. only files that have 'file_ext' as their extension +// 2. all files (only added if 'include_all_files' is true) +// Example: +// file_ext: { ".txt", ".htm;.html" } +// ext_desc: { "Text Document" } +// returned: "Text Document\0*.txt\0HTML Document\0.htm;.html\0" +// "All Files\0*.*\0\0" (in one big string) +std::wstring FormatFilterForExtensions( + const std::vector<std::wstring>& file_ext, + const std::vector<std::wstring>& ext_desc, + bool include_all_files); // Prompt the user for location to save a file. 'suggested_name' is a full path // that gives the dialog box a hint as to how to initialize itself. diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 5afb9a6..3dd7887 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -1781,9 +1781,8 @@ void RenderView::UpdateTargetURL(WebView* webview, const GURL& url) { } void RenderView::RunFileChooser(bool multi_select, - const std::wstring& title, - const std::wstring& default_filename, - const std::wstring& filter, + const string16& title, + const FilePath& default_filename, WebFileChooserCallback* file_chooser) { if (file_chooser_.get()) { // TODO(brettw): bug 1235154: This should be a synchronous message to deal @@ -1797,7 +1796,7 @@ void RenderView::RunFileChooser(bool multi_select, } file_chooser_.reset(file_chooser); Send(new ViewHostMsg_RunFileChooser(routing_id_, multi_select, title, - default_filename, filter)); + default_filename)); } void RenderView::AddMessageToConsole(WebView* webview, diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index 409b6ac..dd9b7c6 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -164,9 +164,8 @@ class RenderView : public RenderWidget, virtual void UpdateTargetURL(WebView* webview, const GURL& url); virtual void RunFileChooser(bool multi_select, - const std::wstring& title, - const std::wstring& initial_filename, - const std::wstring& filter, + const string16& title, + const FilePath& initial_filename, WebFileChooserCallback* file_chooser); virtual void AddMessageToConsole(WebView* webview, const std::wstring& message, |