From 1161d18c826c02bedb623c23dbcb7d9d54a7105f Mon Sep 17 00:00:00 2001 From: Marshall Greenblatt Date: Mon, 11 Jun 2012 19:48:55 +0000 Subject: [PATCH] Mac: Add dialogs for input type="file" (issue #632). git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@688 5089003a-bbd8-11dd-ad1f-f1f9622dbc98 --- libcef/browser/browser_host_impl.cc | 37 +++++++++- libcef/browser/browser_host_impl.h | 5 ++ libcef/browser/browser_host_impl_gtk.cc | 7 ++ libcef/browser/browser_host_impl_mac.mm | 89 ++++++++++++++++++++++++- libcef/browser/browser_host_impl_win.cc | 7 ++ 5 files changed, 141 insertions(+), 4 deletions(-) diff --git a/libcef/browser/browser_host_impl.cc b/libcef/browser/browser_host_impl.cc index 0b78d6302..209773891 100644 --- a/libcef/browser/browser_host_impl.cc +++ b/libcef/browser/browser_host_impl.cc @@ -6,6 +6,7 @@ #include "libcef/browser/browser_host_impl.h" #include +#include #include "libcef/browser/browser_context.h" #include "libcef/browser/context.h" @@ -29,6 +30,8 @@ #include "content/public/browser/notification_source.h" #include "content/public/browser/notification_types.h" #include "content/public/browser/resource_request_info.h" +#include "content/public/common/file_chooser_params.h" +#include "content/public/common/selected_file_info.h" namespace { @@ -259,7 +262,7 @@ CefRefPtr CefBrowserHostImpl::GetBrowserByChildID( content::RenderProcessHost::FromID(render_process_id); if (!render_process_host) return NULL; - + content::RenderProcessHost::RenderWidgetHostsIterator iter( render_process_host->GetRenderWidgetHostsIterator()); if (!iter.IsAtEnd()) { @@ -276,7 +279,7 @@ CefRefPtr CefBrowserHostImpl::GetBrowserByChildID( const_cast(widget))); } } - + return NULL; } else { // Use the thread-safe approach. @@ -1020,7 +1023,35 @@ content::JavaScriptDialogCreator* void CefBrowserHostImpl::RunFileChooser( content::WebContents* tab, const content::FileChooserParams& params) { - // TODO(cef): Implement this method to run the file chooser dialog. + content::RenderViewHost* render_view_host = tab->GetRenderViewHost(); + if (!render_view_host) + return; + + if (params.mode != content::FileChooserParams::Open && + params.mode != content::FileChooserParams::OpenMultiple) { + NOTREACHED() << "unsupported file chooser mode requested"; + return; + } + + std::vector fileList; + PlatformRunFileChooser(tab, params, fileList); + + const int kReadFilePermissions = + base::PLATFORM_FILE_OPEN | + base::PLATFORM_FILE_READ | + base::PLATFORM_FILE_EXCLUSIVE_READ | + base::PLATFORM_FILE_ASYNC; + + // Convert FilePath list to SelectedFileInfo list. + std::vector selected_files; + for (size_t i = 0; i < fileList.size(); ++i) { + selected_files.push_back( + content::SelectedFileInfo(fileList[i], FilePath::StringType())); + } + + // Notify our RenderViewHost in all cases. + render_view_host->FilesSelectedInChooser(selected_files, + kReadFilePermissions); } void CefBrowserHostImpl::UpdatePreferredSize(content::WebContents* source, diff --git a/libcef/browser/browser_host_impl.h b/libcef/browser/browser_host_impl.h index 0c8465abb..1d2fdf7b0 100644 --- a/libcef/browser/browser_host_impl.h +++ b/libcef/browser/browser_host_impl.h @@ -312,6 +312,11 @@ class CefBrowserHostImpl : public CefBrowserHost, // processing of shortcut keys. void PlatformHandleKeyboardEvent( const content::NativeWebKeyboardEvent& event); + // Invoke platform specific file open chooser. + void PlatformRunFileChooser( + content::WebContents* contents, + const content::FileChooserParams& params, + std::vector& files); void OnAddressChange(CefRefPtr frame, const GURL& url); diff --git a/libcef/browser/browser_host_impl_gtk.cc b/libcef/browser/browser_host_impl_gtk.cc index 965b9019e..8dec53afe 100644 --- a/libcef/browser/browser_host_impl_gtk.cc +++ b/libcef/browser/browser_host_impl_gtk.cc @@ -131,3 +131,10 @@ void CefBrowserHostImpl::PlatformHandleKeyboardEvent( const content::NativeWebKeyboardEvent& event) { // TODO(cef): Is something required here to handle shortcut keys? } + +void CefBrowserHostImpl::PlatformRunFileChooser( + content::WebContents* contents, + const content::FileChooserParams& params, + std::vector& files) { + NOTIMPLEMENTED(); +} diff --git a/libcef/browser/browser_host_impl_mac.mm b/libcef/browser/browser_host_impl_mac.mm index b652dae87..7070d6cbc 100644 --- a/libcef/browser/browser_host_impl_mac.mm +++ b/libcef/browser/browser_host_impl_mac.mm @@ -6,10 +6,18 @@ #include "libcef/browser/browser_host_impl.h" #import +#import +#include "base/file_util.h" +#include "base/mac/mac_util.h" +#include "base/string_util.h" +#include "base/sys_string_conversions.h" +#include "base/threading/thread_restrictions.h" #include "content/public/browser/native_web_keyboard_event.h" +#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_view.h" -#import "ui/base/cocoa/underlay_opengl_hosting_window.h" +#include "content/public/common/file_chooser_params.h" +#import "ui/base/cocoa/underlay_opengl_hosting_window.h" #include "ui/gfx/rect.h" @@ -50,6 +58,32 @@ @end +namespace { + +// Accept-types to file-types helper. +NSMutableArray* GetFileTypesFromAcceptTypes( + const std::vector& accept_types) { + NSMutableArray* acceptArray = [[NSMutableArray alloc] init]; + for (size_t i=0; i& files) { + NSOpenPanel* openPanel = [NSOpenPanel openPanel]; + if (!params.title.empty()) + [openPanel setTitle:base::SysUTF16ToNSString(params.title)]; + + // Consider default file name if any. + FilePath default_file_name(params.default_file_name); + + if (!default_file_name.empty()) { + if (!default_file_name.BaseName().empty()) { + NSString* defaultName = base::SysUTF8ToNSString( + default_file_name.BaseName().value()); + [openPanel setNameFieldStringValue:defaultName]; + } + + if (!default_file_name.DirName().empty()) { + NSString* defaultDir = base::SysUTF8ToNSString( + default_file_name.DirName().value()); + [openPanel setDirectoryURL:[NSURL fileURLWithPath:defaultDir]]; + } + } + + // Consider supported file types + if (!params.accept_types.empty()) { + [openPanel setAllowedFileTypes:GetFileTypesFromAcceptTypes( + params.accept_types)]; + } + + // Further panel configuration. + [openPanel setAllowsOtherFileTypes:YES]; + [openPanel setAllowsMultipleSelection: + (params.mode == content::FileChooserParams::OpenMultiple)]; + [openPanel setCanChooseFiles:YES]; + [openPanel setCanChooseDirectories:NO]; + + // Show panel. + NSView* view = contents->GetNativeView(); + [openPanel beginSheetModalForWindow:[view window] completionHandler:nil]; + if ([openPanel runModal] == NSFileHandlingPanelOKButton) { + NSArray *urls = [openPanel URLs]; + int i, count = [urls count]; + for (i=0; i& files) { + NOTIMPLEMENTED(); +}