mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-02-16 20:20:51 +01:00
- Add open folder dialog support (FILE_DIALOG_OPEN_FOLDER mode) for CefBrowserHost::RunFileDialog (issue #1030).
- Standardize file dialog behavior across all platforms (issue #1492). -- Show a file type filter list on OS X. -- Show the file extensions as part of the filter list description on all platforms (e.g. "Image Types (*.png;*.gif;*.jpg)"). -- Rename the CefBrowserHost::RunFileDialog |accept_types| argument to |accept_filters| and expand support for filters that will be displayed as-is in addition to the currently supported mime-type and extension-based filters. For example, a filter value of "Supported Image Types|.png;.gif;.jpg" will display "Supported Image Types (*.png;*.gif;*.jpg)" in the filter drop-down list and accept *.png, *.gif and *.jpg files. -- Persist the selected filter item index by passing a new |selected_accept_filter| argument to CefBrowserHost::RunFileDialog and returning the newly selected index via the CefRunFileDialogCallback and CefFileDialogCallback callbacks. -- Rename the CefBrowserHost::RunFileDialog |default_file_name| argument to |default_file_path| and use the directory component, if any, to set the default directory location. If |default_file_path| ends in a trailing path separator it will be treated as a directory without a file name component. -- Add FILE_DIALOG_OVERWRITEPROMPT_FLAG and FILE_DIALOG_HIDEREADONLY_FLAG values to cef_file_dialog_mode_t for controlling those behaviors where possible. git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@1973 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
parent
3eabbb2e7d
commit
e50ea8c29f
@ -195,13 +195,15 @@ typedef struct _cef_run_file_dialog_callback_t {
|
|||||||
cef_base_t base;
|
cef_base_t base;
|
||||||
|
|
||||||
///
|
///
|
||||||
// Called asynchronously after the file dialog is dismissed. If the selection
|
// Called asynchronously after the file dialog is dismissed.
|
||||||
// was successful |file_paths| will be a single value or a list of values
|
// |selected_accept_filter| is the 0-based index of the value selected from
|
||||||
// depending on the dialog mode. If the selection was cancelled |file_paths|
|
// the accept filters array passed to cef_browser_host_t::RunFileDialog.
|
||||||
// will be NULL.
|
// |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,
|
void (CEF_CALLBACK *on_file_dialog_dismissed)(
|
||||||
struct _cef_browser_host_t* browser_host, cef_string_list_t file_paths);
|
struct _cef_run_file_dialog_callback_t* self, int selected_accept_filter,
|
||||||
|
cef_string_list_t file_paths);
|
||||||
} cef_run_file_dialog_callback_t;
|
} cef_run_file_dialog_callback_t;
|
||||||
|
|
||||||
|
|
||||||
@ -315,17 +317,22 @@ typedef struct _cef_browser_host_t {
|
|||||||
// Call to run a file chooser dialog. Only a single file chooser dialog may be
|
// 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.
|
// 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
|
// |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|
|
// default title ("Open" or "Save" depending on the mode). |default_file_path|
|
||||||
// is the default file name to select in the dialog. |accept_types| is a list
|
// is the path with optional directory and/or file name component that will be
|
||||||
// of valid lower-cased MIME types or file extensions specified in an input
|
// initially selected in the dialog. |accept_filters| are used to restrict the
|
||||||
// element and is used to restrict selectable files to such types. |callback|
|
// selectable file types and may any combination of (a) valid lower-cased MIME
|
||||||
// will be executed after the dialog is dismissed or immediately if another
|
// types (e.g. "text/*" or "image/*"), (b) individual file extensions (e.g.
|
||||||
// dialog is already pending. The dialog will be initiated asynchronously on
|
// ".txt" or ".png"), or (c) combined description and file extension delimited
|
||||||
// the UI thread.
|
// using "|" and ";" (e.g. "Image Types|.png;.gif;.jpg").
|
||||||
|
// |selected_accept_filter| is the 0-based index of the filter that will be
|
||||||
|
// selected by default. |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,
|
void (CEF_CALLBACK *run_file_dialog)(struct _cef_browser_host_t* self,
|
||||||
cef_file_dialog_mode_t mode, const cef_string_t* title,
|
cef_file_dialog_mode_t mode, const cef_string_t* title,
|
||||||
const cef_string_t* default_file_name, cef_string_list_t accept_types,
|
const cef_string_t* default_file_path, cef_string_list_t accept_filters,
|
||||||
|
int selected_accept_filter,
|
||||||
struct _cef_run_file_dialog_callback_t* callback);
|
struct _cef_run_file_dialog_callback_t* callback);
|
||||||
|
|
||||||
///
|
///
|
||||||
|
@ -56,12 +56,14 @@ typedef struct _cef_file_dialog_callback_t {
|
|||||||
cef_base_t base;
|
cef_base_t base;
|
||||||
|
|
||||||
///
|
///
|
||||||
// Continue the file selection with the specified |file_paths|. This may be a
|
// Continue the file selection. |selected_accept_filter| should be the 0-based
|
||||||
// single value or a list of values depending on the dialog mode. An NULL
|
// index of the value selected from the accept filters array passed to
|
||||||
|
// cef_dialog_handler_t::OnFileDialog. |file_paths| should be a single value
|
||||||
|
// or a list of values depending on the dialog mode. An NULL |file_paths|
|
||||||
// value is treated the same as calling cancel().
|
// value is treated the same as calling cancel().
|
||||||
///
|
///
|
||||||
void (CEF_CALLBACK *cont)(struct _cef_file_dialog_callback_t* self,
|
void (CEF_CALLBACK *cont)(struct _cef_file_dialog_callback_t* self,
|
||||||
cef_string_list_t file_paths);
|
int selected_accept_filter, cef_string_list_t file_paths);
|
||||||
|
|
||||||
///
|
///
|
||||||
// Cancel the file selection.
|
// Cancel the file selection.
|
||||||
@ -84,17 +86,21 @@ typedef struct _cef_dialog_handler_t {
|
|||||||
// Called to run a file chooser dialog. |mode| represents the type of dialog
|
// 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 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).
|
// 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.
|
// |default_file_path| is the path with optional directory and/or file name
|
||||||
// |accept_types| is a list of valid lower-cased MIME types or file extensions
|
// component that should be initially selected in the dialog. |accept_filters|
|
||||||
// specified in an input element and is used to restrict selectable files to
|
// are used to restrict the selectable file types and may any combination of
|
||||||
// such types. To display a custom dialog return true (1) and execute
|
// (a) valid lower-cased MIME types (e.g. "text/*" or "image/*"), (b)
|
||||||
// |callback| either inline or at a later time. To display the default dialog
|
// individual file extensions (e.g. ".txt" or ".png"), or (c) combined
|
||||||
// return false (0).
|
// description and file extension delimited using "|" and ";" (e.g. "Image
|
||||||
|
// Types|.png;.gif;.jpg"). |selected_accept_filter| is the 0-based index of
|
||||||
|
// the filter that should be selected by default. 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,
|
int (CEF_CALLBACK *on_file_dialog)(struct _cef_dialog_handler_t* self,
|
||||||
struct _cef_browser_t* browser, cef_file_dialog_mode_t mode,
|
struct _cef_browser_t* browser, cef_file_dialog_mode_t mode,
|
||||||
const cef_string_t* title, const cef_string_t* default_file_name,
|
const cef_string_t* title, const cef_string_t* default_file_path,
|
||||||
cef_string_list_t accept_types,
|
cef_string_list_t accept_filters, int selected_accept_filter,
|
||||||
struct _cef_file_dialog_callback_t* callback);
|
struct _cef_file_dialog_callback_t* callback);
|
||||||
} cef_dialog_handler_t;
|
} cef_dialog_handler_t;
|
||||||
|
|
||||||
|
@ -199,14 +199,15 @@ class CefBrowser : public virtual CefBase {
|
|||||||
class CefRunFileDialogCallback : public virtual CefBase {
|
class CefRunFileDialogCallback : public virtual CefBase {
|
||||||
public:
|
public:
|
||||||
///
|
///
|
||||||
// Called asynchronously after the file dialog is dismissed. If the selection
|
// Called asynchronously after the file dialog is dismissed.
|
||||||
// was successful |file_paths| will be a single value or a list of values
|
// |selected_accept_filter| is the 0-based index of the value selected from
|
||||||
// depending on the dialog mode. If the selection was cancelled |file_paths|
|
// the accept filters array passed to CefBrowserHost::RunFileDialog.
|
||||||
// will be empty.
|
// |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)--*/
|
/*--cef(index_param=selected_accept_filter,optional_param=file_paths)--*/
|
||||||
virtual void OnFileDialogDismissed(
|
virtual void OnFileDialogDismissed(
|
||||||
CefRefPtr<CefBrowserHost> browser_host,
|
int selected_accept_filter,
|
||||||
const std::vector<CefString>& file_paths) =0;
|
const std::vector<CefString>& file_paths) =0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -355,20 +356,25 @@ class CefBrowserHost : public virtual CefBase {
|
|||||||
// Call to run a file chooser dialog. Only a single file chooser dialog may be
|
// 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.
|
// 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
|
// |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|
|
// default title ("Open" or "Save" depending on the mode). |default_file_path|
|
||||||
// is the default file name to select in the dialog. |accept_types| is a list
|
// is the path with optional directory and/or file name component that will be
|
||||||
// of valid lower-cased MIME types or file extensions specified in an input
|
// initially selected in the dialog. |accept_filters| are used to restrict the
|
||||||
// element and is used to restrict selectable files to such types. |callback|
|
// selectable file types and may any combination of (a) valid lower-cased MIME
|
||||||
// will be executed after the dialog is dismissed or immediately if another
|
// types (e.g. "text/*" or "image/*"), (b) individual file extensions (e.g.
|
||||||
// dialog is already pending. The dialog will be initiated asynchronously on
|
// ".txt" or ".png"), or (c) combined description and file extension delimited
|
||||||
// the UI thread.
|
// using "|" and ";" (e.g. "Image Types|.png;.gif;.jpg").
|
||||||
|
// |selected_accept_filter| is the 0-based index of the filter that will be
|
||||||
|
// selected by default. |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,
|
/*--cef(optional_param=title,optional_param=default_file_path,
|
||||||
optional_param=accept_types)--*/
|
optional_param=accept_filters,index_param=selected_accept_filter)--*/
|
||||||
virtual void RunFileDialog(FileDialogMode mode,
|
virtual void RunFileDialog(FileDialogMode mode,
|
||||||
const CefString& title,
|
const CefString& title,
|
||||||
const CefString& default_file_name,
|
const CefString& default_file_path,
|
||||||
const std::vector<CefString>& accept_types,
|
const std::vector<CefString>& accept_filters,
|
||||||
|
int selected_accept_filter,
|
||||||
CefRefPtr<CefRunFileDialogCallback> callback) =0;
|
CefRefPtr<CefRunFileDialogCallback> callback) =0;
|
||||||
|
|
||||||
///
|
///
|
||||||
|
@ -48,13 +48,17 @@
|
|||||||
class CefFileDialogCallback : public virtual CefBase {
|
class CefFileDialogCallback : public virtual CefBase {
|
||||||
public:
|
public:
|
||||||
///
|
///
|
||||||
// Continue the file selection with the specified |file_paths|. This may be
|
// Continue the file selection. |selected_accept_filter| should be the 0-based
|
||||||
// a single value or a list of values depending on the dialog mode. An empty
|
// index of the value selected from the accept filters array passed to
|
||||||
// value is treated the same as calling Cancel().
|
// CefDialogHandler::OnFileDialog. |file_paths| should be a single value or a
|
||||||
|
// list of values depending on the dialog mode. An empty |file_paths| value is
|
||||||
|
// treated the same as calling Cancel().
|
||||||
///
|
///
|
||||||
/*--cef(capi_name=cont)--*/
|
/*--cef(capi_name=cont,index_param=selected_accept_filter,
|
||||||
virtual void Continue(const std::vector<CefString>& file_paths) =0;
|
optional_param=file_paths)--*/
|
||||||
|
virtual void Continue(int selected_accept_filter,
|
||||||
|
const std::vector<CefString>& file_paths) =0;
|
||||||
|
|
||||||
///
|
///
|
||||||
// Cancel the file selection.
|
// Cancel the file selection.
|
||||||
///
|
///
|
||||||
@ -76,20 +80,25 @@ class CefDialogHandler : public virtual CefBase {
|
|||||||
// Called to run a file chooser dialog. |mode| represents the type of dialog
|
// 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 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).
|
// 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.
|
// |default_file_path| is the path with optional directory and/or file name
|
||||||
// |accept_types| is a list of valid lower-cased MIME types or file extensions
|
// component that should be initially selected in the dialog. |accept_filters|
|
||||||
// specified in an input element and is used to restrict selectable files to
|
// are used to restrict the selectable file types and may any combination of
|
||||||
// such types. To display a custom dialog return true and execute |callback|
|
// (a) valid lower-cased MIME types (e.g. "text/*" or "image/*"),
|
||||||
// either inline or at a later time. To display the default dialog return
|
// (b) individual file extensions (e.g. ".txt" or ".png"), or (c) combined
|
||||||
// false.
|
// description and file extension delimited using "|" and ";" (e.g.
|
||||||
|
// "Image Types|.png;.gif;.jpg"). |selected_accept_filter| is the 0-based
|
||||||
|
// index of the filter that should be selected by default. 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,
|
/*--cef(optional_param=title,optional_param=default_file_path,
|
||||||
optional_param=accept_types)--*/
|
optional_param=accept_filters,index_param=selected_accept_filter)--*/
|
||||||
virtual bool OnFileDialog(CefRefPtr<CefBrowser> browser,
|
virtual bool OnFileDialog(CefRefPtr<CefBrowser> browser,
|
||||||
FileDialogMode mode,
|
FileDialogMode mode,
|
||||||
const CefString& title,
|
const CefString& title,
|
||||||
const CefString& default_file_name,
|
const CefString& default_file_path,
|
||||||
const std::vector<CefString>& accept_types,
|
const std::vector<CefString>& accept_filters,
|
||||||
|
int selected_accept_filter,
|
||||||
CefRefPtr<CefFileDialogCallback> callback) {
|
CefRefPtr<CefFileDialogCallback> callback) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1720,11 +1720,36 @@ typedef enum {
|
|||||||
///
|
///
|
||||||
FILE_DIALOG_OPEN_MULTIPLE,
|
FILE_DIALOG_OPEN_MULTIPLE,
|
||||||
|
|
||||||
|
///
|
||||||
|
// Like Open, but selects a folder to open.
|
||||||
|
///
|
||||||
|
FILE_DIALOG_OPEN_FOLDER,
|
||||||
|
|
||||||
///
|
///
|
||||||
// Allows picking a nonexistent file, and prompts to overwrite if the file
|
// Allows picking a nonexistent file, and prompts to overwrite if the file
|
||||||
// already exists.
|
// already exists.
|
||||||
///
|
///
|
||||||
FILE_DIALOG_SAVE,
|
FILE_DIALOG_SAVE,
|
||||||
|
|
||||||
|
///
|
||||||
|
// General mask defining the bits used for the type values.
|
||||||
|
///
|
||||||
|
FILE_DIALOG_TYPE_MASK = 0xFF,
|
||||||
|
|
||||||
|
// Qualifiers.
|
||||||
|
// Any of the type values above can be augmented by one or more qualifiers.
|
||||||
|
// These qualifiers further define the dialog behavior.
|
||||||
|
|
||||||
|
///
|
||||||
|
// Prompt to overwrite if the user selects an existing file with the Save
|
||||||
|
// dialog.
|
||||||
|
///
|
||||||
|
FILE_DIALOG_OVERWRITEPROMPT_FLAG = 0x01000000,
|
||||||
|
|
||||||
|
///
|
||||||
|
// Do not display read-only files.
|
||||||
|
///
|
||||||
|
FILE_DIALOG_HIDEREADONLY_FLAG = 0x02000000,
|
||||||
} cef_file_dialog_mode_t;
|
} cef_file_dialog_mode_t;
|
||||||
|
|
||||||
///
|
///
|
||||||
|
@ -200,7 +200,8 @@ class CefFileDialogCallbackImpl : public CefFileDialogCallback {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Continue(const std::vector<CefString>& file_paths) override {
|
void Continue(int selected_accept_filter,
|
||||||
|
const std::vector<CefString>& file_paths) override {
|
||||||
if (CEF_CURRENTLY_ON_UIT()) {
|
if (CEF_CURRENTLY_ON_UIT()) {
|
||||||
if (!callback_.is_null()) {
|
if (!callback_.is_null()) {
|
||||||
std::vector<base::FilePath> vec;
|
std::vector<base::FilePath> vec;
|
||||||
@ -209,12 +210,13 @@ class CefFileDialogCallbackImpl : public CefFileDialogCallback {
|
|||||||
for (; it != file_paths.end(); ++it)
|
for (; it != file_paths.end(); ++it)
|
||||||
vec.push_back(base::FilePath(*it));
|
vec.push_back(base::FilePath(*it));
|
||||||
}
|
}
|
||||||
callback_.Run(vec);
|
callback_.Run(selected_accept_filter, vec);
|
||||||
callback_.Reset();
|
callback_.Reset();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
CEF_POST_TASK(CEF_UIT,
|
CEF_POST_TASK(CEF_UIT,
|
||||||
base::Bind(&CefFileDialogCallbackImpl::Continue, this, file_paths));
|
base::Bind(&CefFileDialogCallbackImpl::Continue, this,
|
||||||
|
selected_accept_filter, file_paths));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,7 +245,7 @@ class CefFileDialogCallbackImpl : public CefFileDialogCallback {
|
|||||||
const CefBrowserHostImpl::RunFileChooserCallback& callback) {
|
const CefBrowserHostImpl::RunFileChooserCallback& callback) {
|
||||||
CEF_REQUIRE_UIT();
|
CEF_REQUIRE_UIT();
|
||||||
std::vector<base::FilePath> file_paths;
|
std::vector<base::FilePath> file_paths;
|
||||||
callback.Run(file_paths);
|
callback.Run(0, file_paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
CefBrowserHostImpl::RunFileChooserCallback callback_;
|
CefBrowserHostImpl::RunFileChooserCallback callback_;
|
||||||
@ -251,32 +253,17 @@ class CefFileDialogCallbackImpl : public CefFileDialogCallback {
|
|||||||
IMPLEMENT_REFCOUNTING(CefFileDialogCallbackImpl);
|
IMPLEMENT_REFCOUNTING(CefFileDialogCallbackImpl);
|
||||||
};
|
};
|
||||||
|
|
||||||
class CefRunFileDialogCallbackWrapper
|
void RunFileDialogDismissed(
|
||||||
: public base::RefCountedThreadSafe<CefRunFileDialogCallbackWrapper> {
|
CefRefPtr<CefRunFileDialogCallback> callback,
|
||||||
public:
|
int selected_accept_filter,
|
||||||
CefRunFileDialogCallbackWrapper(CefRefPtr<CefBrowserHost> host,
|
const std::vector<base::FilePath>& file_paths) {
|
||||||
CefRefPtr<CefRunFileDialogCallback> callback)
|
std::vector<CefString> paths;
|
||||||
: host_(host),
|
if (file_paths.size() > 0) {
|
||||||
callback_(callback) {
|
for (size_t i = 0; i < file_paths.size(); ++i)
|
||||||
|
paths.push_back(file_paths[i].value());
|
||||||
}
|
}
|
||||||
|
callback->OnFileDialogDismissed(selected_accept_filter, paths);
|
||||||
void Callback(const std::vector<base::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:
|
|
||||||
friend class base::RefCountedThreadSafe<CefRunFileDialogCallbackWrapper>;
|
|
||||||
|
|
||||||
~CefRunFileDialogCallbackWrapper() {}
|
|
||||||
|
|
||||||
CefRefPtr<CefBrowserHost> host_;
|
|
||||||
CefRefPtr<CefRunFileDialogCallback> callback_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
@ -712,38 +699,47 @@ void CefBrowserHostImpl::SetZoomLevel(double zoomLevel) {
|
|||||||
void CefBrowserHostImpl::RunFileDialog(
|
void CefBrowserHostImpl::RunFileDialog(
|
||||||
FileDialogMode mode,
|
FileDialogMode mode,
|
||||||
const CefString& title,
|
const CefString& title,
|
||||||
const CefString& default_file_name,
|
const CefString& default_file_path,
|
||||||
const std::vector<CefString>& accept_types,
|
const std::vector<CefString>& accept_filters,
|
||||||
|
int selected_accept_filter,
|
||||||
CefRefPtr<CefRunFileDialogCallback> callback) {
|
CefRefPtr<CefRunFileDialogCallback> callback) {
|
||||||
DCHECK(callback.get());
|
DCHECK(callback.get());
|
||||||
if (!callback.get())
|
if (!callback.get())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
content::FileChooserParams params;
|
FileChooserParams params;
|
||||||
switch (mode) {
|
switch (mode & FILE_DIALOG_TYPE_MASK) {
|
||||||
case FILE_DIALOG_OPEN:
|
case FILE_DIALOG_OPEN:
|
||||||
params.mode = content::FileChooserParams::Open;
|
params.mode = content::FileChooserParams::Open;
|
||||||
break;
|
break;
|
||||||
case FILE_DIALOG_OPEN_MULTIPLE:
|
case FILE_DIALOG_OPEN_MULTIPLE:
|
||||||
params.mode = content::FileChooserParams::OpenMultiple;
|
params.mode = content::FileChooserParams::OpenMultiple;
|
||||||
break;
|
break;
|
||||||
|
case FILE_DIALOG_OPEN_FOLDER:
|
||||||
|
params.mode = content::FileChooserParams::UploadFolder;
|
||||||
|
break;
|
||||||
case FILE_DIALOG_SAVE:
|
case FILE_DIALOG_SAVE:
|
||||||
params.mode = content::FileChooserParams::Save;
|
params.mode = content::FileChooserParams::Save;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DCHECK_GE(selected_accept_filter, 0);
|
||||||
|
params.selected_accept_filter = selected_accept_filter;
|
||||||
|
|
||||||
|
params.overwriteprompt = !!(mode & FILE_DIALOG_OVERWRITEPROMPT_FLAG);
|
||||||
|
params.hidereadonly = !!(mode & FILE_DIALOG_HIDEREADONLY_FLAG);
|
||||||
|
|
||||||
params.title = title;
|
params.title = title;
|
||||||
if (!default_file_name.empty())
|
if (!default_file_path.empty())
|
||||||
params.default_file_name = base::FilePath(default_file_name);
|
params.default_file_name = base::FilePath(default_file_path);
|
||||||
if (!accept_types.empty()) {
|
|
||||||
std::vector<CefString>::const_iterator it = accept_types.begin();
|
if (!accept_filters.empty()) {
|
||||||
for (; it != accept_types.end(); ++it)
|
std::vector<CefString>::const_iterator it = accept_filters.begin();
|
||||||
|
for (; it != accept_filters.end(); ++it)
|
||||||
params.accept_types.push_back(*it);
|
params.accept_types.push_back(*it);
|
||||||
}
|
}
|
||||||
|
|
||||||
scoped_refptr<CefRunFileDialogCallbackWrapper> wrapper =
|
RunFileChooser(params, base::Bind(RunFileDialogDismissed, callback));
|
||||||
new CefRunFileDialogCallbackWrapper(this, callback);
|
|
||||||
RunFileChooser(params,
|
|
||||||
base::Bind(&CefRunFileDialogCallbackWrapper::Callback, wrapper));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefBrowserHostImpl::StartDownload(const CefString& url) {
|
void CefBrowserHostImpl::StartDownload(const CefString& url) {
|
||||||
@ -1773,7 +1769,7 @@ void CefBrowserHostImpl::OnSetFocus(cef_focus_source_t source) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CefBrowserHostImpl::RunFileChooser(
|
void CefBrowserHostImpl::RunFileChooser(
|
||||||
const content::FileChooserParams& params,
|
const FileChooserParams& params,
|
||||||
const RunFileChooserCallback& callback) {
|
const RunFileChooserCallback& callback) {
|
||||||
CEF_POST_TASK(CEF_UIT,
|
CEF_POST_TASK(CEF_UIT,
|
||||||
base::Bind(&CefBrowserHostImpl::RunFileChooserOnUIThread, this, params,
|
base::Bind(&CefBrowserHostImpl::RunFileChooserOnUIThread, this, params,
|
||||||
@ -2269,7 +2265,7 @@ void CefBrowserHostImpl::WebContentsCreated(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CefBrowserHostImpl::DidNavigateMainFramePostCommit(
|
void CefBrowserHostImpl::DidNavigateMainFramePostCommit(
|
||||||
content::WebContents* tab) {
|
content::WebContents* web_contents) {
|
||||||
base::AutoLock lock_scope(state_lock_);
|
base::AutoLock lock_scope(state_lock_);
|
||||||
has_document_ = false;
|
has_document_ = false;
|
||||||
}
|
}
|
||||||
@ -2283,15 +2279,25 @@ content::JavaScriptDialogManager*
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CefBrowserHostImpl::RunFileChooser(
|
void CefBrowserHostImpl::RunFileChooser(
|
||||||
content::WebContents* tab,
|
content::WebContents* web_contents,
|
||||||
const content::FileChooserParams& params) {
|
const content::FileChooserParams& params) {
|
||||||
content::RenderViewHost* render_view_host = tab->GetRenderViewHost();
|
content::RenderViewHost* render_view_host = web_contents->GetRenderViewHost();
|
||||||
if (!render_view_host)
|
if (!render_view_host)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
RunFileChooserOnUIThread(params,
|
if (params.mode == content::FileChooserParams::UploadFolder) {
|
||||||
|
// TODO(cef): Implement the logic necessary for the 'webkitdirectory'
|
||||||
|
// attribute. See CEF issue #958.
|
||||||
|
OnRunFileChooserDelegateCallback(
|
||||||
|
web_contents, params.mode, 0, std::vector<base::FilePath>());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileChooserParams cef_params;
|
||||||
|
static_cast<content::FileChooserParams&>(cef_params) = params;
|
||||||
|
RunFileChooserOnUIThread(cef_params,
|
||||||
base::Bind(&CefBrowserHostImpl::OnRunFileChooserDelegateCallback, this,
|
base::Bind(&CefBrowserHostImpl::OnRunFileChooserDelegateCallback, this,
|
||||||
tab, params.mode));
|
web_contents, params.mode));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CefBrowserHostImpl::SetPendingPopupInfo(
|
bool CefBrowserHostImpl::SetPendingPopupInfo(
|
||||||
@ -2931,19 +2937,13 @@ void CefBrowserHostImpl::OnLoadEnd(CefRefPtr<CefFrame> frame,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CefBrowserHostImpl::RunFileChooserOnUIThread(
|
void CefBrowserHostImpl::RunFileChooserOnUIThread(
|
||||||
const content::FileChooserParams& params,
|
const FileChooserParams& params,
|
||||||
const RunFileChooserCallback& callback) {
|
const RunFileChooserCallback& callback) {
|
||||||
CEF_REQUIRE_UIT();
|
CEF_REQUIRE_UIT();
|
||||||
|
|
||||||
if (file_chooser_pending_) {
|
if (file_chooser_pending_) {
|
||||||
// Dismiss the new dialog immediately.
|
// Dismiss the new dialog immediately.
|
||||||
callback.Run(std::vector<base::FilePath>());
|
callback.Run(0, std::vector<base::FilePath>());
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (params.mode == content::FileChooserParams::UploadFolder) {
|
|
||||||
NOTIMPLEMENTED();
|
|
||||||
callback.Run(std::vector<base::FilePath>());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2958,7 +2958,7 @@ void CefBrowserHostImpl::RunFileChooserOnUIThread(
|
|||||||
if (client_.get()) {
|
if (client_.get()) {
|
||||||
CefRefPtr<CefDialogHandler> handler = client_->GetDialogHandler();
|
CefRefPtr<CefDialogHandler> handler = client_->GetDialogHandler();
|
||||||
if (handler.get()) {
|
if (handler.get()) {
|
||||||
cef_file_dialog_mode_t mode = FILE_DIALOG_OPEN;
|
int mode = FILE_DIALOG_OPEN;
|
||||||
switch (params.mode) {
|
switch (params.mode) {
|
||||||
case content::FileChooserParams::Open:
|
case content::FileChooserParams::Open:
|
||||||
mode = FILE_DIALOG_OPEN;
|
mode = FILE_DIALOG_OPEN;
|
||||||
@ -2966,6 +2966,9 @@ void CefBrowserHostImpl::RunFileChooserOnUIThread(
|
|||||||
case content::FileChooserParams::OpenMultiple:
|
case content::FileChooserParams::OpenMultiple:
|
||||||
mode = FILE_DIALOG_OPEN_MULTIPLE;
|
mode = FILE_DIALOG_OPEN_MULTIPLE;
|
||||||
break;
|
break;
|
||||||
|
case content::FileChooserParams::UploadFolder:
|
||||||
|
mode = FILE_DIALOG_OPEN_FOLDER;
|
||||||
|
break;
|
||||||
case content::FileChooserParams::Save:
|
case content::FileChooserParams::Save:
|
||||||
mode = FILE_DIALOG_SAVE;
|
mode = FILE_DIALOG_SAVE;
|
||||||
break;
|
break;
|
||||||
@ -2974,17 +2977,28 @@ void CefBrowserHostImpl::RunFileChooserOnUIThread(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CefString> accept_types;
|
if (params.overwriteprompt)
|
||||||
std::vector<base::string16>::const_iterator it =
|
mode |= FILE_DIALOG_OVERWRITEPROMPT_FLAG;
|
||||||
params.accept_types.begin();
|
if (params.hidereadonly)
|
||||||
|
mode |= FILE_DIALOG_HIDEREADONLY_FLAG;
|
||||||
|
|
||||||
|
std::vector<base::string16>::const_iterator it;
|
||||||
|
|
||||||
|
std::vector<CefString> accept_filters;
|
||||||
|
it = params.accept_types.begin();
|
||||||
for (; it != params.accept_types.end(); ++it)
|
for (; it != params.accept_types.end(); ++it)
|
||||||
accept_types.push_back(*it);
|
accept_filters.push_back(*it);
|
||||||
|
|
||||||
CefRefPtr<CefFileDialogCallbackImpl> callbackImpl(
|
CefRefPtr<CefFileDialogCallbackImpl> callbackImpl(
|
||||||
new CefFileDialogCallbackImpl(host_callback));
|
new CefFileDialogCallbackImpl(host_callback));
|
||||||
handled = handler->OnFileDialog(this, mode, params.title,
|
handled = handler->OnFileDialog(
|
||||||
params.default_file_name.value(),
|
this,
|
||||||
accept_types, callbackImpl.get());
|
static_cast<cef_file_dialog_mode_t>(mode),
|
||||||
|
params.title,
|
||||||
|
params.default_file_name.value(),
|
||||||
|
accept_filters,
|
||||||
|
params.selected_accept_filter,
|
||||||
|
callbackImpl.get());
|
||||||
if (!handled) {
|
if (!handled) {
|
||||||
if (callbackImpl->IsConnected()) {
|
if (callbackImpl->IsConnected()) {
|
||||||
callbackImpl->Disconnect();
|
callbackImpl->Disconnect();
|
||||||
@ -3003,22 +3017,25 @@ void CefBrowserHostImpl::RunFileChooserOnUIThread(
|
|||||||
|
|
||||||
void CefBrowserHostImpl::OnRunFileChooserCallback(
|
void CefBrowserHostImpl::OnRunFileChooserCallback(
|
||||||
const RunFileChooserCallback& callback,
|
const RunFileChooserCallback& callback,
|
||||||
|
int selected_accept_filter,
|
||||||
const std::vector<base::FilePath>& file_paths) {
|
const std::vector<base::FilePath>& file_paths) {
|
||||||
CEF_REQUIRE_UIT();
|
CEF_REQUIRE_UIT();
|
||||||
|
|
||||||
file_chooser_pending_ = false;
|
file_chooser_pending_ = false;
|
||||||
|
|
||||||
// Execute the callback asynchronously.
|
// Execute the callback asynchronously.
|
||||||
CEF_POST_TASK(CEF_UIT, base::Bind(callback, file_paths));
|
CEF_POST_TASK(CEF_UIT,
|
||||||
|
base::Bind(callback, selected_accept_filter, file_paths));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefBrowserHostImpl::OnRunFileChooserDelegateCallback(
|
void CefBrowserHostImpl::OnRunFileChooserDelegateCallback(
|
||||||
content::WebContents* tab,
|
content::WebContents* web_contents,
|
||||||
content::FileChooserParams::Mode mode,
|
content::FileChooserParams::Mode mode,
|
||||||
|
int selected_accept_filter,
|
||||||
const std::vector<base::FilePath>& file_paths) {
|
const std::vector<base::FilePath>& file_paths) {
|
||||||
CEF_REQUIRE_UIT();
|
CEF_REQUIRE_UIT();
|
||||||
|
|
||||||
content::RenderViewHost* render_view_host = tab->GetRenderViewHost();
|
content::RenderViewHost* render_view_host = web_contents->GetRenderViewHost();
|
||||||
if (!render_view_host)
|
if (!render_view_host)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -97,6 +97,18 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
|||||||
virtual void OnResponse(const std::string& response) =0;
|
virtual void OnResponse(const std::string& response) =0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Extend content::FileChooserParams with some options unique to CEF.
|
||||||
|
struct FileChooserParams : public content::FileChooserParams {
|
||||||
|
// 0-based index of the selected value in |accept_types|.
|
||||||
|
int selected_accept_filter = 0;
|
||||||
|
|
||||||
|
// True if the Save dialog should prompt before overwriting files.
|
||||||
|
bool overwriteprompt = true;
|
||||||
|
|
||||||
|
// True if read-only files should be hidden.
|
||||||
|
bool hidereadonly = true;
|
||||||
|
};
|
||||||
|
|
||||||
~CefBrowserHostImpl() override;
|
~CefBrowserHostImpl() override;
|
||||||
|
|
||||||
// Create a new CefBrowserHostImpl instance.
|
// Create a new CefBrowserHostImpl instance.
|
||||||
@ -142,8 +154,9 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
|||||||
void RunFileDialog(
|
void RunFileDialog(
|
||||||
FileDialogMode mode,
|
FileDialogMode mode,
|
||||||
const CefString& title,
|
const CefString& title,
|
||||||
const CefString& default_file_name,
|
const CefString& default_file_path,
|
||||||
const std::vector<CefString>& accept_types,
|
const std::vector<CefString>& accept_filters,
|
||||||
|
int selected_accept_filter,
|
||||||
CefRefPtr<CefRunFileDialogCallback> callback) override;
|
CefRefPtr<CefRunFileDialogCallback> callback) override;
|
||||||
void StartDownload(const CefString& url) override;
|
void StartDownload(const CefString& url) override;
|
||||||
void Print() override;
|
void Print() override;
|
||||||
@ -307,13 +320,13 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
|||||||
void OnSetFocus(cef_focus_source_t source);
|
void OnSetFocus(cef_focus_source_t source);
|
||||||
|
|
||||||
// The argument vector will be empty if the dialog was cancelled.
|
// The argument vector will be empty if the dialog was cancelled.
|
||||||
typedef base::Callback<void(const std::vector<base::FilePath>&)>
|
typedef base::Callback<void(int, const std::vector<base::FilePath>&)>
|
||||||
RunFileChooserCallback;
|
RunFileChooserCallback;
|
||||||
|
|
||||||
// Run the file chooser dialog specified by |params|. Only a single dialog may
|
// Run the file chooser dialog specified by |params|. Only a single dialog may
|
||||||
// be pending at any given time. |callback| will be executed asynchronously
|
// be pending at any given time. |callback| will be executed asynchronously
|
||||||
// after the dialog is dismissed or if another dialog is already pending.
|
// after the dialog is dismissed or if another dialog is already pending.
|
||||||
void RunFileChooser(const content::FileChooserParams& params,
|
void RunFileChooser(const FileChooserParams& params,
|
||||||
const RunFileChooserCallback& callback);
|
const RunFileChooserCallback& callback);
|
||||||
|
|
||||||
// Used when creating a new popup window.
|
// Used when creating a new popup window.
|
||||||
@ -383,11 +396,11 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
|||||||
const GURL& target_url,
|
const GURL& target_url,
|
||||||
content::WebContents* new_contents) override;
|
content::WebContents* new_contents) override;
|
||||||
void DidNavigateMainFramePostCommit(
|
void DidNavigateMainFramePostCommit(
|
||||||
content::WebContents* tab) override;
|
content::WebContents* web_contents) override;
|
||||||
content::JavaScriptDialogManager* GetJavaScriptDialogManager(
|
content::JavaScriptDialogManager* GetJavaScriptDialogManager(
|
||||||
content::WebContents* source) override;
|
content::WebContents* source) override;
|
||||||
void RunFileChooser(
|
void RunFileChooser(
|
||||||
content::WebContents* tab,
|
content::WebContents* web_contents,
|
||||||
const content::FileChooserParams& params) override;
|
const content::FileChooserParams& params) override;
|
||||||
void FindReply(
|
void FindReply(
|
||||||
content::WebContents* web_contents,
|
content::WebContents* web_contents,
|
||||||
@ -528,7 +541,7 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
|||||||
// Invoke platform specific handling for the external protocol.
|
// Invoke platform specific handling for the external protocol.
|
||||||
void PlatformHandleExternalProtocol(const GURL& url);
|
void PlatformHandleExternalProtocol(const GURL& url);
|
||||||
// Invoke platform specific file chooser dialog.
|
// Invoke platform specific file chooser dialog.
|
||||||
void PlatformRunFileChooser(const content::FileChooserParams& params,
|
void PlatformRunFileChooser(const FileChooserParams& params,
|
||||||
RunFileChooserCallback callback);
|
RunFileChooserCallback callback);
|
||||||
|
|
||||||
void PlatformTranslateKeyEvent(content::NativeWebKeyboardEvent& native_event,
|
void PlatformTranslateKeyEvent(content::NativeWebKeyboardEvent& native_event,
|
||||||
@ -565,17 +578,19 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
|||||||
int http_status_code);
|
int http_status_code);
|
||||||
|
|
||||||
// Continuation from RunFileChooser.
|
// Continuation from RunFileChooser.
|
||||||
void RunFileChooserOnUIThread(const content::FileChooserParams& params,
|
void RunFileChooserOnUIThread(const FileChooserParams& params,
|
||||||
const RunFileChooserCallback& callback);
|
const RunFileChooserCallback& callback);
|
||||||
|
|
||||||
// Used with RunFileChooser to clear the |file_chooser_pending_| flag.
|
// Used with RunFileChooser to clear the |file_chooser_pending_| flag.
|
||||||
void OnRunFileChooserCallback(const RunFileChooserCallback& callback,
|
void OnRunFileChooserCallback(const RunFileChooserCallback& callback,
|
||||||
|
int selected_accept_filter,
|
||||||
const std::vector<base::FilePath>& file_paths);
|
const std::vector<base::FilePath>& file_paths);
|
||||||
|
|
||||||
// Used with WebContentsDelegate::RunFileChooser to notify the WebContents.
|
// Used with WebContentsDelegate::RunFileChooser to notify the WebContents.
|
||||||
void OnRunFileChooserDelegateCallback(
|
void OnRunFileChooserDelegateCallback(
|
||||||
content::WebContents* tab,
|
content::WebContents* web_contents,
|
||||||
content::FileChooserParams::Mode mode,
|
content::FileChooserParams::Mode mode,
|
||||||
|
int selected_accept_filter,
|
||||||
const std::vector<base::FilePath>& file_paths);
|
const std::vector<base::FilePath>& file_paths);
|
||||||
|
|
||||||
void OnDevToolsWebContentsDestroyed();
|
void OnDevToolsWebContentsDestroyed();
|
||||||
|
@ -282,11 +282,10 @@ void CefBrowserHostImpl::PlatformHandleKeyboardEvent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CefBrowserHostImpl::PlatformRunFileChooser(
|
void CefBrowserHostImpl::PlatformRunFileChooser(
|
||||||
const content::FileChooserParams& params,
|
const FileChooserParams& params,
|
||||||
RunFileChooserCallback callback) {
|
RunFileChooserCallback callback) {
|
||||||
NOTIMPLEMENTED();
|
NOTIMPLEMENTED();
|
||||||
std::vector<base::FilePath> files;
|
callback.Run(0, std::vector<base::FilePath>());
|
||||||
callback.Run(files);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefBrowserHostImpl::PlatformHandleExternalProtocol(const GURL& url) {
|
void CefBrowserHostImpl::PlatformHandleExternalProtocol(const GURL& url) {
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "base/files/file_util.h"
|
#include "base/files/file_util.h"
|
||||||
#include "base/mac/mac_util.h"
|
#include "base/mac/mac_util.h"
|
||||||
#include "base/mac/scoped_nsautorelease_pool.h"
|
#include "base/mac/scoped_nsautorelease_pool.h"
|
||||||
|
#include "base/strings/string_split.h"
|
||||||
#include "base/strings/string_util.h"
|
#include "base/strings/string_util.h"
|
||||||
#include "base/strings/sys_string_conversions.h"
|
#include "base/strings/sys_string_conversions.h"
|
||||||
#include "base/strings/utf_string_conversions.h"
|
#include "base/strings/utf_string_conversions.h"
|
||||||
@ -23,6 +24,7 @@
|
|||||||
#include "content/public/browser/render_widget_host_view.h"
|
#include "content/public/browser/render_widget_host_view.h"
|
||||||
#include "content/public/browser/web_contents.h"
|
#include "content/public/browser/web_contents.h"
|
||||||
#include "content/public/common/file_chooser_params.h"
|
#include "content/public/common/file_chooser_params.h"
|
||||||
|
#include "grit/cef_strings.h"
|
||||||
#include "grit/ui_strings.h"
|
#include "grit/ui_strings.h"
|
||||||
#include "net/base/mime_util.h"
|
#include "net/base/mime_util.h"
|
||||||
#include "third_party/WebKit/public/web/WebInputEvent.h"
|
#include "third_party/WebKit/public/web/WebInputEvent.h"
|
||||||
@ -170,33 +172,216 @@
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
base::string16 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 base::string16();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddFilters(NSPopUpButton *button,
|
||||||
|
const std::vector<base::string16>& accept_filters,
|
||||||
|
bool include_all_files,
|
||||||
|
std::vector<std::vector<base::string16> >* all_extensions) {
|
||||||
|
for (size_t i = 0; i < accept_filters.size(); ++i) {
|
||||||
|
const base::string16& filter = accept_filters[i];
|
||||||
|
if (filter.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::vector<base::string16> extensions;
|
||||||
|
base::string16 description;
|
||||||
|
|
||||||
|
size_t sep_index = filter.find('|');
|
||||||
|
if (sep_index != std::string::npos) {
|
||||||
|
// Treat as a filter of the form "Filter Name|.ext1;.ext2;.ext3".
|
||||||
|
description = filter.substr(0, sep_index);
|
||||||
|
|
||||||
|
std::vector<base::string16> ext;
|
||||||
|
base::SplitString(filter.substr(sep_index + 1), ';', &ext);
|
||||||
|
for (size_t x = 0; x < ext.size(); ++x) {
|
||||||
|
const base::string16& file_ext = ext[x];
|
||||||
|
if (!file_ext.empty() && file_ext[0] == '.')
|
||||||
|
extensions.push_back(file_ext);
|
||||||
|
}
|
||||||
|
} else if (filter[0] == '.') {
|
||||||
|
// Treat as an extension beginning with the '.' character.
|
||||||
|
extensions.push_back(filter);
|
||||||
|
} else {
|
||||||
|
// Otherwise convert mime type to one or more extensions.
|
||||||
|
const std::string& ascii = base::UTF16ToASCII(filter);
|
||||||
|
std::vector<base::FilePath::StringType> ext;
|
||||||
|
net::GetExtensionsForMimeType(ascii, &ext);
|
||||||
|
if (!ext.empty()) {
|
||||||
|
for (size_t x = 0; x < ext.size(); ++x)
|
||||||
|
extensions.push_back(base::ASCIIToUTF16("." + ext[x]));
|
||||||
|
description = GetDescriptionFromMimeType(ascii);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extensions.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Don't display a crazy number of extensions since the NSPopUpButton width
|
||||||
|
// will keep growing.
|
||||||
|
const size_t kMaxExtensions = 10;
|
||||||
|
|
||||||
|
base::string16 ext_str;
|
||||||
|
for (size_t x = 0; x < std::min(kMaxExtensions, extensions.size()); ++x) {
|
||||||
|
const base::string16& pattern = base::ASCIIToUTF16("*") + extensions[x];
|
||||||
|
if (x != 0)
|
||||||
|
ext_str += base::ASCIIToUTF16(";");
|
||||||
|
ext_str += pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extensions.size() > kMaxExtensions)
|
||||||
|
ext_str += base::ASCIIToUTF16(";...");
|
||||||
|
|
||||||
|
if (description.empty()) {
|
||||||
|
description = ext_str;
|
||||||
|
} else {
|
||||||
|
description +=
|
||||||
|
base::ASCIIToUTF16(" (") + ext_str + base::ASCIIToUTF16(")");
|
||||||
|
}
|
||||||
|
|
||||||
|
[button addItemWithTitle:base::SysUTF16ToNSString(description)];
|
||||||
|
|
||||||
|
all_extensions->push_back(extensions);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the *.* filter, but only if we have added other filters (otherwise it
|
||||||
|
// is implied).
|
||||||
|
if (include_all_files && !all_extensions->empty()) {
|
||||||
|
[button addItemWithTitle:base::SysUTF8ToNSString("All Files (*)")];
|
||||||
|
all_extensions->push_back(std::vector<base::string16>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// Used to manage the file type filter in the NSSavePanel/NSOpenPanel.
|
||||||
|
@interface CefFilterDelegate : NSObject {
|
||||||
|
@private
|
||||||
|
NSSavePanel* panel_;
|
||||||
|
std::vector<std::vector<base::string16> > extensions_;
|
||||||
|
int selected_index_;
|
||||||
|
}
|
||||||
|
- (id)initWithPanel:(NSSavePanel*)panel
|
||||||
|
andAcceptFilters:(const std::vector<base::string16>&)accept_filters
|
||||||
|
andFilterIndex:(int)index;
|
||||||
|
- (void)setFilter:(int)index;
|
||||||
|
- (int)filter;
|
||||||
|
- (void)filterSelectionChanged:(id)sender;
|
||||||
|
- (void)setFileExtension;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation CefFilterDelegate
|
||||||
|
|
||||||
|
- (id)initWithPanel:(NSSavePanel*)panel
|
||||||
|
andAcceptFilters:(const std::vector<base::string16>&)accept_filters
|
||||||
|
andFilterIndex:(int)index {
|
||||||
|
if (self = [super init]) {
|
||||||
|
DCHECK(panel);
|
||||||
|
panel_ = panel;
|
||||||
|
selected_index_ = 0;
|
||||||
|
|
||||||
|
NSPopUpButton *button = [[NSPopUpButton alloc] init];
|
||||||
|
AddFilters(button, accept_filters, true, &extensions_);
|
||||||
|
[button sizeToFit];
|
||||||
|
[button setTarget:self];
|
||||||
|
[button setAction:@selector(filterSelectionChanged:)];
|
||||||
|
|
||||||
|
if (index < static_cast<int>(extensions_.size())) {
|
||||||
|
[button selectItemAtIndex:index];
|
||||||
|
[self setFilter:index];
|
||||||
|
}
|
||||||
|
|
||||||
|
[panel_ setAccessoryView:button];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the current filter index.
|
||||||
|
- (void)setFilter:(int)index {
|
||||||
|
DCHECK(index >= 0 && index < static_cast<int>(extensions_.size()));
|
||||||
|
selected_index_ = index;
|
||||||
|
|
||||||
|
// Set the selectable file types. For open panels this limits the files that
|
||||||
|
// can be selected. For save panels this applies a default file extenion when
|
||||||
|
// the dialog is dismissed if none is already provided.
|
||||||
|
NSMutableArray* acceptArray = nil;
|
||||||
|
if (!extensions_[index].empty()) {
|
||||||
|
acceptArray = [[NSMutableArray alloc] init];
|
||||||
|
for (size_t i = 0; i < extensions_[index].size(); ++i) {
|
||||||
|
[acceptArray addObject:
|
||||||
|
base::SysUTF16ToNSString(extensions_[index][i].substr(1))];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[panel_ setAllowedFileTypes:acceptArray];
|
||||||
|
|
||||||
|
if (![panel_ isKindOfClass:[NSOpenPanel class]]) {
|
||||||
|
// For save panels set the file extension.
|
||||||
|
[self setFileExtension];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the current filter index.
|
||||||
|
- (int)filter {
|
||||||
|
return selected_index_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when the selected filter is changed via the NSPopUpButton.
|
||||||
|
- (void)filterSelectionChanged:(id)sender {
|
||||||
|
NSPopUpButton *button = (NSPopUpButton*)sender;
|
||||||
|
[self setFilter:[button indexOfSelectedItem]];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the extension on the currently selected file name.
|
||||||
|
- (void)setFileExtension {
|
||||||
|
const std::vector<base::string16>& filter = extensions_[selected_index_];
|
||||||
|
if (filter.empty()) {
|
||||||
|
// All extensions are allowed so don't change anything.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
base::FilePath path(base::SysNSStringToUTF8([panel_ nameFieldStringValue]));
|
||||||
|
|
||||||
|
// If the file name currently includes an extension from |filter| then don't
|
||||||
|
// change anything.
|
||||||
|
base::string16 extension = base::UTF8ToUTF16(path.Extension());
|
||||||
|
if (!extension.empty()) {
|
||||||
|
for (size_t i = 0; i < filter.size(); ++i) {
|
||||||
|
if (filter[i] == extension)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change the extension to the first value in |filter|.
|
||||||
|
path = path.ReplaceExtension(base::UTF16ToUTF8(filter[0]));
|
||||||
|
[panel_ setNameFieldStringValue:base::SysUTF8ToNSString(path.value())];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// Accept-types to file-types helper.
|
void RunOpenFileDialog(const CefBrowserHostImpl::FileChooserParams& params,
|
||||||
NSMutableArray* GetFileTypesFromAcceptTypes(
|
|
||||||
const std::vector<base::string16>& accept_types) {
|
|
||||||
NSMutableArray* acceptArray = [[NSMutableArray alloc] init];
|
|
||||||
for (size_t i=0; i<accept_types.size(); i++) {
|
|
||||||
std::string ascii_type = base::UTF16ToASCII(accept_types[i]);
|
|
||||||
if (ascii_type.length()) {
|
|
||||||
// Just treat as extension if contains '.' as the first character.
|
|
||||||
if (ascii_type[0] == '.') {
|
|
||||||
[acceptArray addObject:base::SysUTF8ToNSString(ascii_type.substr(1))];
|
|
||||||
} else {
|
|
||||||
// Otherwise convert mime type to one or more extensions.
|
|
||||||
std::vector<base::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,
|
NSView* view,
|
||||||
|
int* filter_index,
|
||||||
std::vector<base::FilePath>* files) {
|
std::vector<base::FilePath>* files) {
|
||||||
NSOpenPanel* openPanel = [NSOpenPanel openPanel];
|
NSOpenPanel* openPanel = [NSOpenPanel openPanel];
|
||||||
|
|
||||||
@ -206,39 +391,51 @@ void RunOpenFileDialog(const content::FileChooserParams& params,
|
|||||||
} else {
|
} else {
|
||||||
title = l10n_util::GetStringUTF16(
|
title = l10n_util::GetStringUTF16(
|
||||||
params.mode == content::FileChooserParams::Open ?
|
params.mode == content::FileChooserParams::Open ?
|
||||||
IDS_OPEN_FILE_DIALOG_TITLE : IDS_OPEN_FILES_DIALOG_TITLE);
|
IDS_OPEN_FILE_DIALOG_TITLE :
|
||||||
|
(params.mode == content::FileChooserParams::OpenMultiple ?
|
||||||
|
IDS_OPEN_FILES_DIALOG_TITLE : IDS_SELECT_FOLDER_DIALOG_TITLE));
|
||||||
}
|
}
|
||||||
[openPanel setTitle:base::SysUTF16ToNSString(title)];
|
[openPanel setTitle:base::SysUTF16ToNSString(title)];
|
||||||
|
|
||||||
// Consider default file name if any.
|
std::string filename, directory;
|
||||||
base::FilePath default_file_name(params.default_file_name);
|
if (!params.default_file_name.empty()) {
|
||||||
|
if (params.mode == content::FileChooserParams::UploadFolder ||
|
||||||
if (!default_file_name.empty()) {
|
params.default_file_name.EndsWithSeparator()) {
|
||||||
if (!default_file_name.BaseName().empty()) {
|
// The value is only a directory.
|
||||||
NSString* defaultName = base::SysUTF8ToNSString(
|
directory = params.default_file_name.value();
|
||||||
default_file_name.BaseName().value());
|
} else {
|
||||||
[openPanel setNameFieldStringValue:defaultName];
|
// The value is a file name and possibly a directory.
|
||||||
}
|
filename = params.default_file_name.BaseName().value();
|
||||||
|
directory = params.default_file_name.DirName().value();
|
||||||
if (!default_file_name.DirName().empty()) {
|
|
||||||
NSString* defaultDir = base::SysUTF8ToNSString(
|
|
||||||
default_file_name.DirName().value());
|
|
||||||
[openPanel setDirectoryURL:[NSURL fileURLWithPath:defaultDir]];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!filename.empty()) {
|
||||||
|
[openPanel setNameFieldStringValue:base::SysUTF8ToNSString(filename)];
|
||||||
|
}
|
||||||
|
if (!directory.empty()) {
|
||||||
|
[openPanel setDirectoryURL:
|
||||||
|
[NSURL fileURLWithPath:base::SysUTF8ToNSString(directory)]];
|
||||||
|
}
|
||||||
|
|
||||||
// Consider supported file types
|
CefFilterDelegate* filter_delegate = nil;
|
||||||
if (!params.accept_types.empty()) {
|
if (params.mode != content::FileChooserParams::UploadFolder &&
|
||||||
[openPanel setAllowedFileTypes:GetFileTypesFromAcceptTypes(
|
!params.accept_types.empty()) {
|
||||||
params.accept_types)];
|
// Add the file filter control.
|
||||||
|
filter_delegate =
|
||||||
|
[[CefFilterDelegate alloc] initWithPanel:openPanel
|
||||||
|
andAcceptFilters:params.accept_types
|
||||||
|
andFilterIndex:*filter_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Further panel configuration.
|
// Further panel configuration.
|
||||||
[openPanel setAllowsOtherFileTypes:YES];
|
[openPanel setAllowsOtherFileTypes:YES];
|
||||||
[openPanel setAllowsMultipleSelection:
|
[openPanel setAllowsMultipleSelection:
|
||||||
(params.mode == content::FileChooserParams::OpenMultiple)];
|
(params.mode == content::FileChooserParams::OpenMultiple)];
|
||||||
[openPanel setCanChooseFiles:YES];
|
[openPanel setCanChooseFiles:
|
||||||
[openPanel setCanChooseDirectories:NO];
|
(params.mode != content::FileChooserParams::UploadFolder)];
|
||||||
|
[openPanel setCanChooseDirectories:
|
||||||
|
(params.mode == content::FileChooserParams::UploadFolder)];
|
||||||
|
[openPanel setShowsHiddenFiles:!params.hidereadonly];
|
||||||
|
|
||||||
// Show panel.
|
// Show panel.
|
||||||
[openPanel beginSheetModalForWindow:[view window] completionHandler:nil];
|
[openPanel beginSheetModalForWindow:[view window] completionHandler:nil];
|
||||||
@ -251,11 +448,16 @@ void RunOpenFileDialog(const content::FileChooserParams& params,
|
|||||||
files->push_back(base::FilePath(base::SysNSStringToUTF8([url path])));
|
files->push_back(base::FilePath(base::SysNSStringToUTF8([url path])));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (filter_delegate != nil)
|
||||||
|
*filter_index = [filter_delegate filter];
|
||||||
|
|
||||||
[NSApp endSheet:openPanel];
|
[NSApp endSheet:openPanel];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RunSaveFileDialog(const content::FileChooserParams& params,
|
bool RunSaveFileDialog(const CefBrowserHostImpl::FileChooserParams& params,
|
||||||
NSView* view,
|
NSView* view,
|
||||||
|
int* filter_index,
|
||||||
base::FilePath* file) {
|
base::FilePath* file) {
|
||||||
NSSavePanel* savePanel = [NSSavePanel savePanel];
|
NSSavePanel* savePanel = [NSSavePanel savePanel];
|
||||||
|
|
||||||
@ -266,30 +468,36 @@ bool RunSaveFileDialog(const content::FileChooserParams& params,
|
|||||||
title = l10n_util::GetStringUTF16(IDS_SAVE_AS_DIALOG_TITLE);
|
title = l10n_util::GetStringUTF16(IDS_SAVE_AS_DIALOG_TITLE);
|
||||||
[savePanel setTitle:base::SysUTF16ToNSString(title)];
|
[savePanel setTitle:base::SysUTF16ToNSString(title)];
|
||||||
|
|
||||||
// Consider default file name if any.
|
std::string filename, directory;
|
||||||
base::FilePath default_file_name(params.default_file_name);
|
if (!params.default_file_name.empty()) {
|
||||||
|
if (params.default_file_name.EndsWithSeparator()) {
|
||||||
if (!default_file_name.empty()) {
|
// The value is only a directory.
|
||||||
if (!default_file_name.BaseName().empty()) {
|
directory = params.default_file_name.value();
|
||||||
NSString* defaultName = base::SysUTF8ToNSString(
|
} else {
|
||||||
default_file_name.BaseName().value());
|
// The value is a file name and possibly a directory.
|
||||||
[savePanel setNameFieldStringValue:defaultName];
|
filename = params.default_file_name.BaseName().value();
|
||||||
}
|
directory = params.default_file_name.DirName().value();
|
||||||
|
|
||||||
if (!default_file_name.DirName().empty()) {
|
|
||||||
NSString* defaultDir = base::SysUTF8ToNSString(
|
|
||||||
default_file_name.DirName().value());
|
|
||||||
[savePanel setDirectoryURL:[NSURL fileURLWithPath:defaultDir]];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!filename.empty()) {
|
||||||
|
[savePanel setNameFieldStringValue:base::SysUTF8ToNSString(filename)];
|
||||||
|
}
|
||||||
|
if (!directory.empty()) {
|
||||||
|
[savePanel setDirectoryURL:
|
||||||
|
[NSURL fileURLWithPath:base::SysUTF8ToNSString(directory)]];
|
||||||
|
}
|
||||||
|
|
||||||
// Consider supported file types
|
CefFilterDelegate* filter_delegate = nil;
|
||||||
if (!params.accept_types.empty()) {
|
if (!params.accept_types.empty()) {
|
||||||
[savePanel setAllowedFileTypes:GetFileTypesFromAcceptTypes(
|
// Add the file filter control.
|
||||||
params.accept_types)];
|
filter_delegate =
|
||||||
|
[[CefFilterDelegate alloc] initWithPanel:savePanel
|
||||||
|
andAcceptFilters:params.accept_types
|
||||||
|
andFilterIndex:*filter_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
[savePanel setAllowsOtherFileTypes:YES];
|
[savePanel setAllowsOtherFileTypes:YES];
|
||||||
|
[savePanel setShowsHiddenFiles:!params.hidereadonly];
|
||||||
|
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
|
||||||
@ -300,6 +508,10 @@ bool RunSaveFileDialog(const content::FileChooserParams& params,
|
|||||||
*file = base::FilePath([path UTF8String]);
|
*file = base::FilePath([path UTF8String]);
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (filter_delegate != nil)
|
||||||
|
*filter_index = [filter_delegate filter];
|
||||||
|
|
||||||
[NSApp endSheet:savePanel];
|
[NSApp endSheet:savePanel];
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
@ -491,22 +703,26 @@ void CefBrowserHostImpl::PlatformHandleKeyboardEvent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CefBrowserHostImpl::PlatformRunFileChooser(
|
void CefBrowserHostImpl::PlatformRunFileChooser(
|
||||||
const content::FileChooserParams& params,
|
const FileChooserParams& params,
|
||||||
RunFileChooserCallback callback) {
|
RunFileChooserCallback callback) {
|
||||||
std::vector<base::FilePath> files;
|
std::vector<base::FilePath> files;
|
||||||
|
int filter_index = params.selected_accept_filter;
|
||||||
|
NSView* owner = PlatformGetWindowHandle();
|
||||||
|
|
||||||
if (params.mode == content::FileChooserParams::Open ||
|
if (params.mode == content::FileChooserParams::Open ||
|
||||||
params.mode == content::FileChooserParams::OpenMultiple) {
|
params.mode == content::FileChooserParams::OpenMultiple ||
|
||||||
RunOpenFileDialog(params, PlatformGetWindowHandle(), &files);
|
params.mode == content::FileChooserParams::UploadFolder) {
|
||||||
|
RunOpenFileDialog(params, owner, &filter_index, &files);
|
||||||
} else if (params.mode == content::FileChooserParams::Save) {
|
} else if (params.mode == content::FileChooserParams::Save) {
|
||||||
base::FilePath file;
|
base::FilePath file;
|
||||||
if (RunSaveFileDialog(params, PlatformGetWindowHandle(), &file))
|
if (RunSaveFileDialog(params, owner, &filter_index, &file)) {
|
||||||
files.push_back(file);
|
files.push_back(file);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
NOTIMPLEMENTED();
|
NOTIMPLEMENTED();
|
||||||
}
|
}
|
||||||
|
|
||||||
callback.Run(files);
|
callback.Run(filter_index, files);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefBrowserHostImpl::PlatformHandleExternalProtocol(const GURL& url) {
|
void CefBrowserHostImpl::PlatformHandleExternalProtocol(const GURL& url) {
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <commdlg.h>
|
#include <commdlg.h>
|
||||||
#include <dwmapi.h>
|
#include <dwmapi.h>
|
||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
|
#include <shlobj.h>
|
||||||
#include <wininet.h>
|
#include <wininet.h>
|
||||||
#include <winspool.h>
|
#include <winspool.h>
|
||||||
|
|
||||||
@ -19,9 +20,11 @@
|
|||||||
#include "base/files/file_util.h"
|
#include "base/files/file_util.h"
|
||||||
#include "base/i18n/case_conversion.h"
|
#include "base/i18n/case_conversion.h"
|
||||||
#include "base/memory/ref_counted_memory.h"
|
#include "base/memory/ref_counted_memory.h"
|
||||||
|
#include "base/strings/string_split.h"
|
||||||
#include "base/strings/string_util.h"
|
#include "base/strings/string_util.h"
|
||||||
#include "base/strings/utf_string_conversions.h"
|
#include "base/strings/utf_string_conversions.h"
|
||||||
#include "base/win/registry.h"
|
#include "base/win/registry.h"
|
||||||
|
#include "base/win/scoped_comptr.h"
|
||||||
#include "base/win/windows_version.h"
|
#include "base/win/windows_version.h"
|
||||||
#include "content/common/cursors/webcursor.h"
|
#include "content/common/cursors/webcursor.h"
|
||||||
#include "content/public/browser/native_web_keyboard_event.h"
|
#include "content/public/browser/native_web_keyboard_event.h"
|
||||||
@ -140,14 +143,8 @@ std::wstring FormatFilterForExtensions(
|
|||||||
ext_name = ext_name.substr(ext_index);
|
ext_name = ext_name.substr(ext_index);
|
||||||
|
|
||||||
if (!GetRegistryDescriptionFromExtension(first_extension, &desc)) {
|
if (!GetRegistryDescriptionFromExtension(first_extension, &desc)) {
|
||||||
// The extension doesn't exist in the registry. Create a description
|
// The extension doesn't exist in the registry.
|
||||||
// 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;
|
include_all_files = true;
|
||||||
desc = l10n_util::GetStringFUTF16(
|
|
||||||
IDS_APP_SAVEAS_EXTENSION_FORMAT,
|
|
||||||
base::i18n::ToUpper(base::WideToUTF16(ext_name)),
|
|
||||||
ext_name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,33 +186,54 @@ std::wstring GetDescriptionFromMimeType(const std::string& mime_type) {
|
|||||||
return std::wstring();
|
return std::wstring();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::wstring GetFilterStringFromAcceptTypes(
|
std::wstring GetFilterString(
|
||||||
const std::vector<base::string16>& accept_types) {
|
const std::vector<base::string16>& accept_filters) {
|
||||||
std::vector<std::wstring> extensions;
|
std::vector<std::wstring> extensions;
|
||||||
std::vector<std::wstring> descriptions;
|
std::vector<std::wstring> descriptions;
|
||||||
|
|
||||||
for (size_t i = 0; i < accept_types.size(); ++i) {
|
for (size_t i = 0; i < accept_filters.size(); ++i) {
|
||||||
std::string ascii_type = base::UTF16ToASCII(accept_types[i]);
|
const base::string16& filter = accept_filters[i];
|
||||||
if (ascii_type.length()) {
|
if (filter.empty())
|
||||||
// Just treat as extension if contains '.' as the first character.
|
continue;
|
||||||
if (ascii_type[0] == '.') {
|
|
||||||
extensions.push_back(L"*" + base::ASCIIToUTF16(ascii_type));
|
size_t sep_index = filter.find('|');
|
||||||
descriptions.push_back(std::wstring());
|
if (sep_index != base::string16::npos) {
|
||||||
} else {
|
// Treat as a filter of the form "Filter Name|.ext1;.ext2;.ext3".
|
||||||
// Otherwise convert mime type to one or more extensions.
|
const base::string16& desc = filter.substr(0, sep_index);
|
||||||
std::vector<base::FilePath::StringType> ext;
|
std::vector<base::string16> ext;
|
||||||
std::wstring ext_str;
|
base::SplitString(filter.substr(sep_index + 1), ';', &ext);
|
||||||
net::GetExtensionsForMimeType(ascii_type, &ext);
|
std::wstring ext_str;
|
||||||
if (ext.size() > 0) {
|
for (size_t x = 0; x < ext.size(); ++x) {
|
||||||
for (size_t x = 0; x < ext.size(); ++x) {
|
const base::string16& file_ext = ext[x];
|
||||||
if (x != 0)
|
if (!file_ext.empty() && file_ext[0] == '.') {
|
||||||
ext_str += L";";
|
if (!ext_str.empty())
|
||||||
ext_str += L"*." + ext[x];
|
ext_str += L";";
|
||||||
}
|
ext_str += L"*" + file_ext;
|
||||||
extensions.push_back(ext_str);
|
|
||||||
descriptions.push_back(GetDescriptionFromMimeType(ascii_type));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!ext_str.empty()) {
|
||||||
|
extensions.push_back(ext_str);
|
||||||
|
descriptions.push_back(desc);
|
||||||
|
}
|
||||||
|
} else if (filter[0] == L'.') {
|
||||||
|
// Treat as an extension beginning with the '.' character.
|
||||||
|
extensions.push_back(L"*" + filter);
|
||||||
|
descriptions.push_back(std::wstring());
|
||||||
|
} else {
|
||||||
|
// Otherwise convert mime type to one or more extensions.
|
||||||
|
const std::string& ascii = base::UTF16ToASCII(filter);
|
||||||
|
std::vector<base::FilePath::StringType> ext;
|
||||||
|
std::wstring ext_str;
|
||||||
|
net::GetExtensionsForMimeType(ascii, &ext);
|
||||||
|
if (!ext.empty()) {
|
||||||
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,8 +242,9 @@ std::wstring GetFilterStringFromAcceptTypes(
|
|||||||
|
|
||||||
// from chrome/browser/views/shell_dialogs_win.cc
|
// from chrome/browser/views/shell_dialogs_win.cc
|
||||||
|
|
||||||
bool RunOpenFileDialog(const content::FileChooserParams& params,
|
bool RunOpenFileDialog(const CefBrowserHostImpl::FileChooserParams& params,
|
||||||
HWND owner,
|
HWND owner,
|
||||||
|
int* filter_index,
|
||||||
base::FilePath* path) {
|
base::FilePath* path) {
|
||||||
OPENFILENAME ofn;
|
OPENFILENAME ofn;
|
||||||
|
|
||||||
@ -235,22 +254,25 @@ bool RunOpenFileDialog(const content::FileChooserParams& params,
|
|||||||
ofn.lStructSize = sizeof(ofn);
|
ofn.lStructSize = sizeof(ofn);
|
||||||
ofn.hwndOwner = owner;
|
ofn.hwndOwner = owner;
|
||||||
|
|
||||||
// Consider default file name if any.
|
|
||||||
base::FilePath default_file_name(params.default_file_name);
|
|
||||||
|
|
||||||
wchar_t filename[MAX_PATH] = {0};
|
wchar_t filename[MAX_PATH] = {0};
|
||||||
|
|
||||||
ofn.lpstrFile = filename;
|
ofn.lpstrFile = filename;
|
||||||
ofn.nMaxFile = MAX_PATH;
|
ofn.nMaxFile = MAX_PATH;
|
||||||
|
|
||||||
std::wstring directory;
|
std::wstring directory;
|
||||||
if (!default_file_name.empty()) {
|
if (!params.default_file_name.empty()) {
|
||||||
base::wcslcpy(filename, default_file_name.value().c_str(),
|
if (params.default_file_name.EndsWithSeparator()) {
|
||||||
arraysize(filename));
|
// The value is only a directory.
|
||||||
|
directory = params.default_file_name.value();
|
||||||
directory = default_file_name.DirName().value();
|
} else {
|
||||||
ofn.lpstrInitialDir = directory.c_str();
|
// The value is a file name and possibly a directory.
|
||||||
|
base::wcslcpy(filename, params.default_file_name.value().c_str(),
|
||||||
|
arraysize(filename));
|
||||||
|
directory = params.default_file_name.DirName().value();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (!directory.empty())
|
||||||
|
ofn.lpstrInitialDir = directory.c_str();
|
||||||
|
|
||||||
std::wstring title;
|
std::wstring title;
|
||||||
if (!params.title.empty())
|
if (!params.title.empty())
|
||||||
@ -264,19 +286,27 @@ bool RunOpenFileDialog(const content::FileChooserParams& params,
|
|||||||
// without having to close Chrome first.
|
// without having to close Chrome first.
|
||||||
ofn.Flags = OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR | OFN_EXPLORER |
|
ofn.Flags = OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR | OFN_EXPLORER |
|
||||||
OFN_ENABLESIZING;
|
OFN_ENABLESIZING;
|
||||||
|
if (params.hidereadonly)
|
||||||
|
ofn.Flags |= OFN_HIDEREADONLY;
|
||||||
|
|
||||||
std::wstring filter = GetFilterStringFromAcceptTypes(params.accept_types);
|
const std::wstring& filter = GetFilterString(params.accept_types);
|
||||||
if (!filter.empty())
|
if (!filter.empty()) {
|
||||||
ofn.lpstrFilter = filter.c_str();
|
ofn.lpstrFilter = filter.c_str();
|
||||||
|
// Indices into |lpstrFilter| start at 1.
|
||||||
|
ofn.nFilterIndex = *filter_index + 1;
|
||||||
|
}
|
||||||
|
|
||||||
bool success = !!GetOpenFileName(&ofn);
|
bool success = !!GetOpenFileName(&ofn);
|
||||||
if (success)
|
if (success) {
|
||||||
|
*filter_index = ofn.nFilterIndex == 0 ? 0 : ofn.nFilterIndex - 1;
|
||||||
*path = base::FilePath(filename);
|
*path = base::FilePath(filename);
|
||||||
|
}
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RunOpenMultiFileDialog(const content::FileChooserParams& params,
|
bool RunOpenMultiFileDialog(const CefBrowserHostImpl::FileChooserParams& params,
|
||||||
HWND owner,
|
HWND owner,
|
||||||
|
int* filter_index,
|
||||||
std::vector<base::FilePath>* paths) {
|
std::vector<base::FilePath>* paths) {
|
||||||
OPENFILENAME ofn;
|
OPENFILENAME ofn;
|
||||||
|
|
||||||
@ -292,6 +322,19 @@ bool RunOpenMultiFileDialog(const content::FileChooserParams& params,
|
|||||||
ofn.lpstrFile = filename.get();
|
ofn.lpstrFile = filename.get();
|
||||||
ofn.nMaxFile = UNICODE_STRING_MAX_CHARS;
|
ofn.nMaxFile = UNICODE_STRING_MAX_CHARS;
|
||||||
|
|
||||||
|
std::wstring directory;
|
||||||
|
if (!params.default_file_name.empty()) {
|
||||||
|
if (params.default_file_name.EndsWithSeparator()) {
|
||||||
|
// The value is only a directory.
|
||||||
|
directory = params.default_file_name.value();
|
||||||
|
} else {
|
||||||
|
// The value is a file name and possibly a directory.
|
||||||
|
directory = params.default_file_name.DirName().value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!directory.empty())
|
||||||
|
ofn.lpstrInitialDir = directory.c_str();
|
||||||
|
|
||||||
std::wstring title;
|
std::wstring title;
|
||||||
if (!params.title.empty())
|
if (!params.title.empty())
|
||||||
title = params.title;
|
title = params.title;
|
||||||
@ -303,11 +346,16 @@ bool RunOpenMultiFileDialog(const content::FileChooserParams& params,
|
|||||||
// We use OFN_NOCHANGEDIR so that the user can rename or delete the directory
|
// We use OFN_NOCHANGEDIR so that the user can rename or delete the directory
|
||||||
// without having to close Chrome first.
|
// without having to close Chrome first.
|
||||||
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER |
|
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER |
|
||||||
OFN_HIDEREADONLY | OFN_ALLOWMULTISELECT | OFN_ENABLESIZING;
|
OFN_ALLOWMULTISELECT | OFN_ENABLESIZING;
|
||||||
|
if (params.hidereadonly)
|
||||||
|
ofn.Flags |= OFN_HIDEREADONLY;
|
||||||
|
|
||||||
std::wstring filter = GetFilterStringFromAcceptTypes(params.accept_types);
|
const std::wstring& filter = GetFilterString(params.accept_types);
|
||||||
if (!filter.empty())
|
if (!filter.empty()) {
|
||||||
ofn.lpstrFilter = filter.c_str();
|
ofn.lpstrFilter = filter.c_str();
|
||||||
|
// Indices into |lpstrFilter| start at 1.
|
||||||
|
ofn.nFilterIndex = *filter_index + 1;
|
||||||
|
}
|
||||||
|
|
||||||
bool success = !!GetOpenFileName(&ofn);
|
bool success = !!GetOpenFileName(&ofn);
|
||||||
|
|
||||||
@ -334,11 +382,84 @@ bool RunOpenMultiFileDialog(const content::FileChooserParams& params,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
*filter_index = ofn.nFilterIndex == 0 ? 0 : ofn.nFilterIndex - 1;
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RunSaveFileDialog(const content::FileChooserParams& params,
|
// The callback function for when the select folder dialog is opened.
|
||||||
|
int CALLBACK BrowseCallbackProc(HWND window,
|
||||||
|
UINT message,
|
||||||
|
LPARAM parameter,
|
||||||
|
LPARAM data)
|
||||||
|
{
|
||||||
|
if (message == BFFM_INITIALIZED) {
|
||||||
|
// WParam is TRUE since passing a path.
|
||||||
|
// data lParam member of the BROWSEINFO structure.
|
||||||
|
SendMessage(window, BFFM_SETSELECTION, TRUE, (LPARAM)data);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RunOpenFolderDialog(const CefBrowserHostImpl::FileChooserParams& params,
|
||||||
|
HWND owner,
|
||||||
|
base::FilePath* path) {
|
||||||
|
wchar_t dir_buffer[MAX_PATH + 1] = {0};
|
||||||
|
|
||||||
|
bool result = false;
|
||||||
|
BROWSEINFO browse_info = {0};
|
||||||
|
browse_info.hwndOwner = owner;
|
||||||
|
browse_info.pszDisplayName = dir_buffer;
|
||||||
|
browse_info.ulFlags = BIF_USENEWUI | BIF_RETURNONLYFSDIRS;
|
||||||
|
|
||||||
|
std::wstring title;
|
||||||
|
if (!params.title.empty())
|
||||||
|
title = params.title;
|
||||||
|
else
|
||||||
|
title = l10n_util::GetStringUTF16(IDS_SELECT_FOLDER_DIALOG_TITLE);
|
||||||
|
if (!title.empty())
|
||||||
|
browse_info.lpszTitle = title.c_str();
|
||||||
|
|
||||||
|
const std::wstring& file_path = params.default_file_name.value();
|
||||||
|
if (!file_path.empty()) {
|
||||||
|
// Highlight the current value.
|
||||||
|
browse_info.lParam = (LPARAM)file_path.c_str();
|
||||||
|
browse_info.lpfn = &BrowseCallbackProc;
|
||||||
|
}
|
||||||
|
|
||||||
|
LPITEMIDLIST list = SHBrowseForFolder(&browse_info);
|
||||||
|
if (list) {
|
||||||
|
STRRET out_dir_buffer;
|
||||||
|
ZeroMemory(&out_dir_buffer, sizeof(out_dir_buffer));
|
||||||
|
out_dir_buffer.uType = STRRET_WSTR;
|
||||||
|
base::win::ScopedComPtr<IShellFolder> shell_folder;
|
||||||
|
if (SHGetDesktopFolder(shell_folder.Receive()) == NOERROR) {
|
||||||
|
HRESULT hr = shell_folder->GetDisplayNameOf(list, SHGDN_FORPARSING,
|
||||||
|
&out_dir_buffer);
|
||||||
|
if (SUCCEEDED(hr) && out_dir_buffer.uType == STRRET_WSTR) {
|
||||||
|
*path = base::FilePath(out_dir_buffer.pOleStr);
|
||||||
|
CoTaskMemFree(out_dir_buffer.pOleStr);
|
||||||
|
result = true;
|
||||||
|
} else {
|
||||||
|
// Use old way if we don't get what we want.
|
||||||
|
wchar_t old_out_dir_buffer[MAX_PATH + 1];
|
||||||
|
if (SHGetPathFromIDList(list, old_out_dir_buffer)) {
|
||||||
|
*path = base::FilePath(old_out_dir_buffer);
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CoTaskMemFree(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RunSaveFileDialog(const CefBrowserHostImpl::FileChooserParams& params,
|
||||||
HWND owner,
|
HWND owner,
|
||||||
|
int* filter_index,
|
||||||
base::FilePath* path) {
|
base::FilePath* path) {
|
||||||
OPENFILENAME ofn;
|
OPENFILENAME ofn;
|
||||||
|
|
||||||
@ -348,22 +469,25 @@ bool RunSaveFileDialog(const content::FileChooserParams& params,
|
|||||||
ofn.lStructSize = sizeof(ofn);
|
ofn.lStructSize = sizeof(ofn);
|
||||||
ofn.hwndOwner = owner;
|
ofn.hwndOwner = owner;
|
||||||
|
|
||||||
// Consider default file name if any.
|
|
||||||
base::FilePath default_file_name(params.default_file_name);
|
|
||||||
|
|
||||||
wchar_t filename[MAX_PATH] = {0};
|
wchar_t filename[MAX_PATH] = {0};
|
||||||
|
|
||||||
ofn.lpstrFile = filename;
|
ofn.lpstrFile = filename;
|
||||||
ofn.nMaxFile = MAX_PATH;
|
ofn.nMaxFile = MAX_PATH;
|
||||||
|
|
||||||
std::wstring directory;
|
std::wstring directory;
|
||||||
if (!default_file_name.empty()) {
|
if (!params.default_file_name.empty()) {
|
||||||
base::wcslcpy(filename, default_file_name.value().c_str(),
|
if (params.default_file_name.EndsWithSeparator()) {
|
||||||
arraysize(filename));
|
// The value is only a directory.
|
||||||
|
directory = params.default_file_name.value();
|
||||||
directory = default_file_name.DirName().value();
|
} else {
|
||||||
ofn.lpstrInitialDir = directory.c_str();
|
// The value is a file name and possibly a directory.
|
||||||
|
base::wcslcpy(filename, params.default_file_name.value().c_str(),
|
||||||
|
arraysize(filename));
|
||||||
|
directory = params.default_file_name.DirName().value();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (!directory.empty())
|
||||||
|
ofn.lpstrInitialDir = directory.c_str();
|
||||||
|
|
||||||
std::wstring title;
|
std::wstring title;
|
||||||
if (!params.title.empty())
|
if (!params.title.empty())
|
||||||
@ -375,16 +499,25 @@ bool RunSaveFileDialog(const content::FileChooserParams& params,
|
|||||||
|
|
||||||
// We use OFN_NOCHANGEDIR so that the user can rename or delete the directory
|
// We use OFN_NOCHANGEDIR so that the user can rename or delete the directory
|
||||||
// without having to close Chrome first.
|
// without having to close Chrome first.
|
||||||
ofn.Flags = OFN_OVERWRITEPROMPT | OFN_EXPLORER | OFN_ENABLESIZING |
|
ofn.Flags = OFN_EXPLORER | OFN_ENABLESIZING | OFN_NOCHANGEDIR |
|
||||||
OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST;
|
OFN_PATHMUSTEXIST;
|
||||||
|
if (params.hidereadonly)
|
||||||
|
ofn.Flags |= OFN_HIDEREADONLY;
|
||||||
|
if (params.overwriteprompt)
|
||||||
|
ofn.Flags |= OFN_OVERWRITEPROMPT;
|
||||||
|
|
||||||
std::wstring filter = GetFilterStringFromAcceptTypes(params.accept_types);
|
const std::wstring& filter = GetFilterString(params.accept_types);
|
||||||
if (!filter.empty())
|
if (!filter.empty()) {
|
||||||
ofn.lpstrFilter = filter.c_str();
|
ofn.lpstrFilter = filter.c_str();
|
||||||
|
// Indices into |lpstrFilter| start at 1.
|
||||||
|
ofn.nFilterIndex = *filter_index + 1;
|
||||||
|
}
|
||||||
|
|
||||||
bool success = !!GetSaveFileName(&ofn);
|
bool success = !!GetSaveFileName(&ofn);
|
||||||
if (success)
|
if (success) {
|
||||||
|
*filter_index = ofn.nFilterIndex == 0 ? 0 : ofn.nFilterIndex - 1;
|
||||||
*path = base::FilePath(filename);
|
*path = base::FilePath(filename);
|
||||||
|
}
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -782,25 +915,32 @@ void CefBrowserHostImpl::PlatformHandleKeyboardEvent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CefBrowserHostImpl::PlatformRunFileChooser(
|
void CefBrowserHostImpl::PlatformRunFileChooser(
|
||||||
const content::FileChooserParams& params,
|
const FileChooserParams& params,
|
||||||
RunFileChooserCallback callback) {
|
RunFileChooserCallback callback) {
|
||||||
|
int filter_index = params.selected_accept_filter;
|
||||||
std::vector<base::FilePath> files;
|
std::vector<base::FilePath> files;
|
||||||
|
|
||||||
|
HWND owner = PlatformGetWindowHandle();
|
||||||
|
|
||||||
if (params.mode == content::FileChooserParams::Open) {
|
if (params.mode == content::FileChooserParams::Open) {
|
||||||
base::FilePath file;
|
base::FilePath file;
|
||||||
if (RunOpenFileDialog(params, PlatformGetWindowHandle(), &file))
|
if (RunOpenFileDialog(params, owner, &filter_index, &file))
|
||||||
files.push_back(file);
|
files.push_back(file);
|
||||||
} else if (params.mode == content::FileChooserParams::OpenMultiple) {
|
} else if (params.mode == content::FileChooserParams::OpenMultiple) {
|
||||||
RunOpenMultiFileDialog(params, PlatformGetWindowHandle(), &files);
|
RunOpenMultiFileDialog(params, owner, &filter_index, &files);
|
||||||
|
} else if (params.mode == content::FileChooserParams::UploadFolder) {
|
||||||
|
base::FilePath file;
|
||||||
|
if (RunOpenFolderDialog(params, owner, &file))
|
||||||
|
files.push_back(file);
|
||||||
} else if (params.mode == content::FileChooserParams::Save) {
|
} else if (params.mode == content::FileChooserParams::Save) {
|
||||||
base::FilePath file;
|
base::FilePath file;
|
||||||
if (RunSaveFileDialog(params, PlatformGetWindowHandle(), &file))
|
if (RunSaveFileDialog(params, owner, &filter_index, &file))
|
||||||
files.push_back(file);
|
files.push_back(file);
|
||||||
} else {
|
} else {
|
||||||
NOTIMPLEMENTED();
|
NOTIMPLEMENTED();
|
||||||
}
|
}
|
||||||
|
|
||||||
callback.Run(files);
|
callback.Run(filter_index, files);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefBrowserHostImpl::PlatformHandleExternalProtocol(const GURL& url) {
|
void CefBrowserHostImpl::PlatformHandleExternalProtocol(const GURL& url) {
|
||||||
|
@ -142,7 +142,7 @@ class CefBeforeDownloadCallbackImpl : public CefBeforeDownloadCallback {
|
|||||||
if (browser.get()) {
|
if (browser.get()) {
|
||||||
handled = true;
|
handled = true;
|
||||||
|
|
||||||
content::FileChooserParams params;
|
CefBrowserHostImpl::FileChooserParams params;
|
||||||
params.mode = content::FileChooserParams::Save;
|
params.mode = content::FileChooserParams::Save;
|
||||||
if (!suggested_path.empty()) {
|
if (!suggested_path.empty()) {
|
||||||
params.default_file_name = suggested_path;
|
params.default_file_name = suggested_path;
|
||||||
@ -169,6 +169,7 @@ class CefBeforeDownloadCallbackImpl : public CefBeforeDownloadCallback {
|
|||||||
|
|
||||||
static void ChooseDownloadPathCallback(
|
static void ChooseDownloadPathCallback(
|
||||||
const content::DownloadTargetCallback& callback,
|
const content::DownloadTargetCallback& callback,
|
||||||
|
int selected_accept_filter,
|
||||||
const std::vector<base::FilePath>& file_paths) {
|
const std::vector<base::FilePath>& file_paths) {
|
||||||
DCHECK_LE(file_paths.size(), (size_t) 1);
|
DCHECK_LE(file_paths.size(), (size_t) 1);
|
||||||
|
|
||||||
|
@ -246,29 +246,34 @@ void CEF_CALLBACK browser_host_set_zoom_level(struct _cef_browser_host_t* self,
|
|||||||
|
|
||||||
void CEF_CALLBACK browser_host_run_file_dialog(struct _cef_browser_host_t* self,
|
void CEF_CALLBACK browser_host_run_file_dialog(struct _cef_browser_host_t* self,
|
||||||
cef_file_dialog_mode_t mode, const cef_string_t* title,
|
cef_file_dialog_mode_t mode, const cef_string_t* title,
|
||||||
const cef_string_t* default_file_name, cef_string_list_t accept_types,
|
const cef_string_t* default_file_path, cef_string_list_t accept_filters,
|
||||||
cef_run_file_dialog_callback_t* callback) {
|
int selected_accept_filter, cef_run_file_dialog_callback_t* callback) {
|
||||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||||
|
|
||||||
DCHECK(self);
|
DCHECK(self);
|
||||||
if (!self)
|
if (!self)
|
||||||
return;
|
return;
|
||||||
|
// Verify param: selected_accept_filter; type: simple_byval
|
||||||
|
DCHECK_GE(selected_accept_filter, 0);
|
||||||
|
if (selected_accept_filter < 0)
|
||||||
|
return;
|
||||||
// Verify param: callback; type: refptr_diff
|
// Verify param: callback; type: refptr_diff
|
||||||
DCHECK(callback);
|
DCHECK(callback);
|
||||||
if (!callback)
|
if (!callback)
|
||||||
return;
|
return;
|
||||||
// Unverified params: title, default_file_name, accept_types
|
// Unverified params: title, default_file_path, accept_filters
|
||||||
|
|
||||||
// Translate param: accept_types; type: string_vec_byref_const
|
// Translate param: accept_filters; type: string_vec_byref_const
|
||||||
std::vector<CefString> accept_typesList;
|
std::vector<CefString> accept_filtersList;
|
||||||
transfer_string_list_contents(accept_types, accept_typesList);
|
transfer_string_list_contents(accept_filters, accept_filtersList);
|
||||||
|
|
||||||
// Execute
|
// Execute
|
||||||
CefBrowserHostCppToC::Get(self)->RunFileDialog(
|
CefBrowserHostCppToC::Get(self)->RunFileDialog(
|
||||||
mode,
|
mode,
|
||||||
CefString(title),
|
CefString(title),
|
||||||
CefString(default_file_name),
|
CefString(default_file_path),
|
||||||
accept_typesList,
|
accept_filtersList,
|
||||||
|
selected_accept_filter,
|
||||||
CefRunFileDialogCallbackCToCpp::Wrap(callback));
|
CefRunFileDialogCallbackCToCpp::Wrap(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,8 +21,8 @@
|
|||||||
int CEF_CALLBACK dialog_handler_on_file_dialog(
|
int CEF_CALLBACK dialog_handler_on_file_dialog(
|
||||||
struct _cef_dialog_handler_t* self, cef_browser_t* browser,
|
struct _cef_dialog_handler_t* self, cef_browser_t* browser,
|
||||||
cef_file_dialog_mode_t mode, const cef_string_t* title,
|
cef_file_dialog_mode_t mode, const cef_string_t* title,
|
||||||
const cef_string_t* default_file_name, cef_string_list_t accept_types,
|
const cef_string_t* default_file_path, cef_string_list_t accept_filters,
|
||||||
cef_file_dialog_callback_t* callback) {
|
int selected_accept_filter, cef_file_dialog_callback_t* callback) {
|
||||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||||
|
|
||||||
DCHECK(self);
|
DCHECK(self);
|
||||||
@ -32,23 +32,28 @@ int CEF_CALLBACK dialog_handler_on_file_dialog(
|
|||||||
DCHECK(browser);
|
DCHECK(browser);
|
||||||
if (!browser)
|
if (!browser)
|
||||||
return 0;
|
return 0;
|
||||||
|
// Verify param: selected_accept_filter; type: simple_byval
|
||||||
|
DCHECK_GE(selected_accept_filter, 0);
|
||||||
|
if (selected_accept_filter < 0)
|
||||||
|
return 0;
|
||||||
// Verify param: callback; type: refptr_diff
|
// Verify param: callback; type: refptr_diff
|
||||||
DCHECK(callback);
|
DCHECK(callback);
|
||||||
if (!callback)
|
if (!callback)
|
||||||
return 0;
|
return 0;
|
||||||
// Unverified params: title, default_file_name, accept_types
|
// Unverified params: title, default_file_path, accept_filters
|
||||||
|
|
||||||
// Translate param: accept_types; type: string_vec_byref_const
|
// Translate param: accept_filters; type: string_vec_byref_const
|
||||||
std::vector<CefString> accept_typesList;
|
std::vector<CefString> accept_filtersList;
|
||||||
transfer_string_list_contents(accept_types, accept_typesList);
|
transfer_string_list_contents(accept_filters, accept_filtersList);
|
||||||
|
|
||||||
// Execute
|
// Execute
|
||||||
bool _retval = CefDialogHandlerCppToC::Get(self)->OnFileDialog(
|
bool _retval = CefDialogHandlerCppToC::Get(self)->OnFileDialog(
|
||||||
CefBrowserCToCpp::Wrap(browser),
|
CefBrowserCToCpp::Wrap(browser),
|
||||||
mode,
|
mode,
|
||||||
CefString(title),
|
CefString(title),
|
||||||
CefString(default_file_name),
|
CefString(default_file_path),
|
||||||
accept_typesList,
|
accept_filtersList,
|
||||||
|
selected_accept_filter,
|
||||||
CefFileDialogCallbackCToCpp::Wrap(callback));
|
CefFileDialogCallbackCToCpp::Wrap(callback));
|
||||||
|
|
||||||
// Return type: bool
|
// Return type: bool
|
||||||
|
@ -17,16 +17,18 @@
|
|||||||
// MEMBER FUNCTIONS - Body may be edited by hand.
|
// MEMBER FUNCTIONS - Body may be edited by hand.
|
||||||
|
|
||||||
void CEF_CALLBACK file_dialog_callback_cont(
|
void CEF_CALLBACK file_dialog_callback_cont(
|
||||||
struct _cef_file_dialog_callback_t* self, cef_string_list_t file_paths) {
|
struct _cef_file_dialog_callback_t* self, int selected_accept_filter,
|
||||||
|
cef_string_list_t file_paths) {
|
||||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||||
|
|
||||||
DCHECK(self);
|
DCHECK(self);
|
||||||
if (!self)
|
if (!self)
|
||||||
return;
|
return;
|
||||||
// Verify param: file_paths; type: string_vec_byref_const
|
// Verify param: selected_accept_filter; type: simple_byval
|
||||||
DCHECK(file_paths);
|
DCHECK_GE(selected_accept_filter, 0);
|
||||||
if (!file_paths)
|
if (selected_accept_filter < 0)
|
||||||
return;
|
return;
|
||||||
|
// Unverified params: file_paths
|
||||||
|
|
||||||
// Translate param: file_paths; type: string_vec_byref_const
|
// Translate param: file_paths; type: string_vec_byref_const
|
||||||
std::vector<CefString> file_pathsList;
|
std::vector<CefString> file_pathsList;
|
||||||
@ -34,6 +36,7 @@ void CEF_CALLBACK file_dialog_callback_cont(
|
|||||||
|
|
||||||
// Execute
|
// Execute
|
||||||
CefFileDialogCallbackCppToC::Get(self)->Continue(
|
CefFileDialogCallbackCppToC::Get(self)->Continue(
|
||||||
|
selected_accept_filter,
|
||||||
file_pathsList);
|
file_pathsList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,28 +11,24 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include "libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.h"
|
#include "libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.h"
|
||||||
#include "libcef_dll/ctocpp/browser_host_ctocpp.h"
|
|
||||||
#include "libcef_dll/transfer_util.h"
|
#include "libcef_dll/transfer_util.h"
|
||||||
|
|
||||||
|
|
||||||
// MEMBER FUNCTIONS - Body may be edited by hand.
|
// MEMBER FUNCTIONS - Body may be edited by hand.
|
||||||
|
|
||||||
void CEF_CALLBACK run_file_dialog_callback_cont(
|
void CEF_CALLBACK run_file_dialog_callback_on_file_dialog_dismissed(
|
||||||
struct _cef_run_file_dialog_callback_t* self,
|
struct _cef_run_file_dialog_callback_t* self, int selected_accept_filter,
|
||||||
struct _cef_browser_host_t* browser_host, cef_string_list_t file_paths) {
|
cef_string_list_t file_paths) {
|
||||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||||
|
|
||||||
DCHECK(self);
|
DCHECK(self);
|
||||||
if (!self)
|
if (!self)
|
||||||
return;
|
return;
|
||||||
// Verify param: browser_host; type: refptr_diff
|
// Verify param: selected_accept_filter; type: simple_byval
|
||||||
DCHECK(browser_host);
|
DCHECK_GE(selected_accept_filter, 0);
|
||||||
if (!browser_host)
|
if (selected_accept_filter < 0)
|
||||||
return;
|
|
||||||
// Verify param: file_paths; type: string_vec_byref_const
|
|
||||||
DCHECK(file_paths);
|
|
||||||
if (!file_paths)
|
|
||||||
return;
|
return;
|
||||||
|
// Unverified params: file_paths
|
||||||
|
|
||||||
// Translate param: file_paths; type: string_vec_byref_const
|
// Translate param: file_paths; type: string_vec_byref_const
|
||||||
std::vector<CefString> file_pathsList;
|
std::vector<CefString> file_pathsList;
|
||||||
@ -40,7 +36,7 @@ void CEF_CALLBACK run_file_dialog_callback_cont(
|
|||||||
|
|
||||||
// Execute
|
// Execute
|
||||||
CefRunFileDialogCallbackCppToC::Get(self)->OnFileDialogDismissed(
|
CefRunFileDialogCallbackCppToC::Get(self)->OnFileDialogDismissed(
|
||||||
CefBrowserHostCToCpp::Wrap(browser_host),
|
selected_accept_filter,
|
||||||
file_pathsList);
|
file_pathsList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +47,8 @@ CefRunFileDialogCallbackCppToC::CefRunFileDialogCallbackCppToC(
|
|||||||
CefRunFileDialogCallback* cls)
|
CefRunFileDialogCallback* cls)
|
||||||
: CefCppToC<CefRunFileDialogCallbackCppToC, CefRunFileDialogCallback,
|
: CefCppToC<CefRunFileDialogCallbackCppToC, CefRunFileDialogCallback,
|
||||||
cef_run_file_dialog_callback_t>(cls) {
|
cef_run_file_dialog_callback_t>(cls) {
|
||||||
struct_.struct_.cont = run_file_dialog_callback_cont;
|
struct_.struct_.on_file_dialog_dismissed =
|
||||||
|
run_file_dialog_callback_on_file_dialog_dismissed;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
@ -188,37 +188,42 @@ void CefBrowserHostCToCpp::SetZoomLevel(double zoomLevel) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CefBrowserHostCToCpp::RunFileDialog(FileDialogMode mode,
|
void CefBrowserHostCToCpp::RunFileDialog(FileDialogMode mode,
|
||||||
const CefString& title, const CefString& default_file_name,
|
const CefString& title, const CefString& default_file_path,
|
||||||
const std::vector<CefString>& accept_types,
|
const std::vector<CefString>& accept_filters, int selected_accept_filter,
|
||||||
CefRefPtr<CefRunFileDialogCallback> callback) {
|
CefRefPtr<CefRunFileDialogCallback> callback) {
|
||||||
if (CEF_MEMBER_MISSING(struct_, run_file_dialog))
|
if (CEF_MEMBER_MISSING(struct_, run_file_dialog))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||||
|
|
||||||
|
// Verify param: selected_accept_filter; type: simple_byval
|
||||||
|
DCHECK_GE(selected_accept_filter, 0);
|
||||||
|
if (selected_accept_filter < 0)
|
||||||
|
return;
|
||||||
// Verify param: callback; type: refptr_diff
|
// Verify param: callback; type: refptr_diff
|
||||||
DCHECK(callback.get());
|
DCHECK(callback.get());
|
||||||
if (!callback.get())
|
if (!callback.get())
|
||||||
return;
|
return;
|
||||||
// Unverified params: title, default_file_name, accept_types
|
// Unverified params: title, default_file_path, accept_filters
|
||||||
|
|
||||||
// Translate param: accept_types; type: string_vec_byref_const
|
// Translate param: accept_filters; type: string_vec_byref_const
|
||||||
cef_string_list_t accept_typesList = cef_string_list_alloc();
|
cef_string_list_t accept_filtersList = cef_string_list_alloc();
|
||||||
DCHECK(accept_typesList);
|
DCHECK(accept_filtersList);
|
||||||
if (accept_typesList)
|
if (accept_filtersList)
|
||||||
transfer_string_list_contents(accept_types, accept_typesList);
|
transfer_string_list_contents(accept_filters, accept_filtersList);
|
||||||
|
|
||||||
// Execute
|
// Execute
|
||||||
struct_->run_file_dialog(struct_,
|
struct_->run_file_dialog(struct_,
|
||||||
mode,
|
mode,
|
||||||
title.GetStruct(),
|
title.GetStruct(),
|
||||||
default_file_name.GetStruct(),
|
default_file_path.GetStruct(),
|
||||||
accept_typesList,
|
accept_filtersList,
|
||||||
|
selected_accept_filter,
|
||||||
CefRunFileDialogCallbackCppToC::Wrap(callback));
|
CefRunFileDialogCallbackCppToC::Wrap(callback));
|
||||||
|
|
||||||
// Restore param:accept_types; type: string_vec_byref_const
|
// Restore param:accept_filters; type: string_vec_byref_const
|
||||||
if (accept_typesList)
|
if (accept_filtersList)
|
||||||
cef_string_list_free(accept_typesList);
|
cef_string_list_free(accept_filtersList);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefBrowserHostCToCpp::StartDownload(const CefString& url) {
|
void CefBrowserHostCToCpp::StartDownload(const CefString& url) {
|
||||||
|
@ -47,8 +47,8 @@ class CefBrowserHostCToCpp
|
|||||||
virtual double GetZoomLevel() OVERRIDE;
|
virtual double GetZoomLevel() OVERRIDE;
|
||||||
virtual void SetZoomLevel(double zoomLevel) OVERRIDE;
|
virtual void SetZoomLevel(double zoomLevel) OVERRIDE;
|
||||||
virtual void RunFileDialog(FileDialogMode mode, const CefString& title,
|
virtual void RunFileDialog(FileDialogMode mode, const CefString& title,
|
||||||
const CefString& default_file_name,
|
const CefString& default_file_path,
|
||||||
const std::vector<CefString>& accept_types,
|
const std::vector<CefString>& accept_filters, int selected_accept_filter,
|
||||||
CefRefPtr<CefRunFileDialogCallback> callback) OVERRIDE;
|
CefRefPtr<CefRunFileDialogCallback> callback) OVERRIDE;
|
||||||
virtual void StartDownload(const CefString& url) OVERRIDE;
|
virtual void StartDownload(const CefString& url) OVERRIDE;
|
||||||
virtual void Print() OVERRIDE;
|
virtual void Print() OVERRIDE;
|
||||||
|
@ -20,8 +20,8 @@
|
|||||||
|
|
||||||
bool CefDialogHandlerCToCpp::OnFileDialog(CefRefPtr<CefBrowser> browser,
|
bool CefDialogHandlerCToCpp::OnFileDialog(CefRefPtr<CefBrowser> browser,
|
||||||
FileDialogMode mode, const CefString& title,
|
FileDialogMode mode, const CefString& title,
|
||||||
const CefString& default_file_name,
|
const CefString& default_file_path,
|
||||||
const std::vector<CefString>& accept_types,
|
const std::vector<CefString>& accept_filters, int selected_accept_filter,
|
||||||
CefRefPtr<CefFileDialogCallback> callback) {
|
CefRefPtr<CefFileDialogCallback> callback) {
|
||||||
if (CEF_MEMBER_MISSING(struct_, on_file_dialog))
|
if (CEF_MEMBER_MISSING(struct_, on_file_dialog))
|
||||||
return false;
|
return false;
|
||||||
@ -32,30 +32,35 @@ bool CefDialogHandlerCToCpp::OnFileDialog(CefRefPtr<CefBrowser> browser,
|
|||||||
DCHECK(browser.get());
|
DCHECK(browser.get());
|
||||||
if (!browser.get())
|
if (!browser.get())
|
||||||
return false;
|
return false;
|
||||||
|
// Verify param: selected_accept_filter; type: simple_byval
|
||||||
|
DCHECK_GE(selected_accept_filter, 0);
|
||||||
|
if (selected_accept_filter < 0)
|
||||||
|
return false;
|
||||||
// Verify param: callback; type: refptr_diff
|
// Verify param: callback; type: refptr_diff
|
||||||
DCHECK(callback.get());
|
DCHECK(callback.get());
|
||||||
if (!callback.get())
|
if (!callback.get())
|
||||||
return false;
|
return false;
|
||||||
// Unverified params: title, default_file_name, accept_types
|
// Unverified params: title, default_file_path, accept_filters
|
||||||
|
|
||||||
// Translate param: accept_types; type: string_vec_byref_const
|
// Translate param: accept_filters; type: string_vec_byref_const
|
||||||
cef_string_list_t accept_typesList = cef_string_list_alloc();
|
cef_string_list_t accept_filtersList = cef_string_list_alloc();
|
||||||
DCHECK(accept_typesList);
|
DCHECK(accept_filtersList);
|
||||||
if (accept_typesList)
|
if (accept_filtersList)
|
||||||
transfer_string_list_contents(accept_types, accept_typesList);
|
transfer_string_list_contents(accept_filters, accept_filtersList);
|
||||||
|
|
||||||
// Execute
|
// Execute
|
||||||
int _retval = struct_->on_file_dialog(struct_,
|
int _retval = struct_->on_file_dialog(struct_,
|
||||||
CefBrowserCppToC::Wrap(browser),
|
CefBrowserCppToC::Wrap(browser),
|
||||||
mode,
|
mode,
|
||||||
title.GetStruct(),
|
title.GetStruct(),
|
||||||
default_file_name.GetStruct(),
|
default_file_path.GetStruct(),
|
||||||
accept_typesList,
|
accept_filtersList,
|
||||||
|
selected_accept_filter,
|
||||||
CefFileDialogCallbackCppToC::Wrap(callback));
|
CefFileDialogCallbackCppToC::Wrap(callback));
|
||||||
|
|
||||||
// Restore param:accept_types; type: string_vec_byref_const
|
// Restore param:accept_filters; type: string_vec_byref_const
|
||||||
if (accept_typesList)
|
if (accept_filtersList)
|
||||||
cef_string_list_free(accept_typesList);
|
cef_string_list_free(accept_filtersList);
|
||||||
|
|
||||||
// Return type: bool
|
// Return type: bool
|
||||||
return _retval?true:false;
|
return _retval?true:false;
|
||||||
|
@ -35,8 +35,8 @@ class CefDialogHandlerCToCpp
|
|||||||
|
|
||||||
// CefDialogHandler methods
|
// CefDialogHandler methods
|
||||||
bool OnFileDialog(CefRefPtr<CefBrowser> browser, FileDialogMode mode,
|
bool OnFileDialog(CefRefPtr<CefBrowser> browser, FileDialogMode mode,
|
||||||
const CefString& title, const CefString& default_file_name,
|
const CefString& title, const CefString& default_file_path,
|
||||||
const std::vector<CefString>& accept_types,
|
const std::vector<CefString>& accept_filters, int selected_accept_filter,
|
||||||
CefRefPtr<CefFileDialogCallback> callback) override;
|
CefRefPtr<CefFileDialogCallback> callback) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -16,13 +16,19 @@
|
|||||||
|
|
||||||
// VIRTUAL METHODS - Body may be edited by hand.
|
// VIRTUAL METHODS - Body may be edited by hand.
|
||||||
|
|
||||||
void CefFileDialogCallbackCToCpp::Continue(
|
void CefFileDialogCallbackCToCpp::Continue(int selected_accept_filter,
|
||||||
const std::vector<CefString>& file_paths) {
|
const std::vector<CefString>& file_paths) {
|
||||||
if (CEF_MEMBER_MISSING(struct_, cont))
|
if (CEF_MEMBER_MISSING(struct_, cont))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||||
|
|
||||||
|
// Verify param: selected_accept_filter; type: simple_byval
|
||||||
|
DCHECK_GE(selected_accept_filter, 0);
|
||||||
|
if (selected_accept_filter < 0)
|
||||||
|
return;
|
||||||
|
// Unverified params: file_paths
|
||||||
|
|
||||||
// Translate param: file_paths; type: string_vec_byref_const
|
// Translate param: file_paths; type: string_vec_byref_const
|
||||||
cef_string_list_t file_pathsList = cef_string_list_alloc();
|
cef_string_list_t file_pathsList = cef_string_list_alloc();
|
||||||
DCHECK(file_pathsList);
|
DCHECK(file_pathsList);
|
||||||
@ -31,6 +37,7 @@ void CefFileDialogCallbackCToCpp::Continue(
|
|||||||
|
|
||||||
// Execute
|
// Execute
|
||||||
struct_->cont(struct_,
|
struct_->cont(struct_,
|
||||||
|
selected_accept_filter,
|
||||||
file_pathsList);
|
file_pathsList);
|
||||||
|
|
||||||
// Restore param:file_paths; type: string_vec_byref_const
|
// Restore param:file_paths; type: string_vec_byref_const
|
||||||
|
@ -34,7 +34,8 @@ class CefFileDialogCallbackCToCpp
|
|||||||
cef_file_dialog_callback_t>(str) {}
|
cef_file_dialog_callback_t>(str) {}
|
||||||
|
|
||||||
// CefFileDialogCallback methods
|
// CefFileDialogCallback methods
|
||||||
virtual void Continue(const std::vector<CefString>& file_paths) OVERRIDE;
|
virtual void Continue(int selected_accept_filter,
|
||||||
|
const std::vector<CefString>& file_paths) OVERRIDE;
|
||||||
virtual void Cancel() OVERRIDE;
|
virtual void Cancel() OVERRIDE;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
// for more information.
|
// for more information.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "libcef_dll/cpptoc/browser_host_cpptoc.h"
|
|
||||||
#include "libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.h"
|
#include "libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.h"
|
||||||
#include "libcef_dll/transfer_util.h"
|
#include "libcef_dll/transfer_util.h"
|
||||||
|
|
||||||
@ -18,17 +17,17 @@
|
|||||||
// VIRTUAL METHODS - Body may be edited by hand.
|
// VIRTUAL METHODS - Body may be edited by hand.
|
||||||
|
|
||||||
void CefRunFileDialogCallbackCToCpp::OnFileDialogDismissed(
|
void CefRunFileDialogCallbackCToCpp::OnFileDialogDismissed(
|
||||||
CefRefPtr<CefBrowserHost> browser_host,
|
int selected_accept_filter, const std::vector<CefString>& file_paths) {
|
||||||
const std::vector<CefString>& file_paths) {
|
if (CEF_MEMBER_MISSING(struct_, on_file_dialog_dismissed))
|
||||||
if (CEF_MEMBER_MISSING(struct_, cont))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||||
|
|
||||||
// Verify param: browser_host; type: refptr_diff
|
// Verify param: selected_accept_filter; type: simple_byval
|
||||||
DCHECK(browser_host.get());
|
DCHECK_GE(selected_accept_filter, 0);
|
||||||
if (!browser_host.get())
|
if (selected_accept_filter < 0)
|
||||||
return;
|
return;
|
||||||
|
// Unverified params: file_paths
|
||||||
|
|
||||||
// Translate param: file_paths; type: string_vec_byref_const
|
// Translate param: file_paths; type: string_vec_byref_const
|
||||||
cef_string_list_t file_pathsList = cef_string_list_alloc();
|
cef_string_list_t file_pathsList = cef_string_list_alloc();
|
||||||
@ -37,8 +36,8 @@ void CefRunFileDialogCallbackCToCpp::OnFileDialogDismissed(
|
|||||||
transfer_string_list_contents(file_paths, file_pathsList);
|
transfer_string_list_contents(file_paths, file_pathsList);
|
||||||
|
|
||||||
// Execute
|
// Execute
|
||||||
struct_->cont(struct_,
|
struct_->on_file_dialog_dismissed(struct_,
|
||||||
CefBrowserHostCppToC::Wrap(browser_host),
|
selected_accept_filter,
|
||||||
file_pathsList);
|
file_pathsList);
|
||||||
|
|
||||||
// Restore param:file_paths; type: string_vec_byref_const
|
// Restore param:file_paths; type: string_vec_byref_const
|
||||||
|
@ -36,7 +36,7 @@ class CefRunFileDialogCallbackCToCpp
|
|||||||
cef_run_file_dialog_callback_t>(str) {}
|
cef_run_file_dialog_callback_t>(str) {}
|
||||||
|
|
||||||
// CefRunFileDialogCallback methods
|
// CefRunFileDialogCallback methods
|
||||||
void OnFileDialogDismissed(CefRefPtr<CefBrowserHost> browser_host,
|
void OnFileDialogDismissed(int selected_accept_filter,
|
||||||
const std::vector<CefString>& file_paths) override;
|
const std::vector<CefString>& file_paths) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -195,8 +195,9 @@ bool ClientHandler::OnContextMenuCommand(
|
|||||||
bool ClientHandler::OnFileDialog(CefRefPtr<CefBrowser> browser,
|
bool ClientHandler::OnFileDialog(CefRefPtr<CefBrowser> browser,
|
||||||
FileDialogMode mode,
|
FileDialogMode mode,
|
||||||
const CefString& title,
|
const CefString& title,
|
||||||
const CefString& default_file_name,
|
const CefString& default_file_path,
|
||||||
const std::vector<CefString>& accept_types,
|
const std::vector<CefString>& accept_filters,
|
||||||
|
int selected_accept_filter,
|
||||||
CefRefPtr<CefFileDialogCallback> callback) {
|
CefRefPtr<CefFileDialogCallback> callback) {
|
||||||
CEF_REQUIRE_UI_THREAD();
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
|
||||||
@ -841,12 +842,16 @@ void ClientHandler::EndTracing() {
|
|||||||
|
|
||||||
// Results in a call to OnFileDialogDismissed.
|
// Results in a call to OnFileDialogDismissed.
|
||||||
handler_->GetBrowser()->GetHost()->RunFileDialog(
|
handler_->GetBrowser()->GetHost()->RunFileDialog(
|
||||||
FILE_DIALOG_SAVE, CefString(), path, std::vector<CefString>(),
|
FILE_DIALOG_SAVE,
|
||||||
|
CefString(), // title
|
||||||
|
path,
|
||||||
|
std::vector<CefString>(), // accept_filters
|
||||||
|
0, // selected_accept_filter
|
||||||
this);
|
this);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void OnFileDialogDismissed(
|
virtual void OnFileDialogDismissed(
|
||||||
CefRefPtr<CefBrowserHost> browser_host,
|
int selected_accept_filter,
|
||||||
const std::vector<CefString>& file_paths) OVERRIDE {
|
const std::vector<CefString>& file_paths) OVERRIDE {
|
||||||
CEF_REQUIRE_UI_THREAD();
|
CEF_REQUIRE_UI_THREAD();
|
||||||
if (!file_paths.empty()) {
|
if (!file_paths.empty()) {
|
||||||
|
@ -111,8 +111,9 @@ class ClientHandler : public CefClient,
|
|||||||
virtual bool OnFileDialog(CefRefPtr<CefBrowser> browser,
|
virtual bool OnFileDialog(CefRefPtr<CefBrowser> browser,
|
||||||
FileDialogMode mode,
|
FileDialogMode mode,
|
||||||
const CefString& title,
|
const CefString& title,
|
||||||
const CefString& default_file_name,
|
const CefString& default_file_path,
|
||||||
const std::vector<CefString>& accept_types,
|
const std::vector<CefString>& accept_filters,
|
||||||
|
int selected_accept_filter,
|
||||||
CefRefPtr<CefFileDialogCallback> callback) OVERRIDE;
|
CefRefPtr<CefFileDialogCallback> callback) OVERRIDE;
|
||||||
|
|
||||||
// CefDisplayHandler methods
|
// CefDisplayHandler methods
|
||||||
|
@ -50,52 +50,74 @@ std::string GetDescriptionFromMimeType(const std::string& mime_type) {
|
|||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddFiltersForAcceptTypes(GtkFileChooser* chooser,
|
void AddFilters(GtkFileChooser* chooser,
|
||||||
const std::vector<CefString>& accept_types,
|
const std::vector<CefString>& accept_filters,
|
||||||
bool include_all_files) {
|
bool include_all_files,
|
||||||
|
std::vector<GtkFileFilter*>* filters) {
|
||||||
bool has_filter = false;
|
bool has_filter = false;
|
||||||
|
|
||||||
for (size_t i = 0; i < accept_types.size(); ++i) {
|
for (size_t i = 0; i < accept_filters.size(); ++i) {
|
||||||
std::string ascii_type = accept_types[i];
|
const std::string& filter = accept_filters[i];
|
||||||
if (ascii_type.length()) {
|
if (filter.empty())
|
||||||
// Just treat as extension if contains '.' as the first character.
|
continue;
|
||||||
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<CefString> ext;
|
std::vector<std::string> extensions;
|
||||||
CefGetExtensionsForMimeType(ascii_type, ext);
|
std::string description;
|
||||||
for (size_t x = 0; x < ext.size(); ++x) {
|
|
||||||
if (!filter)
|
|
||||||
filter = gtk_file_filter_new();
|
|
||||||
std::string pattern = "*." + ext[x].ToString();
|
|
||||||
gtk_file_filter_add_pattern(filter, pattern.c_str());
|
|
||||||
|
|
||||||
if (description_from_ext) {
|
size_t sep_index = filter.find('|');
|
||||||
if (x != 0)
|
if (sep_index != std::string::npos) {
|
||||||
description += ";";
|
// Treat as a filter of the form "Filter Name|.ext1;.ext2;.ext3".
|
||||||
description += pattern;
|
description = filter.substr(0, sep_index);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter) {
|
const std::string& exts = filter.substr(sep_index + 1);
|
||||||
gtk_file_filter_set_name(filter, description.c_str());
|
size_t last = 0;
|
||||||
gtk_file_chooser_add_filter(chooser, filter);
|
size_t size = exts.size();
|
||||||
if (!has_filter)
|
for (size_t i = 0; i <= size; ++i) {
|
||||||
has_filter = true;
|
if (i == size || exts[i] == ';') {
|
||||||
|
std::string ext(exts, last, i - last);
|
||||||
|
if (!ext.empty() && ext[0] == '.')
|
||||||
|
extensions.push_back(ext);
|
||||||
|
last = i + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (filter[0] == '.') {
|
||||||
|
// Treat as an extension beginning with the '.' character.
|
||||||
|
extensions.push_back(filter);
|
||||||
|
} else {
|
||||||
|
// Otherwise convert mime type to one or more extensions.
|
||||||
|
description = GetDescriptionFromMimeType(filter);
|
||||||
|
|
||||||
|
std::vector<CefString> ext;
|
||||||
|
CefGetExtensionsForMimeType(filter, ext);
|
||||||
|
for (size_t x = 0; x < ext.size(); ++x)
|
||||||
|
extensions.push_back("." + ext[x].ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (extensions.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
GtkFileFilter* gtk_filter = gtk_file_filter_new();
|
||||||
|
|
||||||
|
std::string ext_str;
|
||||||
|
for (size_t x = 0; x < extensions.size(); ++x) {
|
||||||
|
const std::string& pattern = "*" + extensions[x];
|
||||||
|
if (x != 0)
|
||||||
|
ext_str += ";";
|
||||||
|
ext_str += pattern;
|
||||||
|
gtk_file_filter_add_pattern(gtk_filter, pattern.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (description.empty())
|
||||||
|
description = ext_str;
|
||||||
|
else
|
||||||
|
description += " (" + ext_str + ")";
|
||||||
|
|
||||||
|
gtk_file_filter_set_name(gtk_filter, description.c_str());
|
||||||
|
gtk_file_chooser_add_filter(chooser, gtk_filter);
|
||||||
|
if (!has_filter)
|
||||||
|
has_filter = true;
|
||||||
|
|
||||||
|
filters->push_back(gtk_filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the *.* filter, but only if we have added other filters (otherwise it
|
// Add the *.* filter, but only if we have added other filters (otherwise it
|
||||||
@ -103,7 +125,7 @@ void AddFiltersForAcceptTypes(GtkFileChooser* chooser,
|
|||||||
if (include_all_files && has_filter) {
|
if (include_all_files && has_filter) {
|
||||||
GtkFileFilter* filter = gtk_file_filter_new();
|
GtkFileFilter* filter = gtk_file_filter_new();
|
||||||
gtk_file_filter_add_pattern(filter, "*");
|
gtk_file_filter_add_pattern(filter, "*");
|
||||||
gtk_file_filter_set_name(filter, "All Files");
|
gtk_file_filter_set_name(filter, "All Files (*)");
|
||||||
gtk_file_chooser_add_filter(chooser, filter);
|
gtk_file_chooser_add_filter(chooser, filter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -113,17 +135,26 @@ void AddFiltersForAcceptTypes(GtkFileChooser* chooser,
|
|||||||
bool ClientHandler::OnFileDialog(CefRefPtr<CefBrowser> browser,
|
bool ClientHandler::OnFileDialog(CefRefPtr<CefBrowser> browser,
|
||||||
FileDialogMode mode,
|
FileDialogMode mode,
|
||||||
const CefString& title,
|
const CefString& title,
|
||||||
const CefString& default_file_name,
|
const CefString& default_file_path,
|
||||||
const std::vector<CefString>& accept_types,
|
const std::vector<CefString>& accept_filters,
|
||||||
|
int selected_accept_filter,
|
||||||
CefRefPtr<CefFileDialogCallback> callback) {
|
CefRefPtr<CefFileDialogCallback> callback) {
|
||||||
std::vector<CefString> files;
|
std::vector<CefString> files;
|
||||||
|
|
||||||
GtkFileChooserAction action;
|
GtkFileChooserAction action;
|
||||||
const gchar* accept_button;
|
const gchar* accept_button;
|
||||||
if (mode == FILE_DIALOG_OPEN || mode == FILE_DIALOG_OPEN_MULTIPLE) {
|
|
||||||
|
// Remove any modifier flags.
|
||||||
|
FileDialogMode mode_type =
|
||||||
|
static_cast<FileDialogMode>(mode & FILE_DIALOG_TYPE_MASK);
|
||||||
|
|
||||||
|
if (mode_type == FILE_DIALOG_OPEN || mode_type == FILE_DIALOG_OPEN_MULTIPLE) {
|
||||||
action = GTK_FILE_CHOOSER_ACTION_OPEN;
|
action = GTK_FILE_CHOOSER_ACTION_OPEN;
|
||||||
accept_button = GTK_STOCK_OPEN;
|
accept_button = GTK_STOCK_OPEN;
|
||||||
} else if (mode == FILE_DIALOG_SAVE) {
|
} else if (mode_type == FILE_DIALOG_OPEN_FOLDER) {
|
||||||
|
action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
|
||||||
|
accept_button = GTK_STOCK_OPEN;
|
||||||
|
} else if (mode_type == FILE_DIALOG_SAVE) {
|
||||||
action = GTK_FILE_CHOOSER_ACTION_SAVE;
|
action = GTK_FILE_CHOOSER_ACTION_SAVE;
|
||||||
accept_button = GTK_STOCK_SAVE;
|
accept_button = GTK_STOCK_SAVE;
|
||||||
} else {
|
} else {
|
||||||
@ -131,12 +162,6 @@ bool ClientHandler::OnFileDialog(CefRefPtr<CefBrowser> browser,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string base_name;
|
|
||||||
if (!default_file_name.empty()) {
|
|
||||||
base_name =
|
|
||||||
basename(const_cast<char*>(default_file_name.ToString().c_str()));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string title_str;
|
std::string title_str;
|
||||||
if (!title.empty()) {
|
if (!title.empty()) {
|
||||||
title_str = title;
|
title_str = title;
|
||||||
@ -148,6 +173,9 @@ bool ClientHandler::OnFileDialog(CefRefPtr<CefBrowser> browser,
|
|||||||
case FILE_DIALOG_OPEN_MULTIPLE:
|
case FILE_DIALOG_OPEN_MULTIPLE:
|
||||||
title_str = "Open Files";
|
title_str = "Open Files";
|
||||||
break;
|
break;
|
||||||
|
case FILE_DIALOG_OPEN_FOLDER:
|
||||||
|
title_str = "Open Folder";
|
||||||
|
break;
|
||||||
case FILE_DIALOG_SAVE:
|
case FILE_DIALOG_SAVE:
|
||||||
title_str = "Save File";
|
title_str = "Save File";
|
||||||
break;
|
break;
|
||||||
@ -166,28 +194,39 @@ bool ClientHandler::OnFileDialog(CefRefPtr<CefBrowser> browser,
|
|||||||
accept_button, GTK_RESPONSE_ACCEPT,
|
accept_button, GTK_RESPONSE_ACCEPT,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
if (mode == FILE_DIALOG_OPEN_MULTIPLE) {
|
if (mode_type == FILE_DIALOG_OPEN_MULTIPLE)
|
||||||
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE);
|
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE);
|
||||||
} else if (mode == FILE_DIALOG_SAVE) {
|
|
||||||
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog),
|
if (mode_type == FILE_DIALOG_SAVE) {
|
||||||
TRUE);
|
gtk_file_chooser_set_do_overwrite_confirmation(
|
||||||
|
GTK_FILE_CHOOSER(dialog),
|
||||||
|
!!(mode & FILE_DIALOG_OVERWRITEPROMPT_FLAG));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode == FILE_DIALOG_SAVE && !base_name.empty()) {
|
gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(dialog),
|
||||||
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog),
|
!(mode & FILE_DIALOG_HIDEREADONLY_FLAG));
|
||||||
base_name.c_str());
|
|
||||||
|
if (!default_file_path.empty()) {
|
||||||
|
gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog),
|
||||||
|
default_file_path.ToString().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
AddFiltersForAcceptTypes(GTK_FILE_CHOOSER(dialog), accept_types, true);
|
std::vector<GtkFileFilter*> filters;
|
||||||
|
AddFilters(GTK_FILE_CHOOSER(dialog), accept_filters, true, &filters);
|
||||||
|
if (selected_accept_filter < static_cast<int>(filters.size())) {
|
||||||
|
gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog),
|
||||||
|
filters[selected_accept_filter]);
|
||||||
|
}
|
||||||
|
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
|
||||||
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
|
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
|
||||||
if (mode == FILE_DIALOG_OPEN || mode == FILE_DIALOG_SAVE) {
|
if (mode_type == FILE_DIALOG_OPEN || mode_type == FILE_DIALOG_OPEN_FOLDER ||
|
||||||
|
mode_type == FILE_DIALOG_SAVE) {
|
||||||
char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
||||||
files.push_back(std::string(filename));
|
files.push_back(std::string(filename));
|
||||||
success = true;
|
success = true;
|
||||||
} else if (mode == FILE_DIALOG_OPEN_MULTIPLE) {
|
} else if (mode_type == FILE_DIALOG_OPEN_MULTIPLE) {
|
||||||
GSList* filenames =
|
GSList* filenames =
|
||||||
gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog));
|
gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog));
|
||||||
if (filenames) {
|
if (filenames) {
|
||||||
@ -203,10 +242,24 @@ bool ClientHandler::OnFileDialog(CefRefPtr<CefBrowser> browser,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int filter_index = selected_accept_filter;
|
||||||
|
if (success) {
|
||||||
|
GtkFileFilter* selected_filter =
|
||||||
|
gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(dialog));
|
||||||
|
if (selected_filter != NULL) {
|
||||||
|
for (size_t x = 0; x < filters.size(); ++x) {
|
||||||
|
if (filters[x] == selected_filter) {
|
||||||
|
filter_index = x;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gtk_widget_destroy(dialog);
|
gtk_widget_destroy(dialog);
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
callback->Continue(files);
|
callback->Continue(filter_index, files);
|
||||||
else
|
else
|
||||||
callback->Cancel();
|
callback->Cancel();
|
||||||
|
|
||||||
|
@ -14,19 +14,63 @@ namespace {
|
|||||||
const char kTestUrl[] = "http://tests/dialogs";
|
const char kTestUrl[] = "http://tests/dialogs";
|
||||||
const char kFileOpenMessageName[] = "DialogTest.FileOpen";
|
const char kFileOpenMessageName[] = "DialogTest.FileOpen";
|
||||||
const char kFileOpenMultipleMessageName[] = "DialogTest.FileOpenMultiple";
|
const char kFileOpenMultipleMessageName[] = "DialogTest.FileOpenMultiple";
|
||||||
|
const char kFileOpenFolderMessageName[] = "DialogTest.FileOpenFolder";
|
||||||
const char kFileSaveMessageName[] = "DialogTest.FileSave";
|
const char kFileSaveMessageName[] = "DialogTest.FileSave";
|
||||||
|
|
||||||
|
#if defined(OS_WIN)
|
||||||
|
#define PATH_SEP '\\'
|
||||||
|
#else
|
||||||
|
#define PATH_SEP '/'
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Store persistent dialog state information.
|
||||||
|
class DialogState : public base::RefCountedThreadSafe<DialogState> {
|
||||||
|
public:
|
||||||
|
DialogState()
|
||||||
|
: mode_(FILE_DIALOG_OPEN),
|
||||||
|
last_selected_filter_(0),
|
||||||
|
pending_(false) {}
|
||||||
|
|
||||||
|
cef_file_dialog_mode_t mode_;
|
||||||
|
int last_selected_filter_;
|
||||||
|
CefString last_file_;
|
||||||
|
bool pending_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(DialogState);
|
||||||
|
};
|
||||||
|
|
||||||
// Callback executed when the file dialog is dismissed.
|
// Callback executed when the file dialog is dismissed.
|
||||||
class DialogCallback : public CefRunFileDialogCallback {
|
class DialogCallback : public CefRunFileDialogCallback {
|
||||||
public:
|
public:
|
||||||
explicit DialogCallback(
|
DialogCallback(
|
||||||
CefRefPtr<CefMessageRouterBrowserSide::Callback> router_callback)
|
CefRefPtr<CefMessageRouterBrowserSide::Callback> router_callback,
|
||||||
: router_callback_(router_callback) {
|
scoped_refptr<DialogState> dialog_state)
|
||||||
|
: router_callback_(router_callback),
|
||||||
|
dialog_state_(dialog_state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void OnFileDialogDismissed(
|
virtual void OnFileDialogDismissed(
|
||||||
CefRefPtr<CefBrowserHost> browser_host,
|
int last_selected_filter,
|
||||||
const std::vector<CefString>& file_paths) OVERRIDE {
|
const std::vector<CefString>& file_paths) OVERRIDE {
|
||||||
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
DCHECK(dialog_state_->pending_);
|
||||||
|
|
||||||
|
if (!file_paths.empty()) {
|
||||||
|
if (dialog_state_->mode_ != FILE_DIALOG_OPEN_FOLDER)
|
||||||
|
dialog_state_->last_selected_filter_ = last_selected_filter;
|
||||||
|
|
||||||
|
dialog_state_->last_file_ = file_paths[0];
|
||||||
|
if (dialog_state_->mode_ == FILE_DIALOG_OPEN_FOLDER) {
|
||||||
|
std::string last_file = dialog_state_->last_file_;
|
||||||
|
if (last_file[last_file.length() - 1] != PATH_SEP) {
|
||||||
|
// Add a trailing slash so we know it's a directory. Otherwise, file
|
||||||
|
// dialogs will think the last path component is a file name.
|
||||||
|
last_file += PATH_SEP;
|
||||||
|
dialog_state_->last_file_ = last_file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Send a message back to the render process with the list of file paths.
|
// Send a message back to the render process with the list of file paths.
|
||||||
std::string response;
|
std::string response;
|
||||||
for (int i = 0; i < static_cast<int>(file_paths.size()); ++i) {
|
for (int i = 0; i < static_cast<int>(file_paths.size()); ++i) {
|
||||||
@ -37,12 +81,17 @@ class DialogCallback : public CefRunFileDialogCallback {
|
|||||||
|
|
||||||
router_callback_->Success(response);
|
router_callback_->Success(response);
|
||||||
router_callback_ = NULL;
|
router_callback_ = NULL;
|
||||||
|
|
||||||
|
dialog_state_->pending_ = false;
|
||||||
|
dialog_state_ = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CefRefPtr<CefMessageRouterBrowserSide::Callback> router_callback_;
|
CefRefPtr<CefMessageRouterBrowserSide::Callback> router_callback_;
|
||||||
|
scoped_refptr<DialogState> dialog_state_;
|
||||||
|
|
||||||
IMPLEMENT_REFCOUNTING(DialogCallback);
|
IMPLEMENT_REFCOUNTING(DialogCallback);
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(DialogCallback);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle messages in the browser process.
|
// Handle messages in the browser process.
|
||||||
@ -57,36 +106,72 @@ class Handler : public CefMessageRouterBrowserSide::Handler {
|
|||||||
const CefString& request,
|
const CefString& request,
|
||||||
bool persistent,
|
bool persistent,
|
||||||
CefRefPtr<Callback> callback) OVERRIDE {
|
CefRefPtr<Callback> callback) OVERRIDE {
|
||||||
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
|
||||||
// Only handle messages from the test URL.
|
// Only handle messages from the test URL.
|
||||||
const std::string& url = frame->GetURL();
|
const std::string& url = frame->GetURL();
|
||||||
if (url.find(kTestUrl) != 0)
|
if (url.find(kTestUrl) != 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Sample file type filter.
|
if (!dialog_state_.get())
|
||||||
std::vector<CefString> file_types;
|
dialog_state_ = new DialogState;
|
||||||
file_types.push_back("text/*");
|
|
||||||
file_types.push_back(".log");
|
|
||||||
file_types.push_back(".patch");
|
|
||||||
|
|
||||||
CefRefPtr<DialogCallback> dialog_callback(new DialogCallback(callback));
|
// Make sure we're only running one dialog at a time.
|
||||||
|
DCHECK(!dialog_state_->pending_);
|
||||||
|
|
||||||
|
std::vector<CefString> accept_filters;
|
||||||
|
std::string title;
|
||||||
|
|
||||||
const std::string& message_name = request;
|
const std::string& message_name = request;
|
||||||
if (message_name == kFileOpenMessageName) {
|
if (message_name == kFileOpenMessageName) {
|
||||||
browser->GetHost()->RunFileDialog(FILE_DIALOG_OPEN, "My Open Dialog",
|
dialog_state_->mode_ = FILE_DIALOG_OPEN;
|
||||||
"test.txt", file_types, dialog_callback.get());
|
title = "My Open Dialog";
|
||||||
} else if (message_name == kFileOpenMultipleMessageName) {
|
} else if (message_name == kFileOpenMultipleMessageName) {
|
||||||
browser->GetHost()->RunFileDialog(FILE_DIALOG_OPEN_MULTIPLE,
|
dialog_state_->mode_ = FILE_DIALOG_OPEN_MULTIPLE;
|
||||||
"My Open Multiple Dialog", CefString(), file_types,
|
title = "My Open Multiple Dialog";
|
||||||
dialog_callback.get());
|
} else if (message_name == kFileOpenFolderMessageName) {
|
||||||
|
dialog_state_->mode_ = FILE_DIALOG_OPEN_FOLDER;
|
||||||
|
title = "My Open Folder Dialog";
|
||||||
} else if (message_name == kFileSaveMessageName) {
|
} else if (message_name == kFileSaveMessageName) {
|
||||||
browser->GetHost()->RunFileDialog(FILE_DIALOG_SAVE, "My Save Dialog",
|
dialog_state_->mode_ = static_cast<cef_file_dialog_mode_t>(
|
||||||
"test.txt", file_types, dialog_callback.get());
|
FILE_DIALOG_SAVE | FILE_DIALOG_OVERWRITEPROMPT_FLAG);
|
||||||
|
title = "My Save Dialog";
|
||||||
} else {
|
} else {
|
||||||
NOTREACHED();
|
NOTREACHED();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dialog_state_->mode_ != FILE_DIALOG_OPEN_FOLDER) {
|
||||||
|
// Build filters based on mime time.
|
||||||
|
accept_filters.push_back("text/*");
|
||||||
|
|
||||||
|
// Build filters based on file extension.
|
||||||
|
accept_filters.push_back(".log");
|
||||||
|
accept_filters.push_back(".patch");
|
||||||
|
|
||||||
|
// Add specific filters as-is.
|
||||||
|
accept_filters.push_back("Document Files|.doc;.odt");
|
||||||
|
accept_filters.push_back("Image Files|.png;.jpg;.gif");
|
||||||
|
accept_filters.push_back("PDF Files|.pdf");
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog_state_->pending_ = true;
|
||||||
|
|
||||||
|
browser->GetHost()->RunFileDialog(
|
||||||
|
dialog_state_->mode_,
|
||||||
|
title,
|
||||||
|
dialog_state_->last_file_,
|
||||||
|
accept_filters,
|
||||||
|
dialog_state_->last_selected_filter_,
|
||||||
|
new DialogCallback(callback, dialog_state_));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
scoped_refptr<DialogState> dialog_state_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(Handler);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -57,6 +57,7 @@ Click a button to show the associated dialog type.
|
|||||||
<br/>input type="file": <input type="file" name="pic" accept="text/*,.js,.css,image/*">
|
<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('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('fom', 'FileOpenMultiple');" value="Show File Open Multiple"> <span id="fom"></span>
|
||||||
|
<br/><input type="button" onclick="show_file_dialog('fof', 'FileOpenFolder');" value="Show File Open Folder"> <span id="fof"></span>
|
||||||
<br/><input type="button" onclick="show_file_dialog('fs', 'FileSave');" value="Show File Save"> <span id="fs"></span>
|
<br/><input type="button" onclick="show_file_dialog('fs', 'FileSave');" value="Show File Save"> <span id="fs"></span>
|
||||||
<p id="time"></p>
|
<p id="time"></p>
|
||||||
</form>
|
</form>
|
||||||
|
@ -22,6 +22,7 @@ class DialogTestHandler : public TestHandler {
|
|||||||
: mode(dialog_mode),
|
: mode(dialog_mode),
|
||||||
title("Test Title"),
|
title("Test Title"),
|
||||||
default_file_name("Test File Name"),
|
default_file_name("Test File Name"),
|
||||||
|
selected_accept_filter(1), // Something other than 0 for testing.
|
||||||
callback_async(false),
|
callback_async(false),
|
||||||
callback_cancel(false) {
|
callback_cancel(false) {
|
||||||
accept_types.push_back("text/*");
|
accept_types.push_back("text/*");
|
||||||
@ -33,6 +34,7 @@ class DialogTestHandler : public TestHandler {
|
|||||||
CefString title;
|
CefString title;
|
||||||
CefString default_file_name;
|
CefString default_file_name;
|
||||||
std::vector<CefString> accept_types;
|
std::vector<CefString> accept_types;
|
||||||
|
int selected_accept_filter;
|
||||||
|
|
||||||
bool callback_async; // True if the callback should execute asynchronously.
|
bool callback_async; // True if the callback should execute asynchronously.
|
||||||
bool callback_cancel; // True if the callback should cancel.
|
bool callback_cancel; // True if the callback should cancel.
|
||||||
@ -46,17 +48,18 @@ class DialogTestHandler : public TestHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OnFileDialogDismissed(
|
void OnFileDialogDismissed(
|
||||||
CefRefPtr<CefBrowserHost> browser_host,
|
int selected_accept_filter,
|
||||||
const std::vector<CefString>& file_paths) override {
|
const std::vector<CefString>& file_paths) override {
|
||||||
handler_->got_onfiledialogdismissed_.yes();
|
handler_->got_onfiledialogdismissed_.yes();
|
||||||
|
|
||||||
std::string url = browser_host->GetBrowser()->GetMainFrame()->GetURL();
|
if (handler_->config_.callback_cancel) {
|
||||||
EXPECT_STREQ(kTestUrl, url.c_str());
|
EXPECT_EQ(0, selected_accept_filter);
|
||||||
|
|
||||||
if (handler_->config_.callback_cancel)
|
|
||||||
EXPECT_TRUE(file_paths.empty());
|
EXPECT_TRUE(file_paths.empty());
|
||||||
else
|
} else {
|
||||||
|
EXPECT_EQ(handler_->config_.selected_accept_filter,
|
||||||
|
selected_accept_filter);
|
||||||
TestStringVectorEqual(handler_->config_.callback_paths, file_paths);
|
TestStringVectorEqual(handler_->config_.callback_paths, file_paths);
|
||||||
|
}
|
||||||
|
|
||||||
handler_->DestroyTest();
|
handler_->DestroyTest();
|
||||||
handler_ = NULL;
|
handler_ = NULL;
|
||||||
@ -89,6 +92,7 @@ class DialogTestHandler : public TestHandler {
|
|||||||
config_.title,
|
config_.title,
|
||||||
config_.default_file_name,
|
config_.default_file_name,
|
||||||
config_.accept_types,
|
config_.accept_types,
|
||||||
|
config_.selected_accept_filter,
|
||||||
new Callback(this));
|
new Callback(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,7 +100,8 @@ class DialogTestHandler : public TestHandler {
|
|||||||
if (config_.callback_cancel)
|
if (config_.callback_cancel)
|
||||||
callback->Cancel();
|
callback->Cancel();
|
||||||
else
|
else
|
||||||
callback->Continue(config_.callback_paths);
|
callback->Continue(config_.selected_accept_filter,
|
||||||
|
config_.callback_paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
// CefDialogHandler
|
// CefDialogHandler
|
||||||
@ -106,6 +111,7 @@ class DialogTestHandler : public TestHandler {
|
|||||||
const CefString& title,
|
const CefString& title,
|
||||||
const CefString& default_file_name,
|
const CefString& default_file_name,
|
||||||
const std::vector<CefString>& accept_types,
|
const std::vector<CefString>& accept_types,
|
||||||
|
int selected_accept_filter,
|
||||||
CefRefPtr<CefFileDialogCallback> callback) override {
|
CefRefPtr<CefFileDialogCallback> callback) override {
|
||||||
got_onfiledialog_.yes();
|
got_onfiledialog_.yes();
|
||||||
|
|
||||||
@ -157,6 +163,22 @@ TEST(DialogTest, FileEmptyParams) {
|
|||||||
ReleaseAndWaitForDestructor(handler);
|
ReleaseAndWaitForDestructor(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(DialogTest, FileAdditionalFlags) {
|
||||||
|
DialogTestHandler::TestConfig config(
|
||||||
|
static_cast<cef_file_dialog_mode_t>(FILE_DIALOG_OPEN |
|
||||||
|
FILE_DIALOG_HIDEREADONLY_FLAG |
|
||||||
|
FILE_DIALOG_OVERWRITEPROMPT_FLAG));
|
||||||
|
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();
|
||||||
|
ReleaseAndWaitForDestructor(handler);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(DialogTest, FileOpen) {
|
TEST(DialogTest, FileOpen) {
|
||||||
DialogTestHandler::TestConfig config(FILE_DIALOG_OPEN);
|
DialogTestHandler::TestConfig config(FILE_DIALOG_OPEN);
|
||||||
config.callback_async = false;
|
config.callback_async = false;
|
||||||
@ -243,6 +265,48 @@ TEST(DialogTest, FileOpenMultipleAsyncCancel) {
|
|||||||
ReleaseAndWaitForDestructor(handler);
|
ReleaseAndWaitForDestructor(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(DialogTest, FileOpenFolder) {
|
||||||
|
DialogTestHandler::TestConfig config(FILE_DIALOG_OPEN_FOLDER);
|
||||||
|
config.callback_async = false;
|
||||||
|
config.callback_cancel = false;
|
||||||
|
config.callback_paths.push_back("/path/to/folder");
|
||||||
|
|
||||||
|
CefRefPtr<DialogTestHandler> handler = new DialogTestHandler(config);
|
||||||
|
handler->ExecuteTest();
|
||||||
|
ReleaseAndWaitForDestructor(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(DialogTest, FileOpenFolderCancel) {
|
||||||
|
DialogTestHandler::TestConfig config(FILE_DIALOG_OPEN_FOLDER);
|
||||||
|
config.callback_async = false;
|
||||||
|
config.callback_cancel = true;
|
||||||
|
|
||||||
|
CefRefPtr<DialogTestHandler> handler = new DialogTestHandler(config);
|
||||||
|
handler->ExecuteTest();
|
||||||
|
ReleaseAndWaitForDestructor(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(DialogTest, FileOpenFolderAsync) {
|
||||||
|
DialogTestHandler::TestConfig config(FILE_DIALOG_OPEN_FOLDER);
|
||||||
|
config.callback_async = true;
|
||||||
|
config.callback_cancel = false;
|
||||||
|
config.callback_paths.push_back("/path/to/folder");
|
||||||
|
|
||||||
|
CefRefPtr<DialogTestHandler> handler = new DialogTestHandler(config);
|
||||||
|
handler->ExecuteTest();
|
||||||
|
ReleaseAndWaitForDestructor(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(DialogTest, FileOpenFolderAsyncCancel) {
|
||||||
|
DialogTestHandler::TestConfig config(FILE_DIALOG_OPEN_FOLDER);
|
||||||
|
config.callback_async = false;
|
||||||
|
config.callback_cancel = true;
|
||||||
|
|
||||||
|
CefRefPtr<DialogTestHandler> handler = new DialogTestHandler(config);
|
||||||
|
handler->ExecuteTest();
|
||||||
|
ReleaseAndWaitForDestructor(handler);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(DialogTest, FileSave) {
|
TEST(DialogTest, FileSave) {
|
||||||
DialogTestHandler::TestConfig config(FILE_DIALOG_SAVE);
|
DialogTestHandler::TestConfig config(FILE_DIALOG_SAVE);
|
||||||
config.callback_async = false;
|
config.callback_async = false;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user