| 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; | 
|  |