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/memory/weak_ptr.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/WebKit/public/platform/WebIDBCallbacks.h"
25
26namespace content {
27
28class LevelDBComparator;
29class LevelDBDatabase;
30
31class LevelDBFactory {
32 public:
33  virtual ~LevelDBFactory() {}
34  virtual leveldb::Status OpenLevelDB(
35      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
42class CONTENT_EXPORT IndexedDBBackingStore
43    : public base::RefCounted<IndexedDBBackingStore> {
44 public:
45  class CONTENT_EXPORT Transaction;
46
47  static scoped_refptr<IndexedDBBackingStore> Open(
48      const std::string& origin_identifier,
49      const base::FilePath& path_base,
50      const std::string& file_identifier,
51      WebKit::WebIDBCallbacks::DataLoss* data_loss);
52
53  static scoped_refptr<IndexedDBBackingStore> Open(
54      const std::string& origin_identifier,
55      const base::FilePath& path_base,
56      const std::string& file_identifier,
57      WebKit::WebIDBCallbacks::DataLoss* data_loss,
58      LevelDBFactory* factory);
59  static scoped_refptr<IndexedDBBackingStore> OpenInMemory(
60      const std::string& file_identifier);
61  static scoped_refptr<IndexedDBBackingStore> OpenInMemory(
62      const std::string& file_identifier,
63      LevelDBFactory* factory);
64  base::WeakPtr<IndexedDBBackingStore> GetWeakPtr() {
65    return weak_factory_.GetWeakPtr();
66  }
67
68  virtual std::vector<string16> GetDatabaseNames();
69  virtual bool GetIDBDatabaseMetaData(const string16& name,
70                                      IndexedDBDatabaseMetadata* metadata,
71                                      bool* success) WARN_UNUSED_RESULT;
72  virtual bool CreateIDBDatabaseMetaData(const string16& name,
73                                         const string16& version,
74                                         int64 int_version,
75                                         int64* row_id);
76  virtual bool UpdateIDBDatabaseMetaData(
77      IndexedDBBackingStore::Transaction* transaction,
78      int64 row_id,
79      const string16& version);
80  virtual bool UpdateIDBDatabaseIntVersion(
81      IndexedDBBackingStore::Transaction* transaction,
82      int64 row_id,
83      int64 int_version);
84  virtual bool DeleteDatabase(const 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 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 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, SEEK); }
218    bool Continue(const IndexedDBKey* key, IteratorState state);
219    bool Advance(uint32 count);
220    bool FirstSeek();
221
222    virtual Cursor* Clone() = 0;
223    virtual const IndexedDBKey& primary_key() const;
224    virtual std::string* Value() = 0;
225    virtual const RecordIdentifier& record_identifier() const;
226    virtual bool LoadCurrentRow() = 0;
227
228   protected:
229    Cursor(LevelDBTransaction* transaction,
230           const CursorOptions& cursor_options);
231    explicit Cursor(const IndexedDBBackingStore::Cursor* other);
232
233    virtual std::string EncodeKey(const IndexedDBKey& key) = 0;
234
235    bool IsPastBounds() const;
236    bool HaveEnteredRange() const;
237
238    LevelDBTransaction* transaction_;
239    const CursorOptions cursor_options_;
240    scoped_ptr<LevelDBIterator> iterator_;
241    scoped_ptr<IndexedDBKey> current_key_;
242    IndexedDBBackingStore::RecordIdentifier record_identifier_;
243  };
244
245  virtual scoped_ptr<Cursor> OpenObjectStoreKeyCursor(
246      IndexedDBBackingStore::Transaction* transaction,
247      int64 database_id,
248      int64 object_store_id,
249      const IndexedDBKeyRange& key_range,
250      indexed_db::CursorDirection);
251  virtual scoped_ptr<Cursor> OpenObjectStoreCursor(
252      IndexedDBBackingStore::Transaction* transaction,
253      int64 database_id,
254      int64 object_store_id,
255      const IndexedDBKeyRange& key_range,
256      indexed_db::CursorDirection);
257  virtual scoped_ptr<Cursor> OpenIndexKeyCursor(
258      IndexedDBBackingStore::Transaction* transaction,
259      int64 database_id,
260      int64 object_store_id,
261      int64 index_id,
262      const IndexedDBKeyRange& key_range,
263      indexed_db::CursorDirection);
264  virtual scoped_ptr<Cursor> OpenIndexCursor(
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
272  class Transaction {
273   public:
274    explicit Transaction(IndexedDBBackingStore* backing_store);
275    ~Transaction();
276    void Begin();
277    bool Commit();
278    void Rollback();
279    void Reset() {
280      backing_store_ = NULL;
281      transaction_ = NULL;
282    }
283
284    static LevelDBTransaction* LevelDBTransactionFrom(
285        Transaction* transaction) {
286      return transaction->transaction_;
287    }
288
289   private:
290    IndexedDBBackingStore* backing_store_;
291    scoped_refptr<LevelDBTransaction> transaction_;
292  };
293
294 protected:
295  IndexedDBBackingStore(const std::string& identifier,
296                        scoped_ptr<LevelDBDatabase> db,
297                        scoped_ptr<LevelDBComparator> comparator);
298  virtual ~IndexedDBBackingStore();
299  friend class base::RefCounted<IndexedDBBackingStore>;
300
301 private:
302  static scoped_refptr<IndexedDBBackingStore> Create(
303      const std::string& identifier,
304      scoped_ptr<LevelDBDatabase> db,
305      scoped_ptr<LevelDBComparator> comparator);
306
307  bool FindKeyInIndex(IndexedDBBackingStore::Transaction* transaction,
308                      int64 database_id,
309                      int64 object_store_id,
310                      int64 index_id,
311                      const IndexedDBKey& key,
312                      std::string* found_encoded_primary_key,
313                      bool* found);
314  bool GetIndexes(int64 database_id,
315                  int64 object_store_id,
316                  IndexedDBObjectStoreMetadata::IndexMap* map)
317      WARN_UNUSED_RESULT;
318
319  std::string identifier_;
320
321  scoped_ptr<LevelDBDatabase> db_;
322  scoped_ptr<LevelDBComparator> comparator_;
323  base::WeakPtrFactory<IndexedDBBackingStore> weak_factory_;
324};
325
326}  // namespace content
327
328#endif  // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_BACKING_STORE_H_
329