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 |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a559c1bf1662f5f8bca80c7b98f32beb307f5b67 |
--- /dev/null |
+++ b/webkit/fileapi/file_system_origin_database.cc |
@@ -0,0 +1,190 @@ |
+// Copyright (c) 2011 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/fileapi/file_system_origin_database.h" |
+ |
+#include "base/logging.h" |
+#include "base/string_number_conversions.h" |
+#include "base/string_util.h" |
+#include "base/sys_string_conversions.h" |
+#include "third_party/leveldb/include/leveldb/iterator.h" |
+#include "third_party/leveldb/include/leveldb/write_batch.h" |
+ |
+namespace { |
+ |
+const char kOriginKeyPrefix[] = "ORIGIN:"; |
+const char kLastPathKey[] = "LAST_PATH"; |
+ |
+std::string OriginToOriginKey(const std::string& origin) { |
+ std::string key(kOriginKeyPrefix); |
+ return key + origin; |
+} |
+ |
+const char* LastPathKey() { |
+ return kLastPathKey; |
+} |
+ |
+} |
+ |
+namespace fileapi { |
+ |
+FileSystemOriginDatabase::FileSystemOriginDatabase(const FilePath& path) { |
+#if defined(OS_POSIX) |
+ path_ = path.value(); |
+#elif defined(OS_WIN) |
+ path_ = base::SysWideToUTF8(path.value()); |
+#endif |
+} |
+ |
+FileSystemOriginDatabase::~FileSystemOriginDatabase() { |
+} |
+ |
+bool FileSystemOriginDatabase::Init() { |
+ if (db_.get()) |
+ return true; |
+ |
+ leveldb::Options options; |
+ options.create_if_missing = true; |
+ leveldb::DB* db; |
+ leveldb::Status status = leveldb::DB::Open(options, path_, &db); |
+ if (status.ok()) { |
+ db_.reset(db); |
+ return true; |
+ } |
+ HandleError(status); |
+ return false; |
+} |
+ |
+void FileSystemOriginDatabase::HandleError(leveldb::Status status) { |
+ db_.reset(); |
+ LOG(ERROR) << "FileSystemOriginDatabase failed with error: " << |
+ status.ToString(); |
+} |
+ |
+bool FileSystemOriginDatabase::HasOriginPath(const std::string& origin) { |
+ if (!Init()) |
+ 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(status); |
+ return false; |
+} |
+ |
+bool FileSystemOriginDatabase::GetPathForOrigin( |
+ const std::string& origin, FilePath* directory) { |
+ if (!Init()) |
+ 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::IntToString(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(status); |
+ return false; |
+ } |
+ } |
+ if (status.ok()) { |
+#if defined(OS_POSIX) |
+ *directory = FilePath(path_string); |
+#elif defined(OS_WIN) |
+ *directory = FilePath(base::SysUTF8ToWide(path_string)); |
+#endif |
+ return true; |
+ } |
+ HandleError(status); |
+ return false; |
+} |
+ |
+bool FileSystemOriginDatabase::RemovePathForOrigin(const std::string& origin) { |
+ if (!Init()) |
+ return false; |
+ leveldb::Status status = |
+ db_->Delete(leveldb::WriteOptions(), OriginToOriginKey(origin)); |
+ if (status.ok() || status.IsNotFound()) |
+ return true; |
+ HandleError(status); |
+ return false; |
+} |
+ |
+bool FileSystemOriginDatabase::ListAllOrigins( |
+ std::vector<OriginRecord>* origins) { |
+ if (!Init()) |
+ return false; |
+ DCHECK(origins); |
+ scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(leveldb::ReadOptions())); |
+ std::string origin_key_prefix = OriginToOriginKey(""); |
+ 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()); |
+#if defined(OS_POSIX) |
+ FilePath path = FilePath(iter->value().ToString()); |
+#elif defined(OS_WIN) |
+ FilePath path = FilePath(base::SysUTF8ToWide(iter->value().ToString())); |
+#endif |
+ origins->push_back(OriginRecord(origin, path)); |
+ iter->Next(); |
+ } |
+ return true; |
+} |
+ |
+void FileSystemOriginDatabase::DropDatabase() { |
+ db_.reset(); |
+} |
+ |
+bool FileSystemOriginDatabase::GetLastPathNumber(int* number) { |
+ if (!Init()) |
+ return false; |
+ 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(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(status); |
+ return false; |
+ } |
+ *number = -1; |
+ return true; |
+} |
+ |
+} // namespace fileapi |