Chromium Code Reviews| Index: webkit/fileapi/file_system_origin_database.cc |
| diff --git a/webkit/fileapi/file_system_origin_database.cc b/webkit/fileapi/file_system_origin_database.cc |
| index 125576ae38d1eda4f7dfeae35a63059f1b326c06..e0304f3409cb1cb4ffd77e3338bd3c5ac595dedd 100644 |
| --- a/webkit/fileapi/file_system_origin_database.cc |
| +++ b/webkit/fileapi/file_system_origin_database.cc |
| @@ -4,18 +4,21 @@ |
| #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" |
| #include "base/string_number_conversions.h" |
| #include "base/stringprintf.h" |
| #include "base/string_util.h" |
| -#include "base/sys_string_conversions.h" |
| +#include "base/utf_string_conversions.h" |
|
ericu
2012/03/26 18:39:18
Remove utf_string_conversions.h?
tzik
2012/03/27 02:44:18
Done.
|
| #include "third_party/leveldatabase/src/include/leveldb/iterator.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"; |
| @@ -43,33 +46,109 @@ FileSystemOriginDatabase::OriginRecord::OriginRecord( |
| 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); |
| + // TODO(tzik): Collect status metrics here. |
| 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; |
| + } |
|
ericu
2012/03/26 18:39:18
How about a comment here to match that below:
"De
tzik
2012/03/27 02:44:18
Done. Sounds good.
|
| + 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, leveldb::Status status) { |
| db_.reset(); |
| @@ -78,7 +157,7 @@ void FileSystemOriginDatabase::HandleError( |
| } |
| bool FileSystemOriginDatabase::HasOriginPath(const std::string& origin) { |
| - if (!Init()) |
| + if (!Init(REPAIR_ON_CORRUPTION)) |
| return false; |
| if (origin.empty()) |
| return false; |
| @@ -95,7 +174,7 @@ bool FileSystemOriginDatabase::HasOriginPath(const std::string& origin) { |
| bool FileSystemOriginDatabase::GetPathForOrigin( |
| const std::string& origin, FilePath* directory) { |
| - if (!Init()) |
| + if (!Init(REPAIR_ON_CORRUPTION)) |
| return false; |
| DCHECK(directory); |
| if (origin.empty()) |
| @@ -120,11 +199,7 @@ bool FileSystemOriginDatabase::GetPathForOrigin( |
| } |
| } |
| 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); |
| @@ -132,7 +207,7 @@ bool FileSystemOriginDatabase::GetPathForOrigin( |
| } |
| 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)); |
| @@ -144,7 +219,7 @@ bool FileSystemOriginDatabase::RemovePathForOrigin(const std::string& origin) { |
| 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())); |
| @@ -155,11 +230,7 @@ bool FileSystemOriginDatabase::ListAllOrigins( |
| 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(); |
| } |
| @@ -171,7 +242,7 @@ void FileSystemOriginDatabase::DropDatabase() { |
| } |
| bool FileSystemOriginDatabase::GetLastPathNumber(int* number) { |
| - if (!Init()) |
| + if (!Init(REPAIR_ON_CORRUPTION)) |
| return false; |
| DCHECK(number); |
| std::string number_string; |