blob: 0c8ae67d8948fa1becce82879bf0dbd6f2418984 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/fileapi/file_system_chooser.h"
#include "base/bind.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_client.h"
#include "storage/browser/fileapi/isolated_context.h"
#include "ui/shell_dialogs/select_file_policy.h"
namespace content {
// static
void FileSystemChooser::CreateAndShow(
int render_process_id,
int frame_id,
ResultCallback callback,
scoped_refptr<base::TaskRunner> callback_runner) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RenderFrameHost* rfh = RenderFrameHost::FromID(render_process_id, frame_id);
WebContents* web_contents = WebContents::FromRenderFrameHost(rfh);
auto* listener = new FileSystemChooser(render_process_id, std::move(callback),
std::move(callback_runner));
listener->dialog_ = ui::SelectFileDialog::Create(
listener,
GetContentClient()->browser()->CreateSelectFilePolicy(web_contents));
// TODO(https://crbug.com/878581): Better/more specific options to pass to
// SelectFile.
listener->dialog_->SelectFile(
ui::SelectFileDialog::SELECT_OPEN_FILE, /*title=*/base::string16(),
/*default_path=*/base::FilePath(), /*file_types=*/nullptr,
/*file_type_index=*/0,
/*default_extension=*/base::FilePath::StringType(),
web_contents ? web_contents->GetTopLevelNativeWindow() : nullptr,
/*params=*/nullptr);
}
FileSystemChooser::FileSystemChooser(
int render_process_id,
ResultCallback callback,
scoped_refptr<base::TaskRunner> callback_runner)
: render_process_id_(render_process_id),
callback_(std::move(callback)),
callback_runner_(std::move(callback_runner)) {}
FileSystemChooser::~FileSystemChooser() {
if (dialog_)
dialog_->ListenerDestroyed();
}
void FileSystemChooser::FileSelected(const base::FilePath& path,
int index,
void* params) {
MultiFilesSelected({path}, params);
}
void FileSystemChooser::MultiFilesSelected(
const std::vector<base::FilePath>& files,
void* params) {
auto* isolated_context = storage::IsolatedContext::GetInstance();
DCHECK(isolated_context);
auto* security_policy = ChildProcessSecurityPolicy::GetInstance();
DCHECK(security_policy);
std::vector<blink::mojom::FileSystemEntryPtr> result;
result.reserve(files.size());
for (const auto& path : files) {
auto entry = blink::mojom::FileSystemEntry::New();
entry->file_system_id = isolated_context->RegisterFileSystemForPath(
storage::kFileSystemTypeNativeForPlatformApp, std::string(), path,
&entry->base_name);
// TODO(https://crbug.com/878585): Determine if we always want to grant
// write permission.
security_policy->GrantReadFileSystem(render_process_id_,
entry->file_system_id);
security_policy->GrantWriteFileSystem(render_process_id_,
entry->file_system_id);
security_policy->GrantDeleteFromFileSystem(render_process_id_,
entry->file_system_id);
result.push_back(std::move(entry));
}
callback_runner_->PostTask(
FROM_HERE, base::BindOnce(std::move(callback_), base::File::FILE_OK,
std::move(result)));
delete this;
}
void FileSystemChooser::FileSelectionCanceled(void* params) {
callback_runner_->PostTask(
FROM_HERE,
base::BindOnce(std::move(callback_), base::File::FILE_ERROR_ABORT,
std::vector<blink::mojom::FileSystemEntryPtr>()));
delete this;
}
} // namespace content