| 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 42205ed2a2b1fb14fd6b525e756f5116f336f650..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/files/file_enumerator.h"
|
| -#include "base/files/file_util.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
|
|
|