Commit 5b48ea6b authored by mtomasz@chromium.org's avatar mtomasz@chromium.org

[fsp] Do not allow write operations on read only file systems.

A writable option for provided file systems has been added recently. This CL
adds checks at early stage to fail writing related operations on file systems
which were not mounted as R/W.

TEST=unit_tests: *FileSystemProvider*ReadOnly*
BUG=393506

Review URL: https://codereview.chromium.org/427493002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@285878 0039d316-1c4b-4281-b951-d872f2087c98
parent e4b9afd8
...@@ -28,6 +28,9 @@ CopyEntry::~CopyEntry() { ...@@ -28,6 +28,9 @@ CopyEntry::~CopyEntry() {
} }
bool CopyEntry::Execute(int request_id) { bool CopyEntry::Execute(int request_id) {
if (!file_system_info_.writable())
return false;
scoped_ptr<base::DictionaryValue> values(new base::DictionaryValue); scoped_ptr<base::DictionaryValue> values(new base::DictionaryValue);
values->SetString("sourcePath", source_path_.AsUTF8Unsafe()); values->SetString("sourcePath", source_path_.AsUTF8Unsafe());
values->SetString("targetPath", target_path_.AsUTF8Unsafe()); values->SetString("targetPath", target_path_.AsUTF8Unsafe());
......
...@@ -108,6 +108,29 @@ TEST_F(FileSystemProviderOperationsCopyEntryTest, Execute_NoListener) { ...@@ -108,6 +108,29 @@ TEST_F(FileSystemProviderOperationsCopyEntryTest, Execute_NoListener) {
EXPECT_FALSE(copy_entry.Execute(kRequestId)); EXPECT_FALSE(copy_entry.Execute(kRequestId));
} }
TEST_F(FileSystemProviderOperationsCopyEntryTest, Execute_ReadOnly) {
util::LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */);
util::StatusCallbackLog callback_log;
const ProvidedFileSystemInfo read_only_file_system_info(
kExtensionId,
kFileSystemId,
"" /* file_system_name */,
false /* writable */,
base::FilePath() /* mount_path */);
CopyEntry copy_entry(NULL,
read_only_file_system_info,
base::FilePath::FromUTF8Unsafe(kSourcePath),
base::FilePath::FromUTF8Unsafe(kTargetPath),
base::Bind(&util::LogStatusCallback, &callback_log));
copy_entry.SetDispatchEventImplForTesting(
base::Bind(&util::LoggingDispatchEventImpl::OnDispatchEventImpl,
base::Unretained(&dispatcher)));
EXPECT_FALSE(copy_entry.Execute(kRequestId));
}
TEST_F(FileSystemProviderOperationsCopyEntryTest, OnSuccess) { TEST_F(FileSystemProviderOperationsCopyEntryTest, OnSuccess) {
util::LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */); util::LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */);
util::StatusCallbackLog callback_log; util::StatusCallbackLog callback_log;
......
...@@ -31,6 +31,9 @@ CreateDirectory::~CreateDirectory() { ...@@ -31,6 +31,9 @@ CreateDirectory::~CreateDirectory() {
} }
bool CreateDirectory::Execute(int request_id) { bool CreateDirectory::Execute(int request_id) {
if (!file_system_info_.writable())
return false;
scoped_ptr<base::DictionaryValue> values(new base::DictionaryValue); scoped_ptr<base::DictionaryValue> values(new base::DictionaryValue);
values->SetString("directoryPath", directory_path_.AsUTF8Unsafe()); values->SetString("directoryPath", directory_path_.AsUTF8Unsafe());
values->SetBoolean("exclusive", exclusive_); values->SetBoolean("exclusive", exclusive_);
......
...@@ -115,6 +115,31 @@ TEST_F(FileSystemProviderOperationsCreateDirectoryTest, Execute_NoListener) { ...@@ -115,6 +115,31 @@ TEST_F(FileSystemProviderOperationsCreateDirectoryTest, Execute_NoListener) {
EXPECT_FALSE(create_directory.Execute(kRequestId)); EXPECT_FALSE(create_directory.Execute(kRequestId));
} }
TEST_F(FileSystemProviderOperationsCreateDirectoryTest, Execute_ReadOnly) {
util::LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */);
util::StatusCallbackLog callback_log;
const ProvidedFileSystemInfo read_only_file_system_info(
kExtensionId,
kFileSystemId,
"" /* file_system_name */,
false /* writable */,
base::FilePath() /* mount_path */);
CreateDirectory create_directory(
NULL,
read_only_file_system_info,
base::FilePath::FromUTF8Unsafe(kDirectoryPath),
false /* exclusive */,
true /* recursive */,
base::Bind(&util::LogStatusCallback, &callback_log));
create_directory.SetDispatchEventImplForTesting(
base::Bind(&util::LoggingDispatchEventImpl::OnDispatchEventImpl,
base::Unretained(&dispatcher)));
EXPECT_FALSE(create_directory.Execute(kRequestId));
}
TEST_F(FileSystemProviderOperationsCreateDirectoryTest, OnSuccess) { TEST_F(FileSystemProviderOperationsCreateDirectoryTest, OnSuccess) {
util::LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */); util::LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */);
util::StatusCallbackLog callback_log; util::StatusCallbackLog callback_log;
......
...@@ -26,6 +26,9 @@ CreateFile::~CreateFile() { ...@@ -26,6 +26,9 @@ CreateFile::~CreateFile() {
} }
bool CreateFile::Execute(int request_id) { bool CreateFile::Execute(int request_id) {
if (!file_system_info_.writable())
return false;
scoped_ptr<base::DictionaryValue> values(new base::DictionaryValue); scoped_ptr<base::DictionaryValue> values(new base::DictionaryValue);
values->SetString("filePath", file_path_.AsUTF8Unsafe()); values->SetString("filePath", file_path_.AsUTF8Unsafe());
......
...@@ -101,6 +101,28 @@ TEST_F(FileSystemProviderOperationsCreateFileTest, Execute_NoListener) { ...@@ -101,6 +101,28 @@ TEST_F(FileSystemProviderOperationsCreateFileTest, Execute_NoListener) {
EXPECT_FALSE(create_file.Execute(kRequestId)); EXPECT_FALSE(create_file.Execute(kRequestId));
} }
TEST_F(FileSystemProviderOperationsCreateFileTest, Execute_ReadOnly) {
util::LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */);
util::StatusCallbackLog callback_log;
const ProvidedFileSystemInfo read_only_file_system_info(
kExtensionId,
kFileSystemId,
"" /* file_system_name */,
false /* writable */,
base::FilePath() /* mount_path */);
CreateFile create_file(NULL,
read_only_file_system_info,
base::FilePath::FromUTF8Unsafe(kFilePath),
base::Bind(&util::LogStatusCallback, &callback_log));
create_file.SetDispatchEventImplForTesting(
base::Bind(&util::LoggingDispatchEventImpl::OnDispatchEventImpl,
base::Unretained(&dispatcher)));
EXPECT_FALSE(create_file.Execute(kRequestId));
}
TEST_F(FileSystemProviderOperationsCreateFileTest, OnSuccess) { TEST_F(FileSystemProviderOperationsCreateFileTest, OnSuccess) {
util::LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */); util::LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */);
util::StatusCallbackLog callback_log; util::StatusCallbackLog callback_log;
......
...@@ -28,6 +28,9 @@ DeleteEntry::~DeleteEntry() { ...@@ -28,6 +28,9 @@ DeleteEntry::~DeleteEntry() {
} }
bool DeleteEntry::Execute(int request_id) { bool DeleteEntry::Execute(int request_id) {
if (!file_system_info_.writable())
return false;
scoped_ptr<base::DictionaryValue> values(new base::DictionaryValue); scoped_ptr<base::DictionaryValue> values(new base::DictionaryValue);
values->SetString("entryPath", entry_path_.AsUTF8Unsafe()); values->SetString("entryPath", entry_path_.AsUTF8Unsafe());
values->SetBoolean("recursive", recursive_); values->SetBoolean("recursive", recursive_);
......
...@@ -41,7 +41,7 @@ class FileSystemProviderOperationsDeleteEntryTest : public testing::Test { ...@@ -41,7 +41,7 @@ class FileSystemProviderOperationsDeleteEntryTest : public testing::Test {
ProvidedFileSystemInfo(kExtensionId, ProvidedFileSystemInfo(kExtensionId,
kFileSystemId, kFileSystemId,
"" /* file_system_name */, "" /* file_system_name */,
false /* writable */, true /* writable */,
base::FilePath() /* mount_path */); base::FilePath() /* mount_path */);
} }
...@@ -107,6 +107,29 @@ TEST_F(FileSystemProviderOperationsDeleteEntryTest, Execute_NoListener) { ...@@ -107,6 +107,29 @@ TEST_F(FileSystemProviderOperationsDeleteEntryTest, Execute_NoListener) {
EXPECT_FALSE(delete_entry.Execute(kRequestId)); EXPECT_FALSE(delete_entry.Execute(kRequestId));
} }
TEST_F(FileSystemProviderOperationsDeleteEntryTest, Execute_ReadOnly) {
util::LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */);
util::StatusCallbackLog callback_log;
const ProvidedFileSystemInfo read_only_file_system_info(
kExtensionId,
kFileSystemId,
"" /* file_system_name */,
false /* writable */,
base::FilePath() /* mount_path */);
DeleteEntry delete_entry(NULL,
read_only_file_system_info,
base::FilePath::FromUTF8Unsafe(kEntryPath),
true /* recursive */,
base::Bind(&util::LogStatusCallback, &callback_log));
delete_entry.SetDispatchEventImplForTesting(
base::Bind(&util::LoggingDispatchEventImpl::OnDispatchEventImpl,
base::Unretained(&dispatcher)));
EXPECT_FALSE(delete_entry.Execute(kRequestId));
}
TEST_F(FileSystemProviderOperationsDeleteEntryTest, OnSuccess) { TEST_F(FileSystemProviderOperationsDeleteEntryTest, OnSuccess) {
util::LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */); util::LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */);
util::StatusCallbackLog callback_log; util::StatusCallbackLog callback_log;
......
...@@ -28,6 +28,9 @@ MoveEntry::~MoveEntry() { ...@@ -28,6 +28,9 @@ MoveEntry::~MoveEntry() {
} }
bool MoveEntry::Execute(int request_id) { bool MoveEntry::Execute(int request_id) {
if (!file_system_info_.writable())
return false;
scoped_ptr<base::DictionaryValue> values(new base::DictionaryValue); scoped_ptr<base::DictionaryValue> values(new base::DictionaryValue);
values->SetString("sourcePath", source_path_.AsUTF8Unsafe()); values->SetString("sourcePath", source_path_.AsUTF8Unsafe());
values->SetString("targetPath", target_path_.AsUTF8Unsafe()); values->SetString("targetPath", target_path_.AsUTF8Unsafe());
......
...@@ -108,6 +108,29 @@ TEST_F(FileSystemProviderOperationsMoveEntryTest, Execute_NoListener) { ...@@ -108,6 +108,29 @@ TEST_F(FileSystemProviderOperationsMoveEntryTest, Execute_NoListener) {
EXPECT_FALSE(move_entry.Execute(kRequestId)); EXPECT_FALSE(move_entry.Execute(kRequestId));
} }
TEST_F(FileSystemProviderOperationsMoveEntryTest, Execute_ReadOnly) {
util::LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */);
util::StatusCallbackLog callback_log;
const ProvidedFileSystemInfo read_only_file_system_info(
kExtensionId,
kFileSystemId,
"" /* file_system_name */,
false /* writable */,
base::FilePath() /* mount_path */);
MoveEntry move_entry(NULL,
read_only_file_system_info,
base::FilePath::FromUTF8Unsafe(kSourcePath),
base::FilePath::FromUTF8Unsafe(kTargetPath),
base::Bind(&util::LogStatusCallback, &callback_log));
move_entry.SetDispatchEventImplForTesting(
base::Bind(&util::LoggingDispatchEventImpl::OnDispatchEventImpl,
base::Unretained(&dispatcher)));
EXPECT_FALSE(move_entry.Execute(kRequestId));
}
TEST_F(FileSystemProviderOperationsMoveEntryTest, OnSuccess) { TEST_F(FileSystemProviderOperationsMoveEntryTest, OnSuccess) {
util::LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */); util::LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */);
util::StatusCallbackLog callback_log; util::StatusCallbackLog callback_log;
......
...@@ -29,6 +29,11 @@ OpenFile::~OpenFile() { ...@@ -29,6 +29,11 @@ OpenFile::~OpenFile() {
} }
bool OpenFile::Execute(int request_id) { bool OpenFile::Execute(int request_id) {
if (!file_system_info_.writable() &&
mode_ == ProvidedFileSystemInterface::OPEN_FILE_MODE_WRITE) {
return false;
}
scoped_ptr<base::DictionaryValue> values(new base::DictionaryValue); scoped_ptr<base::DictionaryValue> values(new base::DictionaryValue);
values->SetString("filePath", file_path_.AsUTF8Unsafe()); values->SetString("filePath", file_path_.AsUTF8Unsafe());
......
...@@ -147,6 +147,48 @@ TEST_F(FileSystemProviderOperationsOpenFileTest, Execute_NoListener) { ...@@ -147,6 +147,48 @@ TEST_F(FileSystemProviderOperationsOpenFileTest, Execute_NoListener) {
EXPECT_FALSE(open_file.Execute(kRequestId)); EXPECT_FALSE(open_file.Execute(kRequestId));
} }
TEST_F(FileSystemProviderOperationsOpenFileTest, Execute_ReadOnly) {
util::LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */);
CallbackLogger callback_logger;
const ProvidedFileSystemInfo read_only_file_system_info(
kExtensionId,
kFileSystemId,
"" /* file_system_name */,
false /* writable */,
base::FilePath() /* mount_path */);
// Opening for read on a read-only file system is allowed.
{
OpenFile open_file(NULL,
read_only_file_system_info,
base::FilePath::FromUTF8Unsafe(kFilePath),
ProvidedFileSystemInterface::OPEN_FILE_MODE_READ,
base::Bind(&CallbackLogger::OnOpenFile,
base::Unretained(&callback_logger)));
open_file.SetDispatchEventImplForTesting(
base::Bind(&util::LoggingDispatchEventImpl::OnDispatchEventImpl,
base::Unretained(&dispatcher)));
EXPECT_TRUE(open_file.Execute(kRequestId));
}
// Opening for write on a read-only file system is forbidden and must fail.
{
OpenFile open_file(NULL,
read_only_file_system_info,
base::FilePath::FromUTF8Unsafe(kFilePath),
ProvidedFileSystemInterface::OPEN_FILE_MODE_WRITE,
base::Bind(&CallbackLogger::OnOpenFile,
base::Unretained(&callback_logger)));
open_file.SetDispatchEventImplForTesting(
base::Bind(&util::LoggingDispatchEventImpl::OnDispatchEventImpl,
base::Unretained(&dispatcher)));
EXPECT_FALSE(open_file.Execute(kRequestId));
}
}
TEST_F(FileSystemProviderOperationsOpenFileTest, OnSuccess) { TEST_F(FileSystemProviderOperationsOpenFileTest, OnSuccess) {
util::LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */); util::LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */);
CallbackLogger callback_logger; CallbackLogger callback_logger;
......
...@@ -28,6 +28,9 @@ Truncate::~Truncate() { ...@@ -28,6 +28,9 @@ Truncate::~Truncate() {
} }
bool Truncate::Execute(int request_id) { bool Truncate::Execute(int request_id) {
if (!file_system_info_.writable())
return false;
scoped_ptr<base::DictionaryValue> values(new base::DictionaryValue); scoped_ptr<base::DictionaryValue> values(new base::DictionaryValue);
values->SetString("filePath", file_path_.AsUTF8Unsafe()); values->SetString("filePath", file_path_.AsUTF8Unsafe());
values->SetDouble("length", length_); values->SetDouble("length", length_);
......
...@@ -108,6 +108,29 @@ TEST_F(FileSystemProviderOperationsTruncateTest, Execute_NoListener) { ...@@ -108,6 +108,29 @@ TEST_F(FileSystemProviderOperationsTruncateTest, Execute_NoListener) {
EXPECT_FALSE(truncate.Execute(kRequestId)); EXPECT_FALSE(truncate.Execute(kRequestId));
} }
TEST_F(FileSystemProviderOperationsTruncateTest, Execute_ReadOnly) {
util::LoggingDispatchEventImpl dispatcher(false /* dispatch_reply */);
util::StatusCallbackLog callback_log;
const ProvidedFileSystemInfo read_only_file_system_info(
kExtensionId,
kFileSystemId,
"" /* file_system_name */,
false /* writable */,
base::FilePath() /* mount_path */);
Truncate truncate(NULL,
file_system_info_,
base::FilePath::FromUTF8Unsafe(kFilePath),
kTruncateLength,
base::Bind(&util::LogStatusCallback, &callback_log));
truncate.SetDispatchEventImplForTesting(
base::Bind(&util::LoggingDispatchEventImpl::OnDispatchEventImpl,
base::Unretained(&dispatcher)));
EXPECT_FALSE(truncate.Execute(kRequestId));
}
TEST_F(FileSystemProviderOperationsTruncateTest, OnSuccess) { TEST_F(FileSystemProviderOperationsTruncateTest, OnSuccess) {
util::LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */); util::LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */);
util::StatusCallbackLog callback_log; util::StatusCallbackLog callback_log;
......
...@@ -69,7 +69,8 @@ test_util.mountFileSystem = function(callback) { ...@@ -69,7 +69,8 @@ test_util.mountFileSystem = function(callback) {
chrome.fileSystemProvider.mount( chrome.fileSystemProvider.mount(
{ {
fileSystemId: test_util.FILE_SYSTEM_ID, fileSystemId: test_util.FILE_SYSTEM_ID,
displayName: test_util.FILE_SYSTEM_NAME displayName: test_util.FILE_SYSTEM_NAME,
writable: true
}, },
function() { function() {
var volumeId = var volumeId =
......
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