diff options
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/chrome_plugin_host.cc | 13 | ||||
-rw-r--r-- | chrome/browser/render_view_host.cc | 23 | ||||
-rw-r--r-- | chrome/browser/render_view_host.h | 9 | ||||
-rw-r--r-- | chrome/browser/render_view_host_delegate.h | 5 | ||||
-rw-r--r-- | chrome/browser/resource_message_filter.h | 5 | ||||
-rw-r--r-- | chrome/browser/shell_dialogs.h | 8 | ||||
-rw-r--r-- | chrome/browser/views/shell_dialogs.cc | 79 | ||||
-rw-r--r-- | chrome/browser/web_contents.cc | 23 | ||||
-rw-r--r-- | chrome/browser/web_contents.h | 7 |
9 files changed, 159 insertions, 13 deletions
diff --git a/chrome/browser/chrome_plugin_host.cc b/chrome/browser/chrome_plugin_host.cc index 008a7fe..55f1dd1 100644 --- a/chrome/browser/chrome_plugin_host.cc +++ b/chrome/browser/chrome_plugin_host.cc @@ -694,6 +694,18 @@ CPError STDCALL CPB_PluginThreadAsyncCall(CPID id, return CPERR_SUCCESS; } +CPError STDCALL CPB_OpenFileDialog(CPID id, + CPBrowsingContext context, + bool multiple_files, + const char *title, + const char *filter, + void *user_data) { + NOTREACHED() << + "Open file dialog should only be called from the renderer process."; + + return CPERR_FAILURE; +} + } CPBrowserFuncs* GetCPBrowserFuncsForBrowser() { @@ -727,6 +739,7 @@ CPBrowserFuncs* GetCPBrowserFuncsForBrowser() { browser_funcs.response_funcs = &response_funcs; browser_funcs.send_sync_message = CPB_SendSyncMessage; browser_funcs.plugin_thread_async_call = CPB_PluginThreadAsyncCall; + browser_funcs.open_file_dialog = CPB_OpenFileDialog; request_funcs.size = sizeof(request_funcs); request_funcs.start_request = CPR_StartRequest; diff --git a/chrome/browser/render_view_host.cc b/chrome/browser/render_view_host.cc index 0d43757..6fa62b8 100644 --- a/chrome/browser/render_view_host.cc +++ b/chrome/browser/render_view_host.cc @@ -600,7 +600,19 @@ void RenderViewHost::InstallMissingPlugin() { void RenderViewHost::FileSelected(const std::wstring& path) { RendererSecurityPolicy::GetInstance()->GrantUploadFile(process()->host_id(), path); - Send(new ViewMsg_RunFileChooserResponse(routing_id_, path)); + std::vector<std::wstring> files; + files.push_back(path); + Send(new ViewMsg_RunFileChooserResponse(routing_id_, files)); +} + +void RenderViewHost::MultiFilesSelected( + const std::vector<std::wstring>& files) { + for (std::vector<std::wstring>::const_iterator file = files.begin(); + file != files.end(); ++file) { + RendererSecurityPolicy::GetInstance()->GrantUploadFile( + process()->host_id(), *file); + } + Send(new ViewMsg_RunFileChooserResponse(routing_id_, files)); } void RenderViewHost::LoadStateChanged(const GURL& url, @@ -1057,8 +1069,13 @@ void RenderViewHost::OnMsgSetTooltipText(const std::wstring& tooltip_text) { } } -void RenderViewHost::OnMsgRunFileChooser(const std::wstring& default_file) { - delegate_->RunFileChooser(default_file); +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); } void RenderViewHost::OnMsgRunJavaScriptMessage( diff --git a/chrome/browser/render_view_host.h b/chrome/browser/render_view_host.h index 0dec873..f95720e 100644 --- a/chrome/browser/render_view_host.h +++ b/chrome/browser/render_view_host.h @@ -365,6 +365,10 @@ class RenderViewHost : public RenderWidgetHost { // an Open File dialog for the form. void FileSelected(const std::wstring& path); + // Notifies the Listener that many files have been chosen by the user from + // an Open File dialog for the form. + void MultiFilesSelected(const std::vector<std::wstring>& files); + // Notifies the RenderViewHost that its load state changed. void LoadStateChanged(const GURL& url, net::LoadState load_state); @@ -469,7 +473,10 @@ class RenderViewHost : public RenderWidgetHost { #endif void OnMsgGoToEntryAtOffset(int offset); void OnMsgSetTooltipText(const std::wstring& tooltip_text); - void OnMsgRunFileChooser(const std::wstring& default_file); + void OnMsgRunFileChooser(bool multiple_files, + const std::wstring& title, + const std::wstring& default_file, + const std::wstring& filter); void OnMsgRunJavaScriptMessage(const std::wstring& message, const std::wstring& default_prompt, const int flags, diff --git a/chrome/browser/render_view_host_delegate.h b/chrome/browser/render_view_host_delegate.h index 91cc531..1fd0c41 100644 --- a/chrome/browser/render_view_host_delegate.h +++ b/chrome/browser/render_view_host_delegate.h @@ -259,7 +259,10 @@ class RenderViewHostDelegate { int* forward_list_count) { } // A file chooser should be shown. - virtual void RunFileChooser(const std::wstring& default_file) { } + virtual void RunFileChooser(bool multiple_files, + const std::wstring& title, + const std::wstring& default_file, + const std::wstring& filter) { } // A javascript message, confirmation or prompt should be shown. virtual void RunJavaScriptMessage(const std::wstring& message, diff --git a/chrome/browser/resource_message_filter.h b/chrome/browser/resource_message_filter.h index badf7b4..640b138 100644 --- a/chrome/browser/resource_message_filter.h +++ b/chrome/browser/resource_message_filter.h @@ -98,6 +98,11 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter, void OnPluginSyncMessage(const FilePath& plugin_path, const std::vector<uint8>& message, std::vector<uint8> *retval); + void OnPluginFileDialog(const IPC::Message& msg, + bool multiple_files, + const std::wstring& title, + const std::wstring& filter, + uint32 user_data); // Cache fonts for the renderer. See ResourceMessageFilter::OnLoadFont // implementation for more details diff --git a/chrome/browser/shell_dialogs.h b/chrome/browser/shell_dialogs.h index 183081dc..54f601c 100644 --- a/chrome/browser/shell_dialogs.h +++ b/chrome/browser/shell_dialogs.h @@ -37,7 +37,8 @@ class SelectFileDialog enum Type { SELECT_FOLDER, SELECT_SAVEAS_FILE, - SELECT_OPEN_FILE + SELECT_OPEN_FILE, + SELECT_OPEN_MULTI_FILE }; virtual ~SelectFileDialog() {} @@ -52,6 +53,11 @@ class SelectFileDialog // SelectFile. virtual void FileSelected(const std::wstring& path, void* params) = 0; + // Notifies the Listener that many files have been selected. The + // files are in |files|. |params| is contextual passed to SelectFile. + virtual void MultiFilesSelected( + const std::vector<std::wstring>& files, void* params) {}; + // Notifies the Listener that the file/folder selection was aborted (via // the user canceling or closing the selection dialog box, for example). // |params| is contextual passed to SelectFile. diff --git a/chrome/browser/views/shell_dialogs.cc b/chrome/browser/views/shell_dialogs.cc index e38d81f..ab85d0a 100644 --- a/chrome/browser/views/shell_dialogs.cc +++ b/chrome/browser/views/shell_dialogs.cc @@ -215,6 +215,10 @@ class SelectFileDialogImpl : public SelectFileDialog, // Notifies the listener that a folder was chosen. Run on the ui thread. void FileSelected(const std::wstring& path, void* params, RunState run_state); + // Notifies listener that multiple files were chosen. Run on the ui thread. + void MultiFilesSelected(const std::vector<std::wstring>& paths, void* params, + RunState run_state); + // Notifies the listener that no file was chosen (the action was canceled). // Run on the ui thread. void FileNotSelected(void* params, RunState run_state); @@ -235,6 +239,13 @@ class SelectFileDialogImpl : public SelectFileDialog, HWND owner, std::wstring* path); + // Runs an Open file dialog box that supports multi-select, with similar + // semantics for input paramaters as RunOpenFileDialog. + bool RunOpenMultiFileDialog(const std::wstring& title, + const std::wstring& filter, + HWND owner, + std::vector<std::wstring>* paths); + // The callback function for when the select folder dialog is opened. static int CALLBACK BrowseCallbackProc(HWND window, UINT message, LPARAM parameter, @@ -297,6 +308,13 @@ void SelectFileDialogImpl::ExecuteSelectFile( DisableOwner(run_state.owner); } else if (type == SELECT_OPEN_FILE) { success = RunOpenFileDialog(title, filter, run_state.owner, &path); + } else if (type == SELECT_OPEN_MULTI_FILE) { + std::vector<std::wstring> paths; + if (RunOpenMultiFileDialog(title, filter, run_state.owner, &paths)) { + ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, + &SelectFileDialogImpl::MultiFilesSelected, paths, params, run_state)); + return; + } } if (success) { @@ -316,6 +334,15 @@ void SelectFileDialogImpl::FileSelected(const std::wstring& selected_folder, EndRun(run_state); } +void SelectFileDialogImpl::MultiFilesSelected( + const std::vector<std::wstring>& selected_files, + void* params, + RunState run_state) { + if (listener_) + listener_->MultiFilesSelected(selected_files, params); + EndRun(run_state); +} + void SelectFileDialogImpl::FileNotSelected(void* params, RunState run_state) { if (listener_) listener_->FileSelectionCanceled(params); @@ -419,6 +446,58 @@ bool SelectFileDialogImpl::RunOpenFileDialog( return success; } +bool SelectFileDialogImpl::RunOpenMultiFileDialog( + const std::wstring& title, + const std::wstring& filter, + HWND owner, + std::vector<std::wstring>* paths) { + OPENFILENAME ofn; + // We must do this otherwise the ofn's FlagsEx may be initialized to random + // junk in release builds which can cause the Places Bar not to show up! + ZeroMemory(&ofn, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = owner; + + wchar_t filename[MAX_PATH] = L""; + + ofn.lpstrFile = filename; + ofn.nMaxFile = MAX_PATH; + // We use OFN_NOCHANGEDIR so that the user can rename or delete the directory + // without having to close Chrome first. + ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER + | OFN_HIDEREADONLY | OFN_ALLOWMULTISELECT; + + if (!filter.empty()) { + ofn.lpstrFilter = filter.c_str(); + } + bool success = !!GetOpenFileName(&ofn); + DisableOwner(owner); + if (success) { + std::vector<std::wstring> files; + const wchar_t* selection = ofn.lpstrFile; + while (*selection) { // Empty string indicates end of list. + files.push_back(selection); + // Skip over filename and null-terminator. + selection += files.back().length() + 1; + } + if (files.empty()) { + success = false; + } else if (files.size() == 1) { + // When there is one file, it contains the path and filename. + paths->swap(files); + } else { + // Otherwise, the first string is the path, and the remainder are + // filenames. + std::vector<std::wstring>::iterator path = files.begin(); + for (std::vector<std::wstring>::iterator file = path + 1; + file != files.end(); ++file) { + paths->push_back(*path + L'\\' + *file); + } + } + } + return success; +} + // static SelectFileDialog* SelectFileDialog::Create(Listener* listener) { return new SelectFileDialogImpl(listener); diff --git a/chrome/browser/web_contents.cc b/chrome/browser/web_contents.cc index d8c6e42..90f6491 100644 --- a/chrome/browser/web_contents.cc +++ b/chrome/browser/web_contents.cc @@ -993,12 +993,17 @@ void WebContents::GetHistoryListCount(int* back_list_count, } } -void WebContents::RunFileChooser(const std::wstring& default_file) { +void WebContents::RunFileChooser(bool multiple_files, + const std::wstring& title, + const std::wstring& default_file, + const std::wstring& filter) { HWND toplevel_hwnd = GetAncestor(GetContainerHWND(), GA_ROOT); if (!select_file_dialog_.get()) select_file_dialog_ = SelectFileDialog::Create(this); - select_file_dialog_->SelectFile(SelectFileDialog::SELECT_OPEN_FILE, - std::wstring(), default_file, std::wstring(), + 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, std::wstring(), toplevel_hwnd, NULL); } @@ -1352,10 +1357,16 @@ void WebContents::FileSelected(const std::wstring& path, void* params) { render_view_host()->FileSelected(path); } +void WebContents::MultiFilesSelected(const std::vector<std::wstring>& files, + void* params) { + render_view_host()->MultiFilesSelected(files); +} + + void WebContents::FileSelectionCanceled(void* params) { - // If the user cancels choosing a file to upload we need to pass back the - // empty string. - render_view_host()->FileSelected(std::wstring()); + // If the user cancels choosing a file to upload we pass back an + // empty vector. + render_view_host()->MultiFilesSelected(std::vector<std::wstring>()); } void WebContents::BeforeUnloadFiredFromRenderManager( diff --git a/chrome/browser/web_contents.h b/chrome/browser/web_contents.h index b7bb356..1ac6a56 100644 --- a/chrome/browser/web_contents.h +++ b/chrome/browser/web_contents.h @@ -269,7 +269,10 @@ class WebContents : public TabContents, virtual void GoToEntryAtOffset(int offset); virtual void GetHistoryListCount(int* back_list_count, int* forward_list_count); - virtual void RunFileChooser(const std::wstring& default_file); + virtual void RunFileChooser(bool multiple_files, + const std::wstring& title, + const std::wstring& default_file, + const std::wstring& filter); virtual void RunJavaScriptMessage(const std::wstring& message, const std::wstring& default_prompt, const int flags, @@ -320,6 +323,8 @@ class WebContents : public TabContents, // SelectFileDialog::Listener ------------------------------------------------ virtual void FileSelected(const std::wstring& path, void* params); + virtual void MultiFilesSelected(const std::vector<std::wstring>& files, + void* params); virtual void FileSelectionCanceled(void* params); // RenderViewHostManager::Delegate ------------------------------------------- |