Commit b1b01366 authored by Naoki Fukino's avatar Naoki Fukino Committed by Commit Bot

Return errors immediately on read-only roots.

If write-related functions are called on read-only roots, we can return
errors immediately instead of making mojo calls which always fail.

Bug: 956852
Test: Ran unit_tests
Change-Id: I81bbe3aea12f683ecf7dc89db698983d35202a67
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2346101Reviewed-by: default avatarShuhei Takahashi <nya@chromium.org>
Commit-Queue: Naoki Fukino <fukino@chromium.org>
Cr-Commit-Position: refs/heads/master@{#796740}
parent ca633aab
...@@ -141,6 +141,10 @@ void ArcDocumentsProviderRoot::ReadDirectory(const base::FilePath& path, ...@@ -141,6 +141,10 @@ void ArcDocumentsProviderRoot::ReadDirectory(const base::FilePath& path,
void ArcDocumentsProviderRoot::DeleteFile(const base::FilePath& path, void ArcDocumentsProviderRoot::DeleteFile(const base::FilePath& path,
StatusCallback callback) { StatusCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (read_only_) {
std::move(callback).Run(base::File::FILE_ERROR_ACCESS_DENIED);
return;
}
ResolveToDocumentId( ResolveToDocumentId(
path, path,
base::BindOnce(&ArcDocumentsProviderRoot::DeleteFileWithDocumentId, base::BindOnce(&ArcDocumentsProviderRoot::DeleteFileWithDocumentId,
...@@ -150,6 +154,10 @@ void ArcDocumentsProviderRoot::DeleteFile(const base::FilePath& path, ...@@ -150,6 +154,10 @@ void ArcDocumentsProviderRoot::DeleteFile(const base::FilePath& path,
void ArcDocumentsProviderRoot::CreateFile(const base::FilePath& path, void ArcDocumentsProviderRoot::CreateFile(const base::FilePath& path,
StatusCallback callback) { StatusCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (read_only_) {
std::move(callback).Run(base::File::FILE_ERROR_ACCESS_DENIED);
return;
}
ResolveToDocumentId( ResolveToDocumentId(
path, base::BindOnce( path, base::BindOnce(
&ArcDocumentsProviderRoot::CreateFileAfterConflictCheck, &ArcDocumentsProviderRoot::CreateFileAfterConflictCheck,
...@@ -159,6 +167,10 @@ void ArcDocumentsProviderRoot::CreateFile(const base::FilePath& path, ...@@ -159,6 +167,10 @@ void ArcDocumentsProviderRoot::CreateFile(const base::FilePath& path,
void ArcDocumentsProviderRoot::CreateDirectory(const base::FilePath& path, void ArcDocumentsProviderRoot::CreateDirectory(const base::FilePath& path,
StatusCallback callback) { StatusCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (read_only_) {
std::move(callback).Run(base::File::FILE_ERROR_ACCESS_DENIED);
return;
}
ResolveToDocumentId( ResolveToDocumentId(
path, base::BindOnce( path, base::BindOnce(
&ArcDocumentsProviderRoot::CreateDirectoryAfterConflictCheck, &ArcDocumentsProviderRoot::CreateDirectoryAfterConflictCheck,
...@@ -169,6 +181,10 @@ void ArcDocumentsProviderRoot::CopyFileLocal(const base::FilePath& src_path, ...@@ -169,6 +181,10 @@ void ArcDocumentsProviderRoot::CopyFileLocal(const base::FilePath& src_path,
const base::FilePath& dest_path, const base::FilePath& dest_path,
StatusCallback callback) { StatusCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (read_only_) {
std::move(callback).Run(base::File::FILE_ERROR_ACCESS_DENIED);
return;
}
if (src_path == dest_path) { if (src_path == dest_path) {
std::move(callback).Run(base::File::FILE_ERROR_INVALID_OPERATION); std::move(callback).Run(base::File::FILE_ERROR_INVALID_OPERATION);
return; return;
...@@ -184,6 +200,10 @@ void ArcDocumentsProviderRoot::MoveFileLocal(const base::FilePath& src_path, ...@@ -184,6 +200,10 @@ void ArcDocumentsProviderRoot::MoveFileLocal(const base::FilePath& src_path,
const base::FilePath& dest_path, const base::FilePath& dest_path,
StatusCallback callback) { StatusCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (read_only_) {
std::move(callback).Run(base::File::FILE_ERROR_ACCESS_DENIED);
return;
}
if (src_path.DirName() == dest_path.DirName()) { if (src_path.DirName() == dest_path.DirName()) {
RenameFileInternal(src_path, dest_path.BaseName().value(), RenameFileInternal(src_path, dest_path.BaseName().value(),
std::move(callback)); std::move(callback));
......
...@@ -86,6 +86,9 @@ class ArcDocumentsProviderRoot : public ArcFileSystemOperationRunner::Observer { ...@@ -86,6 +86,9 @@ class ArcDocumentsProviderRoot : public ArcFileSystemOperationRunner::Observer {
ReadDirectoryCallback callback); ReadDirectoryCallback callback);
// Deletes a file/directory at the given path. // Deletes a file/directory at the given path.
//
// - File::FILE_ERROR_NOT_FOUND if |path| does not exist.
// - File::FILE_ERROR_ACCESS_DENIED if this root is read-only.
void DeleteFile(const base::FilePath& path, StatusCallback callback); void DeleteFile(const base::FilePath& path, StatusCallback callback);
// Creates a file at the given path. // Creates a file at the given path.
...@@ -93,6 +96,7 @@ class ArcDocumentsProviderRoot : public ArcFileSystemOperationRunner::Observer { ...@@ -93,6 +96,7 @@ class ArcDocumentsProviderRoot : public ArcFileSystemOperationRunner::Observer {
// This reports following error code via |callback|: // This reports following error code via |callback|:
// - File::FILE_ERROR_NOT_FOUND if |path|'s parent directory does not exist. // - File::FILE_ERROR_NOT_FOUND if |path|'s parent directory does not exist.
// - File::FILE_ERROR_EXISTS if a file already exists at |path|. // - File::FILE_ERROR_EXISTS if a file already exists at |path|.
// - File::FILE_ERROR_ACCESS_DENIED if this root is read-only.
void CreateFile(const base::FilePath& path, StatusCallback callback); void CreateFile(const base::FilePath& path, StatusCallback callback);
// Creates a directory at the given path. // Creates a directory at the given path.
...@@ -100,6 +104,7 @@ class ArcDocumentsProviderRoot : public ArcFileSystemOperationRunner::Observer { ...@@ -100,6 +104,7 @@ class ArcDocumentsProviderRoot : public ArcFileSystemOperationRunner::Observer {
// This reports following error code via |callback|: // This reports following error code via |callback|:
// - File::FILE_ERROR_NOT_FOUND if |path|'s parent directory does not exist. // - File::FILE_ERROR_NOT_FOUND if |path|'s parent directory does not exist.
// - File::FILE_ERROR_EXISTS if a file already exists at |path|. // - File::FILE_ERROR_EXISTS if a file already exists at |path|.
// - File::FILE_ERROR_ACCESS_DENIED if this root is read-only.
void CreateDirectory(const base::FilePath& path, StatusCallback callback); void CreateDirectory(const base::FilePath& path, StatusCallback callback);
// Copies a file from |src_path| to |dest_path| inside this root. // Copies a file from |src_path| to |dest_path| inside this root.
...@@ -107,6 +112,7 @@ class ArcDocumentsProviderRoot : public ArcFileSystemOperationRunner::Observer { ...@@ -107,6 +112,7 @@ class ArcDocumentsProviderRoot : public ArcFileSystemOperationRunner::Observer {
// This reports following error code via |callback|: // This reports following error code via |callback|:
// - File::FILE_ERROR_NOT_FOUND if |src_path| or the parent directory of // - File::FILE_ERROR_NOT_FOUND if |src_path| or the parent directory of
// |dest_path| does not exist. // |dest_path| does not exist.
// - File::FILE_ERROR_ACCESS_DENIED if this root is read-only.
void CopyFileLocal(const base::FilePath& src_path, void CopyFileLocal(const base::FilePath& src_path,
const base::FilePath& dest_path, const base::FilePath& dest_path,
StatusCallback callback); StatusCallback callback);
...@@ -116,6 +122,7 @@ class ArcDocumentsProviderRoot : public ArcFileSystemOperationRunner::Observer { ...@@ -116,6 +122,7 @@ class ArcDocumentsProviderRoot : public ArcFileSystemOperationRunner::Observer {
// This reports following error code via |callback|: // This reports following error code via |callback|:
// - File::FILE_ERROR_NOT_FOUND if |src_path| or the parent directory of // - File::FILE_ERROR_NOT_FOUND if |src_path| or the parent directory of
// |dest_path| does not exist. // |dest_path| does not exist.
// - File::FILE_ERROR_ACCESS_DENIED if this root is read-only.
void MoveFileLocal(const base::FilePath& src_path, void MoveFileLocal(const base::FilePath& src_path,
const base::FilePath& dest_path, const base::FilePath& dest_path,
StatusCallback callback); StatusCallback callback);
......
...@@ -186,6 +186,10 @@ class ArcDocumentsProviderRootTest : public testing::Test { ...@@ -186,6 +186,10 @@ class ArcDocumentsProviderRootTest : public testing::Test {
ArcFileSystemOperationRunner::GetForBrowserContext(profile_.get()), ArcFileSystemOperationRunner::GetForBrowserContext(profile_.get()),
kAuthority, kRootSpec.document_id, "", false, kAuthority, kRootSpec.document_id, "", false,
std::vector<std::string>()); std::vector<std::string>());
read_only_root_ = std::make_unique<ArcDocumentsProviderRoot>(
ArcFileSystemOperationRunner::GetForBrowserContext(profile_.get()),
kAuthority, kRootSpec.document_id, "read-only", true,
std::vector<std::string>());
} }
void TearDown() override { void TearDown() override {
...@@ -206,6 +210,7 @@ class ArcDocumentsProviderRootTest : public testing::Test { ...@@ -206,6 +210,7 @@ class ArcDocumentsProviderRootTest : public testing::Test {
std::unique_ptr<ArcServiceManager> arc_service_manager_; std::unique_ptr<ArcServiceManager> arc_service_manager_;
std::unique_ptr<TestingProfile> profile_; std::unique_ptr<TestingProfile> profile_;
std::unique_ptr<ArcDocumentsProviderRoot> root_; std::unique_ptr<ArcDocumentsProviderRoot> root_;
std::unique_ptr<ArcDocumentsProviderRoot> read_only_root_;
private: private:
DISALLOW_COPY_AND_ASSIGN(ArcDocumentsProviderRootTest); DISALLOW_COPY_AND_ASSIGN(ArcDocumentsProviderRootTest);
...@@ -639,6 +644,25 @@ TEST_F(ArcDocumentsProviderRootTest, DeleteDirectory) { ...@@ -639,6 +644,25 @@ TEST_F(ArcDocumentsProviderRootTest, DeleteDirectory) {
base::FilePath(FILE_PATH_LITERAL("dir")))); base::FilePath(FILE_PATH_LITERAL("dir"))));
} }
TEST_F(ArcDocumentsProviderRootTest, DeleteFileOnReadOnlyRoot) {
base::RunLoop run_loop;
read_only_root_->DeleteFile(
base::FilePath(FILE_PATH_LITERAL("dir/photo.jpg")),
base::BindOnce(
[](base::RunLoop* run_loop, base::File::Error error) {
run_loop->Quit();
// An attempt to delete a file on read-only root
// should return FILE_ERROR_ACCESS_DENIED error.
EXPECT_EQ(base::File::FILE_ERROR_ACCESS_DENIED, error);
},
&run_loop));
run_loop.Run();
// dir/photo.jpg should not have been removed.
EXPECT_TRUE(fake_file_system_.DocumentExists(
kAuthority, kRootSpec.document_id,
base::FilePath(FILE_PATH_LITERAL("dir/photo.jpg"))));
}
TEST_F(ArcDocumentsProviderRootTest, CreateFile) { TEST_F(ArcDocumentsProviderRootTest, CreateFile) {
// Make sure that dir/new.txt doesn't exist. // Make sure that dir/new.txt doesn't exist.
ASSERT_FALSE(fake_file_system_.DocumentExists( ASSERT_FALSE(fake_file_system_.DocumentExists(
...@@ -751,6 +775,25 @@ TEST_F(ArcDocumentsProviderRootTest, CreateFileInReadOnlyDirectory) { ...@@ -751,6 +775,25 @@ TEST_F(ArcDocumentsProviderRootTest, CreateFileInReadOnlyDirectory) {
base::FilePath(FILE_PATH_LITERAL("dir3/photo.jpg")))); base::FilePath(FILE_PATH_LITERAL("dir3/photo.jpg"))));
} }
TEST_F(ArcDocumentsProviderRootTest, CreateFileOnReadOnlyRoot) {
base::RunLoop run_loop;
read_only_root_->CreateFile(
base::FilePath(FILE_PATH_LITERAL("dir/new.txt")),
base::BindOnce(
[](base::RunLoop* run_loop, base::File::Error error) {
run_loop->Quit();
// An attempt to create a file on read-only root should return
// FILE_ERROR_ACCESS_DENIED error.
EXPECT_EQ(base::File::FILE_ERROR_ACCESS_DENIED, error);
},
&run_loop));
run_loop.Run();
// The dir/new.txt should not have been created.
EXPECT_FALSE(fake_file_system_.DocumentExists(
kAuthority, kRootSpec.document_id,
base::FilePath(FILE_PATH_LITERAL("dir/new.txt"))));
}
TEST_F(ArcDocumentsProviderRootTest, CreateDirectory) { TEST_F(ArcDocumentsProviderRootTest, CreateDirectory) {
// Make sure that directory "dir2" doesn't exist. // Make sure that directory "dir2" doesn't exist.
ASSERT_FALSE(fake_file_system_.DocumentExists( ASSERT_FALSE(fake_file_system_.DocumentExists(
...@@ -821,6 +864,25 @@ TEST_F(ArcDocumentsProviderRootTest, CreateDirectoryParentNotFound) { ...@@ -821,6 +864,25 @@ TEST_F(ArcDocumentsProviderRootTest, CreateDirectoryParentNotFound) {
base::FilePath(FILE_PATH_LITERAL("dir3/new_dir")))); base::FilePath(FILE_PATH_LITERAL("dir3/new_dir"))));
} }
TEST_F(ArcDocumentsProviderRootTest, CreateDirectoryOnReadOnlyRoot) {
base::RunLoop run_loop;
read_only_root_->CreateDirectory(
base::FilePath(FILE_PATH_LITERAL("dir2")),
base::BindOnce(
[](base::RunLoop* run_loop, base::File::Error error) {
run_loop->Quit();
// An attempt to create a directory on read-only root should return
// FILE_ERROR_ACCESS_DENIED error.
EXPECT_EQ(base::File::FILE_ERROR_ACCESS_DENIED, error);
},
&run_loop));
run_loop.Run();
// The dir2 should not have been created.
EXPECT_FALSE(fake_file_system_.DocumentExists(
kAuthority, kRootSpec.document_id,
base::FilePath(FILE_PATH_LITERAL("dir2"))));
}
TEST_F(ArcDocumentsProviderRootTest, CopyFile) { TEST_F(ArcDocumentsProviderRootTest, CopyFile) {
base::RunLoop run_loop; base::RunLoop run_loop;
root_->CopyFileLocal( root_->CopyFileLocal(
...@@ -893,6 +955,30 @@ TEST_F(ArcDocumentsProviderRootTest, CopyFileDestParentNotFound) { ...@@ -893,6 +955,30 @@ TEST_F(ArcDocumentsProviderRootTest, CopyFileDestParentNotFound) {
run_loop.Run(); run_loop.Run();
} }
TEST_F(ArcDocumentsProviderRootTest, CopyFileOnReadOnlyRoot) {
base::RunLoop run_loop;
read_only_root_->CopyFileLocal(
base::FilePath(FILE_PATH_LITERAL("dir/photo.jpg")),
base::FilePath(FILE_PATH_LITERAL("dir/photo2.jpg")),
base::BindOnce(
[](base::RunLoop* run_loop, base::File::Error error) {
run_loop->Quit();
// An attempt to copy a directory on read-only root should return
// FILE_ERROR_ACCESS_DENIED error.
EXPECT_EQ(base::File::FILE_ERROR_ACCESS_DENIED, error);
},
&run_loop));
run_loop.Run();
// dir/photo2.jpg should not be created by the copy.
EXPECT_FALSE(fake_file_system_.DocumentExists(
kAuthority, kRootSpec.document_id,
base::FilePath(FILE_PATH_LITERAL("dir/photo2.jpg"))));
// The source file should still be there.
EXPECT_TRUE(fake_file_system_.DocumentExists(
kAuthority, kRootSpec.document_id,
base::FilePath(FILE_PATH_LITERAL("dir/photo.jpg"))));
}
TEST_F(ArcDocumentsProviderRootTest, RenameFile) { TEST_F(ArcDocumentsProviderRootTest, RenameFile) {
base::RunLoop run_loop; base::RunLoop run_loop;
root_->MoveFileLocal( root_->MoveFileLocal(
...@@ -948,6 +1034,30 @@ TEST_F(ArcDocumentsProviderRootTest, RenameFileNotRenamable) { ...@@ -948,6 +1034,30 @@ TEST_F(ArcDocumentsProviderRootTest, RenameFileNotRenamable) {
base::FilePath(FILE_PATH_LITERAL("dir/no-rename2.jpg")))); base::FilePath(FILE_PATH_LITERAL("dir/no-rename2.jpg"))));
} }
TEST_F(ArcDocumentsProviderRootTest, RenameFileOnReadOnlyRoot) {
base::RunLoop run_loop;
read_only_root_->MoveFileLocal(
base::FilePath(FILE_PATH_LITERAL("dir/photo.jpg")),
base::FilePath(FILE_PATH_LITERAL("dir/photo2.jpg")),
base::BindOnce(
[](base::RunLoop* run_loop, base::File::Error error) {
run_loop->Quit();
// An attempt to rename a file on read-only root should return
// FILE_ERROR_ACCESS_DENIED error.
EXPECT_EQ(base::File::FILE_ERROR_ACCESS_DENIED, error);
},
&run_loop));
run_loop.Run();
// dir/no-rename.jpg should still be there.
EXPECT_TRUE(fake_file_system_.DocumentExists(
kAuthority, kRootSpec.document_id,
base::FilePath(FILE_PATH_LITERAL("dir/no-rename.jpg"))));
// dir/no-rename2.jpg shouldn't be there".
EXPECT_FALSE(fake_file_system_.DocumentExists(
kAuthority, kRootSpec.document_id,
base::FilePath(FILE_PATH_LITERAL("dir/no-rename2.jpg"))));
}
TEST_F(ArcDocumentsProviderRootTest, MoveFile) { TEST_F(ArcDocumentsProviderRootTest, MoveFile) {
base::RunLoop run_loop; base::RunLoop run_loop;
root_->MoveFileLocal( root_->MoveFileLocal(
...@@ -1032,6 +1142,30 @@ TEST_F(ArcDocumentsProviderRootTest, MoveFileDestParentNotFound) { ...@@ -1032,6 +1142,30 @@ TEST_F(ArcDocumentsProviderRootTest, MoveFileDestParentNotFound) {
run_loop.Run(); run_loop.Run();
} }
TEST_F(ArcDocumentsProviderRootTest, MoveFileOnReadOnlyRoot) {
base::RunLoop run_loop;
read_only_root_->MoveFileLocal(
base::FilePath(FILE_PATH_LITERAL("dir/photo.jpg")),
base::FilePath(FILE_PATH_LITERAL("photo.jpg")),
base::BindOnce(
[](base::RunLoop* run_loop, base::File::Error error) {
run_loop->Quit();
// An attempt to move a file on read-only root should return
// FILE_ERROR_ACCESS_DENIED error.
EXPECT_EQ(base::File::FILE_ERROR_ACCESS_DENIED, error);
},
&run_loop));
run_loop.Run();
// The destination file should not be created.
EXPECT_FALSE(fake_file_system_.DocumentExists(
kAuthority, kRootSpec.document_id,
base::FilePath(FILE_PATH_LITERAL("photo.jpg"))));
// The source file should not be gone by move.
EXPECT_TRUE(fake_file_system_.DocumentExists(
kAuthority, kRootSpec.document_id,
base::FilePath(FILE_PATH_LITERAL("dir/photo.jpg"))));
}
TEST_F(ArcDocumentsProviderRootTest, WatchChanged) { TEST_F(ArcDocumentsProviderRootTest, WatchChanged) {
int num_called = 0; int num_called = 0;
auto watcher_callback = base::Bind( auto watcher_callback = base::Bind(
......
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