Index: webkit/browser/fileapi/sandbox_origin_database.cc |
diff --git a/webkit/browser/fileapi/sandbox_origin_database.cc b/webkit/browser/fileapi/sandbox_origin_database.cc |
deleted file mode 100644 |
index d65e9598b0a425df00b6925b6cf028d9cd301915..0000000000000000000000000000000000000000 |
--- a/webkit/browser/fileapi/sandbox_origin_database.cc |
+++ /dev/null |
@@ -1,347 +0,0 @@ |
-// Copyright (c) 2012 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 "webkit/browser/fileapi/sandbox_origin_database.h" |
- |
-#include <set> |
-#include <utility> |
- |
-#include "base/file_util.h" |
-#include "base/files/file_enumerator.h" |
-#include "base/format_macros.h" |
-#include "base/location.h" |
-#include "base/logging.h" |
-#include "base/metrics/histogram.h" |
-#include "base/strings/string_number_conversions.h" |
-#include "base/strings/string_util.h" |
-#include "base/strings/stringprintf.h" |
-#include "third_party/leveldatabase/src/include/leveldb/db.h" |
-#include "third_party/leveldatabase/src/include/leveldb/write_batch.h" |
-#include "webkit/common/fileapi/file_system_util.h" |
- |
-namespace { |
- |
-const base::FilePath::CharType kOriginDatabaseName[] = |
- FILE_PATH_LITERAL("Origins"); |
-const char kOriginKeyPrefix[] = "ORIGIN:"; |
-const char kLastPathKey[] = "LAST_PATH"; |
-const int64 kMinimumReportIntervalHours = 1; |
-const char kInitStatusHistogramLabel[] = "FileSystem.OriginDatabaseInit"; |
-const char kDatabaseRepairHistogramLabel[] = "FileSystem.OriginDatabaseRepair"; |
- |
-enum InitStatus { |
- INIT_STATUS_OK = 0, |
- INIT_STATUS_CORRUPTION, |
- INIT_STATUS_IO_ERROR, |
- INIT_STATUS_UNKNOWN_ERROR, |
- INIT_STATUS_MAX |
-}; |
- |
-enum RepairResult { |
- DB_REPAIR_SUCCEEDED = 0, |
- DB_REPAIR_FAILED, |
- DB_REPAIR_MAX |
-}; |
- |
-std::string OriginToOriginKey(const std::string& origin) { |
- std::string key(kOriginKeyPrefix); |
- return key + origin; |
-} |
- |
-const char* LastPathKey() { |
- return kLastPathKey; |
-} |
- |
-} // namespace |
- |
-namespace storage { |
- |
-SandboxOriginDatabase::SandboxOriginDatabase( |
- const base::FilePath& file_system_directory, |
- leveldb::Env* env_override) |
- : file_system_directory_(file_system_directory), |
- env_override_(env_override) { |
-} |
- |
-SandboxOriginDatabase::~SandboxOriginDatabase() { |
-} |
- |
-bool SandboxOriginDatabase::Init(InitOption init_option, |
- RecoveryOption recovery_option) { |
- if (db_) |
- return true; |
- |
- base::FilePath db_path = GetDatabasePath(); |
- if (init_option == FAIL_IF_NONEXISTENT && !base::PathExists(db_path)) |
- return false; |
- |
- std::string path = FilePathToString(db_path); |
- leveldb::Options options; |
- options.max_open_files = 0; // Use minimum. |
- options.create_if_missing = true; |
- if (env_override_) |
- options.env = env_override_; |
- leveldb::DB* db; |
- leveldb::Status status = leveldb::DB::Open(options, path, &db); |
- ReportInitStatus(status); |
- if (status.ok()) { |
- db_.reset(db); |
- return true; |
- } |
- HandleError(FROM_HERE, status); |
- |
- // Corruption due to missing necessary MANIFEST-* file causes IOError instead |
- // of Corruption error. |
- // Try to repair database even when IOError case. |
- if (!status.IsCorruption() && !status.IsIOError()) |
- return false; |
- |
- switch (recovery_option) { |
- case FAIL_ON_CORRUPTION: |
- return false; |
- case REPAIR_ON_CORRUPTION: |
- LOG(WARNING) << "Attempting to repair SandboxOriginDatabase."; |
- |
- if (RepairDatabase(path)) { |
- UMA_HISTOGRAM_ENUMERATION(kDatabaseRepairHistogramLabel, |
- DB_REPAIR_SUCCEEDED, DB_REPAIR_MAX); |
- LOG(WARNING) << "Repairing SandboxOriginDatabase completed."; |
- return true; |
- } |
- UMA_HISTOGRAM_ENUMERATION(kDatabaseRepairHistogramLabel, |
- DB_REPAIR_FAILED, DB_REPAIR_MAX); |
- // fall through |
- case DELETE_ON_CORRUPTION: |
- if (!base::DeleteFile(file_system_directory_, true)) |
- return false; |
- if (!base::CreateDirectory(file_system_directory_)) |
- return false; |
- return Init(init_option, FAIL_ON_CORRUPTION); |
- } |
- NOTREACHED(); |
- return false; |
-} |
- |
-bool SandboxOriginDatabase::RepairDatabase(const std::string& db_path) { |
- DCHECK(!db_.get()); |
- leveldb::Options options; |
- options.max_open_files = 0; // Use minimum. |
- if (env_override_) |
- options.env = env_override_; |
- if (!leveldb::RepairDB(db_path, options).ok() || |
- !Init(FAIL_IF_NONEXISTENT, FAIL_ON_CORRUPTION)) { |
- LOG(WARNING) << "Failed to repair SandboxOriginDatabase."; |
- return false; |
- } |
- |
- // See if the repaired entries match with what we have on disk. |
- std::set<base::FilePath> directories; |
- base::FileEnumerator file_enum(file_system_directory_, |
- false /* recursive */, |
- base::FileEnumerator::DIRECTORIES); |
- base::FilePath path_each; |
- while (!(path_each = file_enum.Next()).empty()) |
- directories.insert(path_each.BaseName()); |
- std::set<base::FilePath>::iterator db_dir_itr = |
- directories.find(base::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<base::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<base::FilePath>::iterator dir_itr = directories.begin(); |
- dir_itr != directories.end(); |
- ++dir_itr) { |
- if (!base::DeleteFile(file_system_directory_.Append(*dir_itr), |
- true /* recursive */)) { |
- DropDatabase(); |
- return false; |
- } |
- } |
- |
- return true; |
-} |
- |
-void SandboxOriginDatabase::HandleError( |
- const tracked_objects::Location& from_here, |
- const leveldb::Status& status) { |
- db_.reset(); |
- LOG(ERROR) << "SandboxOriginDatabase failed at: " |
- << from_here.ToString() << " with error: " << status.ToString(); |
-} |
- |
-void SandboxOriginDatabase::ReportInitStatus(const leveldb::Status& status) { |
- base::Time now = base::Time::Now(); |
- base::TimeDelta minimum_interval = |
- base::TimeDelta::FromHours(kMinimumReportIntervalHours); |
- if (last_reported_time_ + minimum_interval >= now) |
- return; |
- last_reported_time_ = now; |
- |
- if (status.ok()) { |
- UMA_HISTOGRAM_ENUMERATION(kInitStatusHistogramLabel, |
- INIT_STATUS_OK, INIT_STATUS_MAX); |
- } else if (status.IsCorruption()) { |
- UMA_HISTOGRAM_ENUMERATION(kInitStatusHistogramLabel, |
- INIT_STATUS_CORRUPTION, INIT_STATUS_MAX); |
- } else if (status.IsIOError()) { |
- UMA_HISTOGRAM_ENUMERATION(kInitStatusHistogramLabel, |
- INIT_STATUS_IO_ERROR, INIT_STATUS_MAX); |
- } else { |
- UMA_HISTOGRAM_ENUMERATION(kInitStatusHistogramLabel, |
- INIT_STATUS_UNKNOWN_ERROR, INIT_STATUS_MAX); |
- } |
-} |
- |
-bool SandboxOriginDatabase::HasOriginPath(const std::string& origin) { |
- if (!Init(FAIL_IF_NONEXISTENT, REPAIR_ON_CORRUPTION)) |
- return false; |
- if (origin.empty()) |
- return false; |
- std::string path; |
- leveldb::Status status = |
- db_->Get(leveldb::ReadOptions(), OriginToOriginKey(origin), &path); |
- if (status.ok()) |
- return true; |
- if (status.IsNotFound()) |
- return false; |
- HandleError(FROM_HERE, status); |
- return false; |
-} |
- |
-bool SandboxOriginDatabase::GetPathForOrigin( |
- const std::string& origin, base::FilePath* directory) { |
- if (!Init(CREATE_IF_NONEXISTENT, REPAIR_ON_CORRUPTION)) |
- return false; |
- DCHECK(directory); |
- if (origin.empty()) |
- return false; |
- std::string path_string; |
- std::string origin_key = OriginToOriginKey(origin); |
- leveldb::Status status = |
- db_->Get(leveldb::ReadOptions(), origin_key, &path_string); |
- if (status.IsNotFound()) { |
- int last_path_number; |
- if (!GetLastPathNumber(&last_path_number)) |
- return false; |
- path_string = base::StringPrintf("%03u", last_path_number + 1); |
- // store both back as a single transaction |
- leveldb::WriteBatch batch; |
- batch.Put(LastPathKey(), path_string); |
- batch.Put(origin_key, path_string); |
- status = db_->Write(leveldb::WriteOptions(), &batch); |
- if (!status.ok()) { |
- HandleError(FROM_HERE, status); |
- return false; |
- } |
- } |
- if (status.ok()) { |
- *directory = StringToFilePath(path_string); |
- return true; |
- } |
- HandleError(FROM_HERE, status); |
- return false; |
-} |
- |
-bool SandboxOriginDatabase::RemovePathForOrigin(const std::string& origin) { |
- if (!Init(CREATE_IF_NONEXISTENT, REPAIR_ON_CORRUPTION)) |
- return false; |
- leveldb::Status status = |
- db_->Delete(leveldb::WriteOptions(), OriginToOriginKey(origin)); |
- if (status.ok() || status.IsNotFound()) |
- return true; |
- HandleError(FROM_HERE, status); |
- return false; |
-} |
- |
-bool SandboxOriginDatabase::ListAllOrigins( |
- std::vector<OriginRecord>* origins) { |
- DCHECK(origins); |
- if (!Init(CREATE_IF_NONEXISTENT, REPAIR_ON_CORRUPTION)) { |
- origins->clear(); |
- return false; |
- } |
- scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(leveldb::ReadOptions())); |
- std::string origin_key_prefix = OriginToOriginKey(std::string()); |
- iter->Seek(origin_key_prefix); |
- origins->clear(); |
- while (iter->Valid() && |
- StartsWithASCII(iter->key().ToString(), origin_key_prefix, true)) { |
- std::string origin = |
- iter->key().ToString().substr(origin_key_prefix.length()); |
- base::FilePath path = StringToFilePath(iter->value().ToString()); |
- origins->push_back(OriginRecord(origin, path)); |
- iter->Next(); |
- } |
- return true; |
-} |
- |
-void SandboxOriginDatabase::DropDatabase() { |
- db_.reset(); |
-} |
- |
-base::FilePath SandboxOriginDatabase::GetDatabasePath() const { |
- return file_system_directory_.Append(kOriginDatabaseName); |
-} |
- |
-void SandboxOriginDatabase::RemoveDatabase() { |
- DropDatabase(); |
- base::DeleteFile(GetDatabasePath(), true /* recursive */); |
-} |
- |
-bool SandboxOriginDatabase::GetLastPathNumber(int* number) { |
- DCHECK(db_); |
- DCHECK(number); |
- std::string number_string; |
- leveldb::Status status = |
- db_->Get(leveldb::ReadOptions(), LastPathKey(), &number_string); |
- if (status.ok()) |
- return base::StringToInt(number_string, number); |
- if (!status.IsNotFound()) { |
- HandleError(FROM_HERE, status); |
- return false; |
- } |
- // Verify that this is a totally new database, and initialize it. |
- scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(leveldb::ReadOptions())); |
- iter->SeekToFirst(); |
- if (iter->Valid()) { // DB was not empty, but had no last path number! |
- LOG(ERROR) << "File system origin database is corrupt!"; |
- return false; |
- } |
- // This is always the first write into the database. If we ever add a |
- // version number, they should go in in a single transaction. |
- status = |
- db_->Put(leveldb::WriteOptions(), LastPathKey(), std::string("-1")); |
- if (!status.ok()) { |
- HandleError(FROM_HERE, status); |
- return false; |
- } |
- *number = -1; |
- return true; |
-} |
- |
-} // namespace storage |