Skip to content
Snippets Groups Projects
Commit b8fa0421 authored by thestig@chromium.org's avatar thestig@chromium.org
Browse files

GTK: Allow file I/O in file dialog functions functions on the UI thread.

BUG=61611
TEST=Linux file dialogs don't trigger AssertIOAllowed DCHECKs.
Review URL: http://codereview.chromium.org/4321003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@64859 0039d316-1c4b-4281-b951-d872f2087c98
parent 6e15b7ef
No related branches found
No related tags found
No related merge requests found
......@@ -13,8 +13,9 @@
#include "base/message_loop.h"
#include "base/mime_util.h"
#include "base/sys_string_conversions.h"
#include "base/utf_string_conversions.h"
#include "base/thread.h"
#include "base/thread_restrictions.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/shell_dialogs.h"
......@@ -96,6 +97,17 @@ class SelectFileDialogImpl : public SelectFileDialog {
gint response_id,
bool allow_folder);
// Common function for CreateFileOpenDialog and CreateMultiFileOpenDialog.
GtkWidget* CreateFileOpenHelper(const std::string& title,
const FilePath& default_path,
gfx::NativeWindow parent);
// Wrapper for file_util::DirectoryExists() that allow access on the UI
// thread. Use this only in the file dialog functions, where it's ok
// because the file dialog has to do many stats anyway. One more won't
// hurt too badly and it's likely already cached.
bool CallDirectoryExistsOnUIThread(const FilePath& path);
// Callback for when the user responds to a Save As or Open File dialog.
CHROMEGTK_CALLBACK_1(SelectFileDialogImpl, void,
OnSelectSingleFileDialogResponse, gint);
......@@ -329,48 +341,25 @@ void SelectFileDialogImpl::FileNotSelected(GtkWidget* dialog) {
gtk_widget_destroy(dialog);
}
GtkWidget* SelectFileDialogImpl::CreateSelectFolderDialog(
bool SelectFileDialogImpl::CallDirectoryExistsOnUIThread(const FilePath& path) {
base::ThreadRestrictions::ScopedAllowIO allow_io;
return file_util::DirectoryExists(path);
}
GtkWidget* SelectFileDialogImpl::CreateFileOpenHelper(
const std::string& title,
const FilePath& default_path,
gfx::NativeWindow parent) {
std::string title_string = !title.empty() ? title :
l10n_util::GetStringUTF8(IDS_SELECT_FOLDER_DIALOG_TITLE);
GtkWidget* dialog =
gtk_file_chooser_dialog_new(title_string.c_str(), parent,
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
NULL);
if (!default_path.empty()) {
gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog),
default_path.value().c_str());
} else if (!last_opened_path_->empty()) {
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
last_opened_path_->value().c_str());
}
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE);
g_signal_connect(dialog, "response",
G_CALLBACK(OnSelectSingleFolderDialogResponseThunk), this);
return dialog;
}
GtkWidget* SelectFileDialogImpl::CreateFileOpenDialog(const std::string& title,
const FilePath& default_path, gfx::NativeWindow parent) {
std::string title_string = !title.empty() ? title :
l10n_util::GetStringUTF8(IDS_OPEN_FILE_DIALOG_TITLE);
GtkWidget* dialog =
gtk_file_chooser_dialog_new(title_string.c_str(), parent,
gtk_file_chooser_dialog_new(title.c_str(), parent,
GTK_FILE_CHOOSER_ACTION_OPEN,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
NULL);
AddFilters(GTK_FILE_CHOOSER(dialog));
if (!default_path.empty()) {
if (file_util::DirectoryExists(default_path)) {
if (CallDirectoryExistsOnUIThread(default_path)) {
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
default_path.value().c_str());
} else {
......@@ -383,41 +372,56 @@ GtkWidget* SelectFileDialogImpl::CreateFileOpenDialog(const std::string& title,
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
last_opened_path_->value().c_str());
}
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE);
g_signal_connect(dialog, "response",
G_CALLBACK(OnSelectSingleFileDialogResponseThunk), this);
return dialog;
}
GtkWidget* SelectFileDialogImpl::CreateMultiFileOpenDialog(
GtkWidget* SelectFileDialogImpl::CreateSelectFolderDialog(
const std::string& title,
const FilePath& default_path,
gfx::NativeWindow parent) {
std::string title_string = !title.empty() ? title :
l10n_util::GetStringUTF8(IDS_OPEN_FILES_DIALOG_TITLE);
l10n_util::GetStringUTF8(IDS_SELECT_FOLDER_DIALOG_TITLE);
GtkWidget* dialog =
gtk_file_chooser_dialog_new(title_string.c_str(), parent,
GTK_FILE_CHOOSER_ACTION_OPEN,
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
NULL);
AddFilters(GTK_FILE_CHOOSER(dialog));
if (!default_path.empty()) {
if (file_util::DirectoryExists(default_path)) {
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
default_path.value().c_str());
} else {
// If the file doesn't exist, this will just switch to the correct
// directory. That's good enough.
gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog),
default_path.value().c_str());
}
gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog),
default_path.value().c_str());
} else if (!last_opened_path_->empty()) {
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
last_opened_path_->value().c_str());
}
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE);
g_signal_connect(dialog, "response",
G_CALLBACK(OnSelectSingleFolderDialogResponseThunk), this);
return dialog;
}
GtkWidget* SelectFileDialogImpl::CreateFileOpenDialog(
const std::string& title,
const FilePath& default_path,
gfx::NativeWindow parent) {
std::string title_string = !title.empty() ? title :
l10n_util::GetStringUTF8(IDS_OPEN_FILE_DIALOG_TITLE);
GtkWidget* dialog = CreateFileOpenHelper(title_string, default_path, parent);
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE);
g_signal_connect(dialog, "response",
G_CALLBACK(OnSelectSingleFileDialogResponseThunk), this);
return dialog;
}
GtkWidget* SelectFileDialogImpl::CreateMultiFileOpenDialog(
const std::string& title,
const FilePath& default_path,
gfx::NativeWindow parent) {
std::string title_string = !title.empty() ? title :
l10n_util::GetStringUTF8(IDS_OPEN_FILES_DIALOG_TITLE);
GtkWidget* dialog = CreateFileOpenHelper(title_string, default_path, parent);
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE);
g_signal_connect(dialog, "response",
G_CALLBACK(OnSelectMultiFileDialogResponseThunk), this);
......@@ -515,10 +519,7 @@ void SelectFileDialogImpl::SelectSingleFileHelper(GtkWidget* dialog,
return;
}
// We're accessing the disk from the UI thread here, but in this case it's
// ok because we may have just done lots of stats in the file selection
// dialog. One more won't hurt too badly.
if (file_util::DirectoryExists(path))
if (CallDirectoryExistsOnUIThread(path))
FileNotSelected(dialog);
else
FileSelected(dialog, path);
......@@ -551,7 +552,7 @@ void SelectFileDialogImpl::OnSelectMultiFileDialogResponse(
for (GSList* iter = filenames; iter != NULL; iter = g_slist_next(iter)) {
FilePath path(static_cast<char*>(iter->data));
g_free(iter->data);
if (file_util::DirectoryExists(path))
if (CallDirectoryExistsOnUIThread(path))
continue;
filenames_fp.push_back(path);
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment