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(
&GetHandleTypeFromUrl, fs_url,
base::BindOnce(
&NativeFileSystemManagerImpl::ResolveDragDropTokenWithFileType,
weak_factory_.GetWeakPtr(), binding_context, drag_drop_token_path,
std::move(token_resolved_callback)));
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);
......
......@@ -216,6 +216,117 @@ class NativeFileSystemManagerImplTest : public testing::Test {
return result;
}
void GetEntryFromDropTokenFileTest(
const base::FilePath& file_path,
NativeFileSystemEntryFactory::PathType path_type,
const std::string& expected_file_contents) {
// Create a token representing a dropped file at `file_path`.
mojo::PendingRemote<blink::mojom::NativeFileSystemDragDropToken>
token_remote;
manager_->CreateNativeFileSystemDragDropToken(
path_type, file_path, kBindingContext.process_id(),
token_remote.InitWithNewPipeAndPassReceiver());
// Expect permission requests when the token is sent to be redeemed.
EXPECT_CALL(
permission_context_,
GetReadPermissionGrant(
kTestOrigin, file_path, HandleType::kFile,
NativeFileSystemPermissionContext::UserAction::kDragAndDrop))
.WillOnce(testing::Return(allow_grant_));
EXPECT_CALL(
permission_context_,
GetWritePermissionGrant(
kTestOrigin, file_path, HandleType::kFile,
NativeFileSystemPermissionContext::UserAction::kDragAndDrop))
.WillOnce(testing::Return(allow_grant_));
// Attempt to resolve `token_remote` and store the resulting
// NativeFileSystemFileHandle in `file_remote`.
base::RunLoop await_token_resolution;
blink::mojom::NativeFileSystemEntryPtr native_file_system_entry;
manager_remote_->GetEntryFromDragDropToken(
std::move(token_remote),
base::BindLambdaForTesting([&](blink::mojom::NativeFileSystemEntryPtr
returned_native_file_system_entry) {
native_file_system_entry =
std::move(returned_native_file_system_entry);
await_token_resolution.Quit();
}));
await_token_resolution.Run();
ASSERT_FALSE(native_file_system_entry.is_null());
ASSERT_TRUE(native_file_system_entry->entry_handle->is_file());
mojo::Remote<blink::mojom::NativeFileSystemFileHandle> file_handle(
std::move(native_file_system_entry->entry_handle->get_file()));
// Check to see if the resulting NativeFileSystemFileHandle can read the
// contents of the file at `file_path`.
EXPECT_EQ(ReadStringFromFileRemote(std::move(file_handle)),
expected_file_contents);
}
void GetEntryFromDropTokenDirectoryTest(
const base::FilePath& dir_path,
NativeFileSystemEntryFactory::PathType path_type,
const std::string& expected_child_file_name) {
mojo::PendingRemote<blink::mojom::NativeFileSystemDragDropToken>
token_remote;
manager_->CreateNativeFileSystemDragDropToken(
path_type, dir_path, kBindingContext.process_id(),
token_remote.InitWithNewPipeAndPassReceiver());
// Expect permission requests when the token is sent to be redeemed.
EXPECT_CALL(
permission_context_,
GetReadPermissionGrant(
kTestOrigin, dir_path, HandleType::kDirectory,
NativeFileSystemPermissionContext::UserAction::kDragAndDrop))
.WillOnce(testing::Return(allow_grant_));
EXPECT_CALL(
permission_context_,
GetWritePermissionGrant(
kTestOrigin, dir_path, HandleType::kDirectory,
NativeFileSystemPermissionContext::UserAction::kDragAndDrop))
.WillOnce(testing::Return(allow_grant_));
// Attempt to resolve `token_remote` and store the resulting
// NativeFileSystemDirectoryHandle in `dir_remote`.
base::RunLoop await_token_resolution;
blink::mojom::NativeFileSystemEntryPtr native_file_system_entry;
manager_remote_->GetEntryFromDragDropToken(
std::move(token_remote),
base::BindLambdaForTesting([&](blink::mojom::NativeFileSystemEntryPtr
returned_native_file_system_entry) {
native_file_system_entry =
std::move(returned_native_file_system_entry);
await_token_resolution.Quit();
}));
await_token_resolution.Run();
ASSERT_FALSE(native_file_system_entry.is_null());
ASSERT_TRUE(native_file_system_entry->entry_handle->is_directory());
mojo::Remote<blink::mojom::NativeFileSystemDirectoryHandle> dir_remote(
std::move(native_file_system_entry->entry_handle->get_directory()));
// Use `dir_remote` to verify that dir_path contains a child called
// expected_child_file_name.
base::RunLoop await_get_file;
dir_remote->GetFile(
expected_child_file_name, /*create=*/false,
base::BindLambdaForTesting(
[&](blink::mojom::NativeFileSystemErrorPtr result,
mojo::PendingRemote<blink::mojom::NativeFileSystemFileHandle>
file_handle) {
await_get_file.Quit();
ASSERT_EQ(blink::mojom::NativeFileSystemStatus::kOk,
result->status);
}));
await_get_file.Run();
}
protected:
const GURL kTestURL = GURL("https://example.com/test");
const url::Origin kTestOrigin = url::Origin::Create(kTestURL);
......@@ -745,51 +856,12 @@ TEST_F(NativeFileSystemManagerImplTest, SerializeHandle_ExternalFile) {
TEST_F(NativeFileSystemManagerImplTest,
GetEntryFromDragDropToken_File_ValidPID) {
// Create a file and write some text into it.
base::FilePath file_path = dir_.GetPath().AppendASCII("mr_file");
const base::FilePath file_path = dir_.GetPath().AppendASCII("mr_file");
const std::string file_contents = "Deleted code is debugged code.";
ASSERT_TRUE(base::CreateTemporaryFile(&file_path));
ASSERT_TRUE(base::WriteFile(file_path, file_contents));
// Create a token representing a dropped file at `file_path`.
mojo::PendingRemote<blink::mojom::NativeFileSystemDragDropToken> token_remote;
manager_->CreateNativeFileSystemDragDropToken(
file_path, kBindingContext.process_id(),
token_remote.InitWithNewPipeAndPassReceiver());
// Expect permission requests when the token is sent to be redeemed.
EXPECT_CALL(permission_context_,
GetReadPermissionGrant(
kTestOrigin, file_path, HandleType::kFile,
NativeFileSystemPermissionContext::UserAction::kDragAndDrop))
.WillOnce(testing::Return(allow_grant_));
EXPECT_CALL(permission_context_,
GetWritePermissionGrant(
kTestOrigin, file_path, HandleType::kFile,
NativeFileSystemPermissionContext::UserAction::kDragAndDrop))
.WillOnce(testing::Return(allow_grant_));
// Attempt to resolve `token_remote` and store the resulting
// NativeFileSystemFileHandle in `file_remote`.
base::RunLoop await_token_resolution;
blink::mojom::NativeFileSystemEntryPtr native_file_system_entry;
manager_remote_->GetEntryFromDragDropToken(
std::move(token_remote),
base::BindLambdaForTesting([&](blink::mojom::NativeFileSystemEntryPtr
returned_native_file_system_entry) {
native_file_system_entry = std::move(returned_native_file_system_entry);
await_token_resolution.Quit();
}));
await_token_resolution.Run();
ASSERT_FALSE(native_file_system_entry.is_null());
ASSERT_TRUE(native_file_system_entry->entry_handle->is_file());
mojo::Remote<blink::mojom::NativeFileSystemFileHandle> file_handle(
std::move(native_file_system_entry->entry_handle->get_file()));
// Check to see if the resulting NativeFileSystemFileHandle can read the
// contents of the file at `file_path`.
EXPECT_EQ(ReadStringFromFileRemote(std::move(file_handle)), file_contents);
GetEntryFromDropTokenFileTest(
file_path, NativeFileSystemEntryFactory::PathType::kLocal, file_contents);
}
// NativeFileSystemManager should successfully resolve a
......@@ -800,63 +872,56 @@ TEST_F(NativeFileSystemManagerImplTest,
GetEntryFromDragDropToken_Directory_ValidPID) {
// Create a directory and create a NativeFileSystemDragDropToken representing
// the new directory.
const base::FilePath kDirPath = dir_.GetPath().AppendASCII("mr_dir");
ASSERT_TRUE(base::CreateDirectory(kDirPath));
mojo::PendingRemote<blink::mojom::NativeFileSystemDragDropToken> token_remote;
manager_->CreateNativeFileSystemDragDropToken(
kDirPath, kBindingContext.process_id(),
token_remote.InitWithNewPipeAndPassReceiver());
// Expect permission requests when the token is sent to be redeemed.
EXPECT_CALL(permission_context_,
GetReadPermissionGrant(
kTestOrigin, kDirPath, HandleType::kDirectory,
NativeFileSystemPermissionContext::UserAction::kDragAndDrop))
.WillOnce(testing::Return(allow_grant_));
const base::FilePath dir_path = dir_.GetPath().AppendASCII("mr_dir");
ASSERT_TRUE(base::CreateDirectory(dir_path));
const std::string child_file_name = "child-file-name.txt";
ASSERT_TRUE(base::WriteFile(dir_path.AppendASCII(child_file_name), ""));
GetEntryFromDropTokenDirectoryTest(
dir_path, NativeFileSystemEntryFactory::PathType::kLocal,
child_file_name);
}
EXPECT_CALL(permission_context_,
GetWritePermissionGrant(
kTestOrigin, kDirPath, HandleType::kDirectory,
NativeFileSystemPermissionContext::UserAction::kDragAndDrop))
.WillOnce(testing::Return(allow_grant_));
// NativeFileSystemManager should successfully resolve a
// NativeFileSystemDragDropToken representing a file in the user's file system
// into a valid Remote<blink::mojom::NativeFileSystemFileHandle>, given
// that the PID is valid.
TEST_F(NativeFileSystemManagerImplTest,
GetEntryFromDragDropToken_File_ExternalPath) {
// Create a file and write some text into it.
const base::FilePath file_path = dir_.GetPath().AppendASCII("mr_file");
const std::string file_contents = "Deleted code is debugged code.";
ASSERT_TRUE(base::WriteFile(file_path, file_contents));
// Attempt to resolve `token_remote` and store the resulting
// NativeFileSystemDirectoryHandle in `dir_remote`.
base::RunLoop await_token_resolution;
blink::mojom::NativeFileSystemEntryPtr native_file_system_entry;
manager_remote_->GetEntryFromDragDropToken(
std::move(token_remote),
base::BindLambdaForTesting([&](blink::mojom::NativeFileSystemEntryPtr
returned_native_file_system_entry) {
native_file_system_entry = std::move(returned_native_file_system_entry);
await_token_resolution.Quit();
}));
await_token_resolution.Run();
const base::FilePath virtual_file_path =
base::FilePath::FromUTF8Unsafe(kTestMountPoint)
.Append(file_path.BaseName());
ASSERT_FALSE(native_file_system_entry.is_null());
ASSERT_TRUE(native_file_system_entry->entry_handle->is_directory());
mojo::Remote<blink::mojom::NativeFileSystemDirectoryHandle> dir_remote(
std::move(native_file_system_entry->entry_handle->get_directory()));
GetEntryFromDropTokenFileTest(
virtual_file_path, NativeFileSystemEntryFactory::PathType::kExternal,
file_contents);
}
// Use `dir_remote` to create a child of the directory, and pass the test if
// the child was successfully created at the expected path. Block until this
// happens or test times out.
base::RunLoop await_get_directory;
const std::string kChildDirectory = "child_dir";
dir_remote->GetDirectory(
kChildDirectory, /*create=*/true,
base::BindLambdaForTesting(
[&](blink::mojom::NativeFileSystemErrorPtr result,
mojo::PendingRemote<blink::mojom::NativeFileSystemDirectoryHandle>
directory_handle) {
await_get_directory.Quit();
ASSERT_EQ(blink::mojom::NativeFileSystemStatus::kOk,
result->status);
EXPECT_TRUE(
kDirPath.IsParent(kDirPath.AppendASCII(kChildDirectory)));
}));
await_get_directory.Run();
// NativeFileSystemManager should successfully resolve a
// NativeFileSystemDragDropToken representing a NativeFileSystemDirectoryEntry
// into a valid Remote<blink::mojom::NativeFileSystemDirectoryHandle>, given
// that the PID is valid.
TEST_F(NativeFileSystemManagerImplTest,
GetEntryFromDragDropToken_Directory_ExternalPath) {
// Create a directory and create a NativeFileSystemDragDropToken representing
// the new directory.
const base::FilePath dir_path = dir_.GetPath().AppendASCII("mr_dir");
ASSERT_TRUE(base::CreateDirectory(dir_path));
const std::string child_file_name = "child-file-name.txt";
ASSERT_TRUE(base::WriteFile(dir_path.AppendASCII(child_file_name), ""));
const base::FilePath virtual_dir_path =
base::FilePath::FromUTF8Unsafe(kTestMountPoint)
.Append(dir_path.BaseName());
GetEntryFromDropTokenDirectoryTest(
virtual_dir_path, NativeFileSystemEntryFactory::PathType::kExternal,
child_file_name);
}
// NativeFileSystemManager should refuse to resolve a
......@@ -872,7 +937,8 @@ TEST_F(NativeFileSystemManagerImplTest,
// process attempting to redeem to the token.
mojo::PendingRemote<blink::mojom::NativeFileSystemDragDropToken> token_remote;
manager_->CreateNativeFileSystemDragDropToken(
file_path, /*renderer_id=*/kBindingContext.process_id() - 1,
NativeFileSystemEntryFactory::PathType::kLocal, file_path,
/*renderer_id=*/kBindingContext.process_id() - 1,
token_remote.InitWithNewPipeAndPassReceiver());
// Try to redeem the NativeFileSystemDragDropToken for a
......@@ -897,7 +963,8 @@ TEST_F(NativeFileSystemManagerImplTest,
// process attempting to redeem to the token.
mojo::PendingRemote<blink::mojom::NativeFileSystemDragDropToken> token_remote;
manager_->CreateNativeFileSystemDragDropToken(
kDirPath, /*renderer_id=*/kBindingContext.process_id() - 1,
NativeFileSystemEntryFactory::PathType::kLocal, kDirPath,
/*renderer_id=*/kBindingContext.process_id() - 1,
token_remote.InitWithNewPipeAndPassReceiver());
// Try to redeem the NativeFileSystemDragDropToken for a
......@@ -922,7 +989,8 @@ TEST_F(NativeFileSystemManagerImplTest,
mojo::PendingRemote<blink::mojom::NativeFileSystemDragDropToken> token_remote;
auto drag_drop_token_impl =
std::make_unique<NativeFileSystemDragDropTokenImpl>(
manager_.get(), kDirPath, kBindingContext.process_id(),
manager_.get(), NativeFileSystemEntryFactory::PathType::kLocal,
kDirPath, kBindingContext.process_id(),
token_remote.InitWithNewPipeAndPassReceiver());
// Try to redeem the NativeFileSystemDragDropToken for a
......
......@@ -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