| Index: webkit/fileapi/file_system_origin_database.cc
|
| ===================================================================
|
| --- webkit/fileapi/file_system_origin_database.cc (revision 131715)
|
| +++ webkit/fileapi/file_system_origin_database.cc (working copy)
|
| @@ -4,6 +4,7 @@
|
|
|
| #include "webkit/fileapi/file_system_origin_database.h"
|
|
|
| +#include "base/file_util.h"
|
| #include "base/format_macros.h"
|
| #include "base/location.h"
|
| #include "base/logging.h"
|
| @@ -11,12 +12,13 @@
|
| #include "base/string_number_conversions.h"
|
| #include "base/stringprintf.h"
|
| #include "base/string_util.h"
|
| -#include "base/sys_string_conversions.h"
|
| #include "third_party/leveldatabase/src/include/leveldb/db.h"
|
| #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
|
| +#include "webkit/fileapi/file_system_util.h"
|
|
|
| namespace {
|
|
|
| +const FilePath::CharType kOriginDatabaseName[] = FILE_PATH_LITERAL("Origins");
|
| const char kOriginKeyPrefix[] = "ORIGIN:";
|
| const char kLastPathKey[] = "LAST_PATH";
|
| const int64 kMinimumReportIntervalHours = 1;
|
| @@ -52,34 +54,111 @@
|
| FileSystemOriginDatabase::OriginRecord::~OriginRecord() {
|
| }
|
|
|
| -FileSystemOriginDatabase::FileSystemOriginDatabase(const FilePath& path) {
|
| -#if defined(OS_POSIX)
|
| - path_ = path.value();
|
| -#elif defined(OS_WIN)
|
| - path_ = base::SysWideToUTF8(path.value());
|
| -#endif
|
| +FileSystemOriginDatabase::FileSystemOriginDatabase(
|
| + const FilePath& file_system_directory)
|
| + : file_system_directory_(file_system_directory) {
|
| }
|
|
|
| FileSystemOriginDatabase::~FileSystemOriginDatabase() {
|
| }
|
|
|
| -bool FileSystemOriginDatabase::Init() {
|
| +bool FileSystemOriginDatabase::Init(RecoveryOption recovery_option) {
|
| if (db_.get())
|
| return true;
|
|
|
| + std::string path =
|
| + FilePathToString(file_system_directory_.Append(kOriginDatabaseName));
|
| leveldb::Options options;
|
| options.create_if_missing = true;
|
| leveldb::DB* db;
|
| - leveldb::Status status = leveldb::DB::Open(options, path_, &db);
|
| + leveldb::Status status = leveldb::DB::Open(options, path, &db);
|
| ReportInitStatus(status);
|
| if (status.ok()) {
|
| db_.reset(db);
|
| return true;
|
| }
|
| HandleError(FROM_HERE, status);
|
| +
|
| + switch (recovery_option) {
|
| + case FAIL_ON_CORRUPTION:
|
| + return false;
|
| + case REPAIR_ON_CORRUPTION:
|
| + LOG(WARNING) << "Attempting to repair FileSystemOriginDatabase.";
|
| + if (RepairDatabase(path)) {
|
| + LOG(WARNING) << "Repairing FileSystemOriginDatabase completed.";
|
| + return true;
|
| + }
|
| + // fall through
|
| + case DELETE_ON_CORRUPTION:
|
| + if (!file_util::Delete(file_system_directory_, true))
|
| + return false;
|
| + if (!file_util::CreateDirectory(file_system_directory_))
|
| + return false;
|
| + return Init(FAIL_ON_CORRUPTION);
|
| + }
|
| + NOTREACHED();
|
| return false;
|
| }
|
|
|
| +bool FileSystemOriginDatabase::RepairDatabase(const std::string& db_path) {
|
| + DCHECK(!db_.get());
|
| + if (!leveldb::RepairDB(db_path, leveldb::Options()).ok() ||
|
| + !Init(FAIL_ON_CORRUPTION)) {
|
| + LOG(WARNING) << "Failed to repair FileSystemOriginDatabase.";
|
| + return false;
|
| + }
|
| +
|
| + // See if the repaired entries match with what we have on disk.
|
| + std::set<FilePath> directories;
|
| + file_util::FileEnumerator file_enum(file_system_directory_,
|
| + false /* recursive */,
|
| + file_util::FileEnumerator::DIRECTORIES);
|
| + FilePath path_each;
|
| + while (!(path_each = file_enum.Next()).empty())
|
| + directories.insert(path_each.BaseName());
|
| + std::set<FilePath>::iterator db_dir_itr =
|
| + directories.find(FilePath(kOriginDatabaseName));
|
| + // Make sure we have the database file in its directory and therefore we are
|
| + // working on the correct path.
|
| + DCHECK(db_dir_itr != directories.end());
|
| + directories.erase(db_dir_itr);
|
| +
|
| + std::vector<OriginRecord> origins;
|
| + if (!ListAllOrigins(&origins)) {
|
| + DropDatabase();
|
| + return false;
|
| + }
|
| +
|
| + // Delete any obsolete entries from the origins database.
|
| + for (std::vector<OriginRecord>::iterator db_origin_itr = origins.begin();
|
| + db_origin_itr != origins.end();
|
| + ++db_origin_itr) {
|
| + std::set<FilePath>::iterator dir_itr =
|
| + directories.find(db_origin_itr->path);
|
| + if (dir_itr == directories.end()) {
|
| + if (!RemovePathForOrigin(db_origin_itr->origin)) {
|
| + DropDatabase();
|
| + return false;
|
| + }
|
| + } else {
|
| + directories.erase(dir_itr);
|
| + }
|
| + }
|
| +
|
| + // Delete any directories not listed in the origins database.
|
| + for (std::set<FilePath>::iterator dir_itr = directories.begin();
|
| + dir_itr != directories.end();
|
| + ++dir_itr) {
|
| + if (!file_util::Delete(file_system_directory_.Append(*dir_itr),
|
| + true /* recursive */)) {
|
| + DropDatabase();
|
| + return false;
|
| + }
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| void FileSystemOriginDatabase::HandleError(
|
| const tracked_objects::Location& from_here,
|
| const leveldb::Status& status) {
|
| @@ -106,7 +185,7 @@
|
| }
|
|
|
| bool FileSystemOriginDatabase::HasOriginPath(const std::string& origin) {
|
| - if (!Init())
|
| + if (!Init(REPAIR_ON_CORRUPTION))
|
| return false;
|
| if (origin.empty())
|
| return false;
|
| @@ -123,7 +202,7 @@
|
|
|
| bool FileSystemOriginDatabase::GetPathForOrigin(
|
| const std::string& origin, FilePath* directory) {
|
| - if (!Init())
|
| + if (!Init(REPAIR_ON_CORRUPTION))
|
| return false;
|
| DCHECK(directory);
|
| if (origin.empty())
|
| @@ -148,11 +227,7 @@
|
| }
|
| }
|
| if (status.ok()) {
|
| -#if defined(OS_POSIX)
|
| - *directory = FilePath(path_string);
|
| -#elif defined(OS_WIN)
|
| - *directory = FilePath(base::SysUTF8ToWide(path_string));
|
| -#endif
|
| + *directory = StringToFilePath(path_string);
|
| return true;
|
| }
|
| HandleError(FROM_HERE, status);
|
| @@ -160,7 +235,7 @@
|
| }
|
|
|
| bool FileSystemOriginDatabase::RemovePathForOrigin(const std::string& origin) {
|
| - if (!Init())
|
| + if (!Init(REPAIR_ON_CORRUPTION))
|
| return false;
|
| leveldb::Status status =
|
| db_->Delete(leveldb::WriteOptions(), OriginToOriginKey(origin));
|
| @@ -172,7 +247,7 @@
|
|
|
| bool FileSystemOriginDatabase::ListAllOrigins(
|
| std::vector<OriginRecord>* origins) {
|
| - if (!Init())
|
| + if (!Init(REPAIR_ON_CORRUPTION))
|
| return false;
|
| DCHECK(origins);
|
| scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(leveldb::ReadOptions()));
|
| @@ -183,11 +258,7 @@
|
| StartsWithASCII(iter->key().ToString(), origin_key_prefix, true)) {
|
| std::string origin =
|
| iter->key().ToString().substr(origin_key_prefix.length());
|
| -#if defined(OS_POSIX)
|
| - FilePath path = FilePath(iter->value().ToString());
|
| -#elif defined(OS_WIN)
|
| - FilePath path = FilePath(base::SysUTF8ToWide(iter->value().ToString()));
|
| -#endif
|
| + FilePath path = StringToFilePath(iter->value().ToString());
|
| origins->push_back(OriginRecord(origin, path));
|
| iter->Next();
|
| }
|
| @@ -199,7 +270,7 @@
|
| }
|
|
|
| bool FileSystemOriginDatabase::GetLastPathNumber(int* number) {
|
| - if (!Init())
|
| + if (!Init(REPAIR_ON_CORRUPTION))
|
| return false;
|
| DCHECK(number);
|
| std::string number_string;
|
|
|