| Index: content/browser/indexed_db/indexed_db_callbacks.cc
|
| diff --git a/content/browser/indexed_db/indexed_db_callbacks.cc b/content/browser/indexed_db/indexed_db_callbacks.cc
|
| index 3cd348c5a5a6678ee10b884a95b5f2fc36016799..052eb61df016274ec7c28fdcbac54b802c1e569b 100644
|
| --- a/content/browser/indexed_db/indexed_db_callbacks.cc
|
| +++ b/content/browser/indexed_db/indexed_db_callbacks.cc
|
| @@ -44,10 +44,8 @@ namespace content {
|
|
|
| namespace {
|
|
|
| -// If this is destructed with the connection still living inside it, we assume
|
| -// we have been killed due to IO thread shutdown, and we need to safely schedule
|
| -// the destruction of the connection on the IDB thread, as we should still be in
|
| -// a transaction's operation queue, where we cannot destroy the transaction.
|
| +// The following two objects protect the given objects from being destructed on
|
| +// the IO thread if we have a shutdown or an error.
|
| struct SafeIOThreadConnectionWrapper {
|
| SafeIOThreadConnectionWrapper(std::unique_ptr<IndexedDBConnection> connection)
|
| : connection(std::move(connection)),
|
| @@ -72,6 +70,23 @@ struct SafeIOThreadConnectionWrapper {
|
| DISALLOW_COPY_AND_ASSIGN(SafeIOThreadConnectionWrapper);
|
| };
|
|
|
| +struct SafeIOThreadCursorWrapper {
|
| + SafeIOThreadCursorWrapper(std::unique_ptr<IndexedDBCursor> cursor)
|
| + : cursor(std::move(cursor)),
|
| + idb_runner(base::ThreadTaskRunnerHandle::Get()) {}
|
| + ~SafeIOThreadCursorWrapper() {
|
| + if (cursor)
|
| + idb_runner->DeleteSoon(FROM_HERE, cursor.release());
|
| + }
|
| + SafeIOThreadCursorWrapper(SafeIOThreadCursorWrapper&& other) = default;
|
| +
|
| + std::unique_ptr<IndexedDBCursor> cursor;
|
| + scoped_refptr<base::SequencedTaskRunner> idb_runner;
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(SafeIOThreadCursorWrapper);
|
| +};
|
| +
|
| void ConvertBlobInfo(
|
| const std::vector<IndexedDBBlobInfo>& blob_info,
|
| std::vector<::indexed_db::mojom::BlobInfoPtr>* blob_or_file_info) {
|
| @@ -129,7 +144,7 @@ class IndexedDBCallbacks::IOThreadHelper {
|
| const content::IndexedDBDatabaseMetadata& metadata);
|
| void SendSuccessDatabase(SafeIOThreadConnectionWrapper connection,
|
| const content::IndexedDBDatabaseMetadata& metadata);
|
| - void SendSuccessCursor(std::unique_ptr<IndexedDBCursor> cursor,
|
| + void SendSuccessCursor(SafeIOThreadCursorWrapper cursor,
|
| const IndexedDBKey& key,
|
| const IndexedDBKey& primary_key,
|
| ::indexed_db::mojom::ValuePtr value,
|
| @@ -328,12 +343,14 @@ void IndexedDBCallbacks::OnSuccess(std::unique_ptr<IndexedDBCursor> cursor,
|
| blob_info.swap(value->blob_info);
|
| }
|
|
|
| + SafeIOThreadCursorWrapper cursor_wrapper(std::move(cursor));
|
| +
|
| BrowserThread::PostTask(
|
| BrowserThread::IO, FROM_HERE,
|
| base::Bind(&IOThreadHelper::SendSuccessCursor,
|
| - base::Unretained(io_helper_.get()), base::Passed(&cursor), key,
|
| - primary_key, base::Passed(&mojo_value),
|
| - base::Passed(&blob_info)));
|
| + base::Unretained(io_helper_.get()),
|
| + base::Passed(&cursor_wrapper), key, primary_key,
|
| + base::Passed(&mojo_value), base::Passed(&blob_info)));
|
| complete_ = true;
|
| }
|
|
|
| @@ -574,7 +591,7 @@ void IndexedDBCallbacks::IOThreadHelper::SendSuccessDatabase(
|
| }
|
|
|
| void IndexedDBCallbacks::IOThreadHelper::SendSuccessCursor(
|
| - std::unique_ptr<IndexedDBCursor> cursor,
|
| + SafeIOThreadCursorWrapper cursor,
|
| const IndexedDBKey& key,
|
| const IndexedDBKey& primary_key,
|
| ::indexed_db::mojom::ValuePtr value,
|
| @@ -587,7 +604,7 @@ void IndexedDBCallbacks::IOThreadHelper::SendSuccessCursor(
|
| return;
|
| }
|
| auto cursor_impl = base::MakeUnique<CursorImpl>(
|
| - std::move(cursor), origin_, dispatcher_host_.get(), idb_runner_);
|
| + std::move(cursor.cursor), origin_, dispatcher_host_.get(), idb_runner_);
|
|
|
| if (value && !CreateAllBlobs(blob_info, &value->blob_or_file_info))
|
| return;
|
|
|