This source file includes following definitions.
- ConvertExtensionsToFileTypeInfo
- SelectFile
- StartSelectFile
- FileSelected
- MultiFilesSelected
- FileSelectionCanceled
- SendResponse
- CreateFileSelector
- user_gesture_check_enabled_
- user_gesture_check_enabled_
- FileBrowserHandlerInternalSelectFileFunction
- RunImpl
- OnFilePathSelected
- GrantPermissions
- Respond
#include "chrome/browser/chromeos/extensions/file_manager/file_browser_handler_api.h"
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop_proxy.h"
#include "chrome/browser/chromeos/file_manager/fileapi_util.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/chrome_select_file_policy.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/extensions/api/file_browser_handler_internal.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "ui/shell_dialogs/select_file_dialog.h"
#include "webkit/browser/fileapi/file_system_backend.h"
#include "webkit/browser/fileapi/file_system_context.h"
#include "webkit/common/fileapi/file_system_info.h"
#include "webkit/common/fileapi/file_system_util.h"
using content::BrowserThread;
using extensions::api::file_browser_handler_internal::FileEntryInfo;
using file_manager::FileSelector;
using file_manager::FileSelectorFactory;
using file_manager::util::EntryDefinition;
using file_manager::util::FileDefinition;
namespace SelectFile =
extensions::api::file_browser_handler_internal::SelectFile;
namespace {
const char kNoUserGestureError[] =
"This method can only be called in response to user gesture, such as a "
"mouse click or key press.";
ui::SelectFileDialog::FileTypeInfo ConvertExtensionsToFileTypeInfo(
const std::vector<std::string>& extensions) {
ui::SelectFileDialog::FileTypeInfo file_type_info;
for (size_t i = 0; i < extensions.size(); ++i) {
base::FilePath::StringType allowed_extension =
base::FilePath::FromUTF8Unsafe(extensions[i]).value();
std::vector<base::FilePath::StringType> inner_vector;
inner_vector.push_back(allowed_extension);
file_type_info.extensions.push_back(inner_vector);
}
return file_type_info;
}
class FileSelectorImpl : public FileSelector,
public ui::SelectFileDialog::Listener {
public:
explicit FileSelectorImpl();
virtual ~FileSelectorImpl() OVERRIDE;
protected:
virtual void SelectFile(
const base::FilePath& suggested_name,
const std::vector<std::string>& allowed_extensions,
Browser* browser,
FileBrowserHandlerInternalSelectFileFunction* function) OVERRIDE;
virtual void FileSelected(const base::FilePath& path,
int index,
void* params) OVERRIDE;
virtual void MultiFilesSelected(const std::vector<base::FilePath>& files,
void* params) OVERRIDE;
virtual void FileSelectionCanceled(void* params) OVERRIDE;
private:
bool StartSelectFile(const base::FilePath& suggested_name,
const std::vector<std::string>& allowed_extensions,
Browser* browser);
void SendResponse(bool success, const base::FilePath& selected_path);
scoped_refptr<ui::SelectFileDialog> dialog_;
scoped_refptr<FileBrowserHandlerInternalSelectFileFunction> function_;
DISALLOW_COPY_AND_ASSIGN(FileSelectorImpl);
};
FileSelectorImpl::FileSelectorImpl() {}
FileSelectorImpl::~FileSelectorImpl() {
if (dialog_.get())
dialog_->ListenerDestroyed();
if (function_.get())
SendResponse(false, base::FilePath());
}
void FileSelectorImpl::SelectFile(
const base::FilePath& suggested_name,
const std::vector<std::string>& allowed_extensions,
Browser* browser,
FileBrowserHandlerInternalSelectFileFunction* function) {
function_ = function;
if (!StartSelectFile(suggested_name, allowed_extensions, browser)) {
base::MessageLoopProxy::current()->PostTask(FROM_HERE,
base::Bind(&FileSelectorImpl::FileSelectionCanceled,
base::Unretained(this), static_cast<void*>(NULL)));
}
}
bool FileSelectorImpl::StartSelectFile(
const base::FilePath& suggested_name,
const std::vector<std::string>& allowed_extensions,
Browser* browser) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!dialog_.get());
DCHECK(browser);
if (!browser->window())
return false;
content::WebContents* web_contents =
browser->tab_strip_model()->GetActiveWebContents();
if (!web_contents)
return false;
dialog_ = ui::SelectFileDialog::Create(
this, new ChromeSelectFilePolicy(web_contents));
ui::SelectFileDialog::FileTypeInfo allowed_file_info =
ConvertExtensionsToFileTypeInfo(allowed_extensions);
allowed_file_info.support_drive = true;
dialog_->SelectFile(ui::SelectFileDialog::SELECT_SAVEAS_FILE,
base::string16() ,
suggested_name,
&allowed_file_info,
0 ,
std::string() ,
browser->window()->GetNativeWindow(), NULL );
return dialog_->IsRunning(browser->window()->GetNativeWindow());
}
void FileSelectorImpl::FileSelected(
const base::FilePath& path, int index, void* params) {
SendResponse(true, path);
delete this;
}
void FileSelectorImpl::MultiFilesSelected(
const std::vector<base::FilePath>& files,
void* params) {
NOTREACHED();
}
void FileSelectorImpl::FileSelectionCanceled(
void* params) {
SendResponse(false, base::FilePath());
delete this;
}
void FileSelectorImpl::SendResponse(bool success,
const base::FilePath& selected_path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (function_.get())
function_->OnFilePathSelected(success, selected_path);
function_ = NULL;
}
class FileSelectorFactoryImpl : public FileSelectorFactory {
public:
FileSelectorFactoryImpl() {}
virtual ~FileSelectorFactoryImpl() {}
virtual FileSelector* CreateFileSelector() const OVERRIDE {
return new FileSelectorImpl();
}
private:
DISALLOW_COPY_AND_ASSIGN(FileSelectorFactoryImpl);
};
}
FileBrowserHandlerInternalSelectFileFunction::
FileBrowserHandlerInternalSelectFileFunction()
: file_selector_factory_(new FileSelectorFactoryImpl()),
user_gesture_check_enabled_(true) {
}
FileBrowserHandlerInternalSelectFileFunction::
FileBrowserHandlerInternalSelectFileFunction(
FileSelectorFactory* file_selector_factory,
bool enable_user_gesture_check)
: file_selector_factory_(file_selector_factory),
user_gesture_check_enabled_(enable_user_gesture_check) {
DCHECK(file_selector_factory);
}
FileBrowserHandlerInternalSelectFileFunction::
~FileBrowserHandlerInternalSelectFileFunction() {}
bool FileBrowserHandlerInternalSelectFileFunction::RunImpl() {
scoped_ptr<SelectFile::Params> params(SelectFile::Params::Create(*args_));
base::FilePath suggested_name(params->selection_params.suggested_name);
std::vector<std::string> allowed_extensions;
if (params->selection_params.allowed_file_extensions.get())
allowed_extensions = *params->selection_params.allowed_file_extensions;
if (!user_gesture() && user_gesture_check_enabled_) {
SetError(kNoUserGestureError);
return false;
}
FileSelector* file_selector = file_selector_factory_->CreateFileSelector();
file_selector->SelectFile(suggested_name.BaseName(),
allowed_extensions,
GetCurrentBrowser(),
this);
return true;
}
void FileBrowserHandlerInternalSelectFileFunction::OnFilePathSelected(
bool success,
const base::FilePath& full_path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!success) {
Respond(EntryDefinition(), false);
return;
}
fileapi::ExternalFileSystemBackend* external_backend =
file_manager::util::GetFileSystemContextForRenderViewHost(
GetProfile(), render_view_host())->external_backend();
DCHECK(external_backend);
FileDefinition file_definition;
file_definition.is_directory = false;
external_backend->GetVirtualPath(full_path, &file_definition.virtual_path);
DCHECK(!file_definition.virtual_path.empty());
file_manager::util::ConvertFileDefinitionToEntryDefinition(
GetProfile(),
extension_id(),
file_definition,
base::Bind(
&FileBrowserHandlerInternalSelectFileFunction::GrantPermissions,
this,
full_path,
file_definition));
}
void FileBrowserHandlerInternalSelectFileFunction::GrantPermissions(
const base::FilePath& full_path,
const FileDefinition& file_definition,
const EntryDefinition& entry_definition) {
fileapi::ExternalFileSystemBackend* external_backend =
file_manager::util::GetFileSystemContextForRenderViewHost(
GetProfile(), render_view_host())->external_backend();
DCHECK(external_backend);
external_backend->GrantFileAccessToExtension(extension_id(),
file_definition.virtual_path);
content::ChildProcessSecurityPolicy::GetInstance()->GrantCreateReadWriteFile(
render_view_host()->GetProcess()->GetID(), full_path);
Respond(entry_definition, true);
}
void FileBrowserHandlerInternalSelectFileFunction::Respond(
const EntryDefinition& entry_definition,
bool success) {
scoped_ptr<SelectFile::Results::Result> result(
new SelectFile::Results::Result());
result->success = success;
if (success && entry_definition.error == base::File::FILE_OK) {
result->entry.reset(new FileEntryInfo());
result->entry->file_system_name = entry_definition.file_system_name;
result->entry->file_system_root = entry_definition.file_system_root_url;
result->entry->file_full_path =
"/" + entry_definition.full_path.AsUTF8Unsafe();
result->entry->file_is_directory = entry_definition.is_directory;
}
results_ = SelectFile::Results::Create(*result);
SendResponse(true);
}