Commit a7dfd014 authored by Daniel Murphy's avatar Daniel Murphy Committed by Commit Bot

[IndexedDB] Removing all raw pointers and IndexedDBFactory dependencies

This patch:
* Changes most raw pointers to base::WeakPtr
* Removes the IndexedDBFactory raw pointer in IndexedDBDatabase and
  instead uses callbacks to report:
  1. If blobs are in use for a given origin, and
  2. If the blob journal has been cleaned.
* Changes the IndexedDBActiveBlobRegistry to use callbacks instead of
  the IndexedDBFactory as well, and also use callbacks for calling
  ReportUnusedBlob in IndexedDBOriginFactory. This simplifies the
  testing of that class.

There are no functional changes in this patch, and while all of those
raw pointers should be safe based on the architecture of the code, it
is much safer to store them appropriately now that we have our fancy
new pointer types.

Finally, this patch also does some naming changing in
IndexedDBActiveBlobRegistry to make that class easier to understand.

Bug: 1018741,960992
Change-Id: I6fd402c68d13870f347fe934b85e6281c396901d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1885094
Commit-Queue: Daniel Murphy <dmurph@chromium.org>
Reviewed-by: default avatarKen Rockot <rockot@google.com>
Cr-Commit-Position: refs/heads/master@{#711452}
parent c6c4ec37
...@@ -120,7 +120,7 @@ void DatabaseImpl::CreateTransaction( ...@@ -120,7 +120,7 @@ void DatabaseImpl::CreateTransaction(
transaction_id, transaction_id,
std::set<int64_t>(object_store_ids.begin(), object_store_ids.end()), mode, std::set<int64_t>(object_store_ids.begin(), object_store_ids.end()), mode,
new IndexedDBBackingStore::Transaction( new IndexedDBBackingStore::Transaction(
connection_->database()->backing_store(), durability)); connection_->database()->backing_store()->AsWeakPtr(), durability));
connection_->database()->RegisterAndScheduleTransaction(transaction); connection_->database()->RegisterAndScheduleTransaction(transaction);
dispatcher_host_->CreateAndBindTransactionImpl( dispatcher_host_->CreateAndBindTransactionImpl(
......
...@@ -2,11 +2,13 @@ ...@@ -2,11 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "content/browser/indexed_db/indexed_db_active_blob_registry.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/location.h" #include "base/location.h"
#include "base/stl_util.h" #include "base/stl_util.h"
#include "base/task_runner.h" #include "base/task_runner.h"
#include "content/browser/indexed_db/indexed_db_active_blob_registry.h" #include "base/threading/sequenced_task_runner_handle.h"
#include "content/browser/indexed_db/indexed_db_backing_store.h" #include "content/browser/indexed_db/indexed_db_backing_store.h"
#include "content/browser/indexed_db/indexed_db_factory.h" #include "content/browser/indexed_db/indexed_db_factory.h"
#include "content/browser/indexed_db/indexed_db_leveldb_coding.h" #include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
...@@ -14,38 +16,42 @@ ...@@ -14,38 +16,42 @@
namespace content { namespace content {
IndexedDBActiveBlobRegistry::IndexedDBActiveBlobRegistry( IndexedDBActiveBlobRegistry::IndexedDBActiveBlobRegistry(
IndexedDBBackingStore* backing_store) ReportOutstandingBlobsCallback report_outstanding_blobs,
: backing_store_(backing_store) {} ReportUnusedBlobCallback report_unused_blob)
: report_outstanding_blobs_(std::move(report_outstanding_blobs)),
report_unused_blob_(std::move(report_unused_blob)) {}
IndexedDBActiveBlobRegistry::~IndexedDBActiveBlobRegistry() { IndexedDBActiveBlobRegistry::~IndexedDBActiveBlobRegistry() {}
}
void IndexedDBActiveBlobRegistry::AddBlobRef(int64_t database_id, void IndexedDBActiveBlobRegistry::AddBlobRef(int64_t database_id,
int64_t blob_key) { int64_t blob_key) {
DCHECK(backing_store_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(backing_store_->task_runner()->RunsTasksInCurrentSequence()); DCHECK(report_outstanding_blobs_);
DCHECK(report_unused_blob_);
DCHECK(KeyPrefix::IsValidDatabaseId(database_id)); DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
DCHECK(DatabaseMetaDataKey::IsValidBlobKey(blob_key)); DCHECK(DatabaseMetaDataKey::IsValidBlobKey(blob_key));
DCHECK(!base::Contains(deleted_dbs_, database_id)); DCHECK(!base::Contains(deleted_dbs_, database_id));
bool need_ref = use_tracker_.empty(); bool outstanding_blobs_in_backing_store = !use_tracker_.empty();
SingleDBMap& single_db_map = use_tracker_[database_id]; SingleDBMap& blobs_in_db = use_tracker_[database_id];
auto iter = single_db_map.find(blob_key); auto iter = blobs_in_db.find(blob_key);
if (iter == single_db_map.end()) { if (iter == blobs_in_db.end()) {
single_db_map[blob_key] = false; blobs_in_db[blob_key] = BlobState::kAlive;
if (need_ref) { if (!outstanding_blobs_in_backing_store)
backing_store_->factory()->ReportOutstandingBlobs( report_outstanding_blobs_.Run(true);
backing_store_->origin(), true);
}
} else { } else {
DCHECK(!need_ref); DCHECK(outstanding_blobs_in_backing_store);
DCHECK(!iter->second); // You can't add a reference once it's been deleted. // You can't add a reference once it's been deleted.
DCHECK(iter->second == BlobState::kAlive);
} }
} }
void IndexedDBActiveBlobRegistry::ReleaseBlobRef(int64_t database_id, void IndexedDBActiveBlobRegistry::ReleaseBlobRef(int64_t database_id,
int64_t blob_key) { int64_t blob_key) {
DCHECK(backing_store_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(backing_store_->task_runner()->RunsTasksInCurrentSequence()); DCHECK(report_outstanding_blobs_);
DCHECK(report_unused_blob_);
DCHECK(KeyPrefix::IsValidDatabaseId(database_id)); DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
DCHECK(DatabaseMetaDataKey::IsValidBlobKey(blob_key)); DCHECK(DatabaseMetaDataKey::IsValidBlobKey(blob_key));
const auto& db_pair = use_tracker_.find(database_id); const auto& db_pair = use_tracker_.find(database_id);
...@@ -53,39 +59,37 @@ void IndexedDBActiveBlobRegistry::ReleaseBlobRef(int64_t database_id, ...@@ -53,39 +59,37 @@ void IndexedDBActiveBlobRegistry::ReleaseBlobRef(int64_t database_id,
NOTREACHED(); NOTREACHED();
return; return;
} }
SingleDBMap& single_db = db_pair->second; SingleDBMap& blobs_in_db = db_pair->second;
auto blob_pair = single_db.find(blob_key); auto blob_in_db_it = blobs_in_db.find(blob_key);
if (blob_pair == single_db.end()) { if (blob_in_db_it == blobs_in_db.end()) {
NOTREACHED(); NOTREACHED();
return; return;
} }
bool delete_in_backend = false; bool delete_blob_in_backend = false;
const auto& db_to_delete = deleted_dbs_.find(database_id); const auto& deleted_database_it = deleted_dbs_.find(database_id);
bool db_marked_for_deletion = db_to_delete != deleted_dbs_.end(); bool db_marked_for_deletion = deleted_database_it != deleted_dbs_.end();
// Don't bother deleting the file if we're going to delete its whole // Don't bother deleting the file if we're going to delete its whole
// database directory soon. // database directory soon.
delete_in_backend = blob_pair->second && !db_marked_for_deletion; delete_blob_in_backend =
single_db.erase(blob_pair); blob_in_db_it->second == BlobState::kDeleted && !db_marked_for_deletion;
if (single_db.empty()) { blobs_in_db.erase(blob_in_db_it);
if (blobs_in_db.empty()) {
use_tracker_.erase(db_pair); use_tracker_.erase(db_pair);
if (db_marked_for_deletion) { if (db_marked_for_deletion) {
delete_in_backend = true; delete_blob_in_backend = true;
blob_key = DatabaseMetaDataKey::kAllBlobsKey; blob_key = DatabaseMetaDataKey::kAllBlobsKey;
deleted_dbs_.erase(db_to_delete); deleted_dbs_.erase(deleted_database_it);
} }
} }
if (delete_in_backend) if (delete_blob_in_backend)
backing_store_->ReportBlobUnused(database_id, blob_key); report_unused_blob_.Run(database_id, blob_key);
if (use_tracker_.empty()) { if (use_tracker_.empty())
backing_store_->factory()->ReportOutstandingBlobs(backing_store_->origin(), report_outstanding_blobs_.Run(false);
false);
}
} }
bool IndexedDBActiveBlobRegistry::MarkDeletedCheckIfUsed(int64_t database_id, bool IndexedDBActiveBlobRegistry::MarkDeletedCheckIfUsed(int64_t database_id,
int64_t blob_key) { int64_t blob_key) {
DCHECK(backing_store_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(backing_store_->task_runner()->RunsTasksInCurrentSequence());
DCHECK(KeyPrefix::IsValidDatabaseId(database_id)); DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
const auto& db_pair = use_tracker_.find(database_id); const auto& db_pair = use_tracker_.find(database_id);
if (db_pair == use_tracker_.end()) if (db_pair == use_tracker_.end())
...@@ -101,7 +105,7 @@ bool IndexedDBActiveBlobRegistry::MarkDeletedCheckIfUsed(int64_t database_id, ...@@ -101,7 +105,7 @@ bool IndexedDBActiveBlobRegistry::MarkDeletedCheckIfUsed(int64_t database_id,
if (iter == single_db.end()) if (iter == single_db.end())
return false; return false;
iter->second = true; iter->second = BlobState::kDeleted;
return true; return true;
} }
...@@ -113,29 +117,33 @@ void IndexedDBActiveBlobRegistry::ReleaseBlobRefThreadSafe( ...@@ -113,29 +117,33 @@ void IndexedDBActiveBlobRegistry::ReleaseBlobRefThreadSafe(
const base::FilePath& unused) { const base::FilePath& unused) {
task_runner->PostTask( task_runner->PostTask(
FROM_HERE, base::BindOnce(&IndexedDBActiveBlobRegistry::ReleaseBlobRef, FROM_HERE, base::BindOnce(&IndexedDBActiveBlobRegistry::ReleaseBlobRef,
weak_ptr, database_id, blob_key)); std::move(weak_ptr), database_id, blob_key));
} }
IndexedDBBlobInfo::ReleaseCallback IndexedDBBlobInfo::ReleaseCallback
IndexedDBActiveBlobRegistry::GetFinalReleaseCallback(int64_t database_id, IndexedDBActiveBlobRegistry::GetFinalReleaseCallback(int64_t database_id,
int64_t blob_key) { int64_t blob_key) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return base::BindRepeating( return base::BindRepeating(
&IndexedDBActiveBlobRegistry::ReleaseBlobRefThreadSafe, &IndexedDBActiveBlobRegistry::ReleaseBlobRefThreadSafe,
scoped_refptr<base::TaskRunner>(backing_store_->task_runner()), base::SequencedTaskRunnerHandle::Get(), weak_factory_.GetWeakPtr(),
weak_factory_.GetWeakPtr(), database_id, blob_key); database_id, blob_key);
} }
base::RepeatingClosure IndexedDBActiveBlobRegistry::GetAddBlobRefCallback( base::RepeatingClosure IndexedDBActiveBlobRegistry::GetAddBlobRefCallback(
int64_t database_id, int64_t database_id,
int64_t blob_key) { int64_t blob_key) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return base::BindRepeating(&IndexedDBActiveBlobRegistry::AddBlobRef, return base::BindRepeating(&IndexedDBActiveBlobRegistry::AddBlobRef,
weak_factory_.GetWeakPtr(), database_id, blob_key); weak_factory_.GetWeakPtr(), database_id, blob_key);
} }
void IndexedDBActiveBlobRegistry::ForceShutdown() { void IndexedDBActiveBlobRegistry::ForceShutdown() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
weak_factory_.InvalidateWeakPtrs(); weak_factory_.InvalidateWeakPtrs();
use_tracker_.clear(); use_tracker_.clear();
backing_store_ = nullptr; report_outstanding_blobs_.Reset();
report_unused_blob_.Reset();
} }
} // namespace content } // namespace content
...@@ -11,19 +11,32 @@ ...@@ -11,19 +11,32 @@
#include <set> #include <set>
#include <utility> #include <utility>
#include "base/callback.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "content/browser/indexed_db/indexed_db_blob_info.h" #include "content/browser/indexed_db/indexed_db_blob_info.h"
#include "content/common/content_export.h" #include "content/common/content_export.h"
namespace content { namespace content {
class IndexedDBBackingStore; // Keeps track of blobs that have been sent to the renderer as database
// responses, and determines when the file should be deleted. The database entry
// that the blob files live in could be deleted in the database, but the file
// would need to stay alive while it is still used in the renderer.
// This class must be used on a single sequence, and will call the given
// callbacks back on the same sequence it is constructed on.
class CONTENT_EXPORT IndexedDBActiveBlobRegistry { class CONTENT_EXPORT IndexedDBActiveBlobRegistry {
public: public:
explicit IndexedDBActiveBlobRegistry(IndexedDBBackingStore* backing_store); using ReportOutstandingBlobsCallback = base::RepeatingCallback<void(bool)>;
using ReportUnusedBlobCallback =
base::RepeatingCallback<void(int64_t /*database_id*/,
int64_t /*blob_key*/)>;
explicit IndexedDBActiveBlobRegistry(
ReportOutstandingBlobsCallback report_outstanding_blobs,
ReportUnusedBlobCallback report_unused_blob);
~IndexedDBActiveBlobRegistry(); ~IndexedDBActiveBlobRegistry();
// Most methods of this class, and the closure returned by // Most methods of this class, and the closure returned by
...@@ -31,6 +44,8 @@ class CONTENT_EXPORT IndexedDBActiveBlobRegistry { ...@@ -31,6 +44,8 @@ class CONTENT_EXPORT IndexedDBActiveBlobRegistry {
// runner. The exception is the closure returned by GetFinalReleaseCallback, // runner. The exception is the closure returned by GetFinalReleaseCallback,
// which just calls ReleaseBlobRefThreadSafe. // which just calls ReleaseBlobRefThreadSafe.
// Marks a given blob or a while database as deleted by a transaction, and
// returns if the given blob key (or database) was previously used.
// Use DatabaseMetaDataKey::AllBlobsKey for "the whole database". // Use DatabaseMetaDataKey::AllBlobsKey for "the whole database".
bool MarkDeletedCheckIfUsed(int64_t database_id, int64_t blob_key); bool MarkDeletedCheckIfUsed(int64_t database_id, int64_t blob_key);
...@@ -47,11 +62,14 @@ class CONTENT_EXPORT IndexedDBActiveBlobRegistry { ...@@ -47,11 +62,14 @@ class CONTENT_EXPORT IndexedDBActiveBlobRegistry {
void ForceShutdown(); void ForceShutdown();
private: private:
// Maps blob_key -> IsDeleted; if the record's absent, it's not in active use enum class BlobState { kAlive, kDeleted };
// Maps blob_key -> BlobState; if the record's absent, it's not in active use
// and we don't care if it's deleted. // and we don't care if it's deleted.
typedef std::map<int64_t, bool> SingleDBMap; typedef std::map<int64_t, BlobState> SingleDBMap;
void AddBlobRef(int64_t database_id, int64_t blob_key); void AddBlobRef(int64_t database_id, int64_t blob_key);
// Removes a reference to the given blob.
void ReleaseBlobRef(int64_t database_id, int64_t blob_key); void ReleaseBlobRef(int64_t database_id, int64_t blob_key);
static void ReleaseBlobRefThreadSafe( static void ReleaseBlobRefThreadSafe(
scoped_refptr<base::TaskRunner> task_runner, scoped_refptr<base::TaskRunner> task_runner,
...@@ -60,12 +78,13 @@ class CONTENT_EXPORT IndexedDBActiveBlobRegistry { ...@@ -60,12 +78,13 @@ class CONTENT_EXPORT IndexedDBActiveBlobRegistry {
int64_t blob_key, int64_t blob_key,
const base::FilePath& unused); const base::FilePath& unused);
SEQUENCE_CHECKER(sequence_checker_);
std::map<int64_t, SingleDBMap> use_tracker_; std::map<int64_t, SingleDBMap> use_tracker_;
// Databases that have been marked as deleted by MarkDeletedCheckIfUsed.
std::set<int64_t> deleted_dbs_; std::set<int64_t> deleted_dbs_;
// As long as we've got blobs registered in use_tracker_, ReportOutstandingBlobsCallback report_outstanding_blobs_;
// backing_store_->factory() will keep backing_store_ alive for us. And ReportUnusedBlobCallback report_unused_blob_;
// backing_store_ owns us, so we'll stay alive as long as we're needed.
IndexedDBBackingStore* backing_store_;
base::WeakPtrFactory<IndexedDBActiveBlobRegistry> weak_factory_{this}; base::WeakPtrFactory<IndexedDBActiveBlobRegistry> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(IndexedDBActiveBlobRegistry); DISALLOW_COPY_AND_ASSIGN(IndexedDBActiveBlobRegistry);
......
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include "base/time/time.h" #include "base/time/time.h"
#include "base/timer/timer.h" #include "base/timer/timer.h"
#include "content/browser/indexed_db/indexed_db.h" #include "content/browser/indexed_db/indexed_db.h"
#include "content/browser/indexed_db/indexed_db_active_blob_registry.h"
#include "content/browser/indexed_db/indexed_db_blob_info.h" #include "content/browser/indexed_db/indexed_db_blob_info.h"
#include "content/browser/indexed_db/indexed_db_leveldb_coding.h" #include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
#include "content/browser/indexed_db/scopes/scope_lock.h" #include "content/browser/indexed_db/scopes/scope_lock.h"
...@@ -51,12 +50,12 @@ class FileWriterDelegate; ...@@ -51,12 +50,12 @@ class FileWriterDelegate;
} }
namespace content { namespace content {
class IndexedDBFactory; class IndexedDBActiveBlobRegistry;
struct IndexedDBValue;
class TransactionalLevelDBDatabase; class TransactionalLevelDBDatabase;
class TransactionalLevelDBFactory; class TransactionalLevelDBFactory;
class TransactionalLevelDBIterator; class TransactionalLevelDBIterator;
class TransactionalLevelDBTransaction; class TransactionalLevelDBTransaction;
struct IndexedDBValue;
namespace indexed_db_backing_store_unittest { namespace indexed_db_backing_store_unittest {
class IndexedDBBackingStoreTest; class IndexedDBBackingStoreTest;
...@@ -133,7 +132,7 @@ class CONTENT_EXPORT IndexedDBBackingStore { ...@@ -133,7 +132,7 @@ class CONTENT_EXPORT IndexedDBBackingStore {
class CONTENT_EXPORT Transaction { class CONTENT_EXPORT Transaction {
public: public:
explicit Transaction(IndexedDBBackingStore* backing_store, explicit Transaction(base::WeakPtr<IndexedDBBackingStore> backing_store,
blink::mojom::IDBTransactionDurability durability); blink::mojom::IDBTransactionDurability durability);
virtual ~Transaction(); virtual ~Transaction();
...@@ -179,6 +178,8 @@ class CONTENT_EXPORT IndexedDBBackingStore { ...@@ -179,6 +178,8 @@ class CONTENT_EXPORT IndexedDBBackingStore {
const std::string& object_store_data_key, const std::string& object_store_data_key,
IndexedDBValue* value); IndexedDBValue* value);
base::WeakPtr<Transaction> AsWeakPtr();
// This holds a BlobEntryKey and the encoded IndexedDBBlobInfo vector stored // This holds a BlobEntryKey and the encoded IndexedDBBlobInfo vector stored
// under that key. // under that key.
typedef std::vector<std::pair<BlobEntryKey, std::string> > typedef std::vector<std::pair<BlobEntryKey, std::string> >
...@@ -270,10 +271,11 @@ class CONTENT_EXPORT IndexedDBBackingStore { ...@@ -270,10 +271,11 @@ class CONTENT_EXPORT IndexedDBBackingStore {
void PartitionBlobsToRemove(BlobJournalType* dead_blobs, void PartitionBlobsToRemove(BlobJournalType* dead_blobs,
BlobJournalType* live_blobs) const; BlobJournalType* live_blobs) const;
// The raw pointer is not inherently safe, but IndexedDB destroys // This does NOT mean that this class can outlive the IndexedDBBackingStore.
// transactions & connections before destroying the backing store. // This is only to protect against security issues before this class is
// TODO(dmurph): Convert to WeakPtr. https://crbug.com/960992 // refactored away and this isn't necessary.
IndexedDBBackingStore* backing_store_; // https://crbug.com/1012918
base::WeakPtr<IndexedDBBackingStore> backing_store_;
TransactionalLevelDBFactory* const transactional_leveldb_factory_; TransactionalLevelDBFactory* const transactional_leveldb_factory_;
scoped_refptr<TransactionalLevelDBTransaction> transaction_; scoped_refptr<TransactionalLevelDBTransaction> transaction_;
std::map<std::string, std::unique_ptr<BlobChangeRecord>> blob_change_map_; std::map<std::string, std::unique_ptr<BlobChangeRecord>> blob_change_map_;
...@@ -348,8 +350,7 @@ class CONTENT_EXPORT IndexedDBBackingStore { ...@@ -348,8 +350,7 @@ class CONTENT_EXPORT IndexedDBBackingStore {
virtual bool LoadCurrentRow(leveldb::Status* s) = 0; virtual bool LoadCurrentRow(leveldb::Status* s) = 0;
protected: protected:
Cursor(IndexedDBBackingStore* backing_store, Cursor(base::WeakPtr<Transaction> transaction,
Transaction* transaction,
int64_t database_id, int64_t database_id,
const CursorOptions& cursor_options); const CursorOptions& cursor_options);
explicit Cursor(const IndexedDBBackingStore::Cursor* other); explicit Cursor(const IndexedDBBackingStore::Cursor* other);
...@@ -361,14 +362,11 @@ class CONTENT_EXPORT IndexedDBBackingStore { ...@@ -361,14 +362,11 @@ class CONTENT_EXPORT IndexedDBBackingStore {
bool IsPastBounds() const; bool IsPastBounds() const;
bool HaveEnteredRange() const; bool HaveEnteredRange() const;
// The raw pointer is not inherently safe, but IndexedDB destroys // This does NOT mean that this class can outlive the Transaction.
// transactions & connections before destroying the backing store. // This is only to protect against security issues before this class is
// TODO(dmurph): Convert to WeakPtr. https://crbug.com/960992 // refactored away and this isn't necessary.
IndexedDBBackingStore* backing_store_; // https://crbug.com/1012918
// The raw pointer is not inherently safe, but IndexedDB destroys base::WeakPtr<Transaction> transaction_;
// transactions before cursors.
// TODO(dmurph): Convert to WeakPtr. https://crbug.com/960992
Transaction* transaction_;
int64_t database_id_; int64_t database_id_;
const CursorOptions cursor_options_; const CursorOptions cursor_options_;
std::unique_ptr<TransactionalLevelDBIterator> iterator_; std::unique_ptr<TransactionalLevelDBIterator> iterator_;
...@@ -391,9 +389,15 @@ class CONTENT_EXPORT IndexedDBBackingStore { ...@@ -391,9 +389,15 @@ class CONTENT_EXPORT IndexedDBBackingStore {
IteratorState state, IteratorState state,
leveldb::Status*); leveldb::Status*);
base::WeakPtrFactory<Cursor> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(Cursor); DISALLOW_COPY_AND_ASSIGN(Cursor);
}; };
using BlobFilesCleanedCallback = base::RepeatingClosure;
using ReportOutstandingBlobsCallback =
base::RepeatingCallback<void(/*outstanding_blobs=*/bool)>;
enum class Mode { kInMemory, kOnDisk }; enum class Mode { kInMemory, kOnDisk };
// Schedule an immediate blob journal cleanup if we reach this number of // Schedule an immediate blob journal cleanup if we reach this number of
...@@ -409,11 +413,12 @@ class CONTENT_EXPORT IndexedDBBackingStore { ...@@ -409,11 +413,12 @@ class CONTENT_EXPORT IndexedDBBackingStore {
IndexedDBBackingStore( IndexedDBBackingStore(
Mode backing_store_mode, Mode backing_store_mode,
IndexedDBFactory* indexed_db_factory,
TransactionalLevelDBFactory* transactional_leveldb_factory, TransactionalLevelDBFactory* transactional_leveldb_factory,
const url::Origin& origin, const url::Origin& origin,
const base::FilePath& blob_path, const base::FilePath& blob_path,
std::unique_ptr<TransactionalLevelDBDatabase> db, std::unique_ptr<TransactionalLevelDBDatabase> db,
BlobFilesCleanedCallback blob_files_cleaned,
ReportOutstandingBlobsCallback report_outstanding_blobs,
base::SequencedTaskRunner* task_runner); base::SequencedTaskRunner* task_runner);
virtual ~IndexedDBBackingStore(); virtual ~IndexedDBBackingStore();
...@@ -422,10 +427,9 @@ class CONTENT_EXPORT IndexedDBBackingStore { ...@@ -422,10 +427,9 @@ class CONTENT_EXPORT IndexedDBBackingStore {
leveldb::Status Initialize(bool clean_live_blob_journal); leveldb::Status Initialize(bool clean_live_blob_journal);
const url::Origin& origin() const { return origin_; } const url::Origin& origin() const { return origin_; }
IndexedDBFactory* factory() const { return indexed_db_factory_; }
base::SequencedTaskRunner* task_runner() const { return task_runner_.get(); } base::SequencedTaskRunner* task_runner() const { return task_runner_.get(); }
IndexedDBActiveBlobRegistry* active_blob_registry() { IndexedDBActiveBlobRegistry* active_blob_registry() {
return &active_blob_registry_; return active_blob_registry_.get();
} }
void GrantChildProcessPermissions(int child_process_id); void GrantChildProcessPermissions(int child_process_id);
...@@ -650,7 +654,6 @@ class CONTENT_EXPORT IndexedDBBackingStore { ...@@ -650,7 +654,6 @@ class CONTENT_EXPORT IndexedDBBackingStore {
void DidCommitTransaction(); void DidCommitTransaction();
Mode backing_store_mode_; Mode backing_store_mode_;
IndexedDBFactory* indexed_db_factory_;
TransactionalLevelDBFactory* const transactional_leveldb_factory_; TransactionalLevelDBFactory* const transactional_leveldb_factory_;
const url::Origin origin_; const url::Origin origin_;
base::FilePath blob_path_; base::FilePath blob_path_;
...@@ -677,9 +680,12 @@ class CONTENT_EXPORT IndexedDBBackingStore { ...@@ -677,9 +680,12 @@ class CONTENT_EXPORT IndexedDBBackingStore {
#endif #endif
std::unique_ptr<TransactionalLevelDBDatabase> db_; std::unique_ptr<TransactionalLevelDBDatabase> db_;
BlobFilesCleanedCallback blob_files_cleaned_;
// Whenever blobs are registered in active_blob_registry_, // Whenever blobs are registered in active_blob_registry_,
// indexed_db_factory_ will hold a reference to this backing store. // indexed_db_factory_ will hold a reference to this backing store.
IndexedDBActiveBlobRegistry active_blob_registry_; std::unique_ptr<IndexedDBActiveBlobRegistry> active_blob_registry_;
// Incremented whenever a transaction starts committing, decremented when // Incremented whenever a transaction starts committing, decremented when
// complete. While > 0, temporary journal entries may exist so out-of-band // complete. While > 0, temporary journal entries may exist so out-of-band
......
...@@ -44,13 +44,15 @@ TEST(IndexedDBIOErrorTest, CleanUpTest) { ...@@ -44,13 +44,15 @@ TEST(IndexedDBIOErrorTest, CleanUpTest) {
auto task_runner = base::SequencedTaskRunnerHandle::Get(); auto task_runner = base::SequencedTaskRunnerHandle::Get();
std::unique_ptr<IndexedDBBackingStore> backing_store = std::make_unique< std::unique_ptr<IndexedDBBackingStore> backing_store = std::make_unique<
IndexedDBBackingStore>( IndexedDBBackingStore>(
IndexedDBBackingStore::Mode::kInMemory, nullptr, IndexedDBBackingStore::Mode::kInMemory, &transactional_leveldb_factory,
&transactional_leveldb_factory, origin, path, origin, path,
transactional_leveldb_factory.CreateLevelDBDatabase( transactional_leveldb_factory.CreateLevelDBDatabase(
FakeLevelDBFactory::GetBrokenLevelDB( FakeLevelDBFactory::GetBrokenLevelDB(
leveldb::Status::IOError("It's broken!"), path), leveldb::Status::IOError("It's broken!"), path),
nullptr, task_runner.get(), nullptr, task_runner.get(),
TransactionalLevelDBDatabase::kDefaultMaxOpenIteratorsPerDatabase), TransactionalLevelDBDatabase::kDefaultMaxOpenIteratorsPerDatabase),
IndexedDBBackingStore::BlobFilesCleanedCallback(),
IndexedDBBackingStore::ReportOutstandingBlobsCallback(),
task_runner.get()); task_runner.get());
leveldb::Status s = backing_store->Initialize(false); leveldb::Status s = backing_store->Initialize(false);
EXPECT_FALSE(s.ok()); EXPECT_FALSE(s.ok());
...@@ -79,12 +81,14 @@ TEST(IndexedDBNonRecoverableIOErrorTest, NuancedCleanupTest) { ...@@ -79,12 +81,14 @@ TEST(IndexedDBNonRecoverableIOErrorTest, NuancedCleanupTest) {
for (leveldb::Status error_status : errors) { for (leveldb::Status error_status : errors) {
std::unique_ptr<IndexedDBBackingStore> backing_store = std::make_unique< std::unique_ptr<IndexedDBBackingStore> backing_store = std::make_unique<
IndexedDBBackingStore>( IndexedDBBackingStore>(
IndexedDBBackingStore::Mode::kInMemory, nullptr, IndexedDBBackingStore::Mode::kInMemory, &transactional_leveldb_factory,
&transactional_leveldb_factory, origin, path, origin, path,
transactional_leveldb_factory.CreateLevelDBDatabase( transactional_leveldb_factory.CreateLevelDBDatabase(
FakeLevelDBFactory::GetBrokenLevelDB(error_status, path), nullptr, FakeLevelDBFactory::GetBrokenLevelDB(error_status, path), nullptr,
task_runner.get(), task_runner.get(),
TransactionalLevelDBDatabase::kDefaultMaxOpenIteratorsPerDatabase), TransactionalLevelDBDatabase::kDefaultMaxOpenIteratorsPerDatabase),
IndexedDBBackingStore::BlobFilesCleanedCallback(),
IndexedDBBackingStore::ReportOutstandingBlobsCallback(),
task_runner.get()); task_runner.get());
leveldb::Status s = backing_store->Initialize(false); leveldb::Status s = backing_store->Initialize(false);
ASSERT_TRUE(s.IsIOError()); ASSERT_TRUE(s.IsIOError());
......
...@@ -188,7 +188,7 @@ TEST_F(IndexedDBDatabaseTest, ForcedClose) { ...@@ -188,7 +188,7 @@ TEST_F(IndexedDBDatabaseTest, ForcedClose) {
transaction_id, std::set<int64_t>(scope.begin(), scope.end()), transaction_id, std::set<int64_t>(scope.begin(), scope.end()),
blink::mojom::IDBTransactionMode::ReadOnly, blink::mojom::IDBTransactionMode::ReadOnly,
new IndexedDBBackingStore::Transaction( new IndexedDBBackingStore::Transaction(
backing_store_.get(), backing_store_->AsWeakPtr(),
blink::mojom::IDBTransactionDurability::Relaxed)); blink::mojom::IDBTransactionDurability::Relaxed));
db_->RegisterAndScheduleTransaction(transaction); db_->RegisterAndScheduleTransaction(transaction);
......
...@@ -778,10 +778,14 @@ std::unique_ptr<IndexedDBBackingStore> IndexedDBFactoryImpl::CreateBackingStore( ...@@ -778,10 +778,14 @@ std::unique_ptr<IndexedDBBackingStore> IndexedDBFactoryImpl::CreateBackingStore(
const url::Origin& origin, const url::Origin& origin,
const base::FilePath& blob_path, const base::FilePath& blob_path,
std::unique_ptr<TransactionalLevelDBDatabase> db, std::unique_ptr<TransactionalLevelDBDatabase> db,
IndexedDBBackingStore::BlobFilesCleanedCallback blob_files_cleaned,
IndexedDBBackingStore::ReportOutstandingBlobsCallback
report_outstanding_blobs,
base::SequencedTaskRunner* task_runner) { base::SequencedTaskRunner* task_runner) {
return std::make_unique<IndexedDBBackingStore>( return std::make_unique<IndexedDBBackingStore>(
backing_store_mode, this, transactional_leveldb_factory, origin, backing_store_mode, transactional_leveldb_factory, origin, blob_path,
blob_path, std::move(db), task_runner); std::move(db), std::move(blob_files_cleaned),
std::move(report_outstanding_blobs), task_runner);
} }
std::tuple<std::unique_ptr<IndexedDBBackingStore>, std::tuple<std::unique_ptr<IndexedDBBackingStore>,
...@@ -908,7 +912,12 @@ IndexedDBFactoryImpl::OpenAndVerifyIndexedDBBackingStore( ...@@ -908,7 +912,12 @@ IndexedDBFactoryImpl::OpenAndVerifyIndexedDBBackingStore(
: IndexedDBBackingStore::Mode::kOnDisk; : IndexedDBBackingStore::Mode::kOnDisk;
std::unique_ptr<IndexedDBBackingStore> backing_store = CreateBackingStore( std::unique_ptr<IndexedDBBackingStore> backing_store = CreateBackingStore(
backing_store_mode, &class_factory_->transactional_leveldb_factory(), backing_store_mode, &class_factory_->transactional_leveldb_factory(),
origin, blob_path, std::move(database), context_->TaskRunner()); origin, blob_path, std::move(database),
base::BindRepeating(&IndexedDBFactoryImpl::BlobFilesCleaned,
weak_factory_.GetWeakPtr(), origin),
base::BindRepeating(&IndexedDBFactoryImpl::ReportOutstandingBlobs,
weak_factory_.GetWeakPtr(), origin),
context_->TaskRunner());
status = backing_store->Initialize( status = backing_store->Initialize(
/*cleanup_live_journal=*/(!is_incognito_and_in_memory && /*cleanup_live_journal=*/(!is_incognito_and_in_memory &&
first_open_since_startup)); first_open_since_startup));
......
...@@ -146,6 +146,9 @@ class CONTENT_EXPORT IndexedDBFactoryImpl : public IndexedDBFactory { ...@@ -146,6 +146,9 @@ class CONTENT_EXPORT IndexedDBFactoryImpl : public IndexedDBFactory {
const url::Origin& origin, const url::Origin& origin,
const base::FilePath& blob_path, const base::FilePath& blob_path,
std::unique_ptr<TransactionalLevelDBDatabase> db, std::unique_ptr<TransactionalLevelDBDatabase> db,
IndexedDBBackingStore::BlobFilesCleanedCallback blob_files_cleaned,
IndexedDBBackingStore::ReportOutstandingBlobsCallback
report_outstanding_blobs,
base::SequencedTaskRunner* task_runner); base::SequencedTaskRunner* task_runner);
IndexedDBContextImpl* context() const { return context_; } IndexedDBContextImpl* context() const { return context_; }
...@@ -205,6 +208,7 @@ class CONTENT_EXPORT IndexedDBFactoryImpl : public IndexedDBFactory { ...@@ -205,6 +208,7 @@ class CONTENT_EXPORT IndexedDBFactoryImpl : public IndexedDBFactory {
bool IsBackingStorePendingClose(const url::Origin& origin) const; bool IsBackingStorePendingClose(const url::Origin& origin) const;
SEQUENCE_CHECKER(sequence_checker_); SEQUENCE_CHECKER(sequence_checker_);
// Raw pointer is safe because IndexedDBContextImpl owns this object.
IndexedDBContextImpl* context_; IndexedDBContextImpl* context_;
IndexedDBClassFactory* const class_factory_; IndexedDBClassFactory* const class_factory_;
base::Clock* const clock_; base::Clock* const clock_;
......
...@@ -28,21 +28,24 @@ TransactionalLevelDBFactory* GetTransactionalLevelDBFactory() { ...@@ -28,21 +28,24 @@ TransactionalLevelDBFactory* GetTransactionalLevelDBFactory() {
IndexedDBFakeBackingStore::IndexedDBFakeBackingStore() IndexedDBFakeBackingStore::IndexedDBFakeBackingStore()
: IndexedDBBackingStore(IndexedDBBackingStore::Mode::kInMemory, : IndexedDBBackingStore(IndexedDBBackingStore::Mode::kInMemory,
nullptr /* indexed_db_factory */,
GetTransactionalLevelDBFactory(), GetTransactionalLevelDBFactory(),
url::Origin::Create(GURL("http://localhost:81")), url::Origin::Create(GURL("http://localhost:81")),
base::FilePath(), base::FilePath(),
std::unique_ptr<TransactionalLevelDBDatabase>(), std::unique_ptr<TransactionalLevelDBDatabase>(),
BlobFilesCleanedCallback(),
ReportOutstandingBlobsCallback(),
base::SequencedTaskRunnerHandle::Get().get()) {} base::SequencedTaskRunnerHandle::Get().get()) {}
IndexedDBFakeBackingStore::IndexedDBFakeBackingStore( IndexedDBFakeBackingStore::IndexedDBFakeBackingStore(
IndexedDBFactory* factory, BlobFilesCleanedCallback blob_files_cleaned,
ReportOutstandingBlobsCallback report_outstanding_blobs,
base::SequencedTaskRunner* task_runner) base::SequencedTaskRunner* task_runner)
: IndexedDBBackingStore(IndexedDBBackingStore::Mode::kOnDisk, : IndexedDBBackingStore(IndexedDBBackingStore::Mode::kOnDisk,
factory,
GetTransactionalLevelDBFactory(), GetTransactionalLevelDBFactory(),
url::Origin::Create(GURL("http://localhost:81")), url::Origin::Create(GURL("http://localhost:81")),
base::FilePath(), base::FilePath(),
std::unique_ptr<TransactionalLevelDBDatabase>(), std::unique_ptr<TransactionalLevelDBDatabase>(),
std::move(blob_files_cleaned),
std::move(report_outstanding_blobs),
task_runner) {} task_runner) {}
IndexedDBFakeBackingStore::~IndexedDBFakeBackingStore() {} IndexedDBFakeBackingStore::~IndexedDBFakeBackingStore() {}
......
...@@ -24,13 +24,13 @@ class IndexedDBKeyRange; ...@@ -24,13 +24,13 @@ class IndexedDBKeyRange;
namespace content { namespace content {
class IndexedDBFactory;
class IndexedDBFakeBackingStore : public IndexedDBBackingStore { class IndexedDBFakeBackingStore : public IndexedDBBackingStore {
public: public:
IndexedDBFakeBackingStore(); IndexedDBFakeBackingStore();
IndexedDBFakeBackingStore(IndexedDBFactory* factory, IndexedDBFakeBackingStore(
base::SequencedTaskRunner* task_runner); BlobFilesCleanedCallback blob_files_cleaned,
ReportOutstandingBlobsCallback report_outstanding_blobs,
base::SequencedTaskRunner* task_runner);
~IndexedDBFakeBackingStore() override; ~IndexedDBFakeBackingStore() override;
leveldb::Status DeleteDatabase( leveldb::Status DeleteDatabase(
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/feature_list.h" #include "base/feature_list.h"
#include "base/rand_util.h" #include "base/rand_util.h"
#include "base/stl_util.h" #include "base/stl_util.h"
#include "content/browser/indexed_db/indexed_db_active_blob_registry.h"
#include "content/browser/indexed_db/indexed_db_backing_store.h" #include "content/browser/indexed_db/indexed_db_backing_store.h"
#include "content/browser/indexed_db/indexed_db_class_factory.h" #include "content/browser/indexed_db/indexed_db_class_factory.h"
#include "content/browser/indexed_db/indexed_db_connection.h" #include "content/browser/indexed_db/indexed_db_connection.h"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment