Skip to content

Commit

Permalink
mojo: Start building a leveldb service.
Browse files Browse the repository at this point in the history
This service encapsulates just leveldb and exports an interface for
Get/Put/Write. Instead of writing directly to the filesystem, it instead
takes a mojo:filesystem DirectoryPtr where it stores its data, letting
leveldb be entirely sandboxed.

BUG=585587

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

Cr-Commit-Position: refs/heads/master@{#375949}
  • Loading branch information
eglaysher authored and Commit bot committed Feb 17, 2016
1 parent edf3fda commit b22301f
Show file tree
Hide file tree
Showing 35 changed files with 2,505 additions and 20 deletions.
1 change: 1 addition & 0 deletions BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,7 @@ group("mojo_apptests") {
if (is_win || is_linux) {
deps += [
"//components/filesystem:apptests",
"//components/leveldb:apptests",
"//components/mus/ws:tests",
"//components/resource_provider:apptests",
"//components/resource_provider:resource_provider_unittests",
Expand Down
2 changes: 2 additions & 0 deletions components/filesystem/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ source_set("lib") {
"file_system_app.h",
"file_system_impl.cc",
"file_system_impl.h",
"lock_table.cc",
"lock_table.h",
"util.cc",
"util.h",
]
Expand Down
84 changes: 80 additions & 4 deletions components/filesystem/directory_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,20 @@
#include "components/filesystem/file_impl.h"
#include "components/filesystem/util.h"
#include "mojo/common/common_type_converters.h"
#include "mojo/platform_handle/platform_handle_functions.h"

using mojo::ScopedHandle;

namespace filesystem {

DirectoryImpl::DirectoryImpl(mojo::InterfaceRequest<Directory> request,
base::FilePath directory_path,
scoped_ptr<base::ScopedTempDir> temp_dir)
scoped_ptr<base::ScopedTempDir> temp_dir,
LockTable* lock_table)
: binding_(this, std::move(request)),
directory_path_(directory_path),
temp_dir_(std::move(temp_dir)) {}
temp_dir_(std::move(temp_dir)),
lock_table_(lock_table) {}

DirectoryImpl::~DirectoryImpl() {
}
Expand Down Expand Up @@ -90,11 +95,58 @@ void DirectoryImpl::OpenFile(const mojo::String& raw_path,
}

if (file.is_pending()) {
new FileImpl(std::move(file), std::move(base_file));
new FileImpl(std::move(file), path, std::move(base_file), lock_table_);
}
callback.Run(FileError::OK);
}

void DirectoryImpl::OpenFileHandle(const mojo::String& raw_path,
uint32_t open_flags,
const OpenFileHandleCallback& callback) {
base::FilePath path;
FileError error = ValidatePath(raw_path, directory_path_, &path);
if (error != FileError::OK) {
callback.Run(error, ScopedHandle());
return;
}

#if defined(OS_WIN)
// On Windows, FILE_FLAG_BACKUP_SEMANTICS is needed to open a directory.
if (base::DirectoryExists(path))
open_flags |= base::File::FLAG_BACKUP_SEMANTICS;
#endif // OS_WIN

base::File base_file(path, open_flags);
if (!base_file.IsValid()) {
callback.Run(GetError(base_file), ScopedHandle());
return;
}

base::File::Info info;
if (!base_file.GetInfo(&info)) {
callback.Run(FileError::FAILED, ScopedHandle());
return;
}

if (info.is_directory) {
// We must not return directories as files. In the file abstraction, we can
// fetch raw file descriptors over mojo pipes, and passing a file
// descriptor to a directory is a sandbox escape on Windows.
callback.Run(FileError::NOT_A_FILE, ScopedHandle());
return;
}

MojoHandle mojo_handle;
MojoResult create_result = MojoCreatePlatformHandleWrapper(
base_file.TakePlatformFile(), &mojo_handle);
if (create_result != MOJO_RESULT_OK) {
callback.Run(FileError::FAILED, ScopedHandle());
return;
}

callback.Run(FileError::OK, ScopedHandle(mojo::Handle(mojo_handle)));
}

void DirectoryImpl::OpenDirectory(const mojo::String& raw_path,
mojo::InterfaceRequest<Directory> directory,
uint32_t open_flags,
Expand Down Expand Up @@ -128,7 +180,7 @@ void DirectoryImpl::OpenDirectory(const mojo::String& raw_path,

if (directory.is_pending())
new DirectoryImpl(std::move(directory), path,
scoped_ptr<base::ScopedTempDir>());
scoped_ptr<base::ScopedTempDir>(), lock_table_);
callback.Run(FileError::OK);
}

Expand Down Expand Up @@ -216,6 +268,30 @@ void DirectoryImpl::Flush(const FlushCallback& callback) {
callback.Run(FileError::OK);
}

void DirectoryImpl::StatFile(const mojo::String& raw_path,
const StatFileCallback& callback) {
base::FilePath path;
FileError error = ValidatePath(raw_path, directory_path_, &path);
if (error != FileError::OK) {
callback.Run(error, nullptr);
return;
}

base::File base_file(path, base::File::FLAG_OPEN | base::File::FLAG_READ);
if (!base_file.IsValid()) {
callback.Run(GetError(base_file), nullptr);
return;
}

base::File::Info info;
if (!base_file.GetInfo(&info)) {
callback.Run(FileError::FAILED, nullptr);
return;
}

callback.Run(FileError::OK, MakeFileInformation(info));
}

void DirectoryImpl::ReadEntireFile(const mojo::String& raw_path,
const ReadEntireFileCallback& callback) {
base::FilePath path;
Expand Down
11 changes: 10 additions & 1 deletion components/filesystem/directory_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,16 @@ class ScopedTempDir;

namespace filesystem {

class LockTable;

class DirectoryImpl : public Directory {
public:
// Set |temp_dir| only if there's a temporary directory that should be deleted
// when this object is destroyed.
DirectoryImpl(mojo::InterfaceRequest<Directory> request,
base::FilePath directory_path,
scoped_ptr<base::ScopedTempDir> temp_dir);
scoped_ptr<base::ScopedTempDir> temp_dir,
LockTable* lock_table);
~DirectoryImpl() override;

void set_connection_error_handler(const mojo::Closure& error_handler) {
Expand All @@ -40,6 +43,9 @@ class DirectoryImpl : public Directory {
mojo::InterfaceRequest<File> file,
uint32_t open_flags,
const OpenFileCallback& callback) override;
void OpenFileHandle(const mojo::String& path,
uint32_t open_flags,
const OpenFileHandleCallback& callback) override;
void OpenDirectory(const mojo::String& path,
mojo::InterfaceRequest<Directory> directory,
uint32_t open_flags,
Expand All @@ -55,6 +61,8 @@ class DirectoryImpl : public Directory {
void IsWritable(const mojo::String& path,
const IsWritableCallback& callback) override;
void Flush(const FlushCallback& callback) override;
void StatFile(const mojo::String& path,
const StatFileCallback& callback) override;
void ReadEntireFile(const mojo::String& path,
const ReadEntireFileCallback& callback) override;
void WriteFile(const mojo::String& path,
Expand All @@ -65,6 +73,7 @@ class DirectoryImpl : public Directory {
mojo::StrongBinding<Directory> binding_;
base::FilePath directory_path_;
scoped_ptr<base::ScopedTempDir> temp_dir_;
LockTable* lock_table_;

DISALLOW_COPY_AND_ASSIGN(DirectoryImpl);
};
Expand Down
48 changes: 43 additions & 5 deletions components/filesystem/file_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "base/files/scoped_file.h"
#include "base/logging.h"
#include "build/build_config.h"
#include "components/filesystem/lock_table.h"
#include "components/filesystem/util.h"
#include "mojo/common/common_type_converters.h"
#include "mojo/platform_handle/platform_handle_functions.h"
Expand All @@ -24,22 +25,49 @@ using base::Time;
using mojo::ScopedHandle;

namespace filesystem {
namespace {

const size_t kMaxReadSize = 1 * 1024 * 1024; // 1 MB.

} // namespace

FileImpl::FileImpl(mojo::InterfaceRequest<File> request,
const base::FilePath& path,
uint32_t flags)
: binding_(this, std::move(request)), file_(path, flags) {
uint32_t flags,
LockTable* lock_table)
: binding_(this, std::move(request)),
file_(path, flags),
path_(path),
lock_table_(lock_table) {
DCHECK(file_.IsValid());
}

FileImpl::FileImpl(mojo::InterfaceRequest<File> request, base::File file)
: binding_(this, std::move(request)), file_(std::move(file)) {
FileImpl::FileImpl(mojo::InterfaceRequest<File> request,
const base::FilePath& path,
base::File file,
LockTable* lock_table)
: binding_(this, std::move(request)),
file_(std::move(file)),
path_(path),
lock_table_(lock_table) {
DCHECK(file_.IsValid());
}

FileImpl::~FileImpl() {
if (file_.IsValid())
lock_table_->RemoveFromLockTable(path_);
}

bool FileImpl::IsValid() const {
return file_.IsValid();
}

base::File::Error FileImpl::RawLockFile() {
return file_.Lock();
}

base::File::Error FileImpl::RawUnlockFile() {
return file_.Unlock();
}

void FileImpl::Close(const CloseCallback& callback) {
Expand All @@ -48,6 +76,7 @@ void FileImpl::Close(const CloseCallback& callback) {
return;
}

lock_table_->RemoveFromLockTable(path_);
file_.Close();
callback.Run(FileError::OK);
}
Expand Down Expand Up @@ -268,7 +297,7 @@ void FileImpl::Dup(mojo::InterfaceRequest<File> file,
}

if (file.is_pending())
new FileImpl(std::move(file), std::move(new_file));
new FileImpl(std::move(file), path_, std::move(new_file), lock_table_);
callback.Run(FileError::OK);
}

Expand All @@ -282,6 +311,15 @@ void FileImpl::Flush(const FlushCallback& callback) {
callback.Run(ret ? FileError::OK : FileError::FAILED);
}

void FileImpl::Lock(const LockCallback& callback) {
callback.Run(static_cast<filesystem::FileError>(lock_table_->LockFile(this)));
}

void FileImpl::Unlock(const UnlockCallback& callback) {
callback.Run(
static_cast<filesystem::FileError>(lock_table_->UnlockFile(this)));
}

void FileImpl::AsHandle(const AsHandleCallback& callback) {
if (!file_.IsValid()) {
callback.Run(GetError(file_), ScopedHandle());
Expand Down
24 changes: 22 additions & 2 deletions components/filesystem/file_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,30 @@ class FilePath;

namespace filesystem {

class LockTable;

class FileImpl : public File {
public:
FileImpl(mojo::InterfaceRequest<File> request,
const base::FilePath& path,
uint32_t flags);
FileImpl(mojo::InterfaceRequest<File> request, base::File file);
uint32_t flags,
LockTable* lock_table);
FileImpl(mojo::InterfaceRequest<File> request,
const base::FilePath& path,
base::File file,
LockTable* lock_table);
~FileImpl() override;

// Returns whether the underlying file handle is valid.
bool IsValid() const;

// Attempts to perform the native operating system's locking operations on
// the internal File handle
base::File::Error RawLockFile();
base::File::Error RawUnlockFile();

const base::FilePath& path() const { return path_; }

// |File| implementation:
void Close(const CloseCallback& callback) override;
void Read(uint32_t num_bytes_to_read,
Expand All @@ -50,11 +66,15 @@ class FileImpl : public File {
void Dup(mojo::InterfaceRequest<File> file,
const DupCallback& callback) override;
void Flush(const FlushCallback& callback) override;
void Lock(const LockCallback& callback) override;
void Unlock(const UnlockCallback& callback) override;
void AsHandle(const AsHandleCallback& callback) override;

private:
mojo::StrongBinding<File> binding_;
base::File file_;
base::FilePath path_;
LockTable* lock_table_;

DISALLOW_COPY_AND_ASSIGN(FileImpl);
};
Expand Down
Loading

0 comments on commit b22301f

Please sign in to comment.