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 { ...@@ -15,10 +15,12 @@ namespace content {
NativeFileSystemDragDropTokenImpl::NativeFileSystemDragDropTokenImpl( NativeFileSystemDragDropTokenImpl::NativeFileSystemDragDropTokenImpl(
NativeFileSystemManagerImpl* manager, NativeFileSystemManagerImpl* manager,
NativeFileSystemManagerImpl::PathType path_type,
const base::FilePath& file_path, const base::FilePath& file_path,
int renderer_process_id, int renderer_process_id,
mojo::PendingReceiver<blink::mojom::NativeFileSystemDragDropToken> receiver) mojo::PendingReceiver<blink::mojom::NativeFileSystemDragDropToken> receiver)
: manager_(manager), : manager_(manager),
path_type_(path_type),
file_path_(file_path), file_path_(file_path),
renderer_process_id_(renderer_process_id), renderer_process_id_(renderer_process_id),
token_(base::UnguessableToken::Create()) { token_(base::UnguessableToken::Create()) {
......
...@@ -26,6 +26,7 @@ class CONTENT_EXPORT NativeFileSystemDragDropTokenImpl ...@@ -26,6 +26,7 @@ class CONTENT_EXPORT NativeFileSystemDragDropTokenImpl
public: public:
NativeFileSystemDragDropTokenImpl( NativeFileSystemDragDropTokenImpl(
NativeFileSystemManagerImpl* manager, NativeFileSystemManagerImpl* manager,
NativeFileSystemManagerImpl::PathType path_type,
const base::FilePath& file_path, const base::FilePath& file_path,
int renderer_process_id, int renderer_process_id,
mojo::PendingReceiver<blink::mojom::NativeFileSystemDragDropToken> mojo::PendingReceiver<blink::mojom::NativeFileSystemDragDropToken>
...@@ -41,6 +42,8 @@ class CONTENT_EXPORT NativeFileSystemDragDropTokenImpl ...@@ -41,6 +42,8 @@ class CONTENT_EXPORT NativeFileSystemDragDropTokenImpl
int renderer_process_id() const { return renderer_process_id_; } 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::FilePath& file_path() const { return file_path_; }
const base::UnguessableToken& token() const { return token_; } const base::UnguessableToken& token() const { return token_; }
...@@ -56,6 +59,7 @@ class CONTENT_EXPORT NativeFileSystemDragDropTokenImpl ...@@ -56,6 +59,7 @@ class CONTENT_EXPORT NativeFileSystemDragDropTokenImpl
// Raw pointer since NativeFileSystemManagerImpl owns `this`. // Raw pointer since NativeFileSystemManagerImpl owns `this`.
NativeFileSystemManagerImpl* const manager_; NativeFileSystemManagerImpl* const manager_;
const NativeFileSystemManagerImpl::PathType path_type_;
const base::FilePath file_path_; const base::FilePath file_path_;
const int renderer_process_id_; const int renderer_process_id_;
const base::UnguessableToken token_; const base::UnguessableToken token_;
......
...@@ -151,10 +151,30 @@ bool IsValidTransferToken(NativeFileSystemTransferTokenImpl* token, ...@@ -151,10 +151,30 @@ bool IsValidTransferToken(NativeFileSystemTransferTokenImpl* token,
return true; return true;
} }
HandleType GetFileType(const base::FilePath& file_path) { void GetHandleTypeFromUrl(
base::File::Info file_info; storage::FileSystemURL url,
base::GetFileInfo(file_path, &file_info); base::OnceCallback<void(HandleType)> callback,
return file_info.is_directory ? HandleType::kDirectory : HandleType::kFile; 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 } // namespace
...@@ -300,13 +320,14 @@ void NativeFileSystemManagerImpl::ChooseEntries( ...@@ -300,13 +320,14 @@ void NativeFileSystemManagerImpl::ChooseEntries(
} }
void NativeFileSystemManagerImpl::CreateNativeFileSystemDragDropToken( void NativeFileSystemManagerImpl::CreateNativeFileSystemDragDropToken(
PathType path_type,
const base::FilePath& file_path, const base::FilePath& file_path,
int renderer_id, int renderer_id,
mojo::PendingReceiver<blink::mojom::NativeFileSystemDragDropToken> mojo::PendingReceiver<blink::mojom::NativeFileSystemDragDropToken>
receiver) { receiver) {
auto drag_drop_token_impl = auto drag_drop_token_impl =
std::make_unique<NativeFileSystemDragDropTokenImpl>( 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(); auto token = drag_drop_token_impl->token();
drag_drop_tokens_.emplace(token, std::move(drag_drop_token_impl)); drag_drop_tokens_.emplace(token, std::move(drag_drop_token_impl));
} }
...@@ -360,30 +381,44 @@ void NativeFileSystemManagerImpl::ResolveDragDropToken( ...@@ -360,30 +381,44 @@ void NativeFileSystemManagerImpl::ResolveDragDropToken(
// Look up whether the file path that's associated with the token is a file or // Look up whether the file path that's associated with the token is a file or
// directory and call ResolveDragDropTokenWithFileType with the result. // directory and call ResolveDragDropTokenWithFileType with the result.
const base::FilePath& drag_drop_token_path = FileSystemURLAndFSHandle url = CreateFileSystemURLFromPath(
drag_token_impl->second->file_path(); binding_context.origin, drag_token_impl->second->path_type(),
base::ThreadPool::PostTaskAndReplyWithResult( drag_token_impl->second->file_path());
FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING}, auto fs_url = url.url;
base::BindOnce(&GetFileType, drag_drop_token_path), operation_runner().PostTaskWithThisObject(
FROM_HERE,
base::BindOnce(
&GetHandleTypeFromUrl, fs_url,
base::BindOnce( base::BindOnce(
&NativeFileSystemManagerImpl::ResolveDragDropTokenWithFileType, &NativeFileSystemManagerImpl::ResolveDragDropTokenWithFileType,
weak_factory_.GetWeakPtr(), binding_context, drag_drop_token_path, weak_factory_.GetWeakPtr(), binding_context,
std::move(token_resolved_callback))); drag_token_impl->second->file_path(), std::move(url),
std::move(token_resolved_callback)),
base::SequencedTaskRunnerHandle::Get()));
} }
void NativeFileSystemManagerImpl::ResolveDragDropTokenWithFileType( void NativeFileSystemManagerImpl::ResolveDragDropTokenWithFileType(
const BindingContext& binding_context, const BindingContext& binding_context,
const base::FilePath& file_path, const base::FilePath& file_path,
FileSystemURLAndFSHandle url,
GetEntryFromDragDropTokenCallback token_resolved_callback, GetEntryFromDragDropTokenCallback token_resolved_callback,
HandleType file_type) { 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; blink::mojom::NativeFileSystemEntryPtr entry;
// TODO(mek): Support Drag&Drop of non-local paths.
if (file_type == HandleType::kDirectory) { if (file_type == HandleType::kDirectory) {
entry = CreateDirectoryEntryFromPath(binding_context, PathType::kLocal, entry = blink::mojom::NativeFileSystemEntry::New(
file_path, UserAction::kDragAndDrop); blink::mojom::NativeFileSystemHandle::NewDirectory(
CreateDirectoryHandle(binding_context, url.url,
shared_handle_state)),
url.base_name);
} else { } else {
entry = CreateFileEntryFromPath(binding_context, PathType::kLocal, entry = blink::mojom::NativeFileSystemEntry::New(
file_path, UserAction::kDragAndDrop); blink::mojom::NativeFileSystemHandle::NewFile(
CreateFileHandle(binding_context, url.url, shared_handle_state)),
url.base_name);
} }
std::move(token_resolved_callback).Run(std::move(entry)); std::move(token_resolved_callback).Run(std::move(entry));
......
...@@ -171,6 +171,7 @@ class CONTENT_EXPORT NativeFileSystemManagerImpl ...@@ -171,6 +171,7 @@ class CONTENT_EXPORT NativeFileSystemManagerImpl
// associated remote can be redeemed for a NativeFileSystemEntry object by a // associated remote can be redeemed for a NativeFileSystemEntry object by a
// process with ID matching `renderer_id`. // process with ID matching `renderer_id`.
void CreateNativeFileSystemDragDropToken( void CreateNativeFileSystemDragDropToken(
PathType path_type,
const base::FilePath& file_path, const base::FilePath& file_path,
int renderer_id, int renderer_id,
mojo::PendingReceiver<blink::mojom::NativeFileSystemDragDropToken> mojo::PendingReceiver<blink::mojom::NativeFileSystemDragDropToken>
...@@ -307,6 +308,7 @@ class CONTENT_EXPORT NativeFileSystemManagerImpl ...@@ -307,6 +308,7 @@ class CONTENT_EXPORT NativeFileSystemManagerImpl
void ResolveDragDropTokenWithFileType( void ResolveDragDropTokenWithFileType(
const BindingContext& binding_context, const BindingContext& binding_context,
const base::FilePath& file_path, const base::FilePath& file_path,
FileSystemURLAndFSHandle url,
GetEntryFromDragDropTokenCallback token_resolved_callback, GetEntryFromDragDropTokenCallback token_resolved_callback,
NativeFileSystemPermissionContext::HandleType file_type); NativeFileSystemPermissionContext::HandleType file_type);
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "content/public/common/drop_data.h" #include "content/public/common/drop_data.h"
#include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/network/public/mojom/referrer_policy.mojom-shared.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/file_system_access/native_file_system_drag_drop_token.mojom.h"
#include "third_party/blink/public/mojom/page/drag.mojom.h" #include "third_party/blink/public/mojom/page/drag.mojom.h"
#include "ui/base/clipboard/clipboard_constants.h" #include "ui/base/clipboard/clipboard_constants.h"
...@@ -22,6 +23,29 @@ ...@@ -22,6 +23,29 @@
namespace content { 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( blink::mojom::DragDataPtr DropDataToDragData(
const DropData& drop_data, const DropData& drop_data,
NativeFileSystemManagerImpl* native_file_system_manager, NativeFileSystemManagerImpl* native_file_system_manager,
...@@ -56,11 +80,17 @@ blink::mojom::DragDataPtr DropDataToDragData( ...@@ -56,11 +80,17 @@ blink::mojom::DragDataPtr DropDataToDragData(
blink::mojom::DragItemFilePtr item = blink::mojom::DragItemFile::New(); blink::mojom::DragItemFilePtr item = blink::mojom::DragItemFile::New();
item->path = file.path; item->path = file.path;
item->display_name = file.display_name; item->display_name = file.display_name;
mojo::PendingRemote<blink::mojom::NativeFileSystemDragDropToken> mojo::PendingRemote<blink::mojom::NativeFileSystemDragDropToken>
pending_token; pending_token;
base::FilePath entry_path = file.path;
NativeFileSystemManagerImpl::PathType path_type =
MaybeRemapPath(&entry_path);
native_file_system_manager->CreateNativeFileSystemDragDropToken( 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); item->native_file_system_token = std::move(pending_token);
items.push_back(blink::mojom::DragItem::NewFile(std::move(item))); items.push_back(blink::mojom::DragItem::NewFile(std::move(item)));
} }
for (const content::DropData::FileSystemFileInfo& file_system_file : 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