Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(60)

Side by Side Diff: content/browser/indexed_db/indexed_db_callbacks.cc

Issue 2892223003: [IndexedDB] Added wrapper to cursor to avoid use-after-free on shutdown. (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/indexed_db/indexed_db_callbacks.h" 5 #include "content/browser/indexed_db/indexed_db_callbacks.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <memory> 10 #include <memory>
(...skipping 26 matching lines...) Expand all
37 #include "storage/browser/quota/quota_manager.h" 37 #include "storage/browser/quota/quota_manager.h"
38 38
39 using indexed_db::mojom::CallbacksAssociatedPtrInfo; 39 using indexed_db::mojom::CallbacksAssociatedPtrInfo;
40 using std::swap; 40 using std::swap;
41 using storage::ShareableFileReference; 41 using storage::ShareableFileReference;
42 42
43 namespace content { 43 namespace content {
44 44
45 namespace { 45 namespace {
46 46
47 // If this is destructed with the connection still living inside it, we assume 47 // The following two objects protect the given objects from being destructed on
48 // we have been killed due to IO thread shutdown, and we need to safely schedule 48 // the IO thread if we have a shutdown or an error.
49 // the destruction of the connection on the IDB thread, as we should still be in
50 // a transaction's operation queue, where we cannot destroy the transaction.
51 struct SafeIOThreadConnectionWrapper { 49 struct SafeIOThreadConnectionWrapper {
52 SafeIOThreadConnectionWrapper(std::unique_ptr<IndexedDBConnection> connection) 50 SafeIOThreadConnectionWrapper(std::unique_ptr<IndexedDBConnection> connection)
53 : connection(std::move(connection)), 51 : connection(std::move(connection)),
54 idb_runner(base::ThreadTaskRunnerHandle::Get()) {} 52 idb_runner(base::ThreadTaskRunnerHandle::Get()) {}
55 ~SafeIOThreadConnectionWrapper() { 53 ~SafeIOThreadConnectionWrapper() {
56 if (connection) { 54 if (connection) {
57 idb_runner->PostTask( 55 idb_runner->PostTask(
58 FROM_HERE, base::Bind( 56 FROM_HERE, base::Bind(
59 [](std::unique_ptr<IndexedDBConnection> connection) { 57 [](std::unique_ptr<IndexedDBConnection> connection) {
60 connection->ForceClose(); 58 connection->ForceClose();
61 }, 59 },
62 base::Passed(&connection))); 60 base::Passed(&connection)));
63 } 61 }
64 } 62 }
65 SafeIOThreadConnectionWrapper(SafeIOThreadConnectionWrapper&& other) = 63 SafeIOThreadConnectionWrapper(SafeIOThreadConnectionWrapper&& other) =
66 default; 64 default;
67 65
68 std::unique_ptr<IndexedDBConnection> connection; 66 std::unique_ptr<IndexedDBConnection> connection;
69 scoped_refptr<base::SequencedTaskRunner> idb_runner; 67 scoped_refptr<base::SequencedTaskRunner> idb_runner;
70 68
71 private: 69 private:
72 DISALLOW_COPY_AND_ASSIGN(SafeIOThreadConnectionWrapper); 70 DISALLOW_COPY_AND_ASSIGN(SafeIOThreadConnectionWrapper);
73 }; 71 };
74 72
73 struct SafeIOThreadCursorWrapper {
74 SafeIOThreadCursorWrapper(std::unique_ptr<IndexedDBCursor> cursor)
75 : cursor(std::move(cursor)),
76 idb_runner(base::ThreadTaskRunnerHandle::Get()) {}
77 ~SafeIOThreadCursorWrapper() {
78 if (cursor)
79 idb_runner->DeleteSoon(FROM_HERE, cursor.release());
80 }
81 SafeIOThreadCursorWrapper(SafeIOThreadCursorWrapper&& other) = default;
82
83 std::unique_ptr<IndexedDBCursor> cursor;
84 scoped_refptr<base::SequencedTaskRunner> idb_runner;
85
86 private:
87 DISALLOW_COPY_AND_ASSIGN(SafeIOThreadCursorWrapper);
88 };
89
75 void ConvertBlobInfo( 90 void ConvertBlobInfo(
76 const std::vector<IndexedDBBlobInfo>& blob_info, 91 const std::vector<IndexedDBBlobInfo>& blob_info,
77 std::vector<::indexed_db::mojom::BlobInfoPtr>* blob_or_file_info) { 92 std::vector<::indexed_db::mojom::BlobInfoPtr>* blob_or_file_info) {
78 blob_or_file_info->reserve(blob_info.size()); 93 blob_or_file_info->reserve(blob_info.size());
79 for (const auto& iter : blob_info) { 94 for (const auto& iter : blob_info) {
80 if (!iter.mark_used_callback().is_null()) 95 if (!iter.mark_used_callback().is_null())
81 iter.mark_used_callback().Run(); 96 iter.mark_used_callback().Run();
82 97
83 auto info = ::indexed_db::mojom::BlobInfo::New(); 98 auto info = ::indexed_db::mojom::BlobInfo::New();
84 info->mime_type = iter.type(); 99 info->mime_type = iter.type();
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 void SendError(const IndexedDBDatabaseError& error); 137 void SendError(const IndexedDBDatabaseError& error);
123 void SendSuccessStringList(const std::vector<base::string16>& value); 138 void SendSuccessStringList(const std::vector<base::string16>& value);
124 void SendBlocked(int64_t existing_version); 139 void SendBlocked(int64_t existing_version);
125 void SendUpgradeNeeded(SafeIOThreadConnectionWrapper connection, 140 void SendUpgradeNeeded(SafeIOThreadConnectionWrapper connection,
126 int64_t old_version, 141 int64_t old_version,
127 blink::WebIDBDataLoss data_loss, 142 blink::WebIDBDataLoss data_loss,
128 const std::string& data_loss_message, 143 const std::string& data_loss_message,
129 const content::IndexedDBDatabaseMetadata& metadata); 144 const content::IndexedDBDatabaseMetadata& metadata);
130 void SendSuccessDatabase(SafeIOThreadConnectionWrapper connection, 145 void SendSuccessDatabase(SafeIOThreadConnectionWrapper connection,
131 const content::IndexedDBDatabaseMetadata& metadata); 146 const content::IndexedDBDatabaseMetadata& metadata);
132 void SendSuccessCursor(std::unique_ptr<IndexedDBCursor> cursor, 147 void SendSuccessCursor(SafeIOThreadCursorWrapper cursor,
133 const IndexedDBKey& key, 148 const IndexedDBKey& key,
134 const IndexedDBKey& primary_key, 149 const IndexedDBKey& primary_key,
135 ::indexed_db::mojom::ValuePtr value, 150 ::indexed_db::mojom::ValuePtr value,
136 const std::vector<IndexedDBBlobInfo>& blob_info); 151 const std::vector<IndexedDBBlobInfo>& blob_info);
137 void SendSuccessValue(::indexed_db::mojom::ReturnValuePtr value, 152 void SendSuccessValue(::indexed_db::mojom::ReturnValuePtr value,
138 const std::vector<IndexedDBBlobInfo>& blob_info); 153 const std::vector<IndexedDBBlobInfo>& blob_info);
139 void SendSuccessCursorContinue( 154 void SendSuccessCursorContinue(
140 const IndexedDBKey& key, 155 const IndexedDBKey& key,
141 const IndexedDBKey& primary_key, 156 const IndexedDBKey& primary_key,
142 ::indexed_db::mojom::ValuePtr value, 157 ::indexed_db::mojom::ValuePtr value,
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 336
322 DCHECK_EQ(blink::kWebIDBDataLossNone, data_loss_); 337 DCHECK_EQ(blink::kWebIDBDataLossNone, data_loss_);
323 338
324 ::indexed_db::mojom::ValuePtr mojo_value; 339 ::indexed_db::mojom::ValuePtr mojo_value;
325 std::vector<IndexedDBBlobInfo> blob_info; 340 std::vector<IndexedDBBlobInfo> blob_info;
326 if (value) { 341 if (value) {
327 mojo_value = ConvertAndEraseValue(value); 342 mojo_value = ConvertAndEraseValue(value);
328 blob_info.swap(value->blob_info); 343 blob_info.swap(value->blob_info);
329 } 344 }
330 345
346 SafeIOThreadCursorWrapper cursor_wrapper(std::move(cursor));
347
331 BrowserThread::PostTask( 348 BrowserThread::PostTask(
332 BrowserThread::IO, FROM_HERE, 349 BrowserThread::IO, FROM_HERE,
333 base::Bind(&IOThreadHelper::SendSuccessCursor, 350 base::Bind(&IOThreadHelper::SendSuccessCursor,
334 base::Unretained(io_helper_.get()), base::Passed(&cursor), key, 351 base::Unretained(io_helper_.get()),
335 primary_key, base::Passed(&mojo_value), 352 base::Passed(&cursor_wrapper), key, primary_key,
336 base::Passed(&blob_info))); 353 base::Passed(&mojo_value), base::Passed(&blob_info)));
337 complete_ = true; 354 complete_ = true;
338 } 355 }
339 356
340 void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& key, 357 void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& key,
341 const IndexedDBKey& primary_key, 358 const IndexedDBKey& primary_key,
342 IndexedDBValue* value) { 359 IndexedDBValue* value) {
343 DCHECK(thread_checker_.CalledOnValidThread()); 360 DCHECK(thread_checker_.CalledOnValidThread());
344 DCHECK(!complete_); 361 DCHECK(!complete_);
345 DCHECK(io_helper_); 362 DCHECK(io_helper_);
346 363
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
567 dispatcher_host_.get(), idb_runner_); 584 dispatcher_host_.get(), idb_runner_);
568 585
569 auto request = mojo::MakeRequest(&ptr_info); 586 auto request = mojo::MakeRequest(&ptr_info);
570 dispatcher_host_->AddDatabaseBinding(std::move(database), 587 dispatcher_host_->AddDatabaseBinding(std::move(database),
571 std::move(request)); 588 std::move(request));
572 } 589 }
573 callbacks_->SuccessDatabase(std::move(ptr_info), metadata); 590 callbacks_->SuccessDatabase(std::move(ptr_info), metadata);
574 } 591 }
575 592
576 void IndexedDBCallbacks::IOThreadHelper::SendSuccessCursor( 593 void IndexedDBCallbacks::IOThreadHelper::SendSuccessCursor(
577 std::unique_ptr<IndexedDBCursor> cursor, 594 SafeIOThreadCursorWrapper cursor,
578 const IndexedDBKey& key, 595 const IndexedDBKey& key,
579 const IndexedDBKey& primary_key, 596 const IndexedDBKey& primary_key,
580 ::indexed_db::mojom::ValuePtr value, 597 ::indexed_db::mojom::ValuePtr value,
581 const std::vector<IndexedDBBlobInfo>& blob_info) { 598 const std::vector<IndexedDBBlobInfo>& blob_info) {
582 DCHECK_CURRENTLY_ON(BrowserThread::IO); 599 DCHECK_CURRENTLY_ON(BrowserThread::IO);
583 if (!callbacks_) 600 if (!callbacks_)
584 return; 601 return;
585 if (!dispatcher_host_) { 602 if (!dispatcher_host_) {
586 OnConnectionError(); 603 OnConnectionError();
587 return; 604 return;
588 } 605 }
589 auto cursor_impl = base::MakeUnique<CursorImpl>( 606 auto cursor_impl = base::MakeUnique<CursorImpl>(
590 std::move(cursor), origin_, dispatcher_host_.get(), idb_runner_); 607 std::move(cursor.cursor), origin_, dispatcher_host_.get(), idb_runner_);
591 608
592 if (value && !CreateAllBlobs(blob_info, &value->blob_or_file_info)) 609 if (value && !CreateAllBlobs(blob_info, &value->blob_or_file_info))
593 return; 610 return;
594 611
595 ::indexed_db::mojom::CursorAssociatedPtrInfo ptr_info; 612 ::indexed_db::mojom::CursorAssociatedPtrInfo ptr_info;
596 auto request = mojo::MakeRequest(&ptr_info); 613 auto request = mojo::MakeRequest(&ptr_info);
597 dispatcher_host_->AddCursorBinding(std::move(cursor_impl), 614 dispatcher_host_->AddCursorBinding(std::move(cursor_impl),
598 std::move(request)); 615 std::move(request));
599 callbacks_->SuccessCursor(std::move(ptr_info), key, primary_key, 616 callbacks_->SuccessCursor(std::move(ptr_info), key, primary_key,
600 std::move(value)); 617 std::move(value));
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
749 return true; 766 return true;
750 } 767 }
751 768
752 void IndexedDBCallbacks::IOThreadHelper::OnConnectionError() { 769 void IndexedDBCallbacks::IOThreadHelper::OnConnectionError() {
753 DCHECK_CURRENTLY_ON(BrowserThread::IO); 770 DCHECK_CURRENTLY_ON(BrowserThread::IO);
754 callbacks_.reset(); 771 callbacks_.reset();
755 dispatcher_host_ = nullptr; 772 dispatcher_host_ = nullptr;
756 } 773 }
757 774
758 } // namespace content 775 } // namespace content
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698