Commit 47dec323 authored by Marijn Kruisselbrink's avatar Marijn Kruisselbrink Committed by Commit Bot

[NativeFS] Refactor NFSTransferTokenImpl.

For drag&drop we'll need a different implementation of this
mojo interface. This CL factors out the common code into an abstract
base class, with the existing implementation as a concrete subclass.

Later for drag&drop a different concrete subclass will be added.

Bug: 1080811
Change-Id: Ie16836f315918e1f20dde82fc2a7efac40f67c3d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2221432
Commit-Queue: Marijn Kruisselbrink <mek@chromium.org>
Reviewed-by: default avatarVictor Costan <pwnall@chromium.org>
Cr-Commit-Position: refs/heads/master@{#774361}
parent 829d0de5
......@@ -229,7 +229,7 @@ void NativeFileSystemDirectoryHandleImpl::Resolve(
void NativeFileSystemDirectoryHandleImpl::ResolveImpl(
ResolveCallback callback,
NativeFileSystemTransferTokenImpl* possible_child) {
if (!possible_child) {
if (!possible_child || !possible_child->GetAsFileSystemURL()) {
std::move(callback).Run(
native_file_system_error::FromStatus(
blink::mojom::NativeFileSystemStatus::kOperationFailed),
......@@ -238,7 +238,8 @@ void NativeFileSystemDirectoryHandleImpl::ResolveImpl(
}
const storage::FileSystemURL& parent_url = url();
const storage::FileSystemURL& child_url = possible_child->url();
const storage::FileSystemURL& child_url =
*possible_child->GetAsFileSystemURL();
// If two URLs are of a different type they are definitely not related.
if (parent_url.type() != child_url.type()) {
......
......@@ -108,7 +108,7 @@ void NativeFileSystemFileHandleImpl::IsSameEntry(
void NativeFileSystemFileHandleImpl::IsSameEntryImpl(
IsSameEntryCallback callback,
NativeFileSystemTransferTokenImpl* other) {
if (!other) {
if (!other || !other->GetAsFileSystemURL()) {
std::move(callback).Run(
native_file_system_error::FromStatus(
blink::mojom::NativeFileSystemStatus::kOperationFailed),
......@@ -122,7 +122,7 @@ void NativeFileSystemFileHandleImpl::IsSameEntryImpl(
}
const storage::FileSystemURL& url1 = url();
const storage::FileSystemURL& url2 = other->url();
const storage::FileSystemURL& url2 = *other->GetAsFileSystemURL();
// If two URLs are of a different type they are definitely not related.
if (url1.type() != url2.type()) {
......
......@@ -99,7 +99,7 @@ bool IsValidTransferToken(
return false;
}
if (token->url().origin() != expected_origin) {
if (!token->MatchesOrigin(expected_origin)) {
return false;
}
return true;
......@@ -303,11 +303,13 @@ base::FilePath DeserializePath(const std::string& bytes) {
void NativeFileSystemManagerImpl::DidResolveForSerializeHandle(
SerializeHandleCallback callback,
NativeFileSystemTransferTokenImpl* resolved_token) {
if (!resolved_token) {
if (!resolved_token || !resolved_token->GetAsFileSystemURL()) {
std::move(callback).Run({});
return;
}
const storage::FileSystemURL& url = *resolved_token->GetAsFileSystemURL();
NativeFileSystemHandleData data;
data.set_handle_type(
resolved_token->type() ==
......@@ -315,13 +317,12 @@ void NativeFileSystemManagerImpl::DidResolveForSerializeHandle(
? NativeFileSystemHandleData::kFile
: NativeFileSystemHandleData::kDirectory);
switch (resolved_token->url().type()) {
switch (url.type()) {
case storage::kFileSystemTypeNativeLocal: {
DCHECK_EQ(resolved_token->url().mount_type(),
storage::kFileSystemTypeIsolated);
DCHECK_EQ(url.mount_type(), storage::kFileSystemTypeIsolated);
base::FilePath root_path;
storage::IsolatedContext::GetInstance()->GetRegisteredPath(
resolved_token->shared_handle_state().file_system.id(), &root_path);
url.filesystem_id(), &root_path);
data.mutable_native()->set_root_path(SerializePath(root_path));
base::FilePath relative_path;
......@@ -330,16 +331,16 @@ void NativeFileSystemManagerImpl::DidResolveForSerializeHandle(
// but fails if the path we're looking for is equal to the |root_path|.
// So special case that case (in which case relative path would be empty
// anyway).
if (root_path != resolved_token->url().path()) {
bool relative_path_result = root_path.AppendRelativePath(
resolved_token->url().path(), &relative_path);
if (root_path != url.path()) {
bool relative_path_result =
root_path.AppendRelativePath(url.path(), &relative_path);
DCHECK(relative_path_result);
}
data.mutable_native()->set_relative_path(SerializePath(relative_path));
break;
}
case storage::kFileSystemTypeTemporary: {
base::FilePath virtual_path = resolved_token->url().virtual_path();
base::FilePath virtual_path = url.virtual_path();
data.mutable_sandboxed()->set_virtual_path(SerializePath(virtual_path));
break;
}
......@@ -595,9 +596,7 @@ void NativeFileSystemManagerImpl::DidResolveTransferTokenForFileHandle(
return;
}
file_receivers_.Add(std::make_unique<NativeFileSystemFileHandleImpl>(
this, binding_context, resolved_token->url(),
resolved_token->shared_handle_state()),
file_receivers_.Add(resolved_token->CreateFileHandle(binding_context),
std::move(file_handle_receiver));
}
......@@ -617,9 +616,7 @@ void NativeFileSystemManagerImpl::DidResolveTransferTokenForDirectoryHandle(
}
directory_receivers_.Add(
std::make_unique<NativeFileSystemDirectoryHandleImpl>(
this, binding_context, resolved_token->url(),
resolved_token->shared_handle_state()),
resolved_token->CreateDirectoryHandle(binding_context),
std::move(directory_handle_receiver));
}
......@@ -806,7 +803,7 @@ void NativeFileSystemManagerImpl::CreateTransferTokenImpl(
receiver) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto token_impl = std::make_unique<NativeFileSystemTransferTokenImpl>(
auto token_impl = NativeFileSystemTransferTokenImpl::Create(
url, handle_state,
is_directory ? NativeFileSystemTransferTokenImpl::HandleType::kDirectory
: NativeFileSystemTransferTokenImpl::HandleType::kFile,
......
......@@ -172,17 +172,6 @@ class CONTENT_EXPORT NativeFileSystemManagerImpl
mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken> token,
ResolvedTokenCallback callback);
void DidResolveTransferTokenForFileHandle(
const BindingContext& binding_context,
mojo::PendingReceiver<blink::mojom::NativeFileSystemFileHandle>
file_handle_receiver,
NativeFileSystemTransferTokenImpl* resolved_token);
void DidResolveTransferTokenForDirectoryHandle(
const BindingContext& binding_context,
mojo::PendingReceiver<blink::mojom::NativeFileSystemDirectoryHandle>
directory_handle_receiver,
NativeFileSystemTransferTokenImpl* resolved_token);
storage::FileSystemContext* context() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return context_.get();
......@@ -248,6 +237,16 @@ class CONTENT_EXPORT NativeFileSystemManagerImpl
ResolvedTokenCallback callback,
const base::UnguessableToken& token);
void DidResolveTransferTokenForFileHandle(
const BindingContext& binding_context,
mojo::PendingReceiver<blink::mojom::NativeFileSystemFileHandle>
file_handle_receiver,
NativeFileSystemTransferTokenImpl* resolved_token);
void DidResolveTransferTokenForDirectoryHandle(
const BindingContext& binding_context,
mojo::PendingReceiver<blink::mojom::NativeFileSystemDirectoryHandle>
directory_handle_receiver,
NativeFileSystemTransferTokenImpl* resolved_token);
void DidResolveForSerializeHandle(
SerializeHandleCallback callback,
NativeFileSystemTransferTokenImpl* resolved_token);
......@@ -295,8 +294,8 @@ class CONTENT_EXPORT NativeFileSystemManagerImpl
bool off_the_record_;
// NativeFileSystemTransferTokenImpl owns a Transfer token receiver and is
// removed from this map when the mojo connection is closed.
// NativeFileSystemTransferTokenImpl owns a Transfer token receiver set and is
// removed from this map when all mojo connections are closed.
std::map<base::UnguessableToken,
std::unique_ptr<NativeFileSystemTransferTokenImpl>>
transfer_tokens_;
......
......@@ -339,16 +339,17 @@ TEST_F(NativeFileSystemManagerImplTest, SerializeHandle_SandboxedFile) {
NativeFileSystemTransferTokenImpl* token =
SerializeAndDeserializeToken(std::move(token_remote));
ASSERT_TRUE(token);
EXPECT_EQ(test_file_url, token->url());
ASSERT_TRUE(token->GetAsFileSystemURL());
EXPECT_EQ(test_file_url, *token->GetAsFileSystemURL());
EXPECT_EQ(NativeFileSystemTransferTokenImpl::HandleType::kFile,
token->type());
// Deserialized sandboxed filesystem handles should always be readable and
// writable.
EXPECT_EQ(PermissionStatus::GRANTED,
token->shared_handle_state().read_grant->GetStatus());
EXPECT_EQ(PermissionStatus::GRANTED,
token->shared_handle_state().write_grant->GetStatus());
ASSERT_TRUE(token->GetReadGrant());
EXPECT_EQ(PermissionStatus::GRANTED, token->GetReadGrant()->GetStatus());
ASSERT_TRUE(token->GetWriteGrant());
EXPECT_EQ(PermissionStatus::GRANTED, token->GetWriteGrant()->GetStatus());
}
TEST_F(NativeFileSystemManagerImplTest, SerializeHandle_SandboxedDirectory) {
......@@ -365,16 +366,17 @@ TEST_F(NativeFileSystemManagerImplTest, SerializeHandle_SandboxedDirectory) {
NativeFileSystemTransferTokenImpl* token =
SerializeAndDeserializeToken(std::move(token_remote));
ASSERT_TRUE(token);
EXPECT_EQ(test_file_url, token->url());
ASSERT_TRUE(token->GetAsFileSystemURL());
EXPECT_EQ(test_file_url, *token->GetAsFileSystemURL());
EXPECT_EQ(NativeFileSystemTransferTokenImpl::HandleType::kDirectory,
token->type());
// Deserialized sandboxed filesystem handles should always be readable and
// writable.
EXPECT_EQ(PermissionStatus::GRANTED,
token->shared_handle_state().read_grant->GetStatus());
EXPECT_EQ(PermissionStatus::GRANTED,
token->shared_handle_state().write_grant->GetStatus());
ASSERT_TRUE(token->GetReadGrant());
EXPECT_EQ(PermissionStatus::GRANTED, token->GetReadGrant()->GetStatus());
ASSERT_TRUE(token->GetWriteGrant());
EXPECT_EQ(PermissionStatus::GRANTED, token->GetWriteGrant()->GetStatus());
}
TEST_F(NativeFileSystemManagerImplTest, SerializeHandle_Native_SingleFile) {
......@@ -417,14 +419,16 @@ TEST_F(NativeFileSystemManagerImplTest, SerializeHandle_Native_SingleFile) {
NativeFileSystemTransferTokenImpl* token =
SerializeAndDeserializeToken(std::move(token_remote));
ASSERT_TRUE(token);
EXPECT_EQ(kTestOrigin, token->url().origin());
EXPECT_EQ(kTestPath, token->url().path());
EXPECT_EQ(storage::kFileSystemTypeNativeLocal, token->url().type());
EXPECT_EQ(storage::kFileSystemTypeIsolated, token->url().mount_type());
ASSERT_TRUE(token->GetAsFileSystemURL());
const storage::FileSystemURL& url = *token->GetAsFileSystemURL();
EXPECT_EQ(kTestOrigin, url.origin());
EXPECT_EQ(kTestPath, url.path());
EXPECT_EQ(storage::kFileSystemTypeNativeLocal, url.type());
EXPECT_EQ(storage::kFileSystemTypeIsolated, url.mount_type());
EXPECT_EQ(NativeFileSystemTransferTokenImpl::HandleType::kFile,
token->type());
EXPECT_EQ(ask_grant_, token->shared_handle_state().read_grant);
EXPECT_EQ(ask_grant2_, token->shared_handle_state().write_grant);
EXPECT_EQ(ask_grant_, token->GetReadGrant());
EXPECT_EQ(ask_grant2_, token->GetWriteGrant());
}
TEST_F(NativeFileSystemManagerImplTest,
......@@ -453,14 +457,16 @@ TEST_F(NativeFileSystemManagerImplTest,
NativeFileSystemTransferTokenImpl* token =
SerializeAndDeserializeToken(std::move(token_remote));
ASSERT_TRUE(token);
EXPECT_EQ(kTestOrigin, token->url().origin());
EXPECT_EQ(kTestPath, token->url().path());
EXPECT_EQ(storage::kFileSystemTypeNativeLocal, token->url().type());
EXPECT_EQ(storage::kFileSystemTypeIsolated, token->url().mount_type());
ASSERT_TRUE(token->GetAsFileSystemURL());
const storage::FileSystemURL& url = *token->GetAsFileSystemURL();
EXPECT_EQ(kTestOrigin, url.origin());
EXPECT_EQ(kTestPath, url.path());
EXPECT_EQ(storage::kFileSystemTypeNativeLocal, url.type());
EXPECT_EQ(storage::kFileSystemTypeIsolated, url.mount_type());
EXPECT_EQ(NativeFileSystemTransferTokenImpl::HandleType::kDirectory,
token->type());
EXPECT_EQ(ask_grant_, token->shared_handle_state().read_grant);
EXPECT_EQ(ask_grant2_, token->shared_handle_state().write_grant);
EXPECT_EQ(ask_grant_, token->GetReadGrant());
EXPECT_EQ(ask_grant2_, token->GetWriteGrant());
}
TEST_F(NativeFileSystemManagerImplTest,
......@@ -508,15 +514,17 @@ TEST_F(NativeFileSystemManagerImplTest,
NativeFileSystemTransferTokenImpl* token =
SerializeAndDeserializeToken(std::move(token_remote));
ASSERT_TRUE(token);
EXPECT_EQ(kTestOrigin, token->url().origin());
ASSERT_TRUE(token->GetAsFileSystemURL());
const storage::FileSystemURL& url = *token->GetAsFileSystemURL();
EXPECT_EQ(kTestOrigin, url.origin());
EXPECT_EQ(kDirectoryPath.Append(base::FilePath::FromUTF8Unsafe(kTestName)),
token->url().path());
EXPECT_EQ(storage::kFileSystemTypeNativeLocal, token->url().type());
EXPECT_EQ(storage::kFileSystemTypeIsolated, token->url().mount_type());
url.path());
EXPECT_EQ(storage::kFileSystemTypeNativeLocal, url.type());
EXPECT_EQ(storage::kFileSystemTypeIsolated, url.mount_type());
EXPECT_EQ(NativeFileSystemTransferTokenImpl::HandleType::kFile,
token->type());
EXPECT_EQ(ask_grant_, token->shared_handle_state().read_grant);
EXPECT_EQ(ask_grant2_, token->shared_handle_state().write_grant);
EXPECT_EQ(ask_grant_, token->GetReadGrant());
EXPECT_EQ(ask_grant2_, token->GetWriteGrant());
}
TEST_F(NativeFileSystemManagerImplTest,
......@@ -564,14 +572,16 @@ TEST_F(NativeFileSystemManagerImplTest,
NativeFileSystemTransferTokenImpl* token =
SerializeAndDeserializeToken(std::move(token_remote));
ASSERT_TRUE(token);
EXPECT_EQ(kTestOrigin, token->url().origin());
EXPECT_EQ(kDirectoryPath.AppendASCII(kTestName), token->url().path());
EXPECT_EQ(storage::kFileSystemTypeNativeLocal, token->url().type());
EXPECT_EQ(storage::kFileSystemTypeIsolated, token->url().mount_type());
ASSERT_TRUE(token->GetAsFileSystemURL());
const storage::FileSystemURL& url = *token->GetAsFileSystemURL();
EXPECT_EQ(kTestOrigin, url.origin());
EXPECT_EQ(kDirectoryPath.AppendASCII(kTestName), url.path());
EXPECT_EQ(storage::kFileSystemTypeNativeLocal, url.type());
EXPECT_EQ(storage::kFileSystemTypeIsolated, url.mount_type());
EXPECT_EQ(NativeFileSystemTransferTokenImpl::HandleType::kDirectory,
token->type());
EXPECT_EQ(ask_grant_, token->shared_handle_state().read_grant);
EXPECT_EQ(ask_grant2_, token->shared_handle_state().write_grant);
EXPECT_EQ(ask_grant_, token->GetReadGrant());
EXPECT_EQ(ask_grant2_, token->GetWriteGrant());
}
} // namespace content
......@@ -4,23 +4,96 @@
#include "content/browser/native_file_system/native_file_system_transfer_token_impl.h"
#include "content/browser/native_file_system/native_file_system_directory_handle_impl.h"
#include "content/browser/native_file_system/native_file_system_file_handle_impl.h"
namespace content {
NativeFileSystemTransferTokenImpl::NativeFileSystemTransferTokenImpl(
namespace {
// Concrete implementation for Transfer Tokens created from a
// NativeFileSystemFileHandleImpl or DirectoryHandleImpl. These tokens
// share permission grants with the handle, and are tied to the origin the
// handles were associated with.
class NativeFileSystemTransferTokenImplForHandles
: public NativeFileSystemTransferTokenImpl {
public:
using SharedHandleState = NativeFileSystemManagerImpl::SharedHandleState;
NativeFileSystemTransferTokenImplForHandles(
const storage::FileSystemURL& url,
const NativeFileSystemManagerImpl::SharedHandleState& handle_state,
HandleType type,
NativeFileSystemManagerImpl* manager,
mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken>
receiver)
: NativeFileSystemTransferTokenImpl(type, manager, std::move(receiver)),
url_(url),
handle_state_(handle_state) {
DCHECK_EQ(url_.mount_type() == storage::kFileSystemTypeIsolated,
handle_state_.file_system.is_valid())
<< url_.mount_type();
}
~NativeFileSystemTransferTokenImplForHandles() override = default;
bool MatchesOrigin(const url::Origin& origin) const override {
return url_.origin() == origin;
}
const storage::FileSystemURL* GetAsFileSystemURL() const override {
return &url_;
}
NativeFileSystemPermissionGrant* GetReadGrant() const override {
return handle_state_.read_grant.get();
}
NativeFileSystemPermissionGrant* GetWriteGrant() const override {
return handle_state_.write_grant.get();
}
std::unique_ptr<NativeFileSystemFileHandleImpl> CreateFileHandle(
const NativeFileSystemManagerImpl::BindingContext& binding_context)
override {
DCHECK_EQ(type_, HandleType::kFile);
return std::make_unique<NativeFileSystemFileHandleImpl>(
manager_, binding_context, url_, handle_state_);
}
std::unique_ptr<NativeFileSystemDirectoryHandleImpl> CreateDirectoryHandle(
const NativeFileSystemManagerImpl::BindingContext& binding_context)
override {
DCHECK_EQ(type_, HandleType::kDirectory);
return std::make_unique<NativeFileSystemDirectoryHandleImpl>(
manager_, binding_context, url_, handle_state_);
}
private:
const storage::FileSystemURL url_;
const NativeFileSystemManagerImpl::SharedHandleState handle_state_;
};
} // namespace
// static
std::unique_ptr<NativeFileSystemTransferTokenImpl>
NativeFileSystemTransferTokenImpl::Create(
const storage::FileSystemURL& url,
const SharedHandleState& handle_state,
const NativeFileSystemManagerImpl::SharedHandleState& handle_state,
HandleType type,
NativeFileSystemManagerImpl* manager,
mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken>
receiver) {
return std::make_unique<NativeFileSystemTransferTokenImplForHandles>(
url, handle_state, type, manager, std::move(receiver));
}
NativeFileSystemTransferTokenImpl::NativeFileSystemTransferTokenImpl(
HandleType type,
NativeFileSystemManagerImpl* manager,
mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken> receiver)
: token_(base::UnguessableToken::Create()),
url_(url),
handle_state_(handle_state),
type_(type),
manager_(manager) {
: token_(base::UnguessableToken::Create()), type_(type), manager_(manager) {
DCHECK(manager_);
DCHECK_EQ(url_.mount_type() == storage::kFileSystemTypeIsolated,
handle_state_.file_system.is_valid())
<< url_.mount_type();
receivers_.set_disconnect_handler(
base::BindRepeating(&NativeFileSystemTransferTokenImpl::OnMojoDisconnect,
......
......@@ -15,21 +15,28 @@
namespace content {
// This is the browser side implementation of the NativeFileSystemTransferToken
// mojom interface.
// Base class for blink::mojom::NativeFileSystemTransferToken implementations.
//
// Instances of this class are immutable, but since this implements a mojo
// interface all its methods are called on the same sequence anyway.
// Instances of this class should always be used from the sequence they were
// created on.
class CONTENT_EXPORT NativeFileSystemTransferTokenImpl
: public blink::mojom::NativeFileSystemTransferToken {
public:
using SharedHandleState = NativeFileSystemManagerImpl::SharedHandleState;
enum class HandleType { kFile, kDirectory };
NativeFileSystemTransferTokenImpl(
// Create a token that is tied to a particular origin (the origin of |url|,
// and uses the permission grants in |handle_state| when creating new handles
// out of the token. This is used for postMessage and IndexedDB serialization,
// as well as a couple of other APIs.
static std::unique_ptr<NativeFileSystemTransferTokenImpl> Create(
const storage::FileSystemURL& url,
const SharedHandleState& handle_state,
const NativeFileSystemManagerImpl::SharedHandleState& handle_state,
HandleType type,
NativeFileSystemManagerImpl* manager,
mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken>
receiver);
NativeFileSystemTransferTokenImpl(
HandleType type,
NativeFileSystemManagerImpl* manager,
mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken>
......@@ -37,25 +44,39 @@ class CONTENT_EXPORT NativeFileSystemTransferTokenImpl
~NativeFileSystemTransferTokenImpl() override;
const base::UnguessableToken& token() const { return token_; }
const SharedHandleState& shared_handle_state() const { return handle_state_; }
const storage::FileSystemURL& url() const { return url_; }
HandleType type() const { return type_; }
// Returns true if |origin| is allowed to use this token.
virtual bool MatchesOrigin(const url::Origin& origin) const = 0;
// Can return nullptr if this token isn't represented by a FileSystemURL.
virtual const storage::FileSystemURL* GetAsFileSystemURL() const = 0;
// Returns permission grants associated with this token. These can
// return nullptr if this token does not have associated permission grants.
virtual NativeFileSystemPermissionGrant* GetReadGrant() const = 0;
virtual NativeFileSystemPermissionGrant* GetWriteGrant() const = 0;
virtual std::unique_ptr<NativeFileSystemFileHandleImpl> CreateFileHandle(
const NativeFileSystemManagerImpl::BindingContext& binding_context) = 0;
virtual std::unique_ptr<NativeFileSystemDirectoryHandleImpl>
CreateDirectoryHandle(
const NativeFileSystemManagerImpl::BindingContext& binding_context) = 0;
// blink::mojom::NativeFileSystemTransferToken:
void GetInternalID(GetInternalIDCallback callback) override;
void Clone(mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken>
clone_receiver) override;
private:
void OnMojoDisconnect();
protected:
const base::UnguessableToken token_;
const storage::FileSystemURL url_;
const SharedHandleState handle_state_;
const HandleType type_;
// Raw pointer since NativeFileSystemManagerImpl owns |this|.
NativeFileSystemManagerImpl* const manager_;
private:
void OnMojoDisconnect();
// This token may contain multiple receivers, which includes a receiver for
// the originally constructed instance and then additional receivers for
// each clone. |manager_| must not remove this token until |receivers_| is
......
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