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 <stddef.h>
9 #include <stdint.h>
10 
11 #include <map>
12 #include <memory>
13 #include <set>
14 #include <string>
15 #include <utility>
16 #include <vector>
17 
18 #include "base/files/file_path.h"
19 #include "base/gtest_prod_util.h"
20 #include "base/macros.h"
21 #include "base/memory/ref_counted.h"
22 #include "base/memory/weak_ptr.h"
23 #include "base/sequence_checker.h"
24 #include "base/strings/string_piece.h"
25 #include "base/time/time.h"
26 #include "base/timer/timer.h"
27 #include "components/services/storage/indexed_db/scopes/scope_lock.h"
28 #include "components/services/storage/public/mojom/native_file_system_context.mojom-forward.h"
29 #include "content/browser/indexed_db/indexed_db.h"
30 #include "content/browser/indexed_db/indexed_db_external_object.h"
31 #include "content/browser/indexed_db/indexed_db_external_object_storage.h"
32 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
33 #include "content/common/content_export.h"
34 #include "storage/browser/blob/blob_data_handle.h"
35 #include "storage/browser/blob/mojom/blob_storage_context.mojom-forward.h"
36 #include "storage/common/file_system/file_system_mount_option.h"
37 #include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
38 #include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
39 #include "third_party/leveldatabase/src/include/leveldb/status.h"
40 #include "url/gurl.h"
41 #include "url/origin.h"
42 
43 namespace base {
44 class SequencedTaskRunner;
45 }
46 
47 namespace blink {
48 class IndexedDBKeyRange;
49 struct IndexedDBDatabaseMetadata;
50 }  // namespace blink
51 
52 namespace content {
53 class IndexedDBActiveBlobRegistry;
54 class LevelDBWriteBatch;
55 class TransactionalLevelDBDatabase;
56 class TransactionalLevelDBFactory;
57 class TransactionalLevelDBIterator;
58 class TransactionalLevelDBTransaction;
59 struct IndexedDBValue;
60 
61 namespace indexed_db_backing_store_unittest {
62 class IndexedDBBackingStoreTest;
63 FORWARD_DECLARE_TEST(IndexedDBBackingStoreTest, ReadCorruptionInfo);
64 }  // namespace indexed_db_backing_store_unittest
65 
66 enum class V2SchemaCorruptionStatus {
67   kUnknown = 0,  // Due to other unknown/critical errors.
68   kNo = 1,
69   kYes = 2,
70 };
71 
72 // All interaction with this class should be done on the task runner given to
73 // Open.
74 class CONTENT_EXPORT IndexedDBBackingStore {
75  public:
76   class CONTENT_EXPORT RecordIdentifier {
77    public:
78     RecordIdentifier(const std::string& primary_key, int64_t version);
79     RecordIdentifier();
80     ~RecordIdentifier();
81 
primary_key()82     const std::string& primary_key() const { return primary_key_; }
version()83     int64_t version() const { return version_; }
Reset(const std::string & primary_key,int64_t version)84     void Reset(const std::string& primary_key, int64_t version) {
85       primary_key_ = primary_key;
86       version_ = version;
87     }
88 
89    private:
90     // TODO(jsbell): Make it more clear that this is the *encoded* version of
91     // the key.
92     std::string primary_key_;
93     int64_t version_;
94     DISALLOW_COPY_AND_ASSIGN(RecordIdentifier);
95   };
96 
97   class CONTENT_EXPORT Transaction {
98    public:
99     struct BlobWriteState {
100       BlobWriteState();
101       explicit BlobWriteState(int calls_left, BlobWriteCallback on_complete);
102       ~BlobWriteState();
103       int calls_left = 0;
104       BlobWriteCallback on_complete;
105     };
106 
107     Transaction(base::WeakPtr<IndexedDBBackingStore> backing_store,
108                 blink::mojom::IDBTransactionDurability durability,
109                 blink::mojom::IDBTransactionMode mode);
110     virtual ~Transaction();
111 
112     virtual void Begin(std::vector<ScopeLock> locks);
113 
114     // CommitPhaseOne determines what blobs (if any) need to be written to disk
115     // and updates the primary blob journal, and kicks off the async writing
116     // of the blob files. In case of crash/rollback, the journal indicates what
117     // files should be cleaned up.
118     // The callback will be called eventually on success or failure, or
119     // immediately if phase one is complete due to lack of any blobs to write.
120     virtual leveldb::Status CommitPhaseOne(BlobWriteCallback callback);
121 
122     // CommitPhaseTwo is called once the blob files (if any) have been written
123     // to disk, and commits the actual transaction to the backing store,
124     // including blob journal updates, then deletes any blob files deleted
125     // by the transaction and not referenced by running scripts.
126     virtual leveldb::Status CommitPhaseTwo();
127 
128     // When LevelDBScopes is in single-sequence mode then this will return the
129     // result of the rollback. Otherwise leveldb::Status::OK() is returned.
130     virtual leveldb::Status Rollback();
131 
132     void Reset();
133     leveldb::Status PutExternalObjectsIfNeeded(
134         int64_t database_id,
135         const std::string& object_store_data_key,
136         std::vector<IndexedDBExternalObject>*);
137     void PutExternalObjects(int64_t database_id,
138                             const std::string& object_store_data_key,
139                             std::vector<IndexedDBExternalObject>*);
140 
transaction()141     TransactionalLevelDBTransaction* transaction() {
142       return transaction_.get();
143     }
144 
145     virtual uint64_t GetTransactionSize();
146 
147     leveldb::Status GetExternalObjectsForRecord(
148         int64_t database_id,
149         const std::string& object_store_data_key,
150         IndexedDBValue* value);
151 
152     base::WeakPtr<Transaction> AsWeakPtr();
153 
mode()154     blink::mojom::IDBTransactionMode mode() const { return mode_; }
155 
backing_store()156     IndexedDBBackingStore* backing_store() { return backing_store_.get(); }
157 
158    private:
159     // Called by CommitPhaseOne: Identifies the blob entries to write and adds
160     // them to the recovery blob journal directly (i.e. not as part of the
161     // transaction). Populates blobs_to_write_.
162     leveldb::Status HandleBlobPreTransaction();
163 
164     // Called by CommitPhaseOne: Populates blob_files_to_remove_ by
165     // determining which blobs are deleted as part of the transaction, and
166     // adds blob entry cleanup operations to the transaction. Returns true on
167     // success, false on failure.
168     bool CollectBlobFilesToRemove();
169 
170     // Called by CommitPhaseOne: Kicks off the asynchronous writes of blobs
171     // identified in HandleBlobPreTransaction. The callback will be called
172     // eventually on success or failure.
173     leveldb::Status WriteNewBlobs(BlobWriteCallback callback);
174 
175     // Called by CommitPhaseTwo: Partition blob references in blobs_to_remove_
176     // into live (active references) and dead (no references).
177     void PartitionBlobsToRemove(BlobJournalType* dead_blobs,
178                                 BlobJournalType* live_blobs) const;
179 
180     SEQUENCE_CHECKER(idb_sequence_checker_);
181 
182     // This does NOT mean that this class can outlive the IndexedDBBackingStore.
183     // This is only to protect against security issues before this class is
184     // refactored away and this isn't necessary.
185     // https://crbug.com/1012918
186     base::WeakPtr<IndexedDBBackingStore> backing_store_;
187     TransactionalLevelDBFactory* const transactional_leveldb_factory_;
188     scoped_refptr<TransactionalLevelDBTransaction> transaction_;
189     std::map<std::string, std::unique_ptr<IndexedDBExternalObjectChangeRecord>>
190         external_object_change_map_;
191     std::map<std::string, std::unique_ptr<IndexedDBExternalObjectChangeRecord>>
192         incognito_external_object_map_;
193     int64_t database_id_;
194 
195     // List of blob files being newly written as part of this transaction.
196     // These will be added to the recovery blob journal prior to commit, then
197     // removed after a successful commit.
198     BlobJournalType blobs_to_write_;
199 
200     // List of blob files being deleted as part of this transaction. These will
201     // be added to either the recovery or live blob journal as appropriate
202     // following a successful commit.
203     BlobJournalType blobs_to_remove_;
204 
205     // Populated when blobs are being written to disk. This is saved here (as
206     // opposed to being ephemeral and owned by the WriteBlobToFile callbacks)
207     // because the transaction needs to be able to cancel this operation in
208     // Rollback().
209     base::Optional<BlobWriteState> write_state_;
210 
211     // Set to true between CommitPhaseOne and CommitPhaseTwo/Rollback, to
212     // indicate that the committing_transaction_count_ on the backing store
213     // has been bumped, and journal cleaning should be deferred.
214     bool committing_;
215 
216     // This flag is passed to LevelDBScopes as |sync_on_commit|, converted
217     // via ShouldSyncOnCommit.
218     blink::mojom::IDBTransactionDurability durability_;
219     const blink::mojom::IDBTransactionMode mode_;
220 
221     base::WeakPtrFactory<Transaction> ptr_factory_{this};
222 
223     DISALLOW_COPY_AND_ASSIGN(Transaction);
224   };
225 
226   class Cursor {
227    public:
228     enum IteratorState { READY = 0, SEEK };
229 
230     virtual ~Cursor();
231 
232     struct CursorOptions {
233       CursorOptions();
234       CursorOptions(const CursorOptions& other);
235       ~CursorOptions();
236       int64_t database_id;
237       int64_t object_store_id;
238       int64_t index_id;
239       std::string low_key;
240       bool low_open;
241       std::string high_key;
242       bool high_open;
243       bool forward;
244       bool unique;
245       blink::mojom::IDBTransactionMode mode =
246           blink::mojom::IDBTransactionMode::ReadWrite;
247     };
248 
key()249     const blink::IndexedDBKey& key() const { return *current_key_; }
Continue(leveldb::Status * s)250     bool Continue(leveldb::Status* s) {
251       return Continue(nullptr, nullptr, SEEK, s);
252     }
Continue(const blink::IndexedDBKey * key,IteratorState state,leveldb::Status * s)253     bool Continue(const blink::IndexedDBKey* key,
254                   IteratorState state,
255                   leveldb::Status* s) {
256       return Continue(key, nullptr, state, s);
257     }
258     bool Continue(const blink::IndexedDBKey* key,
259                   const blink::IndexedDBKey* primary_key,
260                   IteratorState state,
261                   leveldb::Status*);
262     bool Advance(uint32_t count, leveldb::Status*);
263     bool FirstSeek(leveldb::Status*);
264 
265     virtual std::unique_ptr<Cursor> Clone() const = 0;
266     virtual const blink::IndexedDBKey& primary_key() const;
267     virtual IndexedDBValue* value() = 0;
268     virtual const RecordIdentifier& record_identifier() const;
269     virtual bool LoadCurrentRow(leveldb::Status* s) = 0;
270 
271    protected:
272     Cursor(base::WeakPtr<Transaction> transaction,
273            int64_t database_id,
274            const CursorOptions& cursor_options);
275     explicit Cursor(const IndexedDBBackingStore::Cursor* other);
276 
277     virtual std::string EncodeKey(const blink::IndexedDBKey& key) = 0;
278     virtual std::string EncodeKey(const blink::IndexedDBKey& key,
279                                   const blink::IndexedDBKey& primary_key) = 0;
280 
281     bool IsPastBounds() const;
282     bool HaveEnteredRange() const;
283 
284     SEQUENCE_CHECKER(idb_sequence_checker_);
285 
286     // This does NOT mean that this class can outlive the Transaction.
287     // This is only to protect against security issues before this class is
288     // refactored away and this isn't necessary.
289     // https://crbug.com/1012918
290     base::WeakPtr<Transaction> transaction_;
291     int64_t database_id_;
292     const CursorOptions cursor_options_;
293     std::unique_ptr<TransactionalLevelDBIterator> iterator_;
294     std::unique_ptr<blink::IndexedDBKey> current_key_;
295     IndexedDBBackingStore::RecordIdentifier record_identifier_;
296 
297    private:
298     enum class ContinueResult { LEVELDB_ERROR, DONE, OUT_OF_BOUNDS };
299 
300     // For cursors with direction Next or NextNoDuplicate.
301     ContinueResult ContinueNext(const blink::IndexedDBKey* key,
302                                 const blink::IndexedDBKey* primary_key,
303                                 IteratorState state,
304                                 leveldb::Status*);
305     // For cursors with direction Prev or PrevNoDuplicate. The PrevNoDuplicate
306     // case has additional complexity of not being symmetric with
307     // NextNoDuplicate.
308     ContinueResult ContinuePrevious(const blink::IndexedDBKey* key,
309                                     const blink::IndexedDBKey* primary_key,
310                                     IteratorState state,
311                                     leveldb::Status*);
312 
313     base::WeakPtrFactory<Cursor> weak_factory_{this};
314 
315     DISALLOW_COPY_AND_ASSIGN(Cursor);
316   };
317 
318   using BlobFilesCleanedCallback = base::RepeatingClosure;
319   using ReportOutstandingBlobsCallback =
320       base::RepeatingCallback<void(/*outstanding_blobs=*/bool)>;
321 
322   enum class Mode { kInMemory, kOnDisk };
323 
324   // Schedule an immediate blob journal cleanup if we reach this number of
325   // requests.
326   static constexpr const int kMaxJournalCleanRequests = 50;
327   // Wait for a maximum of 5 seconds from the first call to the timer since the
328   // last journal cleaning.
329   static constexpr const base::TimeDelta kMaxJournalCleaningWindowTime =
330       base::TimeDelta::FromSeconds(5);
331   // Default to a 2 second timer delay before we clean up blobs.
332   static constexpr const base::TimeDelta kInitialJournalCleaningWindowTime =
333       base::TimeDelta::FromSeconds(2);
334 
335   IndexedDBBackingStore(
336       Mode backing_store_mode,
337       TransactionalLevelDBFactory* transactional_leveldb_factory,
338       const url::Origin& origin,
339       const base::FilePath& blob_path,
340       std::unique_ptr<TransactionalLevelDBDatabase> db,
341       storage::mojom::BlobStorageContext* blob_storage_context,
342       storage::mojom::NativeFileSystemContext* native_file_system_context,
343       BlobFilesCleanedCallback blob_files_cleaned,
344       ReportOutstandingBlobsCallback report_outstanding_blobs,
345       scoped_refptr<base::SequencedTaskRunner> idb_task_runner,
346       scoped_refptr<base::SequencedTaskRunner> io_task_runner);
347   virtual ~IndexedDBBackingStore();
348 
349   // Initializes the backing store. This must be called before doing any
350   // operations or method calls on this object.
351   leveldb::Status Initialize(bool clean_active_blob_journal);
352 
origin()353   const url::Origin& origin() const { return origin_; }
idb_task_runner()354   base::SequencedTaskRunner* idb_task_runner() const {
355     return idb_task_runner_.get();
356   }
active_blob_registry()357   IndexedDBActiveBlobRegistry* active_blob_registry() {
358     return active_blob_registry_.get();
359   }
360 
361   // Compact is public for testing.
362   virtual void Compact();
363   virtual leveldb::Status DeleteDatabase(
364       const base::string16& name,
365       TransactionalLevelDBTransaction* transaction);
366 
367   static bool RecordCorruptionInfo(const base::FilePath& path_base,
368                                    const url::Origin& origin,
369                                    const std::string& message);
370 
371   virtual leveldb::Status GetRecord(
372       IndexedDBBackingStore::Transaction* transaction,
373       int64_t database_id,
374       int64_t object_store_id,
375       const blink::IndexedDBKey& key,
376       IndexedDBValue* record) WARN_UNUSED_RESULT;
377   virtual leveldb::Status PutRecord(
378       IndexedDBBackingStore::Transaction* transaction,
379       int64_t database_id,
380       int64_t object_store_id,
381       const blink::IndexedDBKey& key,
382       IndexedDBValue* value,
383       RecordIdentifier* record) WARN_UNUSED_RESULT;
384   virtual leveldb::Status ClearObjectStore(
385       IndexedDBBackingStore::Transaction* transaction,
386       int64_t database_id,
387       int64_t object_store_id) WARN_UNUSED_RESULT;
388   virtual leveldb::Status DeleteRecord(
389       IndexedDBBackingStore::Transaction* transaction,
390       int64_t database_id,
391       int64_t object_store_id,
392       const RecordIdentifier& record) WARN_UNUSED_RESULT;
393   virtual leveldb::Status DeleteRange(
394       IndexedDBBackingStore::Transaction* transaction,
395       int64_t database_id,
396       int64_t object_store_id,
397       const blink::IndexedDBKeyRange&) WARN_UNUSED_RESULT;
398   virtual leveldb::Status GetKeyGeneratorCurrentNumber(
399       IndexedDBBackingStore::Transaction* transaction,
400       int64_t database_id,
401       int64_t object_store_id,
402       int64_t* current_number) WARN_UNUSED_RESULT;
403   virtual leveldb::Status MaybeUpdateKeyGeneratorCurrentNumber(
404       IndexedDBBackingStore::Transaction* transaction,
405       int64_t database_id,
406       int64_t object_store_id,
407       int64_t new_state,
408       bool check_current) WARN_UNUSED_RESULT;
409   virtual leveldb::Status KeyExistsInObjectStore(
410       IndexedDBBackingStore::Transaction* transaction,
411       int64_t database_id,
412       int64_t object_store_id,
413       const blink::IndexedDBKey& key,
414       RecordIdentifier* found_record_identifier,
415       bool* found) WARN_UNUSED_RESULT;
416 
417   virtual leveldb::Status ClearIndex(
418       IndexedDBBackingStore::Transaction* transaction,
419       int64_t database_id,
420       int64_t object_store_id,
421       int64_t index_id) WARN_UNUSED_RESULT;
422   virtual leveldb::Status PutIndexDataForRecord(
423       IndexedDBBackingStore::Transaction* transaction,
424       int64_t database_id,
425       int64_t object_store_id,
426       int64_t index_id,
427       const blink::IndexedDBKey& key,
428       const RecordIdentifier& record) WARN_UNUSED_RESULT;
429   virtual leveldb::Status GetPrimaryKeyViaIndex(
430       IndexedDBBackingStore::Transaction* transaction,
431       int64_t database_id,
432       int64_t object_store_id,
433       int64_t index_id,
434       const blink::IndexedDBKey& key,
435       std::unique_ptr<blink::IndexedDBKey>* primary_key) WARN_UNUSED_RESULT;
436   virtual leveldb::Status KeyExistsInIndex(
437       IndexedDBBackingStore::Transaction* transaction,
438       int64_t database_id,
439       int64_t object_store_id,
440       int64_t index_id,
441       const blink::IndexedDBKey& key,
442       std::unique_ptr<blink::IndexedDBKey>* found_primary_key,
443       bool* exists) WARN_UNUSED_RESULT;
444 
445   // Public for IndexedDBActiveBlobRegistry::MarkBlobInactive.
446   virtual void ReportBlobUnused(int64_t database_id, int64_t blob_number);
447 
448   base::FilePath GetBlobFileName(int64_t database_id, int64_t key) const;
449 
450   virtual std::unique_ptr<Cursor> OpenObjectStoreKeyCursor(
451       IndexedDBBackingStore::Transaction* transaction,
452       int64_t database_id,
453       int64_t object_store_id,
454       const blink::IndexedDBKeyRange& key_range,
455       blink::mojom::IDBCursorDirection,
456       leveldb::Status*);
457   virtual std::unique_ptr<Cursor> OpenObjectStoreCursor(
458       IndexedDBBackingStore::Transaction* transaction,
459       int64_t database_id,
460       int64_t object_store_id,
461       const blink::IndexedDBKeyRange& key_range,
462       blink::mojom::IDBCursorDirection,
463       leveldb::Status*);
464   virtual std::unique_ptr<Cursor> OpenIndexKeyCursor(
465       IndexedDBBackingStore::Transaction* transaction,
466       int64_t database_id,
467       int64_t object_store_id,
468       int64_t index_id,
469       const blink::IndexedDBKeyRange& key_range,
470       blink::mojom::IDBCursorDirection,
471       leveldb::Status*);
472   virtual std::unique_ptr<Cursor> OpenIndexCursor(
473       IndexedDBBackingStore::Transaction* transaction,
474       int64_t database_id,
475       int64_t object_store_id,
476       int64_t index_id,
477       const blink::IndexedDBKeyRange& key_range,
478       blink::mojom::IDBCursorDirection,
479       leveldb::Status*);
480 
db()481   TransactionalLevelDBDatabase* db() { return db_.get(); }
482 
origin_identifier()483   const std::string& origin_identifier() { return origin_identifier_; }
484 
485   // Returns true if a blob cleanup job is pending on journal_cleaning_timer_.
486   bool IsBlobCleanupPending();
487 
488   int64_t GetInMemoryBlobSize() const;
489 
490 #if DCHECK_IS_ON()
NumBlobFilesDeletedForTesting()491   int NumBlobFilesDeletedForTesting() { return num_blob_files_deleted_; }
NumAggregatedJournalCleaningRequestsForTesting()492   int NumAggregatedJournalCleaningRequestsForTesting() const {
493     return num_aggregated_journal_cleaning_requests_;
494   }
495 #endif
496 
497   // Stops the journal_cleaning_timer_ and runs its pending task.
498   void ForceRunBlobCleanup();
499 
500   // HasV2SchemaCorruption() returns whether the backing store is v2 and
501   // has blob references.
502   V2SchemaCorruptionStatus HasV2SchemaCorruption();
503 
504   // RevertSchemaToV2() updates a backing store state on disk to override its
505   // metadata version to 2.  This allows triggering https://crbug.com/829141 on
506   // an otherwise healthy backing store.
507   leveldb::Status RevertSchemaToV2();
508 
is_incognito()509   bool is_incognito() const { return backing_store_mode_ == Mode::kInMemory; }
510 
511   virtual std::unique_ptr<Transaction> CreateTransaction(
512       blink::mojom::IDBTransactionDurability durability,
513       blink::mojom::IDBTransactionMode mode);
514 
AsWeakPtr()515   base::WeakPtr<IndexedDBBackingStore> AsWeakPtr() {
516     return weak_factory_.GetWeakPtr();
517   }
518 
519   static bool ShouldSyncOnCommit(
520       blink::mojom::IDBTransactionDurability durability);
521 
522  protected:
523   friend class IndexedDBOriginState;
524 
525   leveldb::Status AnyDatabaseContainsBlobs(
526       TransactionalLevelDBDatabase* database,
527       bool* blobs_exist);
528 
529   leveldb::Status UpgradeBlobEntriesToV4(
530       TransactionalLevelDBDatabase* database,
531       LevelDBWriteBatch* write_batch,
532       std::vector<base::FilePath>* empty_blobs_to_delete);
533 
534   // TODO(dmurph): Move this completely to IndexedDBMetadataFactory.
535   leveldb::Status GetCompleteMetadata(
536       std::vector<blink::IndexedDBDatabaseMetadata>* output);
537 
538   // Remove the referenced file on disk.
539   virtual bool RemoveBlobFile(int64_t database_id, int64_t key) const;
540 
541   // Schedule a call to CleanRecoveryJournalIgnoreReturn() via
542   // an owned timer. If this object is destroyed, the timer
543   // will automatically be cancelled.
544   virtual void StartJournalCleaningTimer();
545 
546   // Attempt to clean the recovery journal. This will remove
547   // any referenced files and delete the journal entry. If any
548   // transaction is currently committing this will be deferred
549   // via StartJournalCleaningTimer().
550   void CleanRecoveryJournalIgnoreReturn();
551 
552  private:
553   leveldb::Status FindKeyInIndex(
554       IndexedDBBackingStore::Transaction* transaction,
555       int64_t database_id,
556       int64_t object_store_id,
557       int64_t index_id,
558       const blink::IndexedDBKey& key,
559       std::string* found_encoded_primary_key,
560       bool* found);
561 
562   // Remove the blob directory for the specified database and all contained
563   // blob files.
564   bool RemoveBlobDirectory(int64_t database_id) const;
565 
566   // Synchronously read the key-specified blob journal entry from the backing
567   // store, delete all referenced blob files, and erase the journal entry.
568   // This must not be used while temporary entries are present e.g. during
569   // a two-stage transaction commit with blobs.
570   leveldb::Status CleanUpBlobJournal(const std::string& level_db_key) const;
571 
572   // Synchronously delete the files and/or directories on disk referenced by
573   // the blob journal.
574   leveldb::Status CleanUpBlobJournalEntries(
575       const BlobJournalType& journal) const;
576 
577   void WillCommitTransaction();
578   // Can run a journal cleaning job if one is pending.
579   void DidCommitTransaction();
580 
581   SEQUENCE_CHECKER(idb_sequence_checker_);
582 
583   Mode backing_store_mode_;
584   TransactionalLevelDBFactory* const transactional_leveldb_factory_;
585   const url::Origin origin_;
586   base::FilePath blob_path_;
587 
588   // IndexedDB can store blobs and native file system handles. These mojo
589   // interfaces are used to make this possible by communicating with the
590   // relevant subsystems.
591   // Raw pointers are safe because the bindings are owned by
592   // IndexedDBContextImpl.
593   storage::mojom::BlobStorageContext* blob_storage_context_;
594   storage::mojom::NativeFileSystemContext* native_file_system_context_;
595 
596   // The origin identifier is a key prefix unique to the origin used in the
597   // leveldb backing store to partition data by origin. It is a normalized
598   // version of the origin URL with a versioning suffix appended, e.g.
599   // "http_localhost_81@1" Since only one origin is stored per backing store
600   // this is redundant but necessary for backwards compatibility; the suffix
601   // provides for future flexibility.
602   const std::string origin_identifier_;
603 
604   scoped_refptr<base::SequencedTaskRunner> idb_task_runner_;
605   scoped_refptr<base::SequencedTaskRunner> io_task_runner_;
606   std::set<int> child_process_ids_granted_;
607   std::map<std::string, std::unique_ptr<IndexedDBExternalObjectChangeRecord>>
608       incognito_external_object_map_;
609 
610   bool execute_journal_cleaning_on_no_txns_ = false;
611   int num_aggregated_journal_cleaning_requests_ = 0;
612   base::OneShotTimer journal_cleaning_timer_;
613   base::TimeTicks journal_cleaning_timer_window_start_;
614 
615 #if DCHECK_IS_ON()
616   mutable int num_blob_files_deleted_ = 0;
617 #endif
618 
619   std::unique_ptr<TransactionalLevelDBDatabase> db_;
620 
621   BlobFilesCleanedCallback blob_files_cleaned_;
622 
623   // Whenever blobs are registered in active_blob_registry_,
624   // indexed_db_factory_ will hold a reference to this backing store.
625   std::unique_ptr<IndexedDBActiveBlobRegistry> active_blob_registry_;
626 
627   // Incremented whenever a transaction starts committing, decremented when
628   // complete. While > 0, temporary journal entries may exist so out-of-band
629   // journal cleaning must be deferred.
630   size_t committing_transaction_count_ = 0;
631 
632 #if DCHECK_IS_ON()
633   bool initialized_ = false;
634 #endif
635   base::WeakPtrFactory<IndexedDBBackingStore> weak_factory_{this};
636   DISALLOW_COPY_AND_ASSIGN(IndexedDBBackingStore);
637 };
638 
639 }  // namespace content
640 
641 #endif  // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_BACKING_STORE_H_
642