Home | History | Annotate | Download | only in indexed_db
      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 <map>
      9 #include <set>
     10 #include <string>
     11 #include <utility>
     12 #include <vector>
     13 
     14 #include "base/basictypes.h"
     15 #include "base/files/file_path.h"
     16 #include "base/memory/ref_counted.h"
     17 #include "base/memory/scoped_ptr.h"
     18 #include "base/strings/string_piece.h"
     19 #include "base/time/time.h"
     20 #include "base/timer/timer.h"
     21 #include "content/browser/indexed_db/indexed_db.h"
     22 #include "content/browser/indexed_db/indexed_db_active_blob_registry.h"
     23 #include "content/browser/indexed_db/indexed_db_blob_info.h"
     24 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
     25 #include "content/browser/indexed_db/indexed_db_metadata.h"
     26 #include "content/browser/indexed_db/leveldb/leveldb_iterator.h"
     27 #include "content/browser/indexed_db/leveldb/leveldb_transaction.h"
     28 #include "content/common/content_export.h"
     29 #include "content/common/indexed_db/indexed_db_key.h"
     30 #include "content/common/indexed_db/indexed_db_key_path.h"
     31 #include "content/common/indexed_db/indexed_db_key_range.h"
     32 #include "third_party/leveldatabase/src/include/leveldb/status.h"
     33 #include "url/gurl.h"
     34 #include "webkit/browser/blob/blob_data_handle.h"
     35 
     36 namespace base {
     37 class TaskRunner;
     38 }
     39 
     40 namespace fileapi {
     41 class FileWriterDelegate;
     42 }
     43 
     44 namespace net {
     45 class URLRequestContext;
     46 }
     47 
     48 namespace content {
     49 
     50 class IndexedDBFactory;
     51 class LevelDBComparator;
     52 class LevelDBDatabase;
     53 struct IndexedDBValue;
     54 
     55 class LevelDBFactory {
     56  public:
     57   virtual ~LevelDBFactory() {}
     58   virtual leveldb::Status OpenLevelDB(const base::FilePath& file_name,
     59                                       const LevelDBComparator* comparator,
     60                                       scoped_ptr<LevelDBDatabase>* db,
     61                                       bool* is_disk_full) = 0;
     62   virtual leveldb::Status DestroyLevelDB(const base::FilePath& file_name) = 0;
     63 };
     64 
     65 class CONTENT_EXPORT IndexedDBBackingStore
     66     : public base::RefCounted<IndexedDBBackingStore> {
     67  public:
     68   class CONTENT_EXPORT Transaction;
     69 
     70   class CONTENT_EXPORT Comparator : public LevelDBComparator {
     71    public:
     72     virtual int Compare(const base::StringPiece& a,
     73                         const base::StringPiece& b) const OVERRIDE;
     74     virtual const char* Name() const OVERRIDE;
     75   };
     76 
     77   const GURL& origin_url() const { return origin_url_; }
     78   IndexedDBFactory* factory() const { return indexed_db_factory_; }
     79   base::TaskRunner* task_runner() const { return task_runner_; }
     80   base::OneShotTimer<IndexedDBBackingStore>* close_timer() {
     81     return &close_timer_;
     82   }
     83   IndexedDBActiveBlobRegistry* active_blob_registry() {
     84     return &active_blob_registry_;
     85   }
     86 
     87   static scoped_refptr<IndexedDBBackingStore> Open(
     88       IndexedDBFactory* indexed_db_factory,
     89       const GURL& origin_url,
     90       const base::FilePath& path_base,
     91       net::URLRequestContext* request_context,
     92       blink::WebIDBDataLoss* data_loss,
     93       std::string* data_loss_message,
     94       bool* disk_full,
     95       base::TaskRunner* task_runner,
     96       bool clean_journal);
     97   static scoped_refptr<IndexedDBBackingStore> Open(
     98       IndexedDBFactory* indexed_db_factory,
     99       const GURL& origin_url,
    100       const base::FilePath& path_base,
    101       net::URLRequestContext* request_context,
    102       blink::WebIDBDataLoss* data_loss,
    103       std::string* data_loss_message,
    104       bool* disk_full,
    105       LevelDBFactory* leveldb_factory,
    106       base::TaskRunner* task_runner,
    107       bool clean_journal);
    108   static scoped_refptr<IndexedDBBackingStore> OpenInMemory(
    109       const GURL& origin_url,
    110       base::TaskRunner* task_runner);
    111   static scoped_refptr<IndexedDBBackingStore> OpenInMemory(
    112       const GURL& origin_url,
    113       LevelDBFactory* leveldb_factory,
    114       base::TaskRunner* task_runner);
    115 
    116   void GrantChildProcessPermissions(int child_process_id);
    117 
    118   // Compact is public for testing.
    119   virtual void Compact();
    120   virtual std::vector<base::string16> GetDatabaseNames(leveldb::Status*);
    121   virtual leveldb::Status GetIDBDatabaseMetaData(
    122       const base::string16& name,
    123       IndexedDBDatabaseMetadata* metadata,
    124       bool* success) WARN_UNUSED_RESULT;
    125   virtual leveldb::Status CreateIDBDatabaseMetaData(
    126       const base::string16& name,
    127       const base::string16& version,
    128       int64 int_version,
    129       int64* row_id);
    130   virtual bool UpdateIDBDatabaseIntVersion(
    131       IndexedDBBackingStore::Transaction* transaction,
    132       int64 row_id,
    133       int64 int_version);
    134   virtual leveldb::Status DeleteDatabase(const base::string16& name);
    135 
    136   // Assumes caller has already closed the backing store.
    137   static leveldb::Status DestroyBackingStore(const base::FilePath& path_base,
    138                                              const GURL& origin_url);
    139   static bool RecordCorruptionInfo(const base::FilePath& path_base,
    140                                    const GURL& origin_url,
    141                                    const std::string& message);
    142   leveldb::Status GetObjectStores(
    143       int64 database_id,
    144       IndexedDBDatabaseMetadata::ObjectStoreMap* map) WARN_UNUSED_RESULT;
    145   virtual leveldb::Status CreateObjectStore(
    146       IndexedDBBackingStore::Transaction* transaction,
    147       int64 database_id,
    148       int64 object_store_id,
    149       const base::string16& name,
    150       const IndexedDBKeyPath& key_path,
    151       bool auto_increment);
    152   virtual leveldb::Status DeleteObjectStore(
    153       IndexedDBBackingStore::Transaction* transaction,
    154       int64 database_id,
    155       int64 object_store_id) WARN_UNUSED_RESULT;
    156 
    157   class CONTENT_EXPORT RecordIdentifier {
    158    public:
    159     RecordIdentifier(const std::string& primary_key, int64 version);
    160     RecordIdentifier();
    161     ~RecordIdentifier();
    162 
    163     const std::string& primary_key() const { return primary_key_; }
    164     int64 version() const { return version_; }
    165     void Reset(const std::string& primary_key, int64 version) {
    166       primary_key_ = primary_key;
    167       version_ = version;
    168     }
    169 
    170    private:
    171     // TODO(jsbell): Make it more clear that this is the *encoded* version of
    172     // the key.
    173     std::string primary_key_;
    174     int64 version_;
    175     DISALLOW_COPY_AND_ASSIGN(RecordIdentifier);
    176   };
    177 
    178   class BlobWriteCallback : public base::RefCounted<BlobWriteCallback> {
    179    public:
    180     virtual void Run(bool succeeded) = 0;
    181 
    182    protected:
    183     virtual ~BlobWriteCallback() {}
    184     friend class base::RefCounted<BlobWriteCallback>;
    185   };
    186 
    187   virtual leveldb::Status GetRecord(
    188       IndexedDBBackingStore::Transaction* transaction,
    189       int64 database_id,
    190       int64 object_store_id,
    191       const IndexedDBKey& key,
    192       IndexedDBValue* record) WARN_UNUSED_RESULT;
    193   virtual leveldb::Status PutRecord(
    194       IndexedDBBackingStore::Transaction* transaction,
    195       int64 database_id,
    196       int64 object_store_id,
    197       const IndexedDBKey& key,
    198       IndexedDBValue& value,
    199       ScopedVector<webkit_blob::BlobDataHandle>* handles,
    200       RecordIdentifier* record) WARN_UNUSED_RESULT;
    201   virtual leveldb::Status ClearObjectStore(
    202       IndexedDBBackingStore::Transaction* transaction,
    203       int64 database_id,
    204       int64 object_store_id) WARN_UNUSED_RESULT;
    205   virtual leveldb::Status DeleteRecord(
    206       IndexedDBBackingStore::Transaction* transaction,
    207       int64 database_id,
    208       int64 object_store_id,
    209       const RecordIdentifier& record) WARN_UNUSED_RESULT;
    210   virtual leveldb::Status DeleteRange(
    211       IndexedDBBackingStore::Transaction* transaction,
    212       int64 database_id,
    213       int64 object_store_id,
    214       const IndexedDBKeyRange&) WARN_UNUSED_RESULT;
    215   virtual leveldb::Status GetKeyGeneratorCurrentNumber(
    216       IndexedDBBackingStore::Transaction* transaction,
    217       int64 database_id,
    218       int64 object_store_id,
    219       int64* current_number) WARN_UNUSED_RESULT;
    220   virtual leveldb::Status MaybeUpdateKeyGeneratorCurrentNumber(
    221       IndexedDBBackingStore::Transaction* transaction,
    222       int64 database_id,
    223       int64 object_store_id,
    224       int64 new_state,
    225       bool check_current) WARN_UNUSED_RESULT;
    226   virtual leveldb::Status KeyExistsInObjectStore(
    227       IndexedDBBackingStore::Transaction* transaction,
    228       int64 database_id,
    229       int64 object_store_id,
    230       const IndexedDBKey& key,
    231       RecordIdentifier* found_record_identifier,
    232       bool* found) WARN_UNUSED_RESULT;
    233 
    234   virtual leveldb::Status CreateIndex(
    235       IndexedDBBackingStore::Transaction* transaction,
    236       int64 database_id,
    237       int64 object_store_id,
    238       int64 index_id,
    239       const base::string16& name,
    240       const IndexedDBKeyPath& key_path,
    241       bool is_unique,
    242       bool is_multi_entry) WARN_UNUSED_RESULT;
    243   virtual leveldb::Status DeleteIndex(
    244       IndexedDBBackingStore::Transaction* transaction,
    245       int64 database_id,
    246       int64 object_store_id,
    247       int64 index_id) WARN_UNUSED_RESULT;
    248   virtual leveldb::Status PutIndexDataForRecord(
    249       IndexedDBBackingStore::Transaction* transaction,
    250       int64 database_id,
    251       int64 object_store_id,
    252       int64 index_id,
    253       const IndexedDBKey& key,
    254       const RecordIdentifier& record) WARN_UNUSED_RESULT;
    255   virtual leveldb::Status GetPrimaryKeyViaIndex(
    256       IndexedDBBackingStore::Transaction* transaction,
    257       int64 database_id,
    258       int64 object_store_id,
    259       int64 index_id,
    260       const IndexedDBKey& key,
    261       scoped_ptr<IndexedDBKey>* primary_key) WARN_UNUSED_RESULT;
    262   virtual leveldb::Status KeyExistsInIndex(
    263       IndexedDBBackingStore::Transaction* transaction,
    264       int64 database_id,
    265       int64 object_store_id,
    266       int64 index_id,
    267       const IndexedDBKey& key,
    268       scoped_ptr<IndexedDBKey>* found_primary_key,
    269       bool* exists) WARN_UNUSED_RESULT;
    270 
    271   // Public for IndexedDBActiveBlobRegistry::ReleaseBlobRef.
    272   virtual void ReportBlobUnused(int64 database_id, int64 blob_key);
    273 
    274   base::FilePath GetBlobFileName(int64 database_id, int64 key);
    275 
    276   class Cursor {
    277    public:
    278     virtual ~Cursor();
    279 
    280     enum IteratorState {
    281       READY = 0,
    282       SEEK
    283     };
    284 
    285     struct CursorOptions {
    286       CursorOptions();
    287       ~CursorOptions();
    288       int64 database_id;
    289       int64 object_store_id;
    290       int64 index_id;
    291       std::string low_key;
    292       bool low_open;
    293       std::string high_key;
    294       bool high_open;
    295       bool forward;
    296       bool unique;
    297     };
    298 
    299     const IndexedDBKey& key() const { return *current_key_; }
    300     bool Continue(leveldb::Status* s) { return Continue(NULL, NULL, SEEK, s); }
    301     bool Continue(const IndexedDBKey* key,
    302                   IteratorState state,
    303                   leveldb::Status* s) {
    304       return Continue(key, NULL, state, s);
    305     }
    306     bool Continue(const IndexedDBKey* key,
    307                   const IndexedDBKey* primary_key,
    308                   IteratorState state,
    309                   leveldb::Status*);
    310     bool Advance(uint32 count, leveldb::Status*);
    311     bool FirstSeek(leveldb::Status*);
    312 
    313     virtual Cursor* Clone() = 0;
    314     virtual const IndexedDBKey& primary_key() const;
    315     virtual IndexedDBValue* value() = 0;
    316     virtual const RecordIdentifier& record_identifier() const;
    317     virtual bool LoadCurrentRow() = 0;
    318 
    319    protected:
    320     Cursor(scoped_refptr<IndexedDBBackingStore> backing_store,
    321            Transaction* transaction,
    322            int64 database_id,
    323            const CursorOptions& cursor_options);
    324     explicit Cursor(const IndexedDBBackingStore::Cursor* other);
    325 
    326     virtual std::string EncodeKey(const IndexedDBKey& key) = 0;
    327     virtual std::string EncodeKey(const IndexedDBKey& key,
    328                                   const IndexedDBKey& primary_key) = 0;
    329 
    330     bool IsPastBounds() const;
    331     bool HaveEnteredRange() const;
    332 
    333     IndexedDBBackingStore* backing_store_;
    334     Transaction* transaction_;
    335     int64 database_id_;
    336     const CursorOptions cursor_options_;
    337     scoped_ptr<LevelDBIterator> iterator_;
    338     scoped_ptr<IndexedDBKey> current_key_;
    339     IndexedDBBackingStore::RecordIdentifier record_identifier_;
    340 
    341    private:
    342     DISALLOW_COPY_AND_ASSIGN(Cursor);
    343   };
    344 
    345   virtual scoped_ptr<Cursor> OpenObjectStoreKeyCursor(
    346       IndexedDBBackingStore::Transaction* transaction,
    347       int64 database_id,
    348       int64 object_store_id,
    349       const IndexedDBKeyRange& key_range,
    350       indexed_db::CursorDirection,
    351       leveldb::Status*);
    352   virtual scoped_ptr<Cursor> OpenObjectStoreCursor(
    353       IndexedDBBackingStore::Transaction* transaction,
    354       int64 database_id,
    355       int64 object_store_id,
    356       const IndexedDBKeyRange& key_range,
    357       indexed_db::CursorDirection,
    358       leveldb::Status*);
    359   virtual scoped_ptr<Cursor> OpenIndexKeyCursor(
    360       IndexedDBBackingStore::Transaction* transaction,
    361       int64 database_id,
    362       int64 object_store_id,
    363       int64 index_id,
    364       const IndexedDBKeyRange& key_range,
    365       indexed_db::CursorDirection,
    366       leveldb::Status*);
    367   virtual scoped_ptr<Cursor> OpenIndexCursor(
    368       IndexedDBBackingStore::Transaction* transaction,
    369       int64 database_id,
    370       int64 object_store_id,
    371       int64 index_id,
    372       const IndexedDBKeyRange& key_range,
    373       indexed_db::CursorDirection,
    374       leveldb::Status*);
    375 
    376   class BlobChangeRecord {
    377    public:
    378     BlobChangeRecord(const std::string& key, int64 object_store_id);
    379     ~BlobChangeRecord();
    380     const std::string& key() const { return key_; }
    381     int64 object_store_id() const { return object_store_id_; }
    382     void SetBlobInfo(std::vector<IndexedDBBlobInfo>* blob_info);
    383     std::vector<IndexedDBBlobInfo>& mutable_blob_info() { return blob_info_; }
    384     const std::vector<IndexedDBBlobInfo>& blob_info() const {
    385       return blob_info_;
    386     }
    387     void SetHandles(ScopedVector<webkit_blob::BlobDataHandle>* handles);
    388     scoped_ptr<BlobChangeRecord> Clone() const;
    389 
    390    private:
    391     std::string key_;
    392     int64 object_store_id_;
    393     std::vector<IndexedDBBlobInfo> blob_info_;
    394     ScopedVector<webkit_blob::BlobDataHandle> handles_;
    395     DISALLOW_COPY_AND_ASSIGN(BlobChangeRecord);
    396   };
    397   typedef std::map<std::string, BlobChangeRecord*> BlobChangeMap;
    398 
    399   class Transaction {
    400    public:
    401     explicit Transaction(IndexedDBBackingStore* backing_store);
    402     virtual ~Transaction();
    403     virtual void Begin();
    404     // The callback will be called eventually on success or failure, or
    405     // immediately if phase one is complete due to lack of any blobs to write.
    406     virtual leveldb::Status CommitPhaseOne(scoped_refptr<BlobWriteCallback>);
    407     virtual leveldb::Status CommitPhaseTwo();
    408     virtual void Rollback();
    409     void Reset() {
    410       backing_store_ = NULL;
    411       transaction_ = NULL;
    412     }
    413     leveldb::Status PutBlobInfoIfNeeded(
    414         int64 database_id,
    415         int64 object_store_id,
    416         const std::string& object_store_data_key,
    417         std::vector<IndexedDBBlobInfo>*,
    418         ScopedVector<webkit_blob::BlobDataHandle>* handles);
    419     void PutBlobInfo(int64 database_id,
    420                      int64 object_store_id,
    421                      const std::string& object_store_data_key,
    422                      std::vector<IndexedDBBlobInfo>*,
    423                      ScopedVector<webkit_blob::BlobDataHandle>* handles);
    424 
    425     LevelDBTransaction* transaction() { return transaction_; }
    426 
    427     leveldb::Status GetBlobInfoForRecord(
    428         int64 database_id,
    429         const std::string& object_store_data_key,
    430         IndexedDBValue* value);
    431 
    432     // This holds a BlobEntryKey and the encoded IndexedDBBlobInfo vector stored
    433     // under that key.
    434     typedef std::vector<std::pair<BlobEntryKey, std::string> >
    435         BlobEntryKeyValuePairVec;
    436 
    437     class WriteDescriptor {
    438      public:
    439       WriteDescriptor(const GURL& url, int64_t key, int64_t size);
    440       WriteDescriptor(const base::FilePath& path,
    441                       int64_t key,
    442                       int64_t size,
    443                       base::Time last_modified);
    444 
    445       bool is_file() const { return is_file_; }
    446       const GURL& url() const {
    447         DCHECK(!is_file_);
    448         return url_;
    449       }
    450       const base::FilePath& file_path() const {
    451         DCHECK(is_file_);
    452         return file_path_;
    453       }
    454       int64_t key() const { return key_; }
    455       int64_t size() const { return size_; }
    456       base::Time last_modified() const { return last_modified_; }
    457 
    458      private:
    459       bool is_file_;
    460       GURL url_;
    461       base::FilePath file_path_;
    462       int64_t key_;
    463       int64_t size_;
    464       base::Time last_modified_;
    465     };
    466 
    467     class ChainedBlobWriter : public base::RefCounted<ChainedBlobWriter> {
    468      public:
    469       virtual void set_delegate(
    470           scoped_ptr<fileapi::FileWriterDelegate> delegate) = 0;
    471 
    472       // TODO(ericu): Add a reason in the event of failure.
    473       virtual void ReportWriteCompletion(bool succeeded,
    474                                          int64 bytes_written) = 0;
    475 
    476       virtual void Abort() = 0;
    477 
    478      protected:
    479       virtual ~ChainedBlobWriter() {}
    480       friend class base::RefCounted<ChainedBlobWriter>;
    481     };
    482 
    483     class ChainedBlobWriterImpl;
    484 
    485     typedef std::vector<WriteDescriptor> WriteDescriptorVec;
    486 
    487    private:
    488     class BlobWriteCallbackWrapper;
    489 
    490     leveldb::Status HandleBlobPreTransaction(
    491         BlobEntryKeyValuePairVec* new_blob_entries,
    492         WriteDescriptorVec* new_files_to_write);
    493     // Returns true on success, false on failure.
    494     bool CollectBlobFilesToRemove();
    495     // The callback will be called eventually on success or failure.
    496     void WriteNewBlobs(BlobEntryKeyValuePairVec& new_blob_entries,
    497                        WriteDescriptorVec& new_files_to_write,
    498                        scoped_refptr<BlobWriteCallback> callback);
    499     leveldb::Status SortBlobsToRemove();
    500 
    501     IndexedDBBackingStore* backing_store_;
    502     scoped_refptr<LevelDBTransaction> transaction_;
    503     BlobChangeMap blob_change_map_;
    504     BlobChangeMap incognito_blob_map_;
    505     int64 database_id_;
    506     BlobJournalType blobs_to_remove_;
    507     scoped_refptr<ChainedBlobWriter> chained_blob_writer_;
    508   };
    509 
    510  protected:
    511   IndexedDBBackingStore(IndexedDBFactory* indexed_db_factory,
    512                         const GURL& origin_url,
    513                         const base::FilePath& blob_path,
    514                         net::URLRequestContext* request_context,
    515                         scoped_ptr<LevelDBDatabase> db,
    516                         scoped_ptr<LevelDBComparator> comparator,
    517                         base::TaskRunner* task_runner);
    518   virtual ~IndexedDBBackingStore();
    519   friend class base::RefCounted<IndexedDBBackingStore>;
    520 
    521   bool is_incognito() const { return !indexed_db_factory_; }
    522 
    523   bool SetUpMetadata();
    524 
    525   virtual bool WriteBlobFile(
    526       int64 database_id,
    527       const Transaction::WriteDescriptor& descriptor,
    528       Transaction::ChainedBlobWriter* chained_blob_writer);
    529   virtual bool RemoveBlobFile(int64 database_id, int64 key);
    530   virtual void StartJournalCleaningTimer();
    531   void CleanPrimaryJournalIgnoreReturn();
    532 
    533  private:
    534   static scoped_refptr<IndexedDBBackingStore> Create(
    535       IndexedDBFactory* indexed_db_factory,
    536       const GURL& origin_url,
    537       const base::FilePath& blob_path,
    538       net::URLRequestContext* request_context,
    539       scoped_ptr<LevelDBDatabase> db,
    540       scoped_ptr<LevelDBComparator> comparator,
    541       base::TaskRunner* task_runner);
    542 
    543   static bool ReadCorruptionInfo(const base::FilePath& path_base,
    544                                  const GURL& origin_url,
    545                                  std::string& message);
    546 
    547   leveldb::Status FindKeyInIndex(
    548       IndexedDBBackingStore::Transaction* transaction,
    549       int64 database_id,
    550       int64 object_store_id,
    551       int64 index_id,
    552       const IndexedDBKey& key,
    553       std::string* found_encoded_primary_key,
    554       bool* found);
    555   leveldb::Status GetIndexes(int64 database_id,
    556                              int64 object_store_id,
    557                              IndexedDBObjectStoreMetadata::IndexMap* map)
    558       WARN_UNUSED_RESULT;
    559   bool RemoveBlobDirectory(int64 database_id);
    560   leveldb::Status CleanUpBlobJournal(const std::string& level_db_key);
    561 
    562   IndexedDBFactory* indexed_db_factory_;
    563   const GURL origin_url_;
    564   base::FilePath blob_path_;
    565 
    566   // The origin identifier is a key prefix unique to the origin used in the
    567   // leveldb backing store to partition data by origin. It is a normalized
    568   // version of the origin URL with a versioning suffix appended, e.g.
    569   // "http_localhost_81@1" Since only one origin is stored per backing store
    570   // this is redundant but necessary for backwards compatibility; the suffix
    571   // provides for future flexibility.
    572   const std::string origin_identifier_;
    573 
    574   net::URLRequestContext* request_context_;
    575   base::TaskRunner* task_runner_;
    576   std::set<int> child_process_ids_granted_;
    577   BlobChangeMap incognito_blob_map_;
    578   base::OneShotTimer<IndexedDBBackingStore> journal_cleaning_timer_;
    579 
    580   scoped_ptr<LevelDBDatabase> db_;
    581   scoped_ptr<LevelDBComparator> comparator_;
    582   // Whenever blobs are registered in active_blob_registry_, indexed_db_factory_
    583   // will hold a reference to this backing store.
    584   IndexedDBActiveBlobRegistry active_blob_registry_;
    585   base::OneShotTimer<IndexedDBBackingStore> close_timer_;
    586 
    587   DISALLOW_COPY_AND_ASSIGN(IndexedDBBackingStore);
    588 };
    589 
    590 }  // namespace content
    591 
    592 #endif  // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_BACKING_STORE_H_
    593