Commit c1000477 authored by Marijn Kruisselbrink's avatar Marijn Kruisselbrink Committed by Commit Bot

[FS] Add support for external paths to drag&drop code.

A previous CL made opening files on special volumes via the file picker
and file handling APIs work, this also fixes the entry point for
drag&drop in a similar manner.

The bulk of this change is changing NativeFileSystemMangerImpl to use
the file system backends instead of base::File to determine if a path
is a file or a directory.

Bug: 1132102
Change-Id: I6c64356ea285b717ce63afc9c34d097bcde08016
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2432808Reviewed-by: default avatarVictor Costan <pwnall@chromium.org>
Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Commit-Queue: Marijn Kruisselbrink <mek@chromium.org>
Cr-Commit-Position: refs/heads/master@{#812944}
parent acc6cc94
......@@ -15,10 +15,12 @@ namespace content {
NativeFileSystemDragDropTokenImpl::NativeFileSystemDragDropTokenImpl(
NativeFileSystemManagerImpl* manager,
NativeFileSystemManagerImpl::PathType path_type,
const base::FilePath& file_path,
int renderer_process_id,
mojo::PendingReceiver<blink::mojom::NativeFileSystemDragDropToken> receiver)
: manager_(manager),
path_type_(path_type),
file_path_(file_path),
renderer_process_id_(renderer_process_id),
token_(base::UnguessableToken::Create()) {
......
......@@ -26,6 +26,7 @@ class CONTENT_EXPORT NativeFileSystemDragDropTokenImpl
public:
NativeFileSystemDragDropTokenImpl(
NativeFileSystemManagerImpl* manager,
NativeFileSystemManagerImpl::PathType path_type,
const base::FilePath& file_path,
int renderer_process_id,
mojo::PendingReceiver<blink::mojom::NativeFileSystemDragDropToken>
......@@ -41,6 +42,8 @@ class CONTENT_EXPORT NativeFileSystemDragDropTokenImpl
int renderer_process_id() const { return renderer_process_id_; }
NativeFileSystemManagerImpl::PathType path_type() const { return path_type_; }
const base::FilePath& file_path() const { return file_path_; }
const base::UnguessableToken& token() const { return token_; }
......@@ -56,6 +59,7 @@ class CONTENT_EXPORT NativeFileSystemDragDropTokenImpl
// Raw pointer since NativeFileSystemManagerImpl owns `this`.
NativeFileSystemManagerImpl* const manager_;
const NativeFileSystemManagerImpl::PathType path_type_;
const base::FilePath file_path_;
const int renderer_process_id_;
const base::UnguessableToken token_;
......
......@@ -151,10 +151,30 @@ bool IsValidTransferToken(NativeFileSystemTransferTokenImpl* token,
return true;
}
HandleType GetFileType(const base::FilePath& file_path) {
base::File::Info file_info;
base::GetFileInfo(file_path, &file_info);
return file_info.is_directory ? HandleType::kDirectory : HandleType::kFile;
void GetHandleTypeFromUrl(
storage::FileSystemURL url,
base::OnceCallback<void(HandleType)> callback,
scoped_refptr<base::SequencedTaskRunner> reply_runner,
storage::FileSystemOperationRunner* operation_runner) {
operation_runner->GetMetadata(
url, storage::FileSystemOperation::GET_METADATA_FIELD_IS_DIRECTORY,
base::BindOnce(
[](scoped_refptr<base::SequencedTaskRunner> reply_runner,
base::OnceCallback<void(HandleType)> callback,
base::File::Error result, const base::File::Info& file_info) {
// If we couldn't determine if the url is a directory, it is treated
// as a file. If the web-exposed API is ever changed to allow
// reporting errors when getting a dropped file as a
// FileSystemHandle, this would be one place such errors could be
// triggered.
HandleType type = HandleType::kFile;
if (result == base::File::FILE_OK && file_info.is_directory) {
type = HandleType::kDirectory;
}
reply_runner->PostTask(FROM_HERE,
base::BindOnce(std::move(callback), type));
},
std::move(reply_runner), std::move(callback)));
}
} // namespace
......@@ -300,13 +320,14 @@ void NativeFileSystemManagerImpl::ChooseEntries(
}
void NativeFileSystemManagerImpl::CreateNativeFileSystemDragDropToken(
PathType path_type,
const base::FilePath& file_path,
int renderer_id,
mojo::PendingReceiver<blink::mojom::NativeFileSystemDragDropToken>
receiver) {
auto drag_drop_token_impl =
std::make_unique<NativeFileSystemDragDropTokenImpl>(
this, file_path, renderer_id, std::move(receiver));
this, path_type, file_path, renderer_id, std::move(receiver));
auto token = drag_drop_token_impl->token();
drag_drop_tokens_.emplace(token, std::move(drag_drop_token_impl));
}
......@@ -360,30 +381,44 @@ void NativeFileSystemManagerImpl::ResolveDragDropToken(
// Look up whether the file path that's associated with the token is a file or
// directory and call ResolveDragDropTokenWithFileType with the result.
const base::FilePath& drag_drop_token_path =
drag_token_impl->second->file_path();
base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
base::BindOnce(&GetFileType, drag_drop_token_path),
FileSystemURLAndFSHandle url = CreateFileSystemURLFromPath(
binding_context.origin, drag_token_impl->second->path_type(),
drag_token_impl->second->file_path());
auto fs_url = url.url;
operation_runner().PostTaskWithThisObject(
FROM_HERE,
base::BindOnce(
&NativeFileSystemManagerImpl::ResolveDragDropTokenWithFileType,
weak_factory_.GetWeakPtr(), binding_context, drag_drop_token_path,
std::move(token_resolved_callback)));
&GetHandleTypeFromUrl, fs_url,
base::BindOnce(
&NativeFileSystemManagerImpl::ResolveDragDropTokenWithFileType,
weak_factory_.GetWeakPtr(), binding_context,
drag_token_impl->second->file_path(), std::move(url),
std::move(token_resolved_callback)),
base::SequencedTaskRunnerHandle::Get()));
}
void NativeFileSystemManagerImpl::ResolveDragDropTokenWithFileType(
const BindingContext& binding_context,
const base::FilePath& file_path,
FileSystemURLAndFSHandle url,
GetEntryFromDragDropTokenCallback token_resolved_callback,
HandleType file_type) {
SharedHandleState shared_handle_state = GetSharedHandleStateForPath(
file_path, binding_context.origin, std::move(url.file_system), file_type,
UserAction::kDragAndDrop);
blink::mojom::NativeFileSystemEntryPtr entry;
// TODO(mek): Support Drag&Drop of non-local paths.
if (file_type == HandleType::kDirectory) {
entry = CreateDirectoryEntryFromPath(binding_context, PathType::kLocal,
file_path, UserAction::kDragAndDrop);
entry = blink::mojom::NativeFileSystemEntry::New(
blink::mojom::NativeFileSystemHandle::NewDirectory(
CreateDirectoryHandle(binding_context, url.url,
shared_handle_state)),
url.base_name);
} else {
entry = CreateFileEntryFromPath(binding_context, PathType::kLocal,
file_path, UserAction::kDragAndDrop);
entry = blink::mojom::NativeFileSystemEntry::New(
blink::mojom::NativeFileSystemHandle::NewFile(
CreateFileHandle(binding_context, url.url, shared_handle_state)),
url.base_name);
}
std::move(token_resolved_callback).Run(std::move(entry));
......
......@@ -171,6 +171,7 @@ class CONTENT_EXPORT NativeFileSystemManagerImpl
// associated remote can be redeemed for a NativeFileSystemEntry object by a
// process with ID matching `renderer_id`.
void CreateNativeFileSystemDragDropToken(
PathType path_type,
const base::FilePath& file_path,
int renderer_id,
mojo::PendingReceiver<blink::mojom::NativeFileSystemDragDropToken>
......@@ -307,6 +308,7 @@ class CONTENT_EXPORT NativeFileSystemManagerImpl
void ResolveDragDropTokenWithFileType(
const BindingContext& binding_context,
const base::FilePath& file_path,
FileSystemURLAndFSHandle url,
GetEntryFromDragDropTokenCallback token_resolved_callback,
NativeFileSystemPermissionContext::HandleType file_type);
......
......@@ -14,6 +14,7 @@
#include "content/public/common/drop_data.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/network/public/mojom/referrer_policy.mojom-shared.h"
#include "storage/browser/file_system/external_mount_points.h"
#include "third_party/blink/public/mojom/file_system_access/native_file_system_drag_drop_token.mojom.h"
#include "third_party/blink/public/mojom/page/drag.mojom.h"
#include "ui/base/clipboard/clipboard_constants.h"
......@@ -22,6 +23,29 @@
namespace content {
namespace {
// On Chrome OS paths that exist on an external mount point need to be treated
// differently to make sure the native file system code accesses these paths via
// the correct file system backend. This method checks if this is the case, and
// updates `entry_path` to the path that should be used by the native file
// system implementation.
content::NativeFileSystemEntryFactory::PathType MaybeRemapPath(
base::FilePath* entry_path) {
#if defined(OS_CHROMEOS)
base::FilePath virtual_path;
auto* external_mount_points =
storage::ExternalMountPoints::GetSystemInstance();
if (external_mount_points->GetVirtualPath(*entry_path, &virtual_path)) {
*entry_path = std::move(virtual_path);
return content::NativeFileSystemEntryFactory::PathType::kExternal;
}
#endif
return content::NativeFileSystemEntryFactory::PathType::kLocal;
}
} // namespace
blink::mojom::DragDataPtr DropDataToDragData(
const DropData& drop_data,
NativeFileSystemManagerImpl* native_file_system_manager,
......@@ -56,11 +80,17 @@ blink::mojom::DragDataPtr DropDataToDragData(
blink::mojom::DragItemFilePtr item = blink::mojom::DragItemFile::New();
item->path = file.path;
item->display_name = file.display_name;
mojo::PendingRemote<blink::mojom::NativeFileSystemDragDropToken>
pending_token;
base::FilePath entry_path = file.path;
NativeFileSystemManagerImpl::PathType path_type =
MaybeRemapPath(&entry_path);
native_file_system_manager->CreateNativeFileSystemDragDropToken(
file.path, child_id, pending_token.InitWithNewPipeAndPassReceiver());
path_type, entry_path, child_id,
pending_token.InitWithNewPipeAndPassReceiver());
item->native_file_system_token = std::move(pending_token);
items.push_back(blink::mojom::DragItem::NewFile(std::move(item)));
}
for (const content::DropData::FileSystemFileInfo& file_system_file :
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment