Commit 7655fcb6 authored by Ken Rockot's avatar Ken Rockot Committed by Commit Bot

Move SandboxedVfs to from Blink to //sql

In preparation for reusing most of this thing within the Storage Service
process, this moves SandboxedVfs into //sql and abstracts out the few
Blink-specific dependencies into a small delegate interface.

Bug: 1052045
Change-Id: I947611c63060446692c7f78b4f555b9f90994842
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2351159
Commit-Queue: Ken Rockot <rockot@google.com>
Reviewed-by: default avatarVictor Costan <pwnall@chromium.org>
Cr-Commit-Position: refs/heads/master@{#797368}
parent daa4f2e4
......@@ -38,6 +38,10 @@ component("sql") {
"recover_module/table.h",
"recovery.cc",
"recovery.h",
"sandboxed_vfs.cc",
"sandboxed_vfs.h",
"sandboxed_vfs_file.cc",
"sandboxed_vfs_file.h",
"sql_features.cc",
"sql_features.h",
"sql_memory_dump_provider.cc",
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SQL_SANDBOXED_VFS_H_
#define SQL_SANDBOXED_VFS_H_
#include <stdint.h>
#include <memory>
#include "base/component_export.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/optional.h"
#include "third_party/sqlite/sqlite3.h"
namespace sql {
// SQLite VFS implementation for use within a typical Chromium sandbox
// environment. Instances are thread-friendly.
class COMPONENT_EXPORT(SQL) SandboxedVfs {
public:
// Describes access rights for a path, used by Delegate::GetPathAccess below.
struct PathAccessInfo {
bool can_read = false;
bool can_write = false;
};
// Interface which must be implemented by the environment using a
// SandboxedVfs. This abstracts a handful of operations that don't typically
// work in a sandbox environment given a typical naive implementation.
//
// Instances must be thread-friendly, as methods may be called from any
// thread.
class Delegate {
public:
virtual ~Delegate() = default;
// Opens a file at the given `file_path`. `sqlite_requested_flags` is a
// bitwise combination SQLite flags used when opening files. Returns the
// opened File on success, or an invalid File on failure.
virtual base::File OpenFile(const base::FilePath& file_path,
int sqlite_requested_flags) = 0;
// Deletes a file at the given `file_path`. If `sync_dir` is true, the
// implementation should synchronize the containing directory contents if
// possible. Returns an SQLite error code indicating the status of the
// operation.
virtual int DeleteFile(const base::FilePath& file_path, bool sync_dir) = 0;
// Queries path access information for `file_path`. Returns null if the
// given path does not exist.
virtual base::Optional<PathAccessInfo> GetPathAccess(
const base::FilePath& file_path) = 0;
// Resizes the file at `file_path` (opened in `file`) to `size` bytes,
// returning true if successful and false otherwise. Implementations may
// want to operate on the filesystem via `file_path`, or modify `file`
// directly if possible.
//
// Note that if this is called by the VFS, it's because a direct call to
// SetLength on `file` has already failed. The implementation should not
// attempt to repeat this.
virtual bool SetFileLength(const base::FilePath& file_path,
base::File& file,
size_t size) = 0;
};
// We don't allow SandboxedVfs instances to be destroyed. Once created, they
// are permanently registered in the calling process.
~SandboxedVfs() = delete;
// Constructs a new instance of ths object using `delegate` to support various
// operations from within the sandbox. The VFS is registered with SQLite under
// `name` and if `make_default` is true then the VFS is also set as the global
// default for new database instances within the calling process.
//
// Note that `name` must be globally unique to the calling process.
static void Register(const char* name,
std::unique_ptr<Delegate> delegate,
bool make_default);
Delegate* delegate() const { return delegate_.get(); }
// sqlite3_vfs implementation.
int Open(const char* full_path,
sqlite3_file& result_file,
int requested_flags,
int* granted_flags);
int Delete(const char* full_path, int sync_dir);
int Access(const char* full_path, int flags, int& result);
int FullPathname(const char* file_path, int result_size, char* result);
int Randomness(int result_size, char* result);
int Sleep(int microseconds);
int GetLastError(int message_size, char* message) const;
int CurrentTimeInt64(sqlite3_int64* result_ms);
// Used by SandboxedVfsFile.
void SetLastError(base::File::Error error) { this->last_error_ = error; }
private:
SandboxedVfs(const char* name,
std::unique_ptr<Delegate> delegate,
bool make_default);
sqlite3_vfs sandboxed_vfs_;
const base::Time sqlite_epoch_;
const std::unique_ptr<Delegate> delegate_;
base::File::Error last_error_;
};
} // namespace sql
#endif // SQL_SANDBOXED_VFS_H_
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/modules/webdatabase/sqlite/sandboxed_vfs_file.h"
#include "sql/sandboxed_vfs_file.h"
#include <atomic>
#include <cstring>
......@@ -15,85 +15,83 @@
#include "base/threading/platform_thread.h"
#include "build/build_config.h"
#include "sql/initialization.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/modules/webdatabase/sqlite/sandboxed_vfs.h"
#include "third_party/blink/renderer/modules/webdatabase/web_database_host.h"
#include "sql/sandboxed_vfs.h"
#include "third_party/sqlite/sqlite3.h"
namespace blink {
namespace sql {
namespace {
int SandboxedClose(sqlite3_file* file) {
return SandboxedVfsFile::FromSqliteFile(file)->Close();
return SandboxedVfsFile::FromSqliteFile(*file).Close();
}
int SandboxedRead(sqlite3_file* file,
void* buffer,
int size,
sqlite3_int64 offset) {
return SandboxedVfsFile::FromSqliteFile(file)->Read(buffer, size, offset);
return SandboxedVfsFile::FromSqliteFile(*file).Read(buffer, size, offset);
}
int SandboxedWrite(sqlite3_file* file,
const void* buffer,
int size,
sqlite3_int64 offset) {
return SandboxedVfsFile::FromSqliteFile(file)->Write(buffer, size, offset);
return SandboxedVfsFile::FromSqliteFile(*file).Write(buffer, size, offset);
}
int SandboxedTruncate(sqlite3_file* file, sqlite3_int64 size) {
return SandboxedVfsFile::FromSqliteFile(file)->Truncate(size);
return SandboxedVfsFile::FromSqliteFile(*file).Truncate(size);
}
int SandboxedSync(sqlite3_file* file, int flags) {
return SandboxedVfsFile::FromSqliteFile(file)->Sync(flags);
return SandboxedVfsFile::FromSqliteFile(*file).Sync(flags);
}
int SandboxedFileSize(sqlite3_file* file, sqlite3_int64* result_size) {
return SandboxedVfsFile::FromSqliteFile(file)->FileSize(result_size);
return SandboxedVfsFile::FromSqliteFile(*file).FileSize(result_size);
}
int SandboxedLock(sqlite3_file* file, int mode) {
return SandboxedVfsFile::FromSqliteFile(file)->Lock(mode);
return SandboxedVfsFile::FromSqliteFile(*file).Lock(mode);
}
int SandboxedUnlock(sqlite3_file* file, int mode) {
return SandboxedVfsFile::FromSqliteFile(file)->Unlock(mode);
return SandboxedVfsFile::FromSqliteFile(*file).Unlock(mode);
}
int SandboxedCheckReservedLock(sqlite3_file* file, int* has_reserved_lock) {
return SandboxedVfsFile::FromSqliteFile(file)->CheckReservedLock(
return SandboxedVfsFile::FromSqliteFile(*file).CheckReservedLock(
has_reserved_lock);
}
int SandboxedFileControl(sqlite3_file* file, int opcode, void* data) {
return SandboxedVfsFile::FromSqliteFile(file)->FileControl(opcode, data);
return SandboxedVfsFile::FromSqliteFile(*file).FileControl(opcode, data);
}
int SandboxedSectorSize(sqlite3_file* file) {
return SandboxedVfsFile::FromSqliteFile(file)->SectorSize();
return SandboxedVfsFile::FromSqliteFile(*file).SectorSize();
}
int SandboxedDeviceCharacteristics(sqlite3_file* file) {
return SandboxedVfsFile::FromSqliteFile(file)->DeviceCharacteristics();
return SandboxedVfsFile::FromSqliteFile(*file).DeviceCharacteristics();
}
int SandboxedShmMap(sqlite3_file* file,
int page_index,
int page_size,
int extend_file_if_needed,
void volatile** result) {
return SandboxedVfsFile::FromSqliteFile(file)->ShmMap(
return SandboxedVfsFile::FromSqliteFile(*file).ShmMap(
page_index, page_size, extend_file_if_needed, result);
}
int SandboxedShmLock(sqlite3_file* file, int offset, int size, int flags) {
return SandboxedVfsFile::FromSqliteFile(file)->ShmLock(offset, size, flags);
return SandboxedVfsFile::FromSqliteFile(*file).ShmLock(offset, size, flags);
}
void SandboxedShmBarrier(sqlite3_file* file) {
SandboxedVfsFile::FromSqliteFile(file)->ShmBarrier();
SandboxedVfsFile::FromSqliteFile(*file).ShmBarrier();
}
int SandboxedShmUnmap(sqlite3_file* file, int also_delete_file) {
return SandboxedVfsFile::FromSqliteFile(file)->ShmUnmap(also_delete_file);
return SandboxedVfsFile::FromSqliteFile(*file).ShmUnmap(also_delete_file);
}
int SandboxedFetch(sqlite3_file* file,
sqlite3_int64 offset,
int size,
void** result) {
return SandboxedVfsFile::FromSqliteFile(file)->Fetch(offset, size, result);
return SandboxedVfsFile::FromSqliteFile(*file).Fetch(offset, size, result);
}
int SandboxedUnfetch(sqlite3_file* file,
sqlite3_int64 offset,
void* fetch_result) {
return SandboxedVfsFile::FromSqliteFile(file)->Unfetch(offset, fetch_result);
return SandboxedVfsFile::FromSqliteFile(*file).Unfetch(offset, fetch_result);
}
const sqlite3_io_methods* GetSqliteIoMethods() {
......@@ -130,19 +128,20 @@ const sqlite3_io_methods* GetSqliteIoMethods() {
// static
void SandboxedVfsFile::Create(base::File file,
String file_name,
base::FilePath file_path,
SandboxedVfs* vfs,
sqlite3_file* buffer) {
SandboxedVfsFileSqliteBridge* bridge =
sqlite3_file& buffer) {
SandboxedVfsFileSqliteBridge& bridge =
SandboxedVfsFileSqliteBridge::FromSqliteFile(buffer);
bridge->blink_file =
new SandboxedVfsFile(std::move(file), std::move(file_name), vfs);
bridge->sqlite_file.pMethods = GetSqliteIoMethods();
bridge.sandboxed_vfs_file =
new SandboxedVfsFile(std::move(file), std::move(file_path), vfs);
bridge.sqlite_file.pMethods = GetSqliteIoMethods();
}
// static
SandboxedVfsFile* SandboxedVfsFile::FromSqliteFile(sqlite3_file* sqlite_file) {
return SandboxedVfsFileSqliteBridge::FromSqliteFile(sqlite_file)->blink_file;
SandboxedVfsFile& SandboxedVfsFile::FromSqliteFile(sqlite3_file& sqlite_file) {
return *SandboxedVfsFileSqliteBridge::FromSqliteFile(sqlite_file)
.sandboxed_vfs_file;
}
int SandboxedVfsFile::Close() {
......@@ -216,16 +215,18 @@ int SandboxedVfsFile::Truncate(sqlite3_int64 size) {
if (file_.SetLength(size))
return SQLITE_OK;
// On Mac and Linux, the renderer sandbox blocks ftruncate(), so we have to
// use a sync mojo IPC to ask the browser process to call ftruncate() for us.
// On Mac, the default sandbox blocks ftruncate(), so we have to use a sync
// mojo IPC to ask the browser process to call ftruncate() for us.
//
// TODO(pwnall): Figure out if we can allow ftruncate() in the renderer. It
// would be useful for low-level storage APIs, like the upcoming
// filesystem API.
if (!WebDatabaseHost::GetInstance().SetFileSize(file_name_, size))
return SQLITE_IOERR_TRUNCATE;
// TODO(crbug.com/1084565): Figure out if we can allow ftruncate() in renderer
// and utility processes. It would be useful for low-level storage APIs, like
// the upcoming filesystem API.
if (vfs_->delegate()->SetFileLength(file_path_, file_,
static_cast<size_t>(size))) {
return SQLITE_OK;
}
return SQLITE_OK;
return SQLITE_IOERR_TRUNCATE;
}
int SandboxedVfsFile::Sync(int flags) {
......@@ -508,28 +509,28 @@ int SandboxedVfsFile::Unfetch(sqlite3_int64 offset, void* fetch_result) {
}
SandboxedVfsFile::SandboxedVfsFile(base::File file,
String file_name,
base::FilePath file_path,
SandboxedVfs* vfs)
: file_(std::move(file)),
sqlite_lock_mode_(SQLITE_LOCK_NONE),
vfs_(vfs),
file_name_(std::move(file_name)) {}
file_path_(std::move(file_path)) {}
SandboxedVfsFile::~SandboxedVfsFile() = default;
// static
SandboxedVfsFileSqliteBridge* SandboxedVfsFileSqliteBridge::FromSqliteFile(
sqlite3_file* sqlite_file) {
SandboxedVfsFileSqliteBridge& SandboxedVfsFileSqliteBridge::FromSqliteFile(
sqlite3_file& sqlite_file) {
static_assert(std::is_standard_layout<SandboxedVfsFileSqliteBridge>::value,
"needed for the reinterpret_cast below");
static_assert(offsetof(SandboxedVfsFileSqliteBridge, sqlite_file) == 0,
"sqlite_file must be the first member of the struct.");
SandboxedVfsFileSqliteBridge* bridge =
reinterpret_cast<SandboxedVfsFileSqliteBridge*>(sqlite_file);
DCHECK_EQ(sqlite_file, &bridge->sqlite_file)
SandboxedVfsFileSqliteBridge& bridge =
reinterpret_cast<SandboxedVfsFileSqliteBridge&>(sqlite_file);
DCHECK_EQ(&sqlite_file, &bridge.sqlite_file)
<< "assumed by the reinterpret_casts in the implementation";
return bridge;
}
} // namespace blink
} // namespace sql
......@@ -2,20 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBDATABASE_SQLITE_SANDBOXED_VFS_FILE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBDATABASE_SQLITE_SANDBOXED_VFS_FILE_H_
#ifndef SQL_SANDBOXED_VFS_FILE_H_
#define SQL_SANDBOXED_VFS_FILE_H_
#include "base/files/file.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "base/files/file_path.h"
#include "third_party/sqlite/sqlite3.h"
namespace blink {
namespace sql {
class SandboxedVfs;
class SandboxedVfsFile;
// SQLite VFS file implementation that works in the Chrome renderer sandbox.
// SQLite VFS file implementation that works in a typical Chromium sandbox.
//
// An instance is created when SQLite calls into SandboxedVfs::Open(). The
// instance is deleted by a call to SandboxedVfsFile::Close().
......@@ -32,17 +30,16 @@ class SandboxedVfsFile;
// SQLite's built-in VFSes use the OS support for locking a range of bytes in
// the file, rather locking than the whole file.
class SandboxedVfsFile {
USING_FAST_MALLOC(SandboxedVfsFile);
public:
// Creates an instance in the given buffer.
// Creates an instance in the given buffer. Note that `vfs` MUST outlive the
// returned sqlite3_file object.
static void Create(base::File file,
String file_name,
base::FilePath file_path,
SandboxedVfs* vfs,
sqlite3_file* buffer);
sqlite3_file& buffer);
// Extracts the instance bridged to the given SQLite VFS file.
static SandboxedVfsFile* FromSqliteFile(sqlite3_file* sqlite_file);
static SandboxedVfsFile& FromSqliteFile(sqlite3_file& sqlite_file);
// sqlite3_file implementation.
int Close();
......@@ -68,7 +65,9 @@ class SandboxedVfsFile {
int Unfetch(sqlite3_int64 offset, void* fetch_result);
private:
SandboxedVfsFile(base::File file, String file_name, SandboxedVfs* vfs);
SandboxedVfsFile(base::File file,
base::FilePath file_path,
SandboxedVfs* vfs);
~SandboxedVfsFile();
// Constructed from a file handle passed from the browser process.
......@@ -78,18 +77,18 @@ class SandboxedVfsFile {
// The SandboxedVfs that created this instance.
SandboxedVfs* const vfs_;
// Used to identify the file in IPCs to the browser process.
const String file_name_;
const base::FilePath file_path_;
};
// sqlite3_file "subclass" that bridges to a SandboxedVfsFile instance.
struct SandboxedVfsFileSqliteBridge {
sqlite3_file sqlite_file;
SandboxedVfsFile* blink_file;
SandboxedVfsFile* sandboxed_vfs_file;
static SandboxedVfsFileSqliteBridge* FromSqliteFile(
sqlite3_file* sqlite_file);
static SandboxedVfsFileSqliteBridge& FromSqliteFile(
sqlite3_file& sqlite_file);
};
} // namespace blink
} // namespace sql
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBDATABASE_SQLITE_SANDBOXED_VFS_FILE_H_
#endif // SQL_SANDBOXED_VFS_FILE_H_
......@@ -56,10 +56,8 @@ blink_modules_sources("webdatabase") {
"sql_transaction_state.h",
"sql_transaction_state_machine.cc",
"sql_transaction_state_machine.h",
"sqlite/sandboxed_vfs.cc",
"sqlite/sandboxed_vfs.h",
"sqlite/sandboxed_vfs_file.cc",
"sqlite/sandboxed_vfs_file.h",
"sqlite/sandboxed_vfs_delegate.cc",
"sqlite/sandboxed_vfs_delegate.h",
"sqlite/sql_log.h",
"sqlite/sql_value.cc",
"sqlite/sql_value.h",
......
include_rules = [
"+base/files/file.h",
"+base/files/file_path.h",
"+base/threading/platform_thread.h",
"+sql/initialization.h",
"+sql/sandboxed_vfs.h",
"+third_party/sqlite/sqlite3.h",
]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBDATABASE_SQLITE_SANDBOXED_VFS_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBDATABASE_SQLITE_SANDBOXED_VFS_H_
#include <tuple>
#include "base/files/file.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/sqlite/sqlite3.h"
namespace blink {
class Platform;
// SQLite VFS implementation that works in the Chrome renderer sandbox.
//
// Instances are thread-friendly, and expected to be used on Blink's database
// thread.
class SandboxedVfs {
USING_FAST_MALLOC(SandboxedVfs);
public:
// Factory method for the singleton instance.
static SandboxedVfs& GetInstance();
~SandboxedVfs() = delete;
// Opens a database file.
//
// Returns a SQLite status and a SQLite connection. If the status is not
// SQLITE_OK, the returned connection is null.
std::tuple<int, sqlite3*> OpenDatabase(const String& filename);
// sqlite3_vfs implementation.
int Open(const char* full_path,
sqlite3_file* result_file,
int requested_flags,
int* granted_flags);
int Delete(const char* full_path, int sync_dir);
int Access(const char* full_path, int flags, int* result);
int FullPathname(const char* file_path, int result_size, char* result);
int Randomness(int result_size, char* result);
int Sleep(int microseconds);
int GetLastError(int message_size, char* message) const;
int CurrentTimeInt64(sqlite3_int64* result_ms);
// Used by SandboxedVfsFile.
Platform* GetPlatform() { return platform_; }
void SetLastError(base::File::Error error) { this->last_error_ = error; }
private:
// Use GetInstance() instead of constructing this directly.
SandboxedVfs();
// Registers the VFS with SQLite. Failures are silently ignored.
void RegisterVfs();
sqlite3_vfs sandboxed_vfs_;
const base::Time sqlite_epoch_;
Platform* const platform_;
base::File::Error last_error_;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBDATABASE_SQLITE_SANDBOXED_VFS_H_
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/modules/webdatabase/sqlite/sandboxed_vfs_delegate.h"
#include <tuple>
#include "base/check_op.h"
#include "base/files/file_path.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/modules/webdatabase/web_database_host.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#if defined(OS_WIN)
#include <windows.h>
#endif
namespace blink {
namespace {
// Converts a SQLite full file path to a Blink string.
//
// The argument is guaranteed to be the result of a FullPathname() call, with
// an optional suffix. The suffix always starts with "-".
String StringFromFullPath(const base::FilePath& file_path) {
return String::FromUTF8(file_path.AsUTF8Unsafe());
}
} // namespace
SandboxedVfsDelegate::SandboxedVfsDelegate() = default;
SandboxedVfsDelegate::~SandboxedVfsDelegate() = default;
base::File SandboxedVfsDelegate::OpenFile(const base::FilePath& file_path,
int sqlite_requested_flags) {
DCHECK(!file_path.empty())
<< "WebSQL does not support creating temporary file names";
DCHECK_EQ(0, sqlite_requested_flags & SQLITE_OPEN_DELETEONCLOSE)
<< "SQLITE_OPEN_DELETEONCLOSE should not be used by WebSQL";
DCHECK_EQ(0, sqlite_requested_flags & SQLITE_OPEN_EXCLUSIVE)
<< "SQLITE_OPEN_EXCLUSIVE should not be used by WebSQL";
String file_name = StringFromFullPath(file_path);
return WebDatabaseHost::GetInstance().OpenFile(file_name,
sqlite_requested_flags);
}
int SandboxedVfsDelegate::DeleteFile(const base::FilePath& file_path,
bool sync_dir) {
return WebDatabaseHost::GetInstance().DeleteFile(
StringFromFullPath(file_path), sync_dir);
}
base::Optional<sql::SandboxedVfs::PathAccessInfo>
SandboxedVfsDelegate::GetPathAccess(const base::FilePath& file_path) {
int32_t attributes = WebDatabaseHost::GetInstance().GetFileAttributes(
StringFromFullPath(file_path));
// TODO(pwnall): Make the mojo interface portable across OSes, instead of
// messing around with OS-dependent constants here.
#if defined(OS_WIN)
const bool file_exists =
static_cast<DWORD>(attributes) != INVALID_FILE_ATTRIBUTES;
#else
const bool file_exists = attributes >= 0;
#endif // defined(OS_WIN)
if (!file_exists)
return base::nullopt;
sql::SandboxedVfs::PathAccessInfo access;
#if defined(OS_WIN)
access.can_read = true;
access.can_write = (attributes & FILE_ATTRIBUTE_READONLY) == 0;
#else
access.can_read = (attributes & R_OK) != 0;
access.can_write = (attributes & W_OK) != 0;
#endif // defined(OS_WIN)
return access;
}
bool SandboxedVfsDelegate::SetFileLength(const base::FilePath& file_path,
base::File& file,
size_t size) {
return WebDatabaseHost::GetInstance().SetFileSize(
StringFromFullPath(file_path), size);
}
} // namespace blink
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBDATABASE_SQLITE_SANDBOXED_VFS_DELEGATE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBDATABASE_SQLITE_SANDBOXED_VFS_DELEGATE_H_
#include "sql/sandboxed_vfs.h"
namespace blink {
class SandboxedVfsDelegate : public sql::SandboxedVfs::Delegate {
public:
SandboxedVfsDelegate();
~SandboxedVfsDelegate() override;
// sql::SandboxedVfs::Delegate implementation:
base::File OpenFile(const base::FilePath& file_path,
int sqlite_requested_flags) override;
int DeleteFile(const base::FilePath& file_path, bool sync_dir) override;
base::Optional<sql::SandboxedVfs::PathAccessInfo> GetPathAccess(
const base::FilePath& file_path) override;
bool SetFileLength(const base::FilePath& file_path,
base::File& file,
size_t size) override;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBDATABASE_SQLITE_SANDBOXED_VFS_DELEGATE_H_
......@@ -27,14 +27,41 @@
#include "third_party/blink/renderer/modules/webdatabase/sqlite/sqlite_database.h"
#include "base/notreached.h"
#include "sql/sandboxed_vfs.h"
#include "third_party/blink/renderer/modules/webdatabase/database_authorizer.h"
#include "third_party/blink/renderer/modules/webdatabase/sqlite/sandboxed_vfs.h"
#include "third_party/blink/renderer/modules/webdatabase/sqlite/sandboxed_vfs_delegate.h"
#include "third_party/blink/renderer/modules/webdatabase/sqlite/sql_log.h"
#include "third_party/blink/renderer/modules/webdatabase/sqlite/sqlite_statement.h"
#include "third_party/sqlite/sqlite3.h"
namespace blink {
namespace {
constexpr char kSqliteVfsName[] = "renderer_sandboxed_vfs";
std::tuple<int, sqlite3*> OpenDatabase(const String& filename) {
sql::SandboxedVfs::Register(kSqliteVfsName,
std::make_unique<SandboxedVfsDelegate>(),
/*make_default=*/false);
sqlite3* connection;
constexpr int open_flags =
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_PRIVATECACHE;
int status = sqlite3_open_v2(filename.Utf8().c_str(), &connection, open_flags,
kSqliteVfsName);
if (status != SQLITE_OK) {
// SQLite creates a connection handle in most cases where open fails.
if (connection) {
sqlite3_close(connection);
connection = nullptr;
}
}
return {status, connection};
}
} // namespace
const int kSQLResultDone = SQLITE_DONE;
const int kSQLResultOk = SQLITE_OK;
const int kSQLResultRow = SQLITE_ROW;
......@@ -61,8 +88,11 @@ SQLiteDatabase::~SQLiteDatabase() {
bool SQLiteDatabase::Open(const String& filename) {
Close();
std::tie(open_error_, db_) =
SandboxedVfs::GetInstance().OpenDatabase(filename);
// TODO(pwnall): This doesn't have to be synchronous. WebSQL's open sequence
// is asynchronous, so we could open all the needed files (DB,
// journal, etc.) asynchronously, and store them in a hash table
// that would be used here.
std::tie(open_error_, db_) = OpenDatabase(filename);
if (open_error_ != SQLITE_OK) {
DCHECK_EQ(db_, nullptr);
......
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