OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/child/indexed_db/webidbcursor_impl.h" | 5 #include "content/child/indexed_db/webidbcursor_impl.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <string> | 9 #include <string> |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #include "content/child/indexed_db/indexed_db_dispatcher.h" | 12 #include "content/child/indexed_db/indexed_db_dispatcher.h" |
13 #include "content/child/indexed_db/indexed_db_key_builders.h" | 13 #include "content/child/indexed_db/indexed_db_key_builders.h" |
14 #include "content/child/thread_safe_sender.h" | |
15 #include "content/common/indexed_db/indexed_db_messages.h" | 14 #include "content/common/indexed_db/indexed_db_messages.h" |
| 15 #include "mojo/public/cpp/bindings/strong_associated_binding.h" |
16 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBValue.h" | 16 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBValue.h" |
17 | 17 |
18 using blink::WebBlobInfo; | 18 using blink::WebBlobInfo; |
19 using blink::WebData; | 19 using blink::WebData; |
20 using blink::WebIDBCallbacks; | 20 using blink::WebIDBCallbacks; |
21 using blink::WebIDBKey; | 21 using blink::WebIDBKey; |
22 using blink::WebIDBValue; | 22 using blink::WebIDBValue; |
| 23 using indexed_db::mojom::CallbacksAssociatedPtrInfo; |
| 24 using indexed_db::mojom::CursorAssociatedPtrInfo; |
23 | 25 |
24 namespace content { | 26 namespace content { |
25 | 27 |
26 WebIDBCursorImpl::WebIDBCursorImpl(int32_t ipc_cursor_id, | 28 class WebIDBCursorImpl::IOThreadHelper { |
27 int64_t transaction_id, | 29 public: |
28 ThreadSafeSender* thread_safe_sender) | 30 IOThreadHelper(); |
29 : ipc_cursor_id_(ipc_cursor_id), | 31 ~IOThreadHelper(); |
30 transaction_id_(transaction_id), | 32 |
| 33 void Bind(CursorAssociatedPtrInfo cursor_info); |
| 34 void Advance(uint32_t count, |
| 35 std::unique_ptr<IndexedDBCallbacksImpl> callbacks); |
| 36 void Continue(const IndexedDBKey& key, |
| 37 const IndexedDBKey& primary_key, |
| 38 std::unique_ptr<IndexedDBCallbacksImpl> callbacks); |
| 39 void Prefetch(int32_t count, |
| 40 std::unique_ptr<IndexedDBCallbacksImpl> callbacks); |
| 41 void PrefetchReset(int32_t used_prefetches, |
| 42 int32_t unused_prefetches, |
| 43 const std::vector<std::string>& unused_blob_uuids); |
| 44 |
| 45 private: |
| 46 CallbacksAssociatedPtrInfo GetCallbacksProxy( |
| 47 std::unique_ptr<IndexedDBCallbacksImpl> callbacks); |
| 48 |
| 49 indexed_db::mojom::CursorAssociatedPtr cursor_; |
| 50 |
| 51 DISALLOW_COPY_AND_ASSIGN(IOThreadHelper); |
| 52 }; |
| 53 |
| 54 WebIDBCursorImpl::WebIDBCursorImpl( |
| 55 indexed_db::mojom::CursorAssociatedPtrInfo cursor_info, |
| 56 int64_t transaction_id, |
| 57 scoped_refptr<base::SingleThreadTaskRunner> io_runner) |
| 58 : transaction_id_(transaction_id), |
| 59 helper_(new IOThreadHelper()), |
| 60 io_runner_(std::move(io_runner)), |
31 continue_count_(0), | 61 continue_count_(0), |
32 used_prefetches_(0), | 62 used_prefetches_(0), |
33 pending_onsuccess_callbacks_(0), | 63 pending_onsuccess_callbacks_(0), |
34 prefetch_amount_(kMinPrefetchAmount), | 64 prefetch_amount_(kMinPrefetchAmount), |
35 thread_safe_sender_(thread_safe_sender) {} | 65 weak_factory_(this) { |
| 66 IndexedDBDispatcher::ThreadSpecificInstance()->RegisterCursor(this); |
| 67 io_runner_->PostTask( |
| 68 FROM_HERE, base::Bind(&IOThreadHelper::Bind, base::Unretained(helper_), |
| 69 base::Passed(&cursor_info))); |
| 70 } |
36 | 71 |
37 WebIDBCursorImpl::~WebIDBCursorImpl() { | 72 WebIDBCursorImpl::~WebIDBCursorImpl() { |
38 // It's not possible for there to be pending callbacks that address this | 73 // It's not possible for there to be pending callbacks that address this |
39 // object since inside WebKit, they hold a reference to the object which owns | 74 // object since inside WebKit, they hold a reference to the object which owns |
40 // this object. But, if that ever changed, then we'd need to invalidate | 75 // this object. But, if that ever changed, then we'd need to invalidate |
41 // any such pointers. | 76 // any such pointers. |
42 | 77 IndexedDBDispatcher::ThreadSpecificInstance()->UnregisterCursor(this); |
43 if (ipc_cursor_id_ != kInvalidCursorId) { | 78 io_runner_->DeleteSoon(FROM_HERE, helper_); |
44 // Invalid ID used in tests to avoid really sending this message. | |
45 thread_safe_sender_->Send( | |
46 new IndexedDBHostMsg_CursorDestroyed(ipc_cursor_id_)); | |
47 } | |
48 IndexedDBDispatcher* dispatcher = | |
49 IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get()); | |
50 dispatcher->CursorDestroyed(ipc_cursor_id_); | |
51 } | 79 } |
52 | 80 |
53 void WebIDBCursorImpl::advance(unsigned long count, | 81 void WebIDBCursorImpl::advance(unsigned long count, |
54 WebIDBCallbacks* callbacks_ptr) { | 82 WebIDBCallbacks* callbacks_ptr) { |
55 IndexedDBDispatcher* dispatcher = | |
56 IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get()); | |
57 std::unique_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); | 83 std::unique_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); |
58 if (count <= prefetch_keys_.size()) { | 84 if (count <= prefetch_keys_.size()) { |
59 CachedAdvance(count, callbacks.get()); | 85 CachedAdvance(count, callbacks.get()); |
60 return; | 86 return; |
61 } | 87 } |
62 ResetPrefetchCache(); | 88 ResetPrefetchCache(); |
63 dispatcher->RequestIDBCursorAdvance( | 89 |
64 count, callbacks.release(), ipc_cursor_id_, transaction_id_); | 90 // Reset all cursor prefetch caches except for this cursor. |
| 91 IndexedDBDispatcher::ThreadSpecificInstance()->ResetCursorPrefetchCaches( |
| 92 transaction_id_, this); |
| 93 |
| 94 auto callbacks_impl = base::MakeUnique<IndexedDBCallbacksImpl>( |
| 95 std::move(callbacks), transaction_id_, weak_factory_.GetWeakPtr(), |
| 96 io_runner_); |
| 97 io_runner_->PostTask( |
| 98 FROM_HERE, base::Bind(&IOThreadHelper::Advance, base::Unretained(helper_), |
| 99 count, base::Passed(&callbacks_impl))); |
65 } | 100 } |
66 | 101 |
67 void WebIDBCursorImpl::continueFunction(const WebIDBKey& key, | 102 void WebIDBCursorImpl::continueFunction(const WebIDBKey& key, |
68 WebIDBCallbacks* callbacks_ptr) { | 103 WebIDBCallbacks* callbacks_ptr) { |
69 continueFunction(key, WebIDBKey::createNull(), callbacks_ptr); | 104 continueFunction(key, WebIDBKey::createNull(), callbacks_ptr); |
70 } | 105 } |
71 | 106 |
72 void WebIDBCursorImpl::continueFunction(const WebIDBKey& key, | 107 void WebIDBCursorImpl::continueFunction(const WebIDBKey& key, |
73 const WebIDBKey& primary_key, | 108 const WebIDBKey& primary_key, |
74 WebIDBCallbacks* callbacks_ptr) { | 109 WebIDBCallbacks* callbacks_ptr) { |
75 IndexedDBDispatcher* dispatcher = | |
76 IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get()); | |
77 std::unique_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); | 110 std::unique_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); |
78 | 111 |
79 if (key.keyType() == blink::WebIDBKeyTypeNull && | 112 if (key.keyType() == blink::WebIDBKeyTypeNull && |
80 primary_key.keyType() == blink::WebIDBKeyTypeNull) { | 113 primary_key.keyType() == blink::WebIDBKeyTypeNull) { |
81 // No key(s), so this would qualify for a prefetch. | 114 // No key(s), so this would qualify for a prefetch. |
82 ++continue_count_; | 115 ++continue_count_; |
83 | 116 |
84 if (!prefetch_keys_.empty()) { | 117 if (!prefetch_keys_.empty()) { |
85 // We have a prefetch cache, so serve the result from that. | 118 // We have a prefetch cache, so serve the result from that. |
86 CachedContinue(callbacks.get()); | 119 CachedContinue(callbacks.get()); |
87 return; | 120 return; |
88 } | 121 } |
89 | 122 |
90 if (continue_count_ > kPrefetchContinueThreshold) { | 123 if (continue_count_ > kPrefetchContinueThreshold) { |
91 // Request pre-fetch. | 124 // Request pre-fetch. |
92 ++pending_onsuccess_callbacks_; | 125 ++pending_onsuccess_callbacks_; |
93 dispatcher->RequestIDBCursorPrefetch( | 126 |
94 prefetch_amount_, callbacks.release(), ipc_cursor_id_); | 127 auto callbacks_impl = base::MakeUnique<IndexedDBCallbacksImpl>( |
| 128 std::move(callbacks), transaction_id_, weak_factory_.GetWeakPtr(), |
| 129 io_runner_); |
| 130 io_runner_->PostTask( |
| 131 FROM_HERE, |
| 132 base::Bind(&IOThreadHelper::Prefetch, base::Unretained(helper_), |
| 133 prefetch_amount_, base::Passed(&callbacks_impl))); |
95 | 134 |
96 // Increase prefetch_amount_ exponentially. | 135 // Increase prefetch_amount_ exponentially. |
97 prefetch_amount_ *= 2; | 136 prefetch_amount_ *= 2; |
98 if (prefetch_amount_ > kMaxPrefetchAmount) | 137 if (prefetch_amount_ > kMaxPrefetchAmount) |
99 prefetch_amount_ = kMaxPrefetchAmount; | 138 prefetch_amount_ = kMaxPrefetchAmount; |
100 | 139 |
101 return; | 140 return; |
102 } | 141 } |
103 } else { | 142 } else { |
104 // Key argument supplied. We couldn't prefetch this. | 143 // Key argument supplied. We couldn't prefetch this. |
105 ResetPrefetchCache(); | 144 ResetPrefetchCache(); |
106 } | 145 } |
107 | 146 |
108 dispatcher->RequestIDBCursorContinue(IndexedDBKeyBuilder::Build(key), | 147 // Reset all cursor prefetch caches except for this cursor. |
109 IndexedDBKeyBuilder::Build(primary_key), | 148 IndexedDBDispatcher::ThreadSpecificInstance()->ResetCursorPrefetchCaches( |
110 callbacks.release(), | 149 transaction_id_, this); |
111 ipc_cursor_id_, | 150 |
112 transaction_id_); | 151 auto callbacks_impl = base::MakeUnique<IndexedDBCallbacksImpl>( |
| 152 std::move(callbacks), transaction_id_, weak_factory_.GetWeakPtr(), |
| 153 io_runner_); |
| 154 io_runner_->PostTask( |
| 155 FROM_HERE, |
| 156 base::Bind(&IOThreadHelper::Continue, base::Unretained(helper_), |
| 157 IndexedDBKeyBuilder::Build(key), |
| 158 IndexedDBKeyBuilder::Build(primary_key), |
| 159 base::Passed(&callbacks_impl))); |
113 } | 160 } |
114 | 161 |
115 void WebIDBCursorImpl::postSuccessHandlerCallback() { | 162 void WebIDBCursorImpl::postSuccessHandlerCallback() { |
116 pending_onsuccess_callbacks_--; | 163 pending_onsuccess_callbacks_--; |
117 | 164 |
118 // If the onsuccess callback called continue()/advance() on the cursor | 165 // If the onsuccess callback called continue()/advance() on the cursor |
119 // again, and that request was served by the prefetch cache, then | 166 // again, and that request was served by the prefetch cache, then |
120 // pending_onsuccess_callbacks_ would be incremented. If not, it means the | 167 // pending_onsuccess_callbacks_ would be incremented. If not, it means the |
121 // callback did something else, or nothing at all, in which case we need to | 168 // callback did something else, or nothing at all, in which case we need to |
122 // reset the cache. | 169 // reset the cache. |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 // No prefetch cache, so no need to reset the cursor in the back-end. | 237 // No prefetch cache, so no need to reset the cursor in the back-end. |
191 return; | 238 return; |
192 } | 239 } |
193 | 240 |
194 // Ack any unused blobs. | 241 // Ack any unused blobs. |
195 std::vector<std::string> uuids; | 242 std::vector<std::string> uuids; |
196 for (const auto& value : prefetch_values_) { | 243 for (const auto& value : prefetch_values_) { |
197 for (size_t i = 0, size = value.webBlobInfo.size(); i < size; ++i) | 244 for (size_t i = 0, size = value.webBlobInfo.size(); i < size; ++i) |
198 uuids.push_back(value.webBlobInfo[i].uuid().latin1()); | 245 uuids.push_back(value.webBlobInfo[i].uuid().latin1()); |
199 } | 246 } |
200 if (!uuids.empty()) | |
201 thread_safe_sender_->Send(new IndexedDBHostMsg_AckReceivedBlobs(uuids)); | |
202 | 247 |
203 // Reset the back-end cursor. | 248 // Reset the back-end cursor. |
204 IndexedDBDispatcher* dispatcher = | 249 io_runner_->PostTask( |
205 IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get()); | 250 FROM_HERE, |
206 dispatcher->RequestIDBCursorPrefetchReset( | 251 base::Bind(&IOThreadHelper::PrefetchReset, base::Unretained(helper_), |
207 used_prefetches_, prefetch_keys_.size(), ipc_cursor_id_); | 252 used_prefetches_, prefetch_keys_.size(), uuids)); |
208 | 253 |
209 // Reset the prefetch cache. | 254 // Reset the prefetch cache. |
210 prefetch_keys_.clear(); | 255 prefetch_keys_.clear(); |
211 prefetch_primary_keys_.clear(); | 256 prefetch_primary_keys_.clear(); |
212 prefetch_values_.clear(); | 257 prefetch_values_.clear(); |
213 | 258 |
214 pending_onsuccess_callbacks_ = 0; | 259 pending_onsuccess_callbacks_ = 0; |
215 } | 260 } |
216 | 261 |
| 262 WebIDBCursorImpl::IOThreadHelper::IOThreadHelper() {} |
| 263 |
| 264 WebIDBCursorImpl::IOThreadHelper::~IOThreadHelper() {} |
| 265 |
| 266 void WebIDBCursorImpl::IOThreadHelper::Bind( |
| 267 CursorAssociatedPtrInfo cursor_info) { |
| 268 cursor_.Bind(std::move(cursor_info)); |
| 269 } |
| 270 |
| 271 void WebIDBCursorImpl::IOThreadHelper::Advance( |
| 272 uint32_t count, |
| 273 std::unique_ptr<IndexedDBCallbacksImpl> callbacks) { |
| 274 cursor_->Advance(count, GetCallbacksProxy(std::move(callbacks))); |
| 275 } |
| 276 |
| 277 void WebIDBCursorImpl::IOThreadHelper::Continue( |
| 278 const IndexedDBKey& key, |
| 279 const IndexedDBKey& primary_key, |
| 280 std::unique_ptr<IndexedDBCallbacksImpl> callbacks) { |
| 281 cursor_->Continue(key, primary_key, GetCallbacksProxy(std::move(callbacks))); |
| 282 } |
| 283 |
| 284 void WebIDBCursorImpl::IOThreadHelper::Prefetch( |
| 285 int32_t count, |
| 286 std::unique_ptr<IndexedDBCallbacksImpl> callbacks) { |
| 287 cursor_->Prefetch(count, GetCallbacksProxy(std::move(callbacks))); |
| 288 } |
| 289 |
| 290 void WebIDBCursorImpl::IOThreadHelper::PrefetchReset( |
| 291 int32_t used_prefetches, |
| 292 int32_t unused_prefetches, |
| 293 const std::vector<std::string>& unused_blob_uuids) { |
| 294 cursor_->PrefetchReset(used_prefetches, unused_prefetches, unused_blob_uuids); |
| 295 } |
| 296 |
| 297 CallbacksAssociatedPtrInfo WebIDBCursorImpl::IOThreadHelper::GetCallbacksProxy( |
| 298 std::unique_ptr<IndexedDBCallbacksImpl> callbacks) { |
| 299 CallbacksAssociatedPtrInfo ptr_info; |
| 300 indexed_db::mojom::CallbacksAssociatedRequest request; |
| 301 cursor_.associated_group()->CreateAssociatedInterface( |
| 302 mojo::AssociatedGroup::WILL_PASS_PTR, &ptr_info, &request); |
| 303 mojo::MakeStrongAssociatedBinding(std::move(callbacks), std::move(request)); |
| 304 return ptr_info; |
| 305 } |
| 306 |
217 } // namespace content | 307 } // namespace content |
OLD | NEW |