OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "webkit/fileapi/file_system_origin_database.h" |
| 6 |
| 7 #include "base/logging.h" |
| 8 #include "base/string_number_conversions.h" |
| 9 #include "base/string_util.h" |
| 10 #include "base/sys_string_conversions.h" |
| 11 #include "third_party/leveldb/include/leveldb/iterator.h" |
| 12 #include "third_party/leveldb/include/leveldb/write_batch.h" |
| 13 |
| 14 namespace { |
| 15 |
| 16 const char kOriginKeyPrefix[] = "ORIGIN:"; |
| 17 const char kLastPathKey[] = "LAST_PATH"; |
| 18 |
| 19 std::string OriginToOriginKey(const std::string& origin) { |
| 20 std::string key(kOriginKeyPrefix); |
| 21 return key + origin; |
| 22 } |
| 23 |
| 24 const char* LastPathKey() { |
| 25 return kLastPathKey; |
| 26 } |
| 27 |
| 28 } |
| 29 |
| 30 namespace fileapi { |
| 31 |
| 32 FileSystemOriginDatabase::FileSystemOriginDatabase(const FilePath& path) { |
| 33 #if defined(OS_POSIX) |
| 34 path_ = path.value(); |
| 35 #elif defined(OS_WIN) |
| 36 path_ = base::SysWideToUTF8(path.value()); |
| 37 #endif |
| 38 } |
| 39 |
| 40 FileSystemOriginDatabase::~FileSystemOriginDatabase() { |
| 41 } |
| 42 |
| 43 bool FileSystemOriginDatabase::Init() { |
| 44 if (db_.get()) |
| 45 return true; |
| 46 |
| 47 leveldb::Options options; |
| 48 options.create_if_missing = true; |
| 49 leveldb::DB* db; |
| 50 leveldb::Status status = leveldb::DB::Open(options, path_, &db); |
| 51 if (status.ok()) { |
| 52 db_.reset(db); |
| 53 return true; |
| 54 } |
| 55 HandleError(status); |
| 56 return false; |
| 57 } |
| 58 |
| 59 void FileSystemOriginDatabase::HandleError(leveldb::Status status) { |
| 60 db_.reset(); |
| 61 LOG(ERROR) << "FileSystemOriginDatabase failed with error: " << |
| 62 status.ToString(); |
| 63 } |
| 64 |
| 65 bool FileSystemOriginDatabase::HasOriginPath(const std::string& origin) { |
| 66 if (!Init()) |
| 67 return false; |
| 68 if (origin.empty()) |
| 69 return false; |
| 70 std::string path; |
| 71 leveldb::Status status = |
| 72 db_->Get(leveldb::ReadOptions(), OriginToOriginKey(origin), &path); |
| 73 if (status.ok()) |
| 74 return true; |
| 75 if (status.IsNotFound()) |
| 76 return false; |
| 77 HandleError(status); |
| 78 return false; |
| 79 } |
| 80 |
| 81 bool FileSystemOriginDatabase::GetPathForOrigin( |
| 82 const std::string& origin, FilePath* directory) { |
| 83 if (!Init()) |
| 84 return false; |
| 85 DCHECK(directory); |
| 86 if (origin.empty()) |
| 87 return false; |
| 88 std::string path_string; |
| 89 std::string origin_key = OriginToOriginKey(origin); |
| 90 leveldb::Status status = |
| 91 db_->Get(leveldb::ReadOptions(), origin_key, &path_string); |
| 92 if (status.IsNotFound()) { |
| 93 int last_path_number; |
| 94 if (!GetLastPathNumber(&last_path_number)) |
| 95 return false; |
| 96 path_string = base::IntToString(last_path_number + 1); |
| 97 // store both back as a single transaction |
| 98 leveldb::WriteBatch batch; |
| 99 batch.Put(LastPathKey(), path_string); |
| 100 batch.Put(origin_key, path_string); |
| 101 status = db_->Write(leveldb::WriteOptions(), &batch); |
| 102 if (!status.ok()) { |
| 103 HandleError(status); |
| 104 return false; |
| 105 } |
| 106 } |
| 107 if (status.ok()) { |
| 108 #if defined(OS_POSIX) |
| 109 *directory = FilePath(path_string); |
| 110 #elif defined(OS_WIN) |
| 111 *directory = FilePath(base::SysUTF8ToWide(path_string)); |
| 112 #endif |
| 113 return true; |
| 114 } |
| 115 HandleError(status); |
| 116 return false; |
| 117 } |
| 118 |
| 119 bool FileSystemOriginDatabase::RemovePathForOrigin(const std::string& origin) { |
| 120 if (!Init()) |
| 121 return false; |
| 122 leveldb::Status status = |
| 123 db_->Delete(leveldb::WriteOptions(), OriginToOriginKey(origin)); |
| 124 if (status.ok() || status.IsNotFound()) |
| 125 return true; |
| 126 HandleError(status); |
| 127 return false; |
| 128 } |
| 129 |
| 130 bool FileSystemOriginDatabase::ListAllOrigins( |
| 131 std::vector<OriginRecord>* origins) { |
| 132 if (!Init()) |
| 133 return false; |
| 134 DCHECK(origins); |
| 135 scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(leveldb::ReadOptions())); |
| 136 std::string origin_key_prefix = OriginToOriginKey(""); |
| 137 iter->Seek(origin_key_prefix); |
| 138 origins->clear(); |
| 139 while(iter->Valid() && |
| 140 StartsWithASCII(iter->key().ToString(), origin_key_prefix, true)) { |
| 141 std::string origin = |
| 142 iter->key().ToString().substr(origin_key_prefix.length()); |
| 143 #if defined(OS_POSIX) |
| 144 FilePath path = FilePath(iter->value().ToString()); |
| 145 #elif defined(OS_WIN) |
| 146 FilePath path = FilePath(base::SysUTF8ToWide(iter->value().ToString())); |
| 147 #endif |
| 148 origins->push_back(OriginRecord(origin, path)); |
| 149 iter->Next(); |
| 150 } |
| 151 return true; |
| 152 } |
| 153 |
| 154 void FileSystemOriginDatabase::DropDatabase() { |
| 155 db_.reset(); |
| 156 } |
| 157 |
| 158 bool FileSystemOriginDatabase::GetLastPathNumber(int* number) { |
| 159 if (!Init()) |
| 160 return false; |
| 161 DCHECK(number); |
| 162 std::string number_string; |
| 163 leveldb::Status status = |
| 164 db_->Get(leveldb::ReadOptions(), LastPathKey(), &number_string); |
| 165 if (status.ok()) |
| 166 return base::StringToInt(number_string, number); |
| 167 if (!status.IsNotFound()) { |
| 168 HandleError(status); |
| 169 return false; |
| 170 } |
| 171 // Verify that this is a totally new database, and initialize it. |
| 172 scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(leveldb::ReadOptions())); |
| 173 iter->SeekToFirst(); |
| 174 if (iter->Valid()) { // DB was not empty, but had no last path number! |
| 175 LOG(ERROR) << "File system origin database is corrupt!"; |
| 176 return false; |
| 177 } |
| 178 // This is always the first write into the database. If we ever add a |
| 179 // version number, they should go in in a single transaction. |
| 180 status = |
| 181 db_->Put(leveldb::WriteOptions(), LastPathKey(), std::string("-1")); |
| 182 if (!status.ok()) { |
| 183 HandleError(status); |
| 184 return false; |
| 185 } |
| 186 *number = -1; |
| 187 return true; |
| 188 } |
| 189 |
| 190 } // namespace fileapi |
OLD | NEW |