1 // Copyright (c) 2013 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 #ifndef CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_BACKING_STORE_H_ 6 #define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_BACKING_STORE_H_ 7 8 #include <string> 9 #include <vector> 10 11 #include "base/basictypes.h" 12 #include "base/files/file_path.h" 13 #include "base/memory/ref_counted.h" 14 #include "base/memory/scoped_ptr.h" 15 #include "base/timer/timer.h" 16 #include "content/browser/indexed_db/indexed_db.h" 17 #include "content/browser/indexed_db/indexed_db_metadata.h" 18 #include "content/browser/indexed_db/leveldb/leveldb_iterator.h" 19 #include "content/browser/indexed_db/leveldb/leveldb_transaction.h" 20 #include "content/common/content_export.h" 21 #include "content/common/indexed_db/indexed_db_key.h" 22 #include "content/common/indexed_db/indexed_db_key_path.h" 23 #include "content/common/indexed_db/indexed_db_key_range.h" 24 #include "third_party/leveldatabase/src/include/leveldb/status.h" 25 #include "url/gurl.h" 26 27 namespace content { 28 29 class LevelDBComparator; 30 class LevelDBDatabase; 31 32 class LevelDBFactory { 33 public: 34 virtual ~LevelDBFactory() {} 35 virtual leveldb::Status OpenLevelDB(const base::FilePath& file_name, 36 const LevelDBComparator* comparator, 37 scoped_ptr<LevelDBDatabase>* db, 38 bool* is_disk_full) = 0; 39 virtual bool DestroyLevelDB(const base::FilePath& file_name) = 0; 40 }; 41 42 class CONTENT_EXPORT IndexedDBBackingStore 43 : public base::RefCounted<IndexedDBBackingStore> { 44 public: 45 class CONTENT_EXPORT Transaction; 46 47 const GURL& origin_url() const { return origin_url_; } 48 base::OneShotTimer<IndexedDBBackingStore>* close_timer() { 49 return &close_timer_; 50 } 51 52 static scoped_refptr<IndexedDBBackingStore> Open( 53 const GURL& origin_url, 54 const base::FilePath& path_base, 55 blink::WebIDBDataLoss* data_loss, 56 std::string* data_loss_message, 57 bool* disk_full); 58 59 static scoped_refptr<IndexedDBBackingStore> Open( 60 const GURL& origin_url, 61 const base::FilePath& path_base, 62 blink::WebIDBDataLoss* data_loss, 63 std::string* data_loss_message, 64 bool* disk_full, 65 LevelDBFactory* factory); 66 static scoped_refptr<IndexedDBBackingStore> OpenInMemory( 67 const GURL& origin_url); 68 static scoped_refptr<IndexedDBBackingStore> OpenInMemory( 69 const GURL& origin_url, 70 LevelDBFactory* factory); 71 72 virtual std::vector<base::string16> GetDatabaseNames(); 73 virtual bool GetIDBDatabaseMetaData(const base::string16& name, 74 IndexedDBDatabaseMetadata* metadata, 75 bool* success) WARN_UNUSED_RESULT; 76 virtual bool CreateIDBDatabaseMetaData(const base::string16& name, 77 const base::string16& version, 78 int64 int_version, 79 int64* row_id); 80 virtual bool UpdateIDBDatabaseIntVersion( 81 IndexedDBBackingStore::Transaction* transaction, 82 int64 row_id, 83 int64 int_version); 84 virtual bool DeleteDatabase(const base::string16& name); 85 86 bool GetObjectStores(int64 database_id, 87 IndexedDBDatabaseMetadata::ObjectStoreMap* map) 88 WARN_UNUSED_RESULT; 89 virtual bool CreateObjectStore( 90 IndexedDBBackingStore::Transaction* transaction, 91 int64 database_id, 92 int64 object_store_id, 93 const base::string16& name, 94 const IndexedDBKeyPath& key_path, 95 bool auto_increment); 96 virtual bool DeleteObjectStore( 97 IndexedDBBackingStore::Transaction* transaction, 98 int64 database_id, 99 int64 object_store_id) WARN_UNUSED_RESULT; 100 101 class CONTENT_EXPORT RecordIdentifier { 102 public: 103 RecordIdentifier(const std::string& primary_key, int64 version); 104 RecordIdentifier(); 105 ~RecordIdentifier(); 106 107 const std::string& primary_key() const { return primary_key_; } 108 int64 version() const { return version_; } 109 void Reset(const std::string& primary_key, int64 version) { 110 primary_key_ = primary_key; 111 version_ = version; 112 } 113 114 private: 115 // TODO(jsbell): Make it more clear that this is the *encoded* version of 116 // the key. 117 std::string primary_key_; 118 int64 version_; 119 DISALLOW_COPY_AND_ASSIGN(RecordIdentifier); 120 }; 121 122 virtual bool GetRecord(IndexedDBBackingStore::Transaction* transaction, 123 int64 database_id, 124 int64 object_store_id, 125 const IndexedDBKey& key, 126 std::string* record) WARN_UNUSED_RESULT; 127 virtual bool PutRecord(IndexedDBBackingStore::Transaction* transaction, 128 int64 database_id, 129 int64 object_store_id, 130 const IndexedDBKey& key, 131 const std::string& value, 132 RecordIdentifier* record) WARN_UNUSED_RESULT; 133 virtual bool ClearObjectStore(IndexedDBBackingStore::Transaction* transaction, 134 int64 database_id, 135 int64 object_store_id) WARN_UNUSED_RESULT; 136 virtual bool DeleteRecord(IndexedDBBackingStore::Transaction* transaction, 137 int64 database_id, 138 int64 object_store_id, 139 const RecordIdentifier& record) WARN_UNUSED_RESULT; 140 virtual bool GetKeyGeneratorCurrentNumber( 141 IndexedDBBackingStore::Transaction* transaction, 142 int64 database_id, 143 int64 object_store_id, 144 int64* current_number) WARN_UNUSED_RESULT; 145 virtual bool MaybeUpdateKeyGeneratorCurrentNumber( 146 IndexedDBBackingStore::Transaction* transaction, 147 int64 database_id, 148 int64 object_store_id, 149 int64 new_state, 150 bool check_current) WARN_UNUSED_RESULT; 151 virtual bool KeyExistsInObjectStore( 152 IndexedDBBackingStore::Transaction* transaction, 153 int64 database_id, 154 int64 object_store_id, 155 const IndexedDBKey& key, 156 RecordIdentifier* found_record_identifier, 157 bool* found) WARN_UNUSED_RESULT; 158 159 virtual bool CreateIndex(IndexedDBBackingStore::Transaction* transaction, 160 int64 database_id, 161 int64 object_store_id, 162 int64 index_id, 163 const base::string16& name, 164 const IndexedDBKeyPath& key_path, 165 bool is_unique, 166 bool is_multi_entry) WARN_UNUSED_RESULT; 167 virtual bool DeleteIndex(IndexedDBBackingStore::Transaction* transaction, 168 int64 database_id, 169 int64 object_store_id, 170 int64 index_id) WARN_UNUSED_RESULT; 171 virtual bool PutIndexDataForRecord( 172 IndexedDBBackingStore::Transaction* transaction, 173 int64 database_id, 174 int64 object_store_id, 175 int64 index_id, 176 const IndexedDBKey& key, 177 const RecordIdentifier& record) WARN_UNUSED_RESULT; 178 virtual bool GetPrimaryKeyViaIndex( 179 IndexedDBBackingStore::Transaction* transaction, 180 int64 database_id, 181 int64 object_store_id, 182 int64 index_id, 183 const IndexedDBKey& key, 184 scoped_ptr<IndexedDBKey>* primary_key) WARN_UNUSED_RESULT; 185 virtual bool KeyExistsInIndex(IndexedDBBackingStore::Transaction* transaction, 186 int64 database_id, 187 int64 object_store_id, 188 int64 index_id, 189 const IndexedDBKey& key, 190 scoped_ptr<IndexedDBKey>* found_primary_key, 191 bool* exists) WARN_UNUSED_RESULT; 192 193 class Cursor { 194 public: 195 virtual ~Cursor(); 196 197 enum IteratorState { 198 READY = 0, 199 SEEK 200 }; 201 202 struct CursorOptions { 203 CursorOptions(); 204 ~CursorOptions(); 205 int64 database_id; 206 int64 object_store_id; 207 int64 index_id; 208 std::string low_key; 209 bool low_open; 210 std::string high_key; 211 bool high_open; 212 bool forward; 213 bool unique; 214 }; 215 216 const IndexedDBKey& key() const { return *current_key_; } 217 bool Continue() { return Continue(NULL, NULL, SEEK); } 218 bool Continue(const IndexedDBKey* key, IteratorState state) { 219 return Continue(key, NULL, state); 220 } 221 bool Continue(const IndexedDBKey* key, 222 const IndexedDBKey* primary_key, 223 IteratorState state); 224 bool Advance(uint32 count); 225 bool FirstSeek(); 226 227 virtual Cursor* Clone() = 0; 228 virtual const IndexedDBKey& primary_key() const; 229 virtual std::string* value() = 0; 230 virtual const RecordIdentifier& record_identifier() const; 231 virtual bool LoadCurrentRow() = 0; 232 233 protected: 234 Cursor(LevelDBTransaction* transaction, 235 const CursorOptions& cursor_options); 236 explicit Cursor(const IndexedDBBackingStore::Cursor* other); 237 238 virtual std::string EncodeKey(const IndexedDBKey& key) = 0; 239 virtual std::string EncodeKey(const IndexedDBKey& key, 240 const IndexedDBKey& primary_key) = 0; 241 242 bool IsPastBounds() const; 243 bool HaveEnteredRange() const; 244 245 LevelDBTransaction* transaction_; 246 const CursorOptions cursor_options_; 247 scoped_ptr<LevelDBIterator> iterator_; 248 scoped_ptr<IndexedDBKey> current_key_; 249 IndexedDBBackingStore::RecordIdentifier record_identifier_; 250 }; 251 252 virtual scoped_ptr<Cursor> OpenObjectStoreKeyCursor( 253 IndexedDBBackingStore::Transaction* transaction, 254 int64 database_id, 255 int64 object_store_id, 256 const IndexedDBKeyRange& key_range, 257 indexed_db::CursorDirection); 258 virtual scoped_ptr<Cursor> OpenObjectStoreCursor( 259 IndexedDBBackingStore::Transaction* transaction, 260 int64 database_id, 261 int64 object_store_id, 262 const IndexedDBKeyRange& key_range, 263 indexed_db::CursorDirection); 264 virtual scoped_ptr<Cursor> OpenIndexKeyCursor( 265 IndexedDBBackingStore::Transaction* transaction, 266 int64 database_id, 267 int64 object_store_id, 268 int64 index_id, 269 const IndexedDBKeyRange& key_range, 270 indexed_db::CursorDirection); 271 virtual scoped_ptr<Cursor> OpenIndexCursor( 272 IndexedDBBackingStore::Transaction* transaction, 273 int64 database_id, 274 int64 object_store_id, 275 int64 index_id, 276 const IndexedDBKeyRange& key_range, 277 indexed_db::CursorDirection); 278 279 class Transaction { 280 public: 281 explicit Transaction(IndexedDBBackingStore* backing_store); 282 virtual ~Transaction(); 283 virtual void Begin(); 284 virtual bool Commit(); 285 virtual void Rollback(); 286 void Reset() { 287 backing_store_ = NULL; 288 transaction_ = NULL; 289 } 290 291 LevelDBTransaction* transaction() { return transaction_; } 292 293 private: 294 IndexedDBBackingStore* backing_store_; 295 scoped_refptr<LevelDBTransaction> transaction_; 296 }; 297 298 protected: 299 IndexedDBBackingStore(const GURL& origin_url, 300 scoped_ptr<LevelDBDatabase> db, 301 scoped_ptr<LevelDBComparator> comparator); 302 virtual ~IndexedDBBackingStore(); 303 friend class base::RefCounted<IndexedDBBackingStore>; 304 305 private: 306 static scoped_refptr<IndexedDBBackingStore> Create( 307 const GURL& origin_url, 308 scoped_ptr<LevelDBDatabase> db, 309 scoped_ptr<LevelDBComparator> comparator); 310 311 bool FindKeyInIndex(IndexedDBBackingStore::Transaction* transaction, 312 int64 database_id, 313 int64 object_store_id, 314 int64 index_id, 315 const IndexedDBKey& key, 316 std::string* found_encoded_primary_key, 317 bool* found); 318 bool GetIndexes(int64 database_id, 319 int64 object_store_id, 320 IndexedDBObjectStoreMetadata::IndexMap* map) 321 WARN_UNUSED_RESULT; 322 323 const GURL origin_url_; 324 325 // The origin identifier is a key prefix unique to the origin used in the 326 // leveldb backing store to partition data by origin. It is a normalized 327 // version of the origin URL with a versioning suffix appended, e.g. 328 // "http_localhost_81@1" Since only one origin is stored per backing store 329 // this is redundant but necessary for backwards compatibility; the suffix 330 // provides for future flexibility. 331 const std::string origin_identifier_; 332 333 scoped_ptr<LevelDBDatabase> db_; 334 scoped_ptr<LevelDBComparator> comparator_; 335 base::OneShotTimer<IndexedDBBackingStore> close_timer_; 336 }; 337 338 } // namespace content 339 340 #endif // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_BACKING_STORE_H_ 341