- Provide default implementations of the file chooser dialogs (open, open multiple, save) on all platforms (issue #761).

- Add a new CefBrowserHost::RunFileDialog method that displays the specified file chooser dialog and returns the results asynchronously (issue #761).
- Add a new CefDialogHandler::OnFileDialog callback that allows the application to provide custom UI for file chooser dialogs (issue #761).

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@862 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt 2012-10-16 19:28:07 +00:00
parent dc5ba49aaf
commit eda69594ef
56 changed files with 2475 additions and 264 deletions

View File

@ -242,6 +242,7 @@
'tests/cefclient/client_switches.h',
'tests/unittests/command_line_unittest.cc',
'tests/unittests/cookie_unittest.cc',
'tests/unittests/dialog_unittest.cc',
'tests/unittests/dom_unittest.cc',
'tests/unittests/jsdialog_unittest.cc',
'tests/unittests/navigation_unittest.cc',
@ -744,6 +745,7 @@
'<(DEPTH)/third_party/WebKit/Source/WebKit/chromium/public',
# CEF grit resource includes
'<(grit_out_dir)',
'<(SHARED_INTERMEDIATE_DIR)/ui/ui_strings',
],
'dependencies': [
'<(DEPTH)/content/content.gyp:content_app',
@ -928,7 +930,6 @@
'<@(includes_win)',
'libcef/browser/browser_host_impl_win.cc',
'libcef/browser/browser_main_win.cc',
'libcef/browser/download_manager_delegate_win.cc',
'libcef/browser/javascript_dialog_win.cc',
'libcef/browser/menu_creator_runner_win.cc',
'libcef/browser/menu_creator_runner_win.h',
@ -951,7 +952,6 @@
'libcef/browser/application_mac.mm',
'libcef/browser/browser_host_impl_mac.mm',
'libcef/browser/browser_main_mac.mm',
'libcef/browser/download_manager_delegate_mac.mm',
'libcef/browser/javascript_dialog_mac.mm',
'libcef/browser/menu_creator_runner_mac.h',
'libcef/browser/menu_creator_runner_mac.mm',
@ -971,7 +971,6 @@
'<@(includes_linux)',
'libcef/browser/browser_host_impl_gtk.cc',
'libcef/browser/browser_main_gtk.cc',
'libcef/browser/download_manager_delegate_gtk.cc',
'libcef/browser/gtk_util_stub.cc',
'libcef/browser/javascript_dialog_gtk.cc',
'libcef/browser/menu_creator_runner_gtk.cc',

View File

@ -20,6 +20,7 @@
'include/cef_command_line.h',
'include/cef_context_menu_handler.h',
'include/cef_cookie.h',
'include/cef_dialog_handler.h',
'include/cef_display_handler.h',
'include/cef_dom.h',
'include/cef_download_handler.h',
@ -64,6 +65,7 @@
'include/capi/cef_command_line_capi.h',
'include/capi/cef_context_menu_handler_capi.h',
'include/capi/cef_cookie_capi.h',
'include/capi/cef_dialog_handler_capi.h',
'include/capi/cef_display_handler_capi.h',
'include/capi/cef_dom_capi.h',
'include/capi/cef_download_handler_capi.h',
@ -138,6 +140,8 @@
'libcef_dll/cpptoc/domnode_cpptoc.h',
'libcef_dll/ctocpp/domvisitor_ctocpp.cc',
'libcef_dll/ctocpp/domvisitor_ctocpp.h',
'libcef_dll/ctocpp/dialog_handler_ctocpp.cc',
'libcef_dll/ctocpp/dialog_handler_ctocpp.h',
'libcef_dll/cpptoc/dictionary_value_cpptoc.cc',
'libcef_dll/cpptoc/dictionary_value_cpptoc.h',
'libcef_dll/ctocpp/display_handler_ctocpp.cc',
@ -148,6 +152,8 @@
'libcef_dll/cpptoc/download_item_cpptoc.h',
'libcef_dll/cpptoc/download_item_callback_cpptoc.cc',
'libcef_dll/cpptoc/download_item_callback_cpptoc.h',
'libcef_dll/cpptoc/file_dialog_callback_cpptoc.cc',
'libcef_dll/cpptoc/file_dialog_callback_cpptoc.h',
'libcef_dll/ctocpp/focus_handler_ctocpp.cc',
'libcef_dll/ctocpp/focus_handler_ctocpp.h',
'libcef_dll/cpptoc/frame_cpptoc.cc',
@ -194,6 +200,8 @@
'libcef_dll/ctocpp/resource_handler_ctocpp.h',
'libcef_dll/cpptoc/response_cpptoc.cc',
'libcef_dll/cpptoc/response_cpptoc.h',
'libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.cc',
'libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.h',
'libcef_dll/ctocpp/scheme_handler_factory_ctocpp.cc',
'libcef_dll/ctocpp/scheme_handler_factory_ctocpp.h',
'libcef_dll/cpptoc/scheme_registrar_cpptoc.cc',
@ -276,6 +284,8 @@
'libcef_dll/ctocpp/domnode_ctocpp.h',
'libcef_dll/cpptoc/domvisitor_cpptoc.cc',
'libcef_dll/cpptoc/domvisitor_cpptoc.h',
'libcef_dll/cpptoc/dialog_handler_cpptoc.cc',
'libcef_dll/cpptoc/dialog_handler_cpptoc.h',
'libcef_dll/ctocpp/dictionary_value_ctocpp.cc',
'libcef_dll/ctocpp/dictionary_value_ctocpp.h',
'libcef_dll/cpptoc/display_handler_cpptoc.cc',
@ -286,6 +296,8 @@
'libcef_dll/ctocpp/download_item_ctocpp.h',
'libcef_dll/ctocpp/download_item_callback_ctocpp.cc',
'libcef_dll/ctocpp/download_item_callback_ctocpp.h',
'libcef_dll/ctocpp/file_dialog_callback_ctocpp.cc',
'libcef_dll/ctocpp/file_dialog_callback_ctocpp.h',
'libcef_dll/cpptoc/focus_handler_cpptoc.cc',
'libcef_dll/cpptoc/focus_handler_cpptoc.h',
'libcef_dll/ctocpp/frame_ctocpp.cc',
@ -332,6 +344,8 @@
'libcef_dll/cpptoc/resource_handler_cpptoc.h',
'libcef_dll/ctocpp/response_ctocpp.cc',
'libcef_dll/ctocpp/response_ctocpp.h',
'libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.cc',
'libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.h',
'libcef_dll/cpptoc/scheme_handler_factory_cpptoc.cc',
'libcef_dll/cpptoc/scheme_handler_factory_cpptoc.h',
'libcef_dll/ctocpp/scheme_registrar_ctocpp.cc',

View File

@ -93,6 +93,8 @@
'tests/cefclient/client_renderer.h',
'tests/cefclient/client_switches.cpp',
'tests/cefclient/client_switches.h',
'tests/cefclient/dialog_test.cpp',
'tests/cefclient/dialog_test.h',
'tests/cefclient/dom_test.cpp',
'tests/cefclient/dom_test.h',
'tests/cefclient/res/binding.html',
@ -136,6 +138,8 @@
'tests/cefclient/client_renderer.h',
'tests/cefclient/client_switches.cpp',
'tests/cefclient/client_switches.h',
'tests/cefclient/dialog_test.cpp',
'tests/cefclient/dialog_test.h',
'tests/cefclient/dom_test.cpp',
'tests/cefclient/dom_test.h',
'tests/cefclient/process_helper_mac.cpp',

View File

@ -170,6 +170,27 @@ typedef struct _cef_browser_t {
} cef_browser_t;
///
// Callback structure for cef_browser_host_t::RunFileDialog. The functions of
// this structure will be called on the browser process UI thread.
///
typedef struct _cef_run_file_dialog_callback_t {
///
// Base structure.
///
cef_base_t base;
///
// Called asynchronously after the file dialog is dismissed. If the selection
// was successful |file_paths| will be a single value or a list of values
// depending on the dialog mode. If the selection was cancelled |file_paths|
// will be NULL.
///
void (CEF_CALLBACK *cont)(struct _cef_run_file_dialog_callback_t* self,
struct _cef_browser_host_t* browser_host, cef_string_list_t file_paths);
} cef_run_file_dialog_callback_t;
///
// Structure used to represent the browser process aspects of a browser window.
// The functions of this structure can only be called in the browser process.
@ -252,6 +273,23 @@ typedef struct _cef_browser_host_t {
///
void (CEF_CALLBACK *set_zoom_level)(struct _cef_browser_host_t* self,
double zoomLevel);
///
// Call to run a file chooser dialog. Only a single file chooser dialog may be
// pending at any given time. |mode| represents the type of dialog to display.
// |title| to the title to be used for the dialog and may be NULL to show the
// default title ("Open" or "Save" depending on the mode). |default_file_name|
// is the default file name to select in the dialog. |accept_types| is a list
// of valid lower-cased MIME types or file extensions specified in an input
// element and is used to restrict selectable files to such types. |callback|
// will be executed after the dialog is dismissed or immediately if another
// dialog is already pending. The dialog will be initiated asynchronously on
// the UI thread.
///
void (CEF_CALLBACK *run_file_dialog)(struct _cef_browser_host_t* self,
enum cef_file_dialog_mode_t mode, const cef_string_t* title,
const cef_string_t* default_file_name, cef_string_list_t accept_types,
struct _cef_run_file_dialog_callback_t* callback);
} cef_browser_host_t;

View File

@ -61,6 +61,13 @@ typedef struct _cef_client_t {
struct _cef_context_menu_handler_t* (CEF_CALLBACK *get_context_menu_handler)(
struct _cef_client_t* self);
///
// Return the handler for dialogs. If no handler is provided the default
// implementation will be used.
///
struct _cef_dialog_handler_t* (CEF_CALLBACK *get_dialog_handler)(
struct _cef_client_t* self);
///
// Return the handler for browser display state events.
///

View File

@ -0,0 +1,105 @@
// Copyright (c) 2012 Marshall A. Greenblatt. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the name Chromium Embedded
// Framework nor the names of its contributors may be used to endorse
// or promote products derived from this software without specific prior
// written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool and should not edited
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
#ifndef CEF_INCLUDE_CAPI_CEF_DIALOG_HANDLER_CAPI_H_
#define CEF_INCLUDE_CAPI_CEF_DIALOG_HANDLER_CAPI_H_
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "include/capi/cef_base_capi.h"
///
// Callback structure for asynchronous continuation of file dialog requests.
///
typedef struct _cef_file_dialog_callback_t {
///
// Base structure.
///
cef_base_t base;
///
// Continue the file selection with the specified |file_paths|. This may be a
// single value or a list of values depending on the dialog mode. An NULL
// value is treated the same as calling cancel().
///
void (CEF_CALLBACK *cont)(struct _cef_file_dialog_callback_t* self,
cef_string_list_t file_paths);
///
// Cancel the file selection.
///
void (CEF_CALLBACK *cancel)(struct _cef_file_dialog_callback_t* self);
} cef_file_dialog_callback_t;
///
// Implement this structure to handle dialog events. The functions of this
// structure will be called on the browser process UI thread.
///
typedef struct _cef_dialog_handler_t {
///
// Base structure.
///
cef_base_t base;
///
// Called to run a file chooser dialog. |mode| represents the type of dialog
// to display. |title| to the title to be used for the dialog and may be NULL
// to show the default title ("Open" or "Save" depending on the mode).
// |default_file_name| is the default file name to select in the dialog.
// |accept_types| is a list of valid lower-cased MIME types or file extensions
// specified in an input element and is used to restrict selectable files to
// such types. To display a custom dialog return true (1) and execute
// |callback| either inline or at a later time. To display the default dialog
// return false (0).
///
int (CEF_CALLBACK *on_file_dialog)(struct _cef_dialog_handler_t* self,
struct _cef_browser_t* browser, enum cef_file_dialog_mode_t mode,
const cef_string_t* title, const cef_string_t* default_file_name,
cef_string_list_t accept_types,
struct _cef_file_dialog_callback_t* callback);
} cef_dialog_handler_t;
#ifdef __cplusplus
}
#endif
#endif // CEF_INCLUDE_CAPI_CEF_DIALOG_HANDLER_CAPI_H_

View File

@ -181,6 +181,26 @@ class CefBrowser : public virtual CefBase {
};
///
// Callback interface for CefBrowserHost::RunFileDialog. The methods of this
// class will be called on the browser process UI thread.
///
/*--cef(source=client)--*/
class CefRunFileDialogCallback : public virtual CefBase {
public:
///
// Called asynchronously after the file dialog is dismissed. If the selection
// was successful |file_paths| will be a single value or a list of values
// depending on the dialog mode. If the selection was cancelled |file_paths|
// will be empty.
///
/*--cef(capi_name=cont)--*/
virtual void OnFileDialogDismissed(
CefRefPtr<CefBrowserHost> browser_host,
const std::vector<CefString>& file_paths) =0;
};
///
// Class used to represent the browser process aspects of a browser window. The
// methods of this class can only be called in the browser process. They may be
@ -190,6 +210,8 @@ class CefBrowser : public virtual CefBase {
/*--cef(source=library)--*/
class CefBrowserHost : public virtual CefBase {
public:
typedef cef_file_dialog_mode_t FileDialogMode;
///
// Create a new browser window using the window parameters specified by
// |windowInfo|. All values will be copied internally and the actual window
@ -287,6 +309,26 @@ class CefBrowserHost : public virtual CefBase {
///
/*--cef()--*/
virtual void SetZoomLevel(double zoomLevel) =0;
///
// Call to run a file chooser dialog. Only a single file chooser dialog may be
// pending at any given time. |mode| represents the type of dialog to display.
// |title| to the title to be used for the dialog and may be empty to show the
// default title ("Open" or "Save" depending on the mode). |default_file_name|
// is the default file name to select in the dialog. |accept_types| is a list
// of valid lower-cased MIME types or file extensions specified in an input
// element and is used to restrict selectable files to such types. |callback|
// will be executed after the dialog is dismissed or immediately if another
// dialog is already pending. The dialog will be initiated asynchronously on
// the UI thread.
///
/*--cef(optional_param=title,optional_param=default_file_name,
optional_param=accept_types)--*/
virtual void RunFileDialog(FileDialogMode mode,
const CefString& title,
const CefString& default_file_name,
const std::vector<CefString>& accept_types,
CefRefPtr<CefRunFileDialogCallback> callback) =0;
};
#endif // CEF_INCLUDE_CEF_BROWSER_H_

View File

@ -40,6 +40,7 @@
#include "include/cef_base.h"
#include "include/cef_context_menu_handler.h"
#include "include/cef_dialog_handler.h"
#include "include/cef_display_handler.h"
#include "include/cef_download_handler.h"
#include "include/cef_focus_handler.h"
@ -66,6 +67,15 @@ class CefClient : public virtual CefBase {
return NULL;
}
///
// Return the handler for dialogs. If no handler is provided the default
// implementation will be used.
///
/*--cef()--*/
virtual CefRefPtr<CefDialogHandler> GetDialogHandler() {
return NULL;
}
///
// Return the handler for browser display state events.
///

View File

@ -0,0 +1,98 @@
// Copyright (c) 2012 Marshall A. Greenblatt. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the name Chromium Embedded
// Framework nor the names of its contributors may be used to endorse
// or promote products derived from this software without specific prior
// written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ---------------------------------------------------------------------------
//
// The contents of this file must follow a specific format in order to
// support the CEF translator tool. See the translator.README.txt file in the
// tools directory for more information.
//
#ifndef CEF_INCLUDE_CEF_DIALOG_HANDLER_H_
#define CEF_INCLUDE_CEF_DIALOG_HANDLER_H_
#pragma once
#include "include/cef_base.h"
#include "include/cef_browser.h"
///
// Callback interface for asynchronous continuation of file dialog requests.
///
/*--cef(source=library)--*/
class CefFileDialogCallback : public virtual CefBase {
public:
///
// Continue the file selection with the specified |file_paths|. This may be
// a single value or a list of values depending on the dialog mode. An empty
// value is treated the same as calling Cancel().
///
/*--cef(capi_name=cont)--*/
virtual void Continue(const std::vector<CefString>& file_paths) =0;
///
// Cancel the file selection.
///
/*--cef()--*/
virtual void Cancel() =0;
};
///
// Implement this interface to handle dialog events. The methods of this class
// will be called on the browser process UI thread.
///
/*--cef(source=client)--*/
class CefDialogHandler : public virtual CefBase {
public:
typedef cef_file_dialog_mode_t FileDialogMode;
///
// Called to run a file chooser dialog. |mode| represents the type of dialog
// to display. |title| to the title to be used for the dialog and may be empty
// to show the default title ("Open" or "Save" depending on the mode).
// |default_file_name| is the default file name to select in the dialog.
// |accept_types| is a list of valid lower-cased MIME types or file extensions
// specified in an input element and is used to restrict selectable files to
// such types. To display a custom dialog return true and execute |callback|
// either inline or at a later time. To display the default dialog return
// false.
///
/*--cef(optional_param=title,optional_param=default_file_name,
optional_param=accept_types)--*/
virtual bool OnFileDialog(CefRefPtr<CefBrowser> browser,
FileDialogMode mode,
const CefString& title,
const CefString& default_file_name,
const std::vector<CefString>& accept_types,
CefRefPtr<CefFileDialogCallback> callback) {
return false;
}
};
#endif // CEF_INCLUDE_CEF_DIALOG_HANDLER_H_

View File

@ -1300,6 +1300,26 @@ enum cef_dom_node_type_t {
DOM_NODE_TYPE_XPATH_NAMESPACE,
};
///
// Supported file dialog modes.
///
enum cef_file_dialog_mode_t {
///
// Requires that the file exists before allowing the user to pick it.
///
FILE_DIALOG_OPEN = 0,
///
// Like Open, but allows picking multiple files to open.
///
FILE_DIALOG_OPEN_MULTIPLE,
///
// Allows picking a nonexistent file, and prompts to overwrite if the file
// already exists.
///
FILE_DIALOG_SAVE,
};
#ifdef __cplusplus
}

View File

@ -102,6 +102,99 @@ bool GetCefKeyEvent(const content::NativeWebKeyboardEvent& event,
return true;
}
class CefFileDialogCallbackImpl : public CefFileDialogCallback {
public:
explicit CefFileDialogCallbackImpl(
const CefBrowserHostImpl::RunFileChooserCallback& callback)
: callback_(callback) {
}
~CefFileDialogCallbackImpl() {
if (!callback_.is_null()) {
// The callback is still pending. Cancel it now.
if (CEF_CURRENTLY_ON_UIT()) {
CancelNow(callback_);
} else {
CEF_POST_TASK(CEF_UIT,
base::Bind(&CefFileDialogCallbackImpl::CancelNow, callback_));
}
}
}
virtual void Continue(const std::vector<CefString>& file_paths) OVERRIDE {
if (CEF_CURRENTLY_ON_UIT()) {
if (!callback_.is_null()) {
std::vector<FilePath> vec;
if (!file_paths.empty()) {
std::vector<CefString>::const_iterator it = file_paths.begin();
for (; it != file_paths.end(); ++it)
vec.push_back(FilePath(*it));
}
callback_.Run(vec);
callback_.Reset();
}
} else {
CEF_POST_TASK(CEF_UIT,
base::Bind(&CefFileDialogCallbackImpl::Continue, this, file_paths));
}
}
virtual void Cancel() OVERRIDE {
if (CEF_CURRENTLY_ON_UIT()) {
if (!callback_.is_null()) {
CancelNow(callback_);
callback_.Reset();
}
} else {
CEF_POST_TASK(CEF_UIT,
base::Bind(&CefFileDialogCallbackImpl::Cancel, this));
}
}
bool IsConnected() {
return !callback_.is_null();
}
void Disconnect() {
callback_.Reset();
}
private:
static void CancelNow(
const CefBrowserHostImpl::RunFileChooserCallback& callback) {
CEF_REQUIRE_UIT();
std::vector<FilePath> file_paths;
callback.Run(file_paths);
}
CefBrowserHostImpl::RunFileChooserCallback callback_;
IMPLEMENT_REFCOUNTING(CefFileDialogCallbackImpl);
};
class CefRunFileDialogCallbackWrapper
: public base::RefCountedThreadSafe<CefRunFileDialogCallbackWrapper> {
public:
CefRunFileDialogCallbackWrapper(CefRefPtr<CefBrowserHost> host,
CefRefPtr<CefRunFileDialogCallback> callback)
: host_(host),
callback_(callback) {
}
void Callback(const std::vector<FilePath>& file_paths) {
std::vector<CefString> paths;
if (file_paths.size() > 0) {
for (size_t i = 0; i < file_paths.size(); ++i)
paths.push_back(file_paths[i].value());
}
callback_->OnFileDialogDismissed(host_, paths);
}
private:
CefRefPtr<CefBrowserHost> host_;
CefRefPtr<CefRunFileDialogCallback> callback_;
};
} // namespace
@ -356,6 +449,43 @@ void CefBrowserHostImpl::SetZoomLevel(double zoomLevel) {
}
}
void CefBrowserHostImpl::RunFileDialog(
FileDialogMode mode,
const CefString& title,
const CefString& default_file_name,
const std::vector<CefString>& accept_types,
CefRefPtr<CefRunFileDialogCallback> callback) {
DCHECK(callback.get());
if (!callback.get())
return;
content::FileChooserParams params;
switch (mode) {
case FILE_DIALOG_OPEN:
params.mode = content::FileChooserParams::Open;
break;
case FILE_DIALOG_OPEN_MULTIPLE:
params.mode = content::FileChooserParams::OpenMultiple;
break;
case FILE_DIALOG_SAVE:
params.mode = content::FileChooserParams::Save;
break;
}
params.title = title;
if (!default_file_name.empty())
params.default_file_name = FilePath(default_file_name);
if (!accept_types.empty()) {
std::vector<CefString>::const_iterator it = accept_types.begin();
for (; it != accept_types.end(); ++it)
params.accept_types.push_back(*it);
}
scoped_refptr<CefRunFileDialogCallbackWrapper> wrapper =
new CefRunFileDialogCallbackWrapper(this, callback);
RunFileChooser(params,
base::Bind(&CefRunFileDialogCallbackWrapper::Callback, wrapper));
}
// CefBrowser methods.
// -----------------------------------------------------------------------------
@ -859,6 +989,14 @@ void CefBrowserHostImpl::OnSetFocus(cef_focus_source_t source) {
}
}
void CefBrowserHostImpl::RunFileChooser(
const content::FileChooserParams& params,
const RunFileChooserCallback& callback) {
CEF_POST_TASK(CEF_UIT,
base::Bind(&CefBrowserHostImpl::RunFileChooserOnUIThread, this, params,
callback));
}
// content::WebContentsDelegate methods.
// -----------------------------------------------------------------------------
@ -1096,29 +1234,9 @@ void CefBrowserHostImpl::RunFileChooser(
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<FilePath> 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<ui::SelectedFileInfo> selected_files;
for (size_t i = 0; i < fileList.size(); ++i)
selected_files.push_back(ui::SelectedFileInfo(fileList[i], FilePath()));
// Notify our RenderViewHost in all cases.
render_view_host->FilesSelectedInChooser(selected_files,
kReadFilePermissions);
RunFileChooserOnUIThread(params,
base::Bind(&CefBrowserHostImpl::OnRunFileChooserDelegateCallback, this,
tab));
}
void CefBrowserHostImpl::UpdatePreferredSize(content::WebContents* source,
@ -1397,7 +1515,8 @@ CefBrowserHostImpl::CefBrowserHostImpl(const CefWindowInfo& window_info,
main_frame_id_(CefFrameHostImpl::kInvalidFrameId),
focused_frame_id_(CefFrameHostImpl::kInvalidFrameId),
is_in_onsetfocus_(false),
focus_on_editable_field_(false) {
focus_on_editable_field_(false),
file_chooser_pending_(false) {
web_contents_.reset(web_contents);
web_contents->SetDelegate(this);
@ -1583,3 +1702,109 @@ void CefBrowserHostImpl::OnLoadEnd(CefRefPtr<CefFrame> frame,
}
}
}
void CefBrowserHostImpl::RunFileChooserOnUIThread(
const content::FileChooserParams& params,
const RunFileChooserCallback& callback) {
CEF_REQUIRE_UIT();
if (file_chooser_pending_) {
// Dismiss the new dialog immediately.
callback.Run(std::vector<FilePath>());
return;
}
if (params.mode == content::FileChooserParams::OpenFolder) {
NOTIMPLEMENTED();
callback.Run(std::vector<FilePath>());
return;
}
file_chooser_pending_ = true;
// Ensure that the |file_chooser_pending_| flag is cleared.
const RunFileChooserCallback& host_callback =
base::Bind(&CefBrowserHostImpl::OnRunFileChooserCallback, this, callback);
bool handled = false;
if (client_.get()) {
CefRefPtr<CefDialogHandler> handler = client_->GetDialogHandler();
if (handler.get()) {
cef_file_dialog_mode_t mode;
switch (params.mode) {
case content::FileChooserParams::Open:
mode = FILE_DIALOG_OPEN;
break;
case content::FileChooserParams::OpenMultiple:
mode = FILE_DIALOG_OPEN_MULTIPLE;
break;
case content::FileChooserParams::Save:
mode = FILE_DIALOG_SAVE;
break;
default:
NOTREACHED();
break;
}
std::vector<CefString> accept_types;
std::vector<string16>::const_iterator it = params.accept_types.begin();
for (; it != params.accept_types.end(); ++it)
accept_types.push_back(*it);
CefRefPtr<CefFileDialogCallbackImpl> callbackImpl(
new CefFileDialogCallbackImpl(host_callback));
handled = handler->OnFileDialog(this, mode, params.title,
params.default_file_name.value(),
accept_types, callbackImpl.get());
if (!handled) {
if (callbackImpl->IsConnected()) {
callbackImpl->Disconnect();
} else {
// User executed the callback even though they returned false.
NOTREACHED();
handled = true;
}
}
}
}
if (!handled)
PlatformRunFileChooser(params, host_callback);
}
void CefBrowserHostImpl::OnRunFileChooserCallback(
const RunFileChooserCallback& callback,
const std::vector<FilePath>& file_paths) {
CEF_REQUIRE_UIT();
file_chooser_pending_ = false;
// Execute the callback asynchronously.
CEF_POST_TASK(CEF_UIT, base::Bind(callback, file_paths));
}
void CefBrowserHostImpl::OnRunFileChooserDelegateCallback(
content::WebContents* tab,
const std::vector<FilePath>& file_paths) {
CEF_REQUIRE_UIT();
content::RenderViewHost* render_view_host = tab->GetRenderViewHost();
if (!render_view_host)
return;
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<ui::SelectedFileInfo> selected_files;
for (size_t i = 0; i < file_paths.size(); ++i)
selected_files.push_back(ui::SelectedFileInfo(file_paths[i], FilePath()));
// Notify our RenderViewHost in all cases.
render_view_host->FilesSelectedInChooser(selected_files,
kReadFilePermissions);
}

View File

@ -107,6 +107,12 @@ class CefBrowserHostImpl : public CefBrowserHost,
virtual CefString GetDevToolsURL(bool http_scheme) OVERRIDE;
virtual double GetZoomLevel() OVERRIDE;
virtual void SetZoomLevel(double zoomLevel) OVERRIDE;
virtual void RunFileDialog(
FileDialogMode mode,
const CefString& title,
const CefString& default_file_name,
const std::vector<CefString>& accept_types,
CefRefPtr<CefRunFileDialogCallback> callback) OVERRIDE;
// CefBrowser methods.
virtual CefRefPtr<CefBrowserHost> GetHost() OVERRIDE;
@ -198,6 +204,16 @@ class CefBrowserHostImpl : public CefBrowserHost,
void OnSetFocus(cef_focus_source_t source);
// The argument vector will be empty if the dialog was cancelled.
typedef base::Callback<void(const std::vector<FilePath>&)>
RunFileChooserCallback;
// Run the file chooser dialog specified by |params|. Only a single dialog may
// be pending at any given time. |callback| will be executed asynchronously
// after the dialog is dismissed or if another dialog is already pending.
void RunFileChooser(const content::FileChooserParams& params,
const RunFileChooserCallback& callback);
private:
// content::WebContentsDelegate methods.
virtual content::WebContents* OpenURLFromTab(
@ -342,13 +358,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<FilePath>& files);
// Invoke platform specific handling for the external protocol.
void PlatformHandleExternalProtocol(const GURL& url);
// Invoke platform specific file chooser dialog.
void PlatformRunFileChooser(const content::FileChooserParams& params,
RunFileChooserCallback callback);
void OnAddressChange(CefRefPtr<CefFrame> frame,
const GURL& url);
@ -362,6 +376,19 @@ class CefBrowserHostImpl : public CefBrowserHost,
void OnLoadEnd(CefRefPtr<CefFrame> frame,
const GURL& url);
// Continuation from RunFileChooser.
void RunFileChooserOnUIThread(const content::FileChooserParams& params,
const RunFileChooserCallback& callback);
// Used with RunFileChooser to clear the |file_chooser_pending_| flag.
void OnRunFileChooserCallback(const RunFileChooserCallback& callback,
const std::vector<FilePath>& file_paths);
// Used with WebContentsDelegate::RunFileChooser to notify the WebContents.
void OnRunFileChooserDelegateCallback(
content::WebContents* tab,
const std::vector<FilePath>& file_paths);
CefWindowInfo window_info_;
CefBrowserSettings settings_;
CefRefPtr<CefClient> client_;
@ -431,6 +458,9 @@ class CefBrowserHostImpl : public CefBrowserHost,
// Used for creating and managing context menus.
scoped_ptr<CefMenuCreator> menu_creator_;
// True if a file chooser is currently pending.
bool file_chooser_pending_;
IMPLEMENT_REFCOUNTING(CefBrowserHostImpl);
DISALLOW_EVIL_CONSTRUCTORS(CefBrowserHostImpl);
};

View File

@ -10,8 +10,14 @@
#include "libcef/browser/thread_util.h"
#include "base/bind.h"
#include "base/utf_string_conversions.h"
#include "content/public/browser/web_contents_view.h"
#include "content/public/common/file_chooser_params.h"
#include "content/public/common/renderer_preferences.h"
#include "grit/cef_strings.h"
#include "grit/ui_strings.h"
#include "net/base/mime_util.h"
#include "ui/base/l10n/l10n_util.h"
namespace {
@ -25,6 +31,183 @@ void window_destroyed(GtkWidget* widget, CefBrowserHostImpl* browser) {
CEF_POST_TASK(CEF_UIT, base::Bind(DestroyBrowser, browser));
}
std::string GetDescriptionFromMimeType(const std::string& mime_type) {
// Check for wild card mime types and return an appropriate description.
static const struct {
const char* mime_type;
int string_id;
} kWildCardMimeTypes[] = {
{ "audio", IDS_APP_AUDIO_FILES },
{ "image", IDS_APP_IMAGE_FILES },
{ "text", IDS_APP_TEXT_FILES },
{ "video", IDS_APP_VIDEO_FILES },
};
for (size_t i = 0;
i < sizeof(kWildCardMimeTypes) / sizeof(kWildCardMimeTypes[0]); ++i) {
if (mime_type == std::string(kWildCardMimeTypes[i].mime_type) + "/*")
return l10n_util::GetStringUTF8(kWildCardMimeTypes[i].string_id);
}
return std::string();
}
void AddFiltersForAcceptTypes(GtkFileChooser* chooser,
const std::vector<string16>& accept_types,
bool include_all_files) {
bool has_filter = false;
for (size_t i = 0; i < accept_types.size(); ++i) {
std::string ascii_type = UTF16ToASCII(accept_types[i]);
if (ascii_type.length()) {
// Just treat as extension if contains '.' as the first character.
if (ascii_type[0] == '.') {
GtkFileFilter* filter = gtk_file_filter_new();
std::string pattern = "*" + ascii_type;
gtk_file_filter_add_pattern(filter, pattern.c_str());
gtk_file_filter_set_name(filter, pattern.c_str());
gtk_file_chooser_add_filter(chooser, filter);
if (!has_filter)
has_filter = true;
} else {
// Otherwise convert mime type to one or more extensions.
GtkFileFilter* filter = NULL;
std::string description = GetDescriptionFromMimeType(ascii_type);
bool description_from_ext = description.empty();
std::vector<FilePath::StringType> ext;
net::GetExtensionsForMimeType(ascii_type, &ext);
for (size_t x = 0; x < ext.size(); ++x) {
if (!filter)
filter = gtk_file_filter_new();
std::string pattern = "*." + ext[x];
gtk_file_filter_add_pattern(filter, pattern.c_str());
if (description_from_ext) {
if (x != 0)
description += ";";
description += pattern;
}
}
if (filter) {
gtk_file_filter_set_name(filter, description.c_str());
gtk_file_chooser_add_filter(chooser, filter);
if (!has_filter)
has_filter = true;
}
}
}
}
// Add the *.* filter, but only if we have added other filters (otherwise it
// is implied).
if (include_all_files && has_filter) {
GtkFileFilter* filter = gtk_file_filter_new();
gtk_file_filter_add_pattern(filter, "*");
gtk_file_filter_set_name(filter,
l10n_util::GetStringUTF8(IDS_SAVEAS_ALL_FILES).c_str());
gtk_file_chooser_add_filter(chooser, filter);
}
}
bool RunFileDialog(const content::FileChooserParams& params,
CefWindowHandle widget,
std::vector<FilePath>* files) {
GtkFileChooserAction action;
const gchar* accept_button;
if (params.mode == content::FileChooserParams::Open ||
params.mode == content::FileChooserParams::OpenMultiple) {
action = GTK_FILE_CHOOSER_ACTION_OPEN;
accept_button = GTK_STOCK_OPEN;
} else if (params.mode == content::FileChooserParams::Save) {
action = GTK_FILE_CHOOSER_ACTION_SAVE;
accept_button = GTK_STOCK_SAVE;
} else {
NOTREACHED();
return false;
}
// Consider default file name if any.
FilePath default_file_name(params.default_file_name);
std::string base_name;
if (!default_file_name.empty())
base_name = default_file_name.BaseName().value();
std::string title;
if (!params.title.empty()) {
title = UTF16ToUTF8(params.title);
} else {
int string_id = 0;
switch (params.mode) {
case content::FileChooserParams::Open:
string_id = IDS_OPEN_FILE_DIALOG_TITLE;
break;
case content::FileChooserParams::OpenMultiple:
string_id = IDS_OPEN_FILES_DIALOG_TITLE;
break;
case content::FileChooserParams::Save:
string_id = IDS_SAVE_AS_DIALOG_TITLE;
break;
default:
break;
}
title = l10n_util::GetStringUTF8(string_id);
}
GtkWidget* window = gtk_widget_get_toplevel(GTK_WIDGET(widget));
GtkWidget* dialog = gtk_file_chooser_dialog_new(
title.c_str(),
GTK_WINDOW(window),
action,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
accept_button, GTK_RESPONSE_ACCEPT,
NULL);
if (params.mode == content::FileChooserParams::OpenMultiple) {
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE);
} else if (params.mode == content::FileChooserParams::Save) {
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog),
TRUE);
}
if (params.mode == content::FileChooserParams::Save && !base_name.empty()) {
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog),
base_name.c_str());
}
AddFiltersForAcceptTypes(GTK_FILE_CHOOSER(dialog), params.accept_types, true);
bool success = false;
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
if (params.mode == content::FileChooserParams::Open ||
params.mode == content::FileChooserParams::Save) {
char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
files->push_back(FilePath(filename));
success = true;
} else if (params.mode == content::FileChooserParams::OpenMultiple) {
GSList* filenames =
gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog));
if (filenames) {
for (GSList* iter = filenames; iter != NULL;
iter = g_slist_next(iter)) {
FilePath path(static_cast<char*>(iter->data));
g_free(iter->data);
files->push_back(path);
}
g_slist_free(filenames);
success = true;
}
}
}
gtk_widget_destroy(dialog);
return success;
}
} // namespace
bool CefBrowserHostImpl::PlatformCreateWindow() {
@ -133,10 +316,19 @@ void CefBrowserHostImpl::PlatformHandleKeyboardEvent(
}
void CefBrowserHostImpl::PlatformRunFileChooser(
content::WebContents* contents,
const content::FileChooserParams& params,
std::vector<FilePath>& files) {
NOTIMPLEMENTED();
RunFileChooserCallback callback) {
std::vector<FilePath> files;
if (params.mode == content::FileChooserParams::Open ||
params.mode == content::FileChooserParams::OpenMultiple ||
params.mode == content::FileChooserParams::Save) {
::RunFileDialog(params, PlatformGetWindowHandle(), &files);
} else {
NOTIMPLEMENTED();
}
callback.Run(files);
}
void CefBrowserHostImpl::PlatformHandleExternalProtocol(const GURL& url) {

View File

@ -17,7 +17,10 @@
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"
#include "content/public/common/file_chooser_params.h"
#include "grit/ui_strings.h"
#include "net/base/mime_util.h"
#import "ui/base/cocoa/underlay_opengl_hosting_window.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/rect.h"
@ -76,20 +79,129 @@ NSMutableArray* GetFileTypesFromAcceptTypes(
if (ascii_type.length()) {
// Just treat as extension if contains '.' as the first character.
if (ascii_type[0] == '.') {
[acceptArray addObject:base::SysUTF8ToNSString(ascii_type)];
[acceptArray addObject:base::SysUTF8ToNSString(ascii_type.substr(1))];
} else {
// Otherwise convert mime to UTI.
NSString* mimeType = base::SysUTF8ToNSString(ascii_type);
NSString* UTI = [NSMakeCollectable(
UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType,
(CFStringRef) mimeType, NULL)) autorelease];
[acceptArray addObject:UTI];
// Otherwise convert mime type to one or more extensions.
std::vector<FilePath::StringType> ext;
net::GetExtensionsForMimeType(ascii_type, &ext);
for (size_t x = 0; x < ext.size(); ++x)
[acceptArray addObject:base::SysUTF8ToNSString(ext[x])];
}
}
}
return acceptArray;
}
void RunOpenFileDialog(const content::FileChooserParams& params,
NSView* view,
std::vector<FilePath>* files) {
NSOpenPanel* openPanel = [NSOpenPanel openPanel];
string16 title;
if (!params.title.empty()) {
title = params.title;
} else {
title = l10n_util::GetStringUTF16(
params.mode == content::FileChooserParams::Open ?
IDS_OPEN_FILE_DIALOG_TITLE : IDS_OPEN_FILES_DIALOG_TITLE);
}
[openPanel setTitle:base::SysUTF16ToNSString(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.
[openPanel beginSheetModalForWindow:[view window] completionHandler:nil];
if ([openPanel runModal] == NSFileHandlingPanelOKButton) {
NSArray *urls = [openPanel URLs];
int i, count = [urls count];
for (i=0; i<count; i++) {
NSURL* url = [urls objectAtIndex:i];
if ([url isFileURL])
files->push_back(FilePath(base::SysNSStringToUTF8([url path])));
}
}
[NSApp endSheet:openPanel];
}
bool RunSaveFileDialog(const content::FileChooserParams& params,
NSView* view,
FilePath* file) {
NSSavePanel* savePanel = [NSSavePanel savePanel];
string16 title;
if (!params.title.empty())
title = params.title;
else
title = l10n_util::GetStringUTF16(IDS_SAVE_AS_DIALOG_TITLE);
[savePanel setTitle:base::SysUTF16ToNSString(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());
[savePanel setNameFieldStringValue:defaultName];
}
if (!default_file_name.DirName().empty()) {
NSString* defaultDir = base::SysUTF8ToNSString(
default_file_name.DirName().value());
[savePanel setDirectoryURL:[NSURL fileURLWithPath:defaultDir]];
}
}
// Consider supported file types
if (!params.accept_types.empty()) {
[savePanel setAllowedFileTypes:GetFileTypesFromAcceptTypes(
params.accept_types)];
}
[savePanel setAllowsOtherFileTypes:YES];
bool success = false;
[savePanel beginSheetModalForWindow:[view window] completionHandler:nil];
if ([savePanel runModal] == NSFileHandlingPanelOKButton) {
NSURL * url = [savePanel URL];
NSString* path = [url path];
*file = FilePath([path UTF8String]);
success = true;
}
[NSApp endSheet:savePanel];
return success;
}
} // namespace
bool CefBrowserHostImpl::PlatformViewText(const std::string& text) {
@ -186,56 +298,22 @@ void CefBrowserHostImpl::PlatformHandleKeyboardEvent(
}
void CefBrowserHostImpl::PlatformRunFileChooser(
content::WebContents* contents,
const content::FileChooserParams& params,
std::vector<FilePath>& files) {
NSOpenPanel* openPanel = [NSOpenPanel openPanel];
if (!params.title.empty())
[openPanel setTitle:base::SysUTF16ToNSString(params.title)];
RunFileChooserCallback callback) {
std::vector<FilePath> files;
// 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]];
}
if (params.mode == content::FileChooserParams::Open ||
params.mode == content::FileChooserParams::OpenMultiple) {
RunOpenFileDialog(params, PlatformGetWindowHandle(), &files);
} else if (params.mode == content::FileChooserParams::Save) {
FilePath file;
if (RunSaveFileDialog(params, PlatformGetWindowHandle(), &file))
files.push_back(file);
} else {
NOTIMPLEMENTED();
}
// 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<count; i++) {
NSURL* url = [urls objectAtIndex:i];
if ([url isFileURL])
files.push_back(FilePath(base::SysNSStringToUTF8([url path])));
}
}
[NSApp endSheet:openPanel];
callback.Run(files);
}
void CefBrowserHostImpl::PlatformHandleExternalProtocol(const GURL& url) {

View File

@ -13,6 +13,7 @@
#include "libcef/browser/thread_util.h"
#include "base/i18n/case_conversion.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "base/win/registry.h"
@ -20,6 +21,10 @@
#include "content/public/browser/native_web_keyboard_event.h"
#include "content/public/browser/web_contents_view.h"
#include "content/public/common/file_chooser_params.h"
#include "grit/cef_strings.h"
#include "grit/ui_strings.h"
#include "net/base/mime_util.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/win/hwnd_util.h"
#pragma comment(lib, "dwmapi.lib")
@ -52,10 +57,171 @@ void WriteTextToFile(const std::string& data, const std::wstring& file_path) {
fclose(fp);
}
// From ui/base/dialogs/select_file_dialog_win.cc.
// Get the file type description from the registry. This will be "Text Document"
// for .txt files, "JPEG Image" for .jpg files, etc. If the registry doesn't
// have an entry for the file type, we return false, true if the description was
// found. 'file_ext' must be in form ".txt".
static bool GetRegistryDescriptionFromExtension(const std::wstring& file_ext,
std::wstring* reg_description) {
DCHECK(reg_description);
base::win::RegKey reg_ext(HKEY_CLASSES_ROOT, file_ext.c_str(), KEY_READ);
std::wstring reg_app;
if (reg_ext.ReadValue(NULL, &reg_app) == ERROR_SUCCESS && !reg_app.empty()) {
base::win::RegKey reg_link(HKEY_CLASSES_ROOT, reg_app.c_str(), KEY_READ);
if (reg_link.ReadValue(NULL, reg_description) == ERROR_SUCCESS)
return true;
}
return false;
}
// 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)
// If a description is not provided for a file extension, it will be retrieved
// from the registry. If the file extension does not exist in the registry, it
// will be omitted from the filter, as it is likely a bogus extension.
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::GetStringUTF16(IDS_APP_SAVEAS_ALL_FILES) +
L" (" + all_ext + L")";
DCHECK(file_ext.size() >= ext_desc.size());
if (file_ext.empty())
include_all_files = true;
std::wstring result;
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;
}
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);
// Find the extension name without the preceeding '.' character.
std::wstring ext_name = first_extension;
size_t ext_index = ext_name.find_first_not_of(L'.');
if (ext_index != std::wstring::npos)
ext_name = ext_name.substr(ext_index);
if (!GetRegistryDescriptionFromExtension(first_extension, &desc)) {
// The extension doesn't exist in the registry. Create a description
// based on the unknown extension type (i.e. if the extension is .qqq,
// the we create a description "QQQ File (.qqq)").
include_all_files = true;
desc = l10n_util::GetStringFUTF16(
IDS_APP_SAVEAS_EXTENSION_FORMAT,
base::i18n::ToUpper(WideToUTF16(ext_name)),
ext_name);
}
}
if (!desc.empty())
desc += L" (" + ext + L")";
else
desc = ext;
result.append(desc.c_str(), desc.size() + 1); // Append NULL too.
result.append(ext.c_str(), ext.size() + 1);
}
if (include_all_files) {
result.append(all_desc.c_str(), all_desc.size() + 1);
result.append(all_ext.c_str(), all_ext.size() + 1);
}
result.append(1, '\0'); // Double NULL required.
return result;
}
std::wstring GetDescriptionFromMimeType(const std::string& mime_type) {
// Check for wild card mime types and return an appropriate description.
static const struct {
const char* mime_type;
int string_id;
} kWildCardMimeTypes[] = {
{ "audio", IDS_APP_AUDIO_FILES },
{ "image", IDS_APP_IMAGE_FILES },
{ "text", IDS_APP_TEXT_FILES },
{ "video", IDS_APP_VIDEO_FILES },
};
for (size_t i = 0; i < arraysize(kWildCardMimeTypes); ++i) {
if (mime_type == std::string(kWildCardMimeTypes[i].mime_type) + "/*")
return l10n_util::GetStringUTF16(kWildCardMimeTypes[i].string_id);
}
return std::wstring();
}
std::wstring GetFilterStringFromAcceptTypes(
const std::vector<string16>& accept_types) {
std::vector<std::wstring> extensions;
std::vector<std::wstring> descriptions;
for (size_t i = 0; i < accept_types.size(); ++i) {
std::string ascii_type = UTF16ToASCII(accept_types[i]);
if (ascii_type.length()) {
// Just treat as extension if contains '.' as the first character.
if (ascii_type[0] == '.') {
extensions.push_back(L"*" + ASCIIToWide(ascii_type));
descriptions.push_back(std::wstring());
} else {
// Otherwise convert mime type to one or more extensions.
std::vector<FilePath::StringType> ext;
std::wstring ext_str;
net::GetExtensionsForMimeType(ascii_type, &ext);
if (ext.size() > 0) {
for (size_t x = 0; x < ext.size(); ++x) {
if (x != 0)
ext_str += L";";
ext_str += L"*." + ext[x];
}
extensions.push_back(ext_str);
descriptions.push_back(GetDescriptionFromMimeType(ascii_type));
}
}
}
}
return FormatFilterForExtensions(extensions, descriptions, true);
}
// from chrome/browser/views/shell_dialogs_win.cc
bool RunOpenFileDialog(const std::wstring& filter, HWND owner, FilePath* path) {
bool RunOpenFileDialog(const content::FileChooserParams& params,
HWND owner,
FilePath* path) {
OPENFILENAME ofn;
// We must do this otherwise the ofn's FlagsEx may be initialized to random
@ -64,26 +230,48 @@ bool RunOpenFileDialog(const std::wstring& filter, HWND owner, FilePath* path) {
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = owner;
wchar_t filename[MAX_PATH];
base::wcslcpy(filename, path->value().c_str(), arraysize(filename));
// Consider default file name if any.
FilePath default_file_name(params.default_file_name);
wchar_t filename[MAX_PATH] = {0};
ofn.lpstrFile = filename;
ofn.nMaxFile = MAX_PATH;
std::wstring directory;
if (!default_file_name.empty()) {
base::wcslcpy(filename, default_file_name.value().c_str(),
arraysize(filename));
directory = default_file_name.DirName().value();
ofn.lpstrInitialDir = directory.c_str();
}
std::wstring title;
if (!params.title.empty())
title = params.title;
else
title = l10n_util::GetStringUTF16(IDS_OPEN_FILE_DIALOG_TITLE);
if (!title.empty())
ofn.lpstrTitle = title.c_str();
// We use OFN_NOCHANGEDIR so that the user can rename or delete the directory
// without having to close Chrome first.
ofn.Flags = OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
ofn.Flags = OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR | OFN_EXPLORER |
OFN_ENABLESIZING;
if (!filter.empty()) {
std::wstring filter = GetFilterStringFromAcceptTypes(params.accept_types);
if (!filter.empty())
ofn.lpstrFilter = filter.c_str();
}
bool success = !!GetOpenFileName(&ofn);
if (success)
*path = FilePath(filename);
return success;
}
bool RunOpenMultiFileDialog(const std::wstring& filter, HWND owner,
bool RunOpenMultiFileDialog(const content::FileChooserParams& params,
HWND owner,
std::vector<FilePath>* paths) {
OPENFILENAME ofn;
@ -99,14 +287,23 @@ bool RunOpenMultiFileDialog(const std::wstring& filter, HWND owner,
ofn.lpstrFile = filename.get();
ofn.nMaxFile = UNICODE_STRING_MAX_CHARS;
std::wstring title;
if (!params.title.empty())
title = params.title;
else
title = l10n_util::GetStringUTF16(IDS_OPEN_FILES_DIALOG_TITLE);
if (!title.empty())
ofn.lpstrTitle = title.c_str();
// 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;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER |
OFN_HIDEREADONLY | OFN_ALLOWMULTISELECT | OFN_ENABLESIZING;
if (!filter.empty()) {
std::wstring filter = GetFilterStringFromAcceptTypes(params.accept_types);
if (!filter.empty())
ofn.lpstrFilter = filter.c_str();
}
bool success = !!GetOpenFileName(&ofn);
if (success) {
@ -135,6 +332,57 @@ bool RunOpenMultiFileDialog(const std::wstring& filter, HWND owner,
return success;
}
bool RunSaveFileDialog(const content::FileChooserParams& params,
HWND owner,
FilePath* path) {
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;
// Consider default file name if any.
FilePath default_file_name(params.default_file_name);
wchar_t filename[MAX_PATH] = {0};
ofn.lpstrFile = filename;
ofn.nMaxFile = MAX_PATH;
std::wstring directory;
if (!default_file_name.empty()) {
base::wcslcpy(filename, default_file_name.value().c_str(),
arraysize(filename));
directory = default_file_name.DirName().value();
ofn.lpstrInitialDir = directory.c_str();
}
std::wstring title;
if (!params.title.empty())
title = params.title;
else
title = l10n_util::GetStringUTF16(IDS_SAVE_AS_DIALOG_TITLE);
if (!title.empty())
ofn.lpstrTitle = title.c_str();
// We use OFN_NOCHANGEDIR so that the user can rename or delete the directory
// without having to close Chrome first.
ofn.Flags = OFN_OVERWRITEPROMPT | OFN_EXPLORER | OFN_ENABLESIZING |
OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST;
std::wstring filter = GetFilterStringFromAcceptTypes(params.accept_types);
if (!filter.empty())
ofn.lpstrFilter = filter.c_str();
bool success = !!GetSaveFileName(&ofn);
if (success)
*path = FilePath(filename);
return success;
}
// According to Mozilla in uriloader/exthandler/win/nsOSHelperAppService.cpp:
// "Some versions of windows (Win2k before SP3, Win XP before SP1) crash in
@ -374,16 +622,25 @@ void CefBrowserHostImpl::PlatformHandleKeyboardEvent(
}
void CefBrowserHostImpl::PlatformRunFileChooser(
content::WebContents* contents,
const content::FileChooserParams& params,
std::vector<FilePath>& files) {
if (params.mode == content::FileChooserParams::OpenMultiple) {
RunOpenMultiFileDialog(L"", PlatformGetWindowHandle(), &files);
RunFileChooserCallback callback) {
std::vector<FilePath> files;
if (params.mode == content::FileChooserParams::Open) {
FilePath file;
if (RunOpenFileDialog(params, PlatformGetWindowHandle(), &file))
files.push_back(file);
} else if (params.mode == content::FileChooserParams::OpenMultiple) {
RunOpenMultiFileDialog(params, PlatformGetWindowHandle(), &files);
} else if (params.mode == content::FileChooserParams::Save) {
FilePath file;
if (RunSaveFileDialog(params, PlatformGetWindowHandle(), &file))
files.push_back(file);
} else {
FilePath file_name;
if (RunOpenFileDialog(L"", PlatformGetWindowHandle(), &file_name))
files.push_back(file_name);
NOTIMPLEMENTED();
}
callback.Run(files);
}
void CefBrowserHostImpl::PlatformHandleExternalProtocol(const GURL& url) {

View File

@ -20,6 +20,7 @@
#include "content/public/browser/browser_context.h"
#include "content/public/browser/download_manager.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/file_chooser_params.h"
#include "net/base/net_util.h"
using content::DownloadItem;
@ -135,23 +136,54 @@ class CefBeforeDownloadCallbackImpl : public CefBeforeDownloadCallback {
if (!item || !item->IsInProgress())
return;
FilePath result;
bool handled = false;
if (show_dialog) {
#if defined(OS_WIN) || defined(OS_MACOSX) || defined(TOOLKIT_GTK)
WebContents* web_contents = item->GetWebContents();
result = CefDownloadManagerDelegate::PlatformChooseDownloadPath(
web_contents, suggested_path);
#else
NOTIMPLEMENTED();
#endif
} else {
result = suggested_path;
CefRefPtr<CefBrowserHostImpl> browser =
CefBrowserHostImpl::GetBrowserForContents(web_contents);
if (browser.get()) {
handled = true;
content::FileChooserParams params;
params.mode = content::FileChooserParams::Save;
if (!suggested_path.empty()) {
params.default_file_name = suggested_path;
if (!suggested_path.Extension().empty()) {
params.accept_types.push_back(
CefString(suggested_path.Extension()));
}
}
browser->RunFileChooser(params,
base::Bind(
&CefBeforeDownloadCallbackImpl::ChooseDownloadPathCallback,
callback));
}
}
callback.Run(result,
if (!handled) {
callback.Run(suggested_path,
DownloadItem::TARGET_DISPOSITION_OVERWRITE,
content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
suggested_path);
}
}
static void ChooseDownloadPathCallback(
const content::DownloadTargetCallback& callback,
const std::vector<FilePath>& file_paths) {
DCHECK_LE(file_paths.size(), (size_t) 1);
FilePath path;
if (file_paths.size() > 0)
path = file_paths.front();
// The download will be cancelled if |path| is empty.
callback.Run(path,
DownloadItem::TARGET_DISPOSITION_OVERWRITE,
content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
result);
path);
}
int32 download_id_;

View File

@ -31,9 +31,6 @@ class CefDownloadManagerDelegate
virtual void UpdateItemInPersistentStore(
content::DownloadItem* item) OVERRIDE;
static FilePath PlatformChooseDownloadPath(content::WebContents* web_contents,
const FilePath& suggested_path);
private:
friend class base::RefCountedThreadSafe<CefDownloadManagerDelegate>;

View File

@ -1,43 +0,0 @@
// Copyright (c) 2012 The Chromium Embedded Framework Authors.
// Portions copyright (c) 2011 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 "libcef/browser/download_manager_delegate.h"
#include <gtk/gtk.h>
#include "base/string_util.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"
// static
FilePath CefDownloadManagerDelegate::PlatformChooseDownloadPath(
content::WebContents* web_contents,
const FilePath& suggested_path) {
FilePath result;
gfx::NativeWindow parent_window =
web_contents->GetView()->GetTopLevelNativeWindow();
std::string base_name = suggested_path.BaseName().value();
GtkWidget* dialog = gtk_file_chooser_dialog_new(
"Save File",
parent_window,
GTK_FILE_CHOOSER_ACTION_SAVE,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
NULL);
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog),
TRUE);
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog),
base_name.c_str());
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
char *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
result = FilePath(filename);
}
gtk_widget_destroy(dialog);
return result;
}

View File

@ -1,42 +0,0 @@
// Copyright (c) 2012 The Chromium Embedded Framework Authors.
// Portions copyright (c) 2011 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 "libcef/browser/download_manager_delegate.h"
#import <Cocoa/Cocoa.h>
#include "base/sys_string_conversions.h"
#include "content/public/browser/web_contents.h"
// static
FilePath CefDownloadManagerDelegate::PlatformChooseDownloadPath(
content::WebContents* web_contents,
const FilePath& suggested_path) {
FilePath result;
NSSavePanel* savePanel = [NSSavePanel savePanel];
if (!suggested_path.BaseName().empty()) {
NSString* defaultName = base::SysUTF8ToNSString(
suggested_path.BaseName().value());
[savePanel setNameFieldStringValue:defaultName];
}
if (!suggested_path.DirName().empty()) {
NSString* defaultDir = base::SysUTF8ToNSString(
suggested_path.DirName().value());
[savePanel setDirectoryURL:[NSURL fileURLWithPath:defaultDir]];
}
NSView* view = web_contents->GetNativeView();
[savePanel beginSheetModalForWindow:[view window] completionHandler:nil];
if ([savePanel runModal] == NSFileHandlingPanelOKButton) {
NSURL * url = [savePanel URL];
NSString* path = [url path];
result = FilePath([path UTF8String]);
}
[NSApp endSheet:savePanel];
return result;
}

View File

@ -1,42 +0,0 @@
// Copyright (c) 2012 The Chromium Embedded Framework Authors.
// Portions copyright (c) 2011 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 "libcef/browser/download_manager_delegate.h"
#include <commdlg.h>
#include <windows.h>
#include "base/string_util.h"
#include "content/public/browser/web_contents.h"
// static
FilePath CefDownloadManagerDelegate::PlatformChooseDownloadPath(
content::WebContents* web_contents,
const FilePath& suggested_path) {
FilePath result;
std::wstring file_part = FilePath(suggested_path).BaseName().value();
wchar_t file_name[MAX_PATH];
base::wcslcpy(file_name, file_part.c_str(), arraysize(file_name));
OPENFILENAME save_as;
ZeroMemory(&save_as, sizeof(save_as));
save_as.lStructSize = sizeof(OPENFILENAME);
save_as.hwndOwner = web_contents->GetNativeView();
save_as.lpstrFile = file_name;
save_as.nMaxFile = arraysize(file_name);
std::wstring directory;
if (!suggested_path.empty())
directory = suggested_path.DirName().value();
save_as.lpstrInitialDir = directory.c_str();
save_as.Flags = OFN_OVERWRITEPROMPT | OFN_EXPLORER | OFN_ENABLESIZING |
OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST;
if (GetSaveFileName(&save_as))
result = FilePath(std::wstring(save_as.lpstrFile));
return result;
}

View File

@ -162,6 +162,18 @@ need to be translated for each locale.-->
<message name="IDS_MENU_VIEW_SOURCE" desc="The text label for the View Source... menu item.">
View Source...
</message>
<message name="IDS_APP_AUDIO_FILES" desc="The text label for the Audio Files filter in file open/save dialogs.">
Audio Files
</message>
<message name="IDS_APP_IMAGE_FILES" desc="The text label for the Image Files filter in file open/save dialogs.">
Image Files
</message>
<message name="IDS_APP_TEXT_FILES" desc="The text label for the Text Files filter in file open/save dialogs.">
Text Files
</message>
<message name="IDS_APP_VIDEO_FILES" desc="The text label for the Video Files filter in file open/save dialogs.">
Video Files
</message>
</messages>
</release>
</grit>

View File

@ -13,6 +13,8 @@
#include "libcef_dll/cpptoc/browser_cpptoc.h"
#include "libcef_dll/cpptoc/browser_host_cpptoc.h"
#include "libcef_dll/ctocpp/client_ctocpp.h"
#include "libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.h"
#include "libcef_dll/transfer_util.h"
// GLOBAL FUNCTIONS - Body may be edited by hand.
@ -240,6 +242,34 @@ void CEF_CALLBACK browser_host_set_zoom_level(struct _cef_browser_host_t* self,
zoomLevel);
}
void CEF_CALLBACK browser_host_run_file_dialog(struct _cef_browser_host_t* self,
enum cef_file_dialog_mode_t mode, const cef_string_t* title,
const cef_string_t* default_file_name, cef_string_list_t accept_types,
cef_run_file_dialog_callback_t* callback) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Verify param: callback; type: refptr_diff
DCHECK(callback);
if (!callback)
return;
// Unverified params: title, default_file_name, accept_types
// Translate param: accept_types; type: string_vec_byref_const
std::vector<CefString> accept_typesList;
transfer_string_list_contents(accept_types, accept_typesList);
// Execute
CefBrowserHostCppToC::Get(self)->RunFileDialog(
mode,
CefString(title),
CefString(default_file_name),
accept_typesList,
CefRunFileDialogCallbackCToCpp::Wrap(callback));
}
// CONSTRUCTOR - Do not edit by hand.
@ -257,6 +287,7 @@ CefBrowserHostCppToC::CefBrowserHostCppToC(CefBrowserHost* cls)
struct_.struct_.get_dev_tools_url = browser_host_get_dev_tools_url;
struct_.struct_.get_zoom_level = browser_host_get_zoom_level;
struct_.struct_.set_zoom_level = browser_host_set_zoom_level;
struct_.struct_.run_file_dialog = browser_host_run_file_dialog;
}
#ifndef NDEBUG

View File

@ -12,6 +12,7 @@
#include "libcef_dll/cpptoc/client_cpptoc.h"
#include "libcef_dll/cpptoc/context_menu_handler_cpptoc.h"
#include "libcef_dll/cpptoc/dialog_handler_cpptoc.h"
#include "libcef_dll/cpptoc/display_handler_cpptoc.h"
#include "libcef_dll/cpptoc/download_handler_cpptoc.h"
#include "libcef_dll/cpptoc/focus_handler_cpptoc.h"
@ -43,6 +44,22 @@ struct _cef_context_menu_handler_t* CEF_CALLBACK client_get_context_menu_handler
return CefContextMenuHandlerCppToC::Wrap(_retval);
}
struct _cef_dialog_handler_t* CEF_CALLBACK client_get_dialog_handler(
struct _cef_client_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return NULL;
// Execute
CefRefPtr<CefDialogHandler> _retval = CefClientCppToC::Get(
self)->GetDialogHandler();
// Return type: refptr_same
return CefDialogHandlerCppToC::Wrap(_retval);
}
struct _cef_display_handler_t* CEF_CALLBACK client_get_display_handler(
struct _cef_client_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
@ -220,6 +237,7 @@ int CEF_CALLBACK client_on_process_message_received(struct _cef_client_t* self,
CefClientCppToC::CefClientCppToC(CefClient* cls)
: CefCppToC<CefClientCppToC, CefClient, cef_client_t>(cls) {
struct_.struct_.get_context_menu_handler = client_get_context_menu_handler;
struct_.struct_.get_dialog_handler = client_get_dialog_handler;
struct_.struct_.get_display_handler = client_get_display_handler;
struct_.struct_.get_download_handler = client_get_download_handler;
struct_.struct_.get_focus_handler = client_get_focus_handler;

View File

@ -0,0 +1,71 @@
// Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#include "libcef_dll/cpptoc/dialog_handler_cpptoc.h"
#include "libcef_dll/ctocpp/browser_ctocpp.h"
#include "libcef_dll/ctocpp/file_dialog_callback_ctocpp.h"
#include "libcef_dll/transfer_util.h"
// MEMBER FUNCTIONS - Body may be edited by hand.
int CEF_CALLBACK dialog_handler_on_file_dialog(
struct _cef_dialog_handler_t* self, cef_browser_t* browser,
enum cef_file_dialog_mode_t mode, const cef_string_t* title,
const cef_string_t* default_file_name, cef_string_list_t accept_types,
cef_file_dialog_callback_t* callback) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return 0;
// Verify param: browser; type: refptr_diff
DCHECK(browser);
if (!browser)
return 0;
// Verify param: callback; type: refptr_diff
DCHECK(callback);
if (!callback)
return 0;
// Unverified params: title, default_file_name, accept_types
// Translate param: accept_types; type: string_vec_byref_const
std::vector<CefString> accept_typesList;
transfer_string_list_contents(accept_types, accept_typesList);
// Execute
bool _retval = CefDialogHandlerCppToC::Get(self)->OnFileDialog(
CefBrowserCToCpp::Wrap(browser),
mode,
CefString(title),
CefString(default_file_name),
accept_typesList,
CefFileDialogCallbackCToCpp::Wrap(callback));
// Return type: bool
return _retval;
}
// CONSTRUCTOR - Do not edit by hand.
CefDialogHandlerCppToC::CefDialogHandlerCppToC(CefDialogHandler* cls)
: CefCppToC<CefDialogHandlerCppToC, CefDialogHandler, cef_dialog_handler_t>(
cls) {
struct_.struct_.on_file_dialog = dialog_handler_on_file_dialog;
}
#ifndef NDEBUG
template<> long CefCppToC<CefDialogHandlerCppToC, CefDialogHandler,
cef_dialog_handler_t>::DebugObjCt = 0;
#endif

View File

@ -0,0 +1,37 @@
// Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#ifndef CEF_LIBCEF_DLL_CPPTOC_DIALOG_HANDLER_CPPTOC_H_
#define CEF_LIBCEF_DLL_CPPTOC_DIALOG_HANDLER_CPPTOC_H_
#pragma once
#ifndef USING_CEF_SHARED
#pragma message("Warning: "__FILE__" may be accessed wrapper-side only")
#else // USING_CEF_SHARED
#include "include/cef_dialog_handler.h"
#include "include/capi/cef_dialog_handler_capi.h"
#include "libcef_dll/cpptoc/cpptoc.h"
// Wrap a C++ class with a C structure.
// This class may be instantiated and accessed wrapper-side only.
class CefDialogHandlerCppToC
: public CefCppToC<CefDialogHandlerCppToC, CefDialogHandler,
cef_dialog_handler_t> {
public:
explicit CefDialogHandlerCppToC(CefDialogHandler* cls);
virtual ~CefDialogHandlerCppToC() {}
};
#endif // USING_CEF_SHARED
#endif // CEF_LIBCEF_DLL_CPPTOC_DIALOG_HANDLER_CPPTOC_H_

View File

@ -0,0 +1,67 @@
// Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#include "libcef_dll/cpptoc/file_dialog_callback_cpptoc.h"
#include "libcef_dll/transfer_util.h"
// MEMBER FUNCTIONS - Body may be edited by hand.
void CEF_CALLBACK file_dialog_callback_cont(
struct _cef_file_dialog_callback_t* self, cef_string_list_t file_paths) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Verify param: file_paths; type: string_vec_byref_const
DCHECK(file_paths);
if (!file_paths)
return;
// Translate param: file_paths; type: string_vec_byref_const
std::vector<CefString> file_pathsList;
transfer_string_list_contents(file_paths, file_pathsList);
// Execute
CefFileDialogCallbackCppToC::Get(self)->Continue(
file_pathsList);
}
void CEF_CALLBACK file_dialog_callback_cancel(
struct _cef_file_dialog_callback_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Execute
CefFileDialogCallbackCppToC::Get(self)->Cancel();
}
// CONSTRUCTOR - Do not edit by hand.
CefFileDialogCallbackCppToC::CefFileDialogCallbackCppToC(
CefFileDialogCallback* cls)
: CefCppToC<CefFileDialogCallbackCppToC, CefFileDialogCallback,
cef_file_dialog_callback_t>(cls) {
struct_.struct_.cont = file_dialog_callback_cont;
struct_.struct_.cancel = file_dialog_callback_cancel;
}
#ifndef NDEBUG
template<> long CefCppToC<CefFileDialogCallbackCppToC, CefFileDialogCallback,
cef_file_dialog_callback_t>::DebugObjCt = 0;
#endif

View File

@ -0,0 +1,37 @@
// Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#ifndef CEF_LIBCEF_DLL_CPPTOC_FILE_DIALOG_CALLBACK_CPPTOC_H_
#define CEF_LIBCEF_DLL_CPPTOC_FILE_DIALOG_CALLBACK_CPPTOC_H_
#pragma once
#ifndef BUILDING_CEF_SHARED
#pragma message("Warning: "__FILE__" may be accessed DLL-side only")
#else // BUILDING_CEF_SHARED
#include "include/cef_dialog_handler.h"
#include "include/capi/cef_dialog_handler_capi.h"
#include "libcef_dll/cpptoc/cpptoc.h"
// Wrap a C++ class with a C structure.
// This class may be instantiated and accessed DLL-side only.
class CefFileDialogCallbackCppToC
: public CefCppToC<CefFileDialogCallbackCppToC, CefFileDialogCallback,
cef_file_dialog_callback_t> {
public:
explicit CefFileDialogCallbackCppToC(CefFileDialogCallback* cls);
virtual ~CefFileDialogCallbackCppToC() {}
};
#endif // BUILDING_CEF_SHARED
#endif // CEF_LIBCEF_DLL_CPPTOC_FILE_DIALOG_CALLBACK_CPPTOC_H_

View File

@ -0,0 +1,61 @@
// Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#include "libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.h"
#include "libcef_dll/ctocpp/browser_host_ctocpp.h"
#include "libcef_dll/transfer_util.h"
// MEMBER FUNCTIONS - Body may be edited by hand.
void CEF_CALLBACK run_file_dialog_callback_cont(
struct _cef_run_file_dialog_callback_t* self,
struct _cef_browser_host_t* browser_host, cef_string_list_t file_paths) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Verify param: browser_host; type: refptr_diff
DCHECK(browser_host);
if (!browser_host)
return;
// Verify param: file_paths; type: string_vec_byref_const
DCHECK(file_paths);
if (!file_paths)
return;
// Translate param: file_paths; type: string_vec_byref_const
std::vector<CefString> file_pathsList;
transfer_string_list_contents(file_paths, file_pathsList);
// Execute
CefRunFileDialogCallbackCppToC::Get(self)->OnFileDialogDismissed(
CefBrowserHostCToCpp::Wrap(browser_host),
file_pathsList);
}
// CONSTRUCTOR - Do not edit by hand.
CefRunFileDialogCallbackCppToC::CefRunFileDialogCallbackCppToC(
CefRunFileDialogCallback* cls)
: CefCppToC<CefRunFileDialogCallbackCppToC, CefRunFileDialogCallback,
cef_run_file_dialog_callback_t>(cls) {
struct_.struct_.cont = run_file_dialog_callback_cont;
}
#ifndef NDEBUG
template<> long CefCppToC<CefRunFileDialogCallbackCppToC,
CefRunFileDialogCallback, cef_run_file_dialog_callback_t>::DebugObjCt = 0;
#endif

View File

@ -0,0 +1,39 @@
// Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#ifndef CEF_LIBCEF_DLL_CPPTOC_RUN_FILE_DIALOG_CALLBACK_CPPTOC_H_
#define CEF_LIBCEF_DLL_CPPTOC_RUN_FILE_DIALOG_CALLBACK_CPPTOC_H_
#pragma once
#ifndef USING_CEF_SHARED
#pragma message("Warning: "__FILE__" may be accessed wrapper-side only")
#else // USING_CEF_SHARED
#include "include/cef_browser.h"
#include "include/capi/cef_browser_capi.h"
#include "include/cef_client.h"
#include "include/capi/cef_client_capi.h"
#include "libcef_dll/cpptoc/cpptoc.h"
// Wrap a C++ class with a C structure.
// This class may be instantiated and accessed wrapper-side only.
class CefRunFileDialogCallbackCppToC
: public CefCppToC<CefRunFileDialogCallbackCppToC, CefRunFileDialogCallback,
cef_run_file_dialog_callback_t> {
public:
explicit CefRunFileDialogCallbackCppToC(CefRunFileDialogCallback* cls);
virtual ~CefRunFileDialogCallbackCppToC() {}
};
#endif // USING_CEF_SHARED
#endif // CEF_LIBCEF_DLL_CPPTOC_RUN_FILE_DIALOG_CALLBACK_CPPTOC_H_

View File

@ -11,8 +11,10 @@
//
#include "libcef_dll/cpptoc/client_cpptoc.h"
#include "libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.h"
#include "libcef_dll/ctocpp/browser_ctocpp.h"
#include "libcef_dll/ctocpp/browser_host_ctocpp.h"
#include "libcef_dll/transfer_util.h"
// STATIC METHODS - Body may be edited by hand.
@ -187,6 +189,40 @@ void CefBrowserHostCToCpp::SetZoomLevel(double zoomLevel) {
zoomLevel);
}
void CefBrowserHostCToCpp::RunFileDialog(FileDialogMode mode,
const CefString& title, const CefString& default_file_name,
const std::vector<CefString>& accept_types,
CefRefPtr<CefRunFileDialogCallback> callback) {
if (CEF_MEMBER_MISSING(struct_, run_file_dialog))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: callback; type: refptr_diff
DCHECK(callback.get());
if (!callback.get())
return;
// Unverified params: title, default_file_name, accept_types
// Translate param: accept_types; type: string_vec_byref_const
cef_string_list_t accept_typesList = cef_string_list_alloc();
DCHECK(accept_typesList);
if (accept_typesList)
transfer_string_list_contents(accept_types, accept_typesList);
// Execute
struct_->run_file_dialog(struct_,
mode,
title.GetStruct(),
default_file_name.GetStruct(),
accept_typesList,
CefRunFileDialogCallbackCppToC::Wrap(callback));
// Restore param:accept_types; type: string_vec_byref_const
if (accept_typesList)
cef_string_list_free(accept_typesList);
}
#ifndef NDEBUG
template<> long CefCToCpp<CefBrowserHostCToCpp, CefBrowserHost,

View File

@ -18,6 +18,7 @@
#pragma message("Warning: "__FILE__" may be accessed wrapper-side only")
#else // USING_CEF_SHARED
#include <vector>
#include "include/cef_browser.h"
#include "include/capi/cef_browser_capi.h"
#include "include/cef_client.h"
@ -46,6 +47,10 @@ class CefBrowserHostCToCpp
virtual CefString GetDevToolsURL(bool http_scheme) OVERRIDE;
virtual double GetZoomLevel() OVERRIDE;
virtual void SetZoomLevel(double zoomLevel) OVERRIDE;
virtual void RunFileDialog(FileDialogMode mode, const CefString& title,
const CefString& default_file_name,
const std::vector<CefString>& accept_types,
CefRefPtr<CefRunFileDialogCallback> callback) OVERRIDE;
};
#endif // USING_CEF_SHARED

View File

@ -14,6 +14,7 @@
#include "libcef_dll/cpptoc/process_message_cpptoc.h"
#include "libcef_dll/ctocpp/client_ctocpp.h"
#include "libcef_dll/ctocpp/context_menu_handler_ctocpp.h"
#include "libcef_dll/ctocpp/dialog_handler_ctocpp.h"
#include "libcef_dll/ctocpp/display_handler_ctocpp.h"
#include "libcef_dll/ctocpp/download_handler_ctocpp.h"
#include "libcef_dll/ctocpp/focus_handler_ctocpp.h"
@ -41,6 +42,19 @@ CefRefPtr<CefContextMenuHandler> CefClientCToCpp::GetContextMenuHandler() {
return CefContextMenuHandlerCToCpp::Wrap(_retval);
}
CefRefPtr<CefDialogHandler> CefClientCToCpp::GetDialogHandler() {
if (CEF_MEMBER_MISSING(struct_, get_dialog_handler))
return NULL;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
cef_dialog_handler_t* _retval = struct_->get_dialog_handler(struct_);
// Return type: refptr_same
return CefDialogHandlerCToCpp::Wrap(_retval);
}
CefRefPtr<CefDisplayHandler> CefClientCToCpp::GetDisplayHandler() {
if (CEF_MEMBER_MISSING(struct_, get_display_handler))
return NULL;

View File

@ -33,6 +33,7 @@ class CefClientCToCpp
// CefClient methods
virtual CefRefPtr<CefContextMenuHandler> GetContextMenuHandler() OVERRIDE;
virtual CefRefPtr<CefDialogHandler> GetDialogHandler() OVERRIDE;
virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() OVERRIDE;
virtual CefRefPtr<CefDownloadHandler> GetDownloadHandler() OVERRIDE;
virtual CefRefPtr<CefFocusHandler> GetFocusHandler() OVERRIDE;

View File

@ -0,0 +1,69 @@
// Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#include "libcef_dll/cpptoc/browser_cpptoc.h"
#include "libcef_dll/cpptoc/file_dialog_callback_cpptoc.h"
#include "libcef_dll/ctocpp/dialog_handler_ctocpp.h"
#include "libcef_dll/transfer_util.h"
// VIRTUAL METHODS - Body may be edited by hand.
bool CefDialogHandlerCToCpp::OnFileDialog(CefRefPtr<CefBrowser> browser,
FileDialogMode mode, const CefString& title,
const CefString& default_file_name,
const std::vector<CefString>& accept_types,
CefRefPtr<CefFileDialogCallback> callback) {
if (CEF_MEMBER_MISSING(struct_, on_file_dialog))
return false;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: browser; type: refptr_diff
DCHECK(browser.get());
if (!browser.get())
return false;
// Verify param: callback; type: refptr_diff
DCHECK(callback.get());
if (!callback.get())
return false;
// Unverified params: title, default_file_name, accept_types
// Translate param: accept_types; type: string_vec_byref_const
cef_string_list_t accept_typesList = cef_string_list_alloc();
DCHECK(accept_typesList);
if (accept_typesList)
transfer_string_list_contents(accept_types, accept_typesList);
// Execute
int _retval = struct_->on_file_dialog(struct_,
CefBrowserCppToC::Wrap(browser),
mode,
title.GetStruct(),
default_file_name.GetStruct(),
accept_typesList,
CefFileDialogCallbackCppToC::Wrap(callback));
// Restore param:accept_types; type: string_vec_byref_const
if (accept_typesList)
cef_string_list_free(accept_typesList);
// Return type: bool
return _retval?true:false;
}
#ifndef NDEBUG
template<> long CefCToCpp<CefDialogHandlerCToCpp, CefDialogHandler,
cef_dialog_handler_t>::DebugObjCt = 0;
#endif

View File

@ -0,0 +1,46 @@
// Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_DIALOG_HANDLER_CTOCPP_H_
#define CEF_LIBCEF_DLL_CTOCPP_DIALOG_HANDLER_CTOCPP_H_
#pragma once
#ifndef BUILDING_CEF_SHARED
#pragma message("Warning: "__FILE__" may be accessed DLL-side only")
#else // BUILDING_CEF_SHARED
#include <vector>
#include "include/cef_dialog_handler.h"
#include "include/capi/cef_dialog_handler_capi.h"
#include "libcef_dll/ctocpp/ctocpp.h"
// Wrap a C structure with a C++ class.
// This class may be instantiated and accessed DLL-side only.
class CefDialogHandlerCToCpp
: public CefCToCpp<CefDialogHandlerCToCpp, CefDialogHandler,
cef_dialog_handler_t> {
public:
explicit CefDialogHandlerCToCpp(cef_dialog_handler_t* str)
: CefCToCpp<CefDialogHandlerCToCpp, CefDialogHandler,
cef_dialog_handler_t>(str) {}
virtual ~CefDialogHandlerCToCpp() {}
// CefDialogHandler methods
virtual bool OnFileDialog(CefRefPtr<CefBrowser> browser, FileDialogMode mode,
const CefString& title, const CefString& default_file_name,
const std::vector<CefString>& accept_types,
CefRefPtr<CefFileDialogCallback> callback) OVERRIDE;
};
#endif // BUILDING_CEF_SHARED
#endif // CEF_LIBCEF_DLL_CTOCPP_DIALOG_HANDLER_CTOCPP_H_

View File

@ -0,0 +1,56 @@
// Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#include "libcef_dll/ctocpp/file_dialog_callback_ctocpp.h"
#include "libcef_dll/transfer_util.h"
// VIRTUAL METHODS - Body may be edited by hand.
void CefFileDialogCallbackCToCpp::Continue(
const std::vector<CefString>& file_paths) {
if (CEF_MEMBER_MISSING(struct_, cont))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Translate param: file_paths; type: string_vec_byref_const
cef_string_list_t file_pathsList = cef_string_list_alloc();
DCHECK(file_pathsList);
if (file_pathsList)
transfer_string_list_contents(file_paths, file_pathsList);
// Execute
struct_->cont(struct_,
file_pathsList);
// Restore param:file_paths; type: string_vec_byref_const
if (file_pathsList)
cef_string_list_free(file_pathsList);
}
void CefFileDialogCallbackCToCpp::Cancel() {
if (CEF_MEMBER_MISSING(struct_, cancel))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
struct_->cancel(struct_);
}
#ifndef NDEBUG
template<> long CefCToCpp<CefFileDialogCallbackCToCpp, CefFileDialogCallback,
cef_file_dialog_callback_t>::DebugObjCt = 0;
#endif

View File

@ -0,0 +1,44 @@
// Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_FILE_DIALOG_CALLBACK_CTOCPP_H_
#define CEF_LIBCEF_DLL_CTOCPP_FILE_DIALOG_CALLBACK_CTOCPP_H_
#pragma once
#ifndef USING_CEF_SHARED
#pragma message("Warning: "__FILE__" may be accessed wrapper-side only")
#else // USING_CEF_SHARED
#include <vector>
#include "include/cef_dialog_handler.h"
#include "include/capi/cef_dialog_handler_capi.h"
#include "libcef_dll/ctocpp/ctocpp.h"
// Wrap a C structure with a C++ class.
// This class may be instantiated and accessed wrapper-side only.
class CefFileDialogCallbackCToCpp
: public CefCToCpp<CefFileDialogCallbackCToCpp, CefFileDialogCallback,
cef_file_dialog_callback_t> {
public:
explicit CefFileDialogCallbackCToCpp(cef_file_dialog_callback_t* str)
: CefCToCpp<CefFileDialogCallbackCToCpp, CefFileDialogCallback,
cef_file_dialog_callback_t>(str) {}
virtual ~CefFileDialogCallbackCToCpp() {}
// CefFileDialogCallback methods
virtual void Continue(const std::vector<CefString>& file_paths) OVERRIDE;
virtual void Cancel() OVERRIDE;
};
#endif // USING_CEF_SHARED
#endif // CEF_LIBCEF_DLL_CTOCPP_FILE_DIALOG_CALLBACK_CTOCPP_H_

View File

@ -0,0 +1,54 @@
// Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#include "libcef_dll/cpptoc/browser_host_cpptoc.h"
#include "libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.h"
#include "libcef_dll/transfer_util.h"
// VIRTUAL METHODS - Body may be edited by hand.
void CefRunFileDialogCallbackCToCpp::OnFileDialogDismissed(
CefRefPtr<CefBrowserHost> browser_host,
const std::vector<CefString>& file_paths) {
if (CEF_MEMBER_MISSING(struct_, cont))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: browser_host; type: refptr_diff
DCHECK(browser_host.get());
if (!browser_host.get())
return;
// Translate param: file_paths; type: string_vec_byref_const
cef_string_list_t file_pathsList = cef_string_list_alloc();
DCHECK(file_pathsList);
if (file_pathsList)
transfer_string_list_contents(file_paths, file_pathsList);
// Execute
struct_->cont(struct_,
CefBrowserHostCppToC::Wrap(browser_host),
file_pathsList);
// Restore param:file_paths; type: string_vec_byref_const
if (file_pathsList)
cef_string_list_free(file_pathsList);
}
#ifndef NDEBUG
template<> long CefCToCpp<CefRunFileDialogCallbackCToCpp,
CefRunFileDialogCallback, cef_run_file_dialog_callback_t>::DebugObjCt = 0;
#endif

View File

@ -0,0 +1,46 @@
// Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_RUN_FILE_DIALOG_CALLBACK_CTOCPP_H_
#define CEF_LIBCEF_DLL_CTOCPP_RUN_FILE_DIALOG_CALLBACK_CTOCPP_H_
#pragma once
#ifndef BUILDING_CEF_SHARED
#pragma message("Warning: "__FILE__" may be accessed DLL-side only")
#else // BUILDING_CEF_SHARED
#include <vector>
#include "include/cef_browser.h"
#include "include/capi/cef_browser_capi.h"
#include "include/cef_client.h"
#include "include/capi/cef_client_capi.h"
#include "libcef_dll/ctocpp/ctocpp.h"
// Wrap a C structure with a C++ class.
// This class may be instantiated and accessed DLL-side only.
class CefRunFileDialogCallbackCToCpp
: public CefCToCpp<CefRunFileDialogCallbackCToCpp, CefRunFileDialogCallback,
cef_run_file_dialog_callback_t> {
public:
explicit CefRunFileDialogCallbackCToCpp(cef_run_file_dialog_callback_t* str)
: CefCToCpp<CefRunFileDialogCallbackCToCpp, CefRunFileDialogCallback,
cef_run_file_dialog_callback_t>(str) {}
virtual ~CefRunFileDialogCallbackCToCpp() {}
// CefRunFileDialogCallback methods
virtual void OnFileDialogDismissed(CefRefPtr<CefBrowserHost> browser_host,
const std::vector<CefString>& file_paths) OVERRIDE;
};
#endif // BUILDING_CEF_SHARED
#endif // CEF_LIBCEF_DLL_CTOCPP_RUN_FILE_DIALOG_CALLBACK_CTOCPP_H_

View File

@ -43,6 +43,7 @@
#include "libcef_dll/cpptoc/dictionary_value_cpptoc.h"
#include "libcef_dll/cpptoc/download_item_cpptoc.h"
#include "libcef_dll/cpptoc/download_item_callback_cpptoc.h"
#include "libcef_dll/cpptoc/file_dialog_callback_cpptoc.h"
#include "libcef_dll/cpptoc/frame_cpptoc.h"
#include "libcef_dll/cpptoc/geolocation_callback_cpptoc.h"
#include "libcef_dll/cpptoc/jsdialog_callback_cpptoc.h"
@ -68,6 +69,7 @@
#include "libcef_dll/ctocpp/cookie_visitor_ctocpp.h"
#include "libcef_dll/ctocpp/domevent_listener_ctocpp.h"
#include "libcef_dll/ctocpp/domvisitor_ctocpp.h"
#include "libcef_dll/ctocpp/dialog_handler_ctocpp.h"
#include "libcef_dll/ctocpp/display_handler_ctocpp.h"
#include "libcef_dll/ctocpp/download_handler_ctocpp.h"
#include "libcef_dll/ctocpp/focus_handler_ctocpp.h"
@ -82,6 +84,7 @@
#include "libcef_dll/ctocpp/request_handler_ctocpp.h"
#include "libcef_dll/ctocpp/resource_bundle_handler_ctocpp.h"
#include "libcef_dll/ctocpp/resource_handler_ctocpp.h"
#include "libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.h"
#include "libcef_dll/ctocpp/scheme_handler_factory_ctocpp.h"
#include "libcef_dll/ctocpp/string_visitor_ctocpp.h"
#include "libcef_dll/ctocpp/task_ctocpp.h"
@ -176,11 +179,13 @@ CEF_EXPORT void cef_shutdown() {
DCHECK_EQ(CefDOMEventListenerCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefDOMNodeCppToC::DebugObjCt, 0);
DCHECK_EQ(CefDOMVisitorCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefDialogHandlerCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefDictionaryValueCppToC::DebugObjCt, 0);
DCHECK_EQ(CefDisplayHandlerCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefDownloadHandlerCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefDownloadItemCallbackCppToC::DebugObjCt, 0);
DCHECK_EQ(CefDownloadItemCppToC::DebugObjCt, 0);
DCHECK_EQ(CefFileDialogCallbackCppToC::DebugObjCt, 0);
DCHECK_EQ(CefFocusHandlerCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefFrameCppToC::DebugObjCt, 0);
DCHECK_EQ(CefGeolocationCallbackCppToC::DebugObjCt, 0);
@ -200,6 +205,7 @@ CEF_EXPORT void cef_shutdown() {
DCHECK_EQ(CefRequestHandlerCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefResourceBundleHandlerCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefResourceHandlerCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefRunFileDialogCallbackCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefSchemeHandlerFactoryCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefSchemeRegistrarCppToC::DebugObjCt, 0);
DCHECK_EQ(CefStreamReaderCppToC::DebugObjCt, 0);

View File

@ -35,6 +35,7 @@
#include "libcef_dll/cpptoc/cookie_visitor_cpptoc.h"
#include "libcef_dll/cpptoc/domevent_listener_cpptoc.h"
#include "libcef_dll/cpptoc/domvisitor_cpptoc.h"
#include "libcef_dll/cpptoc/dialog_handler_cpptoc.h"
#include "libcef_dll/cpptoc/display_handler_cpptoc.h"
#include "libcef_dll/cpptoc/download_handler_cpptoc.h"
#include "libcef_dll/cpptoc/focus_handler_cpptoc.h"
@ -49,6 +50,7 @@
#include "libcef_dll/cpptoc/request_handler_cpptoc.h"
#include "libcef_dll/cpptoc/resource_bundle_handler_cpptoc.h"
#include "libcef_dll/cpptoc/resource_handler_cpptoc.h"
#include "libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.h"
#include "libcef_dll/cpptoc/scheme_handler_factory_cpptoc.h"
#include "libcef_dll/cpptoc/string_visitor_cpptoc.h"
#include "libcef_dll/cpptoc/task_cpptoc.h"
@ -73,6 +75,7 @@
#include "libcef_dll/ctocpp/dictionary_value_ctocpp.h"
#include "libcef_dll/ctocpp/download_item_ctocpp.h"
#include "libcef_dll/ctocpp/download_item_callback_ctocpp.h"
#include "libcef_dll/ctocpp/file_dialog_callback_ctocpp.h"
#include "libcef_dll/ctocpp/frame_ctocpp.h"
#include "libcef_dll/ctocpp/geolocation_callback_ctocpp.h"
#include "libcef_dll/ctocpp/jsdialog_callback_ctocpp.h"
@ -168,11 +171,13 @@ CEF_GLOBAL void CefShutdown() {
DCHECK_EQ(CefDOMEventListenerCppToC::DebugObjCt, 0);
DCHECK_EQ(CefDOMNodeCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefDOMVisitorCppToC::DebugObjCt, 0);
DCHECK_EQ(CefDialogHandlerCppToC::DebugObjCt, 0);
DCHECK_EQ(CefDictionaryValueCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefDisplayHandlerCppToC::DebugObjCt, 0);
DCHECK_EQ(CefDownloadHandlerCppToC::DebugObjCt, 0);
DCHECK_EQ(CefDownloadItemCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefDownloadItemCallbackCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefFileDialogCallbackCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefFocusHandlerCppToC::DebugObjCt, 0);
DCHECK_EQ(CefFrameCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefGeolocationCallbackCToCpp::DebugObjCt, 0);
@ -192,6 +197,7 @@ CEF_GLOBAL void CefShutdown() {
DCHECK_EQ(CefRequestHandlerCppToC::DebugObjCt, 0);
DCHECK_EQ(CefResourceBundleHandlerCppToC::DebugObjCt, 0);
DCHECK_EQ(CefResourceHandlerCppToC::DebugObjCt, 0);
DCHECK_EQ(CefRunFileDialogCallbackCppToC::DebugObjCt, 0);
DCHECK_EQ(CefSchemeHandlerFactoryCppToC::DebugObjCt, 0);
DCHECK_EQ(CefSchemeRegistrarCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefStreamReaderCToCpp::DebugObjCt, 0);

View File

@ -262,10 +262,6 @@ void RunPopupTest(CefRefPtr<CefBrowser> browser) {
"window.open('http://www.google.com');", "about:blank", 0);
}
void RunDialogTest(CefRefPtr<CefBrowser> browser) {
browser->GetMainFrame()->LoadURL("http://tests/dialogs");
}
void RunPluginInfoTest(CefRefPtr<CefBrowser> browser) {
class Visitor : public CefWebPluginInfoVisitor {
public:

View File

@ -40,7 +40,6 @@ void RunGetSourceTest(CefRefPtr<CefBrowser> browser);
void RunGetTextTest(CefRefPtr<CefBrowser> browser);
void RunRequestTest(CefRefPtr<CefBrowser> browser);
void RunPopupTest(CefRefPtr<CefBrowser> browser);
void RunDialogTest(CefRefPtr<CefBrowser> browser);
void RunPluginInfoTest(CefRefPtr<CefBrowser> browser);
void RunLocalStorageTest(CefRefPtr<CefBrowser> browser);
void RunAccelerated2DCanvasTest(CefRefPtr<CefBrowser> browser);

View File

@ -69,7 +69,7 @@ BEGIN
MENUITEM "Request", ID_TESTS_REQUEST
MENUITEM "Scheme Handler", ID_TESTS_SCHEME_HANDLER
MENUITEM "JavaScript Binding", ID_TESTS_BINDING
MENUITEM "JavaScript Dialogs", ID_TESTS_DIALOGS
MENUITEM "Dialogs", ID_TESTS_DIALOGS
MENUITEM "Plugin Info", ID_TESTS_PLUGIN_INFO
MENUITEM "DOM Access", ID_TESTS_DOM_ACCESS
MENUITEM "Local Storage", ID_TESTS_LOCALSTORAGE

View File

@ -13,6 +13,7 @@
#include "include/cef_runnable.h"
#include "cefclient/binding_test.h"
#include "cefclient/client_handler.h"
#include "cefclient/dialog_test.h"
#include "cefclient/dom_test.h"
#include "cefclient/scheme_test.h"
#include "cefclient/string_util.h"
@ -86,10 +87,10 @@ gboolean BindingActivated(GtkWidget* widget) {
return FALSE; // Don't stop this message.
}
// Callback for Debug > JavaScript Dialogs... menu item.
// Callback for Debug > Dialogs... menu item.
gboolean DialogsActivated(GtkWidget* widget) {
if (g_handler.get() && g_handler->GetBrowserId())
RunDialogTest(g_handler->GetBrowser());
dialog_test::RunTest(g_handler->GetBrowser());
return FALSE; // Don't stop this message.
}
@ -258,7 +259,7 @@ GtkWidget* CreateMenuBar() {
G_CALLBACK(SchemeHandlerActivated));
AddMenuEntry(debug_menu, "JavaScript Binding",
G_CALLBACK(BindingActivated));
AddMenuEntry(debug_menu, "JavaScript Dialogs",
AddMenuEntry(debug_menu, "Dialogs",
G_CALLBACK(DialogsActivated));
AddMenuEntry(debug_menu, "Plugin Info",
G_CALLBACK(PluginInfoActivated));

View File

@ -13,6 +13,7 @@
#include "include/cef_runnable.h"
#include "cefclient/binding_test.h"
#include "cefclient/client_handler.h"
#include "cefclient/dialog_test.h"
#include "cefclient/dom_test.h"
#include "cefclient/resource_util.h"
#include "cefclient/scheme_test.h"
@ -242,7 +243,7 @@ NSButton* MakeButton(NSRect* rect, NSString* title, NSView* parent) {
[testMenu addItemWithTitle:@"JavaScript Binding"
action:@selector(testBinding:)
keyEquivalent:@""];
[testMenu addItemWithTitle:@"JavaScript Dialogs"
[testMenu addItemWithTitle:@"Dialogs"
action:@selector(testDialogs:)
keyEquivalent:@""];
[testMenu addItemWithTitle:@"Plugin Info"
@ -409,7 +410,7 @@ NSButton* MakeButton(NSRect* rect, NSString* title, NSView* parent) {
- (IBAction)testDialogs:(id)sender {
if (g_handler.get() && g_handler->GetBrowserId())
RunDialogTest(g_handler->GetBrowser());
dialog_test::RunTest(g_handler->GetBrowser());
}
- (IBAction)testPluginInfo:(id)sender {

View File

@ -15,6 +15,7 @@
#include "include/cef_runnable.h"
#include "cefclient/binding_test.h"
#include "cefclient/client_handler.h"
#include "cefclient/dialog_test.h"
#include "cefclient/dom_test.h"
#include "cefclient/resource.h"
#include "cefclient/scheme_test.h"
@ -389,7 +390,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
return 0;
case ID_TESTS_DIALOGS: // Test JavaScript dialogs
if (browser.get())
RunDialogTest(browser);
dialog_test::RunTest(browser);
return 0;
case ID_TESTS_PLUGIN_INFO: // Test plugin info
if (browser.get())

View File

@ -336,8 +336,13 @@ bool ClientApp::OnProcessMessageReceived(
std::make_pair(message_name.ToString(),
browser->GetIdentifier()));
if (it != callback_map_.end()) {
// Keep a local reference to the objects. The callback may remove itself
// from the callback map.
CefRefPtr<CefV8Context> context = it->second.first;
CefRefPtr<CefV8Value> callback = it->second.second;
// Enter the context.
it->second.first->Enter();
context->Enter();
CefV8ValueList arguments;
@ -351,15 +356,14 @@ bool ClientApp::OnProcessMessageReceived(
arguments.push_back(args);
// Execute the callback.
CefRefPtr<CefV8Value> retval =
it->second.second->ExecuteFunction(NULL, arguments);
CefRefPtr<CefV8Value> retval = callback->ExecuteFunction(NULL, arguments);
if (retval.get()) {
if (retval->IsBool())
handled = retval->GetBoolValue();
}
// Exit the context.
it->second.first->Exit();
context->Exit();
}
}

View File

@ -17,6 +17,7 @@
#include "cefclient/cefclient.h"
#include "cefclient/client_renderer.h"
#include "cefclient/client_switches.h"
#include "cefclient/dialog_test.h"
#include "cefclient/dom_test.h"
#include "cefclient/resource_util.h"
#include "cefclient/string_util.h"
@ -491,6 +492,8 @@ void ClientHandler::CreateProcessMessageDelegates(
ProcessMessageDelegateSet& delegates) {
// Create the binding test delegates.
binding_test::CreateProcessMessageDelegates(delegates);
// Create the dialog test delegates.
dialog_test::CreateProcessMessageDelegates(delegates);
}
// static

View File

@ -0,0 +1,106 @@
// Copyright (c) 2012 The Chromium Embedded Framework 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 "cefclient/dialog_test.h"
#include "include/cef_browser.h"
#include <string>
namespace dialog_test {
namespace {
const char* kTestUrl = "http://tests/dialogs";
const char* kFileOpenMessageName = "DialogTest.FileOpen";
const char* kFileOpenMultipleMessageName = "DialogTest.FileOpenMultiple";
const char* kFileSaveMessageName = "DialogTest.FileSave";
class RunFileDialogCallback : public CefRunFileDialogCallback {
public:
explicit RunFileDialogCallback(const std::string& message_name)
: message_name_(message_name) {
}
virtual void OnFileDialogDismissed(
CefRefPtr<CefBrowserHost> browser_host,
const std::vector<CefString>& file_paths) OVERRIDE {
// Send a message back to the render process with the same name and the list
// of file paths.
CefRefPtr<CefProcessMessage> message =
CefProcessMessage::Create(message_name_);
CefRefPtr<CefListValue> args = message->GetArgumentList();
CefRefPtr<CefListValue> val = CefListValue::Create();
for (size_t i = 0; i < file_paths.size(); ++i)
val->SetString(i, file_paths[i]);
args->SetList(0, val);
// This will result in a call to the callback registered via JavaScript in
// dialogs.html.
browser_host->GetBrowser()->SendProcessMessage(PID_RENDERER, message);
}
private:
std::string message_name_;
IMPLEMENT_REFCOUNTING(RunFileDialogCallback);
};
// Handle messages in the browser process.
class ProcessMessageDelegate : public ClientHandler::ProcessMessageDelegate {
public:
ProcessMessageDelegate() {
}
// From ClientHandler::ProcessMessageDelegate.
virtual bool OnProcessMessageReceived(
CefRefPtr<ClientHandler> handler,
CefRefPtr<CefBrowser> browser,
CefProcessId source_process,
CefRefPtr<CefProcessMessage> message) OVERRIDE {
std::string url = browser->GetMainFrame()->GetURL();
if (url.find(kTestUrl) != 0)
return false;
// Sample file type filter.
std::vector<CefString> file_types;
file_types.push_back("text/*");
file_types.push_back(".log");
file_types.push_back(".patch");
std::string message_name = message->GetName();
if (message_name == kFileOpenMessageName) {
browser->GetHost()->RunFileDialog(FILE_DIALOG_OPEN, "My Open Dialog",
"test.txt", file_types, new RunFileDialogCallback(message_name));
return true;
} else if (message_name == kFileOpenMultipleMessageName) {
browser->GetHost()->RunFileDialog(FILE_DIALOG_OPEN_MULTIPLE,
"My Open Multiple Dialog", CefString(), file_types,
new RunFileDialogCallback(message_name));
return true;
} else if (message_name == kFileSaveMessageName) {
browser->GetHost()->RunFileDialog(FILE_DIALOG_SAVE, "My Save Dialog",
"test.txt", file_types, new RunFileDialogCallback(message_name));
return true;
} else {
ASSERT(false); // Not reached.
}
return false;
}
IMPLEMENT_REFCOUNTING(ProcessMessageDelegate);
};
} // namespace
void CreateProcessMessageDelegates(
ClientHandler::ProcessMessageDelegateSet& delegates) {
delegates.insert(new ProcessMessageDelegate);
}
void RunTest(CefRefPtr<CefBrowser> browser) {
browser->GetMainFrame()->LoadURL(kTestUrl);
}
} // namespace dialog_test

View File

@ -0,0 +1,22 @@
// Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#ifndef CEF_TESTS_CEFCLIENT_DIALOG_TEST_H_
#define CEF_TESTS_CEFCLIENT_DIALOG_TEST_H_
#pragma once
#include "cefclient/client_handler.h"
namespace dialog_test {
// Delegate creation. Called from ClientHandler.
void CreateProcessMessageDelegates(
ClientHandler::ProcessMessageDelegateSet& delegates);
// Run the test.
void RunTest(CefRefPtr<CefBrowser> browser);
} // namespace dialog_test
#endif // CEF_TESTS_CEFCLIENT_DIALOG_TEST_H_

View File

@ -30,6 +30,20 @@ function setup() {
setInterval(update_time, 1000);
}
function show_file_dialog(element, test) {
var message = 'DialogTest.' + test;
var target = document.getElementById(element);
// Register for the callback from OnFileDialogDismissed in dialog_test.cpp.
app.setMessageCallback(message, function(msg, paths) {
target.innerText = paths.join();
app.removeMessageCallback(message);
});
// This will result in a call to OnProcessMessageReceived in dialog_test.cpp.
app.sendMessage(message);
}
window.addEventListener('load', setup, false);
</script>
</head>
@ -39,6 +53,10 @@ Click a button to show the associated dialog type.
<br/><input type="button" onclick="show_alert();" value="Show Alert">
<br/><input type="button" onclick="show_confirm();" value="Show Confirm"> <span id="cm"></span>
<br/><input type="button" onclick="show_prompt();" value="Show Prompt"> <span id="pm"></span>
<br/>input type="file": <input type="file" name="pic" accept="text/*,.js,.css,image/*">
<br/><input type="button" onclick="show_file_dialog('fo', 'FileOpen');" value="Show File Open"> <span id="fo"></span>
<br/><input type="button" onclick="show_file_dialog('fom', 'FileOpenMultiple');" value="Show File Open Multiple"> <span id="fom"></span>
<br/><input type="button" onclick="show_file_dialog('fs', 'FileSave');" value="Show File Save"> <span id="fs"></span>
<p id="time"></p>
</form>
</body>

View File

@ -0,0 +1,267 @@
// Copyright (c) 2012 The Chromium Embedded Framework 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 "include/cef_runnable.h"
#include "tests/unittests/test_handler.h"
#include "tests/unittests/test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
const char* kTestUrl = "http://tests/DialogTestHandler";
class DialogTestHandler : public TestHandler {
public:
struct TestConfig {
explicit TestConfig(FileDialogMode dialog_mode)
: mode(dialog_mode),
title("Test Title"),
default_file_name("Test File Name"),
callback_async(false),
callback_cancel(false) {
accept_types.push_back("text/*");
accept_types.push_back(".js");
accept_types.push_back(".css");
}
FileDialogMode mode;
CefString title;
CefString default_file_name;
std::vector<CefString> accept_types;
bool callback_async; // True if the callback should execute asynchronously.
bool callback_cancel; // True if the callback should cancel.
std::vector<CefString> callback_paths; // Resulting paths if not cancelled.
};
class Callback : public CefRunFileDialogCallback {
public:
explicit Callback(DialogTestHandler* handler)
: handler_(handler) {
}
virtual void OnFileDialogDismissed(
CefRefPtr<CefBrowserHost> browser_host,
const std::vector<CefString>& file_paths) OVERRIDE {
handler_->got_onfiledialogdismissed_.yes();
std::string url = browser_host->GetBrowser()->GetMainFrame()->GetURL();
EXPECT_STREQ(kTestUrl, url.c_str());
if (handler_->config_.callback_cancel)
EXPECT_TRUE(file_paths.empty());
else
TestStringVectorEqual(handler_->config_.callback_paths, file_paths);
handler_->DestroyTest();
handler_ = NULL;
}
private:
DialogTestHandler* handler_;
IMPLEMENT_REFCOUNTING(Callback);
};
explicit DialogTestHandler(const TestConfig& config)
: config_(config) {
}
virtual void RunTest() OVERRIDE {
AddResource(kTestUrl, "<html><body>TEST</body></html>", "text/html");
// Create the browser
CreateBrowser(kTestUrl);
}
virtual void OnLoadEnd(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int httpStatusCode) OVERRIDE {
browser->GetHost()->RunFileDialog(config_.mode,
config_.title,
config_.default_file_name,
config_.accept_types,
new Callback(this));
}
void ExecuteCallback(CefRefPtr<CefFileDialogCallback> callback) {
if (config_.callback_cancel)
callback->Cancel();
else
callback->Continue(config_.callback_paths);
}
// CefDialogHandler
virtual bool OnFileDialog(
CefRefPtr<CefBrowser> browser,
FileDialogMode mode,
const CefString& title,
const CefString& default_file_name,
const std::vector<CefString>& accept_types,
CefRefPtr<CefFileDialogCallback> callback) OVERRIDE {
got_onfiledialog_.yes();
std::string url = browser->GetMainFrame()->GetURL();
EXPECT_STREQ(kTestUrl, url.c_str());
EXPECT_EQ(config_.mode, mode);
EXPECT_STREQ(config_.title.ToString().c_str(), title.ToString().c_str());
EXPECT_STREQ(config_.default_file_name.ToString().c_str(),
default_file_name.ToString().c_str());
TestStringVectorEqual(config_.accept_types, accept_types);
if (config_.callback_async) {
CefPostTask(TID_UI,
NewCefRunnableMethod(this, &DialogTestHandler::ExecuteCallback,
callback));
} else {
ExecuteCallback(callback);
}
return true;
}
virtual void DestroyTest() OVERRIDE {
EXPECT_TRUE(got_onfiledialog_);
EXPECT_TRUE(got_onfiledialogdismissed_);
TestHandler::DestroyTest();
}
TestConfig config_;
TrackCallback got_onfiledialog_;
TrackCallback got_onfiledialogdismissed_;
};
} // namespace
// Test with all parameters empty.
TEST(DialogTest, FileEmptyParams) {
DialogTestHandler::TestConfig config(FILE_DIALOG_OPEN);
config.title.clear();
config.default_file_name.clear();
config.accept_types.clear();
config.callback_async = false;
config.callback_cancel = false;
CefRefPtr<DialogTestHandler> handler = new DialogTestHandler(config);
handler->ExecuteTest();
}
TEST(DialogTest, FileOpen) {
DialogTestHandler::TestConfig config(FILE_DIALOG_OPEN);
config.callback_async = false;
config.callback_cancel = false;
config.callback_paths.push_back("/path/to/file1.txt");
CefRefPtr<DialogTestHandler> handler = new DialogTestHandler(config);
handler->ExecuteTest();
}
TEST(DialogTest, FileOpenCancel) {
DialogTestHandler::TestConfig config(FILE_DIALOG_OPEN);
config.callback_async = false;
config.callback_cancel = true;
CefRefPtr<DialogTestHandler> handler = new DialogTestHandler(config);
handler->ExecuteTest();
}
TEST(DialogTest, FileOpenAsync) {
DialogTestHandler::TestConfig config(FILE_DIALOG_OPEN);
config.callback_async = true;
config.callback_cancel = false;
config.callback_paths.push_back("/path/to/file1.txt");
CefRefPtr<DialogTestHandler> handler = new DialogTestHandler(config);
handler->ExecuteTest();
}
TEST(DialogTest, FileOpenAsyncCancel) {
DialogTestHandler::TestConfig config(FILE_DIALOG_OPEN);
config.callback_async = false;
config.callback_cancel = true;
CefRefPtr<DialogTestHandler> handler = new DialogTestHandler(config);
handler->ExecuteTest();
}
TEST(DialogTest, FileOpenMultiple) {
DialogTestHandler::TestConfig config(FILE_DIALOG_OPEN_MULTIPLE);
config.callback_async = false;
config.callback_cancel = false;
config.callback_paths.push_back("/path/to/file1.txt");
config.callback_paths.push_back("/path/to/file2.txt");
CefRefPtr<DialogTestHandler> handler = new DialogTestHandler(config);
handler->ExecuteTest();
}
TEST(DialogTest, FileOpenMultipleCancel) {
DialogTestHandler::TestConfig config(FILE_DIALOG_OPEN_MULTIPLE);
config.callback_async = false;
config.callback_cancel = true;
CefRefPtr<DialogTestHandler> handler = new DialogTestHandler(config);
handler->ExecuteTest();
}
TEST(DialogTest, FileOpenMultipleAsync) {
DialogTestHandler::TestConfig config(FILE_DIALOG_OPEN_MULTIPLE);
config.callback_async = true;
config.callback_cancel = false;
config.callback_paths.push_back("/path/to/file1.txt");
config.callback_paths.push_back("/path/to/file2.txt");
CefRefPtr<DialogTestHandler> handler = new DialogTestHandler(config);
handler->ExecuteTest();
}
TEST(DialogTest, FileOpenMultipleAsyncCancel) {
DialogTestHandler::TestConfig config(FILE_DIALOG_OPEN_MULTIPLE);
config.callback_async = false;
config.callback_cancel = true;
CefRefPtr<DialogTestHandler> handler = new DialogTestHandler(config);
handler->ExecuteTest();
}
TEST(DialogTest, FileSave) {
DialogTestHandler::TestConfig config(FILE_DIALOG_SAVE);
config.callback_async = false;
config.callback_cancel = false;
config.callback_paths.push_back("/path/to/file1.txt");
CefRefPtr<DialogTestHandler> handler = new DialogTestHandler(config);
handler->ExecuteTest();
}
TEST(DialogTest, FileSaveCancel) {
DialogTestHandler::TestConfig config(FILE_DIALOG_SAVE);
config.callback_async = false;
config.callback_cancel = true;
CefRefPtr<DialogTestHandler> handler = new DialogTestHandler(config);
handler->ExecuteTest();
}
TEST(DialogTest, FileSaveAsync) {
DialogTestHandler::TestConfig config(FILE_DIALOG_SAVE);
config.callback_async = true;
config.callback_cancel = false;
config.callback_paths.push_back("/path/to/file1.txt");
CefRefPtr<DialogTestHandler> handler = new DialogTestHandler(config);
handler->ExecuteTest();
}
TEST(DialogTest, FileSaveAsyncCancel) {
DialogTestHandler::TestConfig config(FILE_DIALOG_SAVE);
config.callback_async = false;
config.callback_cancel = true;
CefRefPtr<DialogTestHandler> handler = new DialogTestHandler(config);
handler->ExecuteTest();
}

View File

@ -31,6 +31,7 @@ class TrackCallback {
// Base implementation of CefClient for unit tests. Add new interfaces as needed
// by test cases.
class TestHandler : public CefClient,
public CefDialogHandler,
public CefDisplayHandler,
public CefJSDialogHandler,
public CefLifeSpanHandler,
@ -44,6 +45,9 @@ class TestHandler : public CefClient,
virtual void RunTest() =0;
// CefClient methods. Add new methods as needed by test cases.
virtual CefRefPtr<CefDialogHandler> GetDialogHandler() OVERRIDE {
return this;
}
virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() OVERRIDE {
return this;
}
@ -81,7 +85,7 @@ class TestHandler : public CefClient,
protected:
// Destroy the browser window. Once the window is destroyed test completion
// will be signaled.
void DestroyTest();
virtual void DestroyTest();
void CreateBrowser(const CefString& url);

View File

@ -225,3 +225,11 @@ void TestProcessMessageEqual(CefRefPtr<CefProcessMessage> val1,
TestListEqual(val1->GetArgumentList(), val2->GetArgumentList());
}
void TestStringVectorEqual(const std::vector<CefString>& val1,
const std::vector<CefString>& val2) {
EXPECT_EQ(val1.size(), val2.size());
for (size_t i = 0; i < val1.size(); ++i)
EXPECT_STREQ(val1[i].ToString().c_str(), val2[i].ToString().c_str());
}

View File

@ -56,4 +56,8 @@ void TestDictionaryEqual(CefRefPtr<CefDictionaryValue> val1,
void TestProcessMessageEqual(CefRefPtr<CefProcessMessage> val1,
CefRefPtr<CefProcessMessage> val2);
// Test if two CefString vectors are equal.
void TestStringVectorEqual(const std::vector<CefString>& val1,
const std::vector<CefString>& val2);
#endif // CEF_TESTS_UNITTESTS_TEST_UTIL_H_