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/indexed_db_dispatcher.h" | 5 #include "content/child/indexed_db/indexed_db_dispatcher.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/format_macros.h" | |
10 #include "base/lazy_instance.h" | 9 #include "base/lazy_instance.h" |
11 #include "base/strings/stringprintf.h" | |
12 #include "base/threading/thread_local.h" | 10 #include "base/threading/thread_local.h" |
13 #include "content/child/indexed_db/indexed_db_key_builders.h" | 11 #include "content/child/indexed_db/indexed_db_key_builders.h" |
14 #include "content/child/indexed_db/webidbcursor_impl.h" | 12 #include "content/child/indexed_db/webidbcursor_impl.h" |
15 #include "content/child/indexed_db/webidbdatabase_impl.h" | |
16 #include "content/child/thread_safe_sender.h" | |
17 #include "content/common/indexed_db/indexed_db_messages.h" | 13 #include "content/common/indexed_db/indexed_db_messages.h" |
18 #include "ipc/ipc_channel.h" | 14 #include "ipc/ipc_channel.h" |
19 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseCal
lbacks.h" | 15 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseCal
lbacks.h" |
20 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseErr
or.h" | |
21 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseExc
eption.h" | |
22 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBObservation
.h" | 16 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBObservation
.h" |
23 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBValue.h" | |
24 | 17 |
25 using blink::WebBlobInfo; | |
26 using blink::WebData; | |
27 using blink::WebIDBCallbacks; | |
28 using blink::WebIDBCursor; | |
29 using blink::WebIDBDatabase; | |
30 using blink::WebIDBDatabaseCallbacks; | |
31 using blink::WebIDBDatabaseError; | |
32 using blink::WebIDBKey; | 18 using blink::WebIDBKey; |
33 using blink::WebIDBMetadata; | |
34 using blink::WebIDBObservation; | 19 using blink::WebIDBObservation; |
35 using blink::WebIDBObserver; | 20 using blink::WebIDBObserver; |
36 using blink::WebIDBValue; | |
37 using blink::WebString; | |
38 using blink::WebVector; | |
39 using base::ThreadLocalPointer; | 21 using base::ThreadLocalPointer; |
40 | 22 |
41 namespace content { | 23 namespace content { |
42 static base::LazyInstance<ThreadLocalPointer<IndexedDBDispatcher> >::Leaky | 24 static base::LazyInstance<ThreadLocalPointer<IndexedDBDispatcher> >::Leaky |
43 g_idb_dispatcher_tls = LAZY_INSTANCE_INITIALIZER; | 25 g_idb_dispatcher_tls = LAZY_INSTANCE_INITIALIZER; |
44 | 26 |
45 namespace { | 27 namespace { |
46 | 28 |
47 IndexedDBDispatcher* const kHasBeenDeleted = | 29 IndexedDBDispatcher* const kHasBeenDeleted = |
48 reinterpret_cast<IndexedDBDispatcher*>(0x1); | 30 reinterpret_cast<IndexedDBDispatcher*>(0x1); |
49 | 31 |
50 } // unnamed namespace | 32 } // unnamed namespace |
51 | 33 |
52 IndexedDBDispatcher::IndexedDBDispatcher(ThreadSafeSender* thread_safe_sender) | 34 IndexedDBDispatcher::IndexedDBDispatcher() { |
53 : thread_safe_sender_(thread_safe_sender) { | |
54 g_idb_dispatcher_tls.Pointer()->Set(this); | 35 g_idb_dispatcher_tls.Pointer()->Set(this); |
55 } | 36 } |
56 | 37 |
57 IndexedDBDispatcher::~IndexedDBDispatcher() { | 38 IndexedDBDispatcher::~IndexedDBDispatcher() { |
58 // Clear any pending callbacks - which may result in dispatch requests - | |
59 // before marking the dispatcher as deleted. | |
60 pending_callbacks_.Clear(); | |
61 | |
62 DCHECK(pending_callbacks_.IsEmpty()); | |
63 | |
64 g_idb_dispatcher_tls.Pointer()->Set(kHasBeenDeleted); | 39 g_idb_dispatcher_tls.Pointer()->Set(kHasBeenDeleted); |
65 } | 40 } |
66 | 41 |
67 IndexedDBDispatcher* IndexedDBDispatcher::ThreadSpecificInstance( | 42 IndexedDBDispatcher* IndexedDBDispatcher::ThreadSpecificInstance() { |
68 ThreadSafeSender* thread_safe_sender) { | |
69 if (g_idb_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted) { | 43 if (g_idb_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted) { |
70 NOTREACHED() << "Re-instantiating TLS IndexedDBDispatcher."; | 44 NOTREACHED() << "Re-instantiating TLS IndexedDBDispatcher."; |
71 g_idb_dispatcher_tls.Pointer()->Set(NULL); | 45 g_idb_dispatcher_tls.Pointer()->Set(NULL); |
72 } | 46 } |
73 if (g_idb_dispatcher_tls.Pointer()->Get()) | 47 if (g_idb_dispatcher_tls.Pointer()->Get()) |
74 return g_idb_dispatcher_tls.Pointer()->Get(); | 48 return g_idb_dispatcher_tls.Pointer()->Get(); |
75 | 49 |
76 IndexedDBDispatcher* dispatcher = new IndexedDBDispatcher(thread_safe_sender); | 50 IndexedDBDispatcher* dispatcher = new IndexedDBDispatcher(); |
77 if (WorkerThread::GetCurrentId()) | 51 if (WorkerThread::GetCurrentId()) |
78 WorkerThread::AddObserver(dispatcher); | 52 WorkerThread::AddObserver(dispatcher); |
79 return dispatcher; | 53 return dispatcher; |
80 } | 54 } |
81 | 55 |
82 void IndexedDBDispatcher::WillStopCurrentWorkerThread() { | 56 void IndexedDBDispatcher::WillStopCurrentWorkerThread() { |
83 delete this; | 57 delete this; |
84 } | 58 } |
85 | 59 |
86 std::vector<WebIDBObservation> IndexedDBDispatcher::ConvertObservations( | 60 std::vector<WebIDBObservation> IndexedDBDispatcher::ConvertObservations( |
87 const std::vector<IndexedDBMsg_Observation>& idb_observations) { | 61 const std::vector<IndexedDBMsg_Observation>& idb_observations) { |
88 std::vector<WebIDBObservation> web_observations; | 62 std::vector<WebIDBObservation> web_observations; |
89 for (const auto& idb_observation : idb_observations) { | 63 for (const auto& idb_observation : idb_observations) { |
90 WebIDBObservation web_observation; | 64 WebIDBObservation web_observation; |
91 web_observation.objectStoreId = idb_observation.object_store_id; | 65 web_observation.objectStoreId = idb_observation.object_store_id; |
92 web_observation.type = idb_observation.type; | 66 web_observation.type = idb_observation.type; |
93 web_observation.keyRange = | 67 web_observation.keyRange = |
94 WebIDBKeyRangeBuilder::Build(idb_observation.key_range); | 68 WebIDBKeyRangeBuilder::Build(idb_observation.key_range); |
95 // TODO(palakj): Assign value to web_observation. | 69 // TODO(palakj): Assign value to web_observation. |
96 web_observations.push_back(std::move(web_observation)); | 70 web_observations.push_back(std::move(web_observation)); |
97 } | 71 } |
98 return web_observations; | 72 return web_observations; |
99 } | 73 } |
100 | 74 |
101 void IndexedDBDispatcher::OnMessageReceived(const IPC::Message& msg) { | 75 void IndexedDBDispatcher::OnMessageReceived(const IPC::Message& msg) { |
102 bool handled = true; | 76 bool handled = true; |
103 IPC_BEGIN_MESSAGE_MAP(IndexedDBDispatcher, msg) | 77 IPC_BEGIN_MESSAGE_MAP(IndexedDBDispatcher, msg) |
104 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorAdvance, | |
105 OnSuccessCursorContinue) | |
106 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorContinue, | |
107 OnSuccessCursorContinue) | |
108 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorPrefetch, | |
109 OnSuccessCursorPrefetch) | |
110 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessValue, OnSuccessValue) | |
111 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessInteger, OnSuccessInteger) | |
112 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksError, OnError) | |
113 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksChanges, | 78 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksChanges, |
114 OnDatabaseChanges) | 79 OnDatabaseChanges) |
115 IPC_MESSAGE_UNHANDLED(handled = false) | 80 IPC_MESSAGE_UNHANDLED(handled = false) |
116 IPC_END_MESSAGE_MAP() | 81 IPC_END_MESSAGE_MAP() |
117 // If a message gets here, IndexedDBMessageFilter already determined that it | 82 // If a message gets here, IndexedDBMessageFilter already determined that it |
118 // is an IndexedDB message. | 83 // is an IndexedDB message. |
119 DCHECK(handled) << "Didn't handle a message defined at line " | 84 DCHECK(handled) << "Didn't handle a message defined at line " |
120 << IPC_MESSAGE_ID_LINE(msg.type()); | 85 << IPC_MESSAGE_ID_LINE(msg.type()); |
121 } | 86 } |
122 | 87 |
123 bool IndexedDBDispatcher::Send(IPC::Message* msg) { | |
124 return thread_safe_sender_->Send(msg); | |
125 } | |
126 | |
127 int32_t IndexedDBDispatcher::RegisterObserver( | 88 int32_t IndexedDBDispatcher::RegisterObserver( |
128 std::unique_ptr<WebIDBObserver> observer) { | 89 std::unique_ptr<WebIDBObserver> observer) { |
129 return observers_.Add(observer.release()); | 90 return observers_.Add(observer.release()); |
130 } | 91 } |
131 | 92 |
132 void IndexedDBDispatcher::RemoveObservers( | 93 void IndexedDBDispatcher::RemoveObservers( |
133 const std::vector<int32_t>& observer_ids_to_remove) { | 94 const std::vector<int32_t>& observer_ids_to_remove) { |
134 for (int32_t id : observer_ids_to_remove) | 95 for (int32_t id : observer_ids_to_remove) |
135 observers_.Remove(id); | 96 observers_.Remove(id); |
136 } | 97 } |
137 | 98 |
138 void IndexedDBDispatcher::RequestIDBCursorAdvance( | |
139 unsigned long count, | |
140 WebIDBCallbacks* callbacks_ptr, | |
141 int32_t ipc_cursor_id, | |
142 int64_t transaction_id) { | |
143 // Reset all cursor prefetch caches except for this cursor. | |
144 ResetCursorPrefetchCaches(transaction_id, ipc_cursor_id); | |
145 | |
146 std::unique_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); | |
147 | |
148 int32_t ipc_callbacks_id = pending_callbacks_.Add(callbacks.release()); | |
149 Send(new IndexedDBHostMsg_CursorAdvance( | |
150 ipc_cursor_id, CurrentWorkerId(), ipc_callbacks_id, count)); | |
151 } | |
152 | |
153 void IndexedDBDispatcher::RequestIDBCursorContinue( | |
154 const IndexedDBKey& key, | |
155 const IndexedDBKey& primary_key, | |
156 WebIDBCallbacks* callbacks_ptr, | |
157 int32_t ipc_cursor_id, | |
158 int64_t transaction_id) { | |
159 // Reset all cursor prefetch caches except for this cursor. | |
160 ResetCursorPrefetchCaches(transaction_id, ipc_cursor_id); | |
161 | |
162 std::unique_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); | |
163 | |
164 int32_t ipc_callbacks_id = pending_callbacks_.Add(callbacks.release()); | |
165 Send(new IndexedDBHostMsg_CursorContinue( | |
166 ipc_cursor_id, CurrentWorkerId(), ipc_callbacks_id, key, primary_key)); | |
167 } | |
168 | |
169 void IndexedDBDispatcher::RequestIDBCursorPrefetch( | |
170 int n, | |
171 WebIDBCallbacks* callbacks_ptr, | |
172 int32_t ipc_cursor_id) { | |
173 std::unique_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); | |
174 | |
175 int32_t ipc_callbacks_id = pending_callbacks_.Add(callbacks.release()); | |
176 Send(new IndexedDBHostMsg_CursorPrefetch( | |
177 ipc_cursor_id, CurrentWorkerId(), ipc_callbacks_id, n)); | |
178 } | |
179 | |
180 void IndexedDBDispatcher::RequestIDBCursorPrefetchReset(int used_prefetches, | |
181 int unused_prefetches, | |
182 int32_t ipc_cursor_id) { | |
183 Send(new IndexedDBHostMsg_CursorPrefetchReset( | |
184 ipc_cursor_id, used_prefetches, unused_prefetches)); | |
185 } | |
186 | |
187 void IndexedDBDispatcher::RegisterCursor(int32_t ipc_cursor_id, | |
188 WebIDBCursorImpl* cursor) { | |
189 DCHECK(!base::ContainsKey(cursors_, ipc_cursor_id)); | |
190 cursors_[ipc_cursor_id] = cursor; | |
191 } | |
192 | |
193 void IndexedDBDispatcher::CursorDestroyed(int32_t ipc_cursor_id) { | |
194 cursors_.erase(ipc_cursor_id); | |
195 } | |
196 | |
197 void IndexedDBDispatcher::RegisterMojoOwnedCallbacks( | 99 void IndexedDBDispatcher::RegisterMojoOwnedCallbacks( |
198 IndexedDBCallbacksImpl::InternalState* callbacks) { | 100 IndexedDBCallbacksImpl::InternalState* callbacks) { |
199 mojo_owned_callback_state_.insert(callbacks); | 101 mojo_owned_callback_state_.insert(callbacks); |
200 } | 102 } |
201 | 103 |
202 void IndexedDBDispatcher::UnregisterMojoOwnedCallbacks( | 104 void IndexedDBDispatcher::UnregisterMojoOwnedCallbacks( |
203 IndexedDBCallbacksImpl::InternalState* callbacks) { | 105 IndexedDBCallbacksImpl::InternalState* callbacks) { |
204 DCHECK(base::ContainsValue(mojo_owned_callback_state_, callbacks)); | 106 DCHECK(base::ContainsValue(mojo_owned_callback_state_, callbacks)); |
205 mojo_owned_callback_state_.erase(callbacks); | 107 mojo_owned_callback_state_.erase(callbacks); |
206 } | 108 } |
207 | 109 |
208 void IndexedDBDispatcher::RegisterMojoOwnedDatabaseCallbacks( | 110 void IndexedDBDispatcher::RegisterMojoOwnedDatabaseCallbacks( |
209 blink::WebIDBDatabaseCallbacks* callbacks) { | 111 blink::WebIDBDatabaseCallbacks* callbacks) { |
210 mojo_owned_database_callback_state_.insert(callbacks); | 112 mojo_owned_database_callback_state_.insert(callbacks); |
211 } | 113 } |
212 | 114 |
213 void IndexedDBDispatcher::UnregisterMojoOwnedDatabaseCallbacks( | 115 void IndexedDBDispatcher::UnregisterMojoOwnedDatabaseCallbacks( |
214 blink::WebIDBDatabaseCallbacks* callbacks) { | 116 blink::WebIDBDatabaseCallbacks* callbacks) { |
215 DCHECK(base::ContainsValue(mojo_owned_database_callback_state_, callbacks)); | 117 DCHECK(base::ContainsValue(mojo_owned_database_callback_state_, callbacks)); |
216 mojo_owned_database_callback_state_.erase(callbacks); | 118 mojo_owned_database_callback_state_.erase(callbacks); |
217 } | 119 } |
218 | 120 |
219 // Populate some WebIDBValue members (data & blob info) from the supplied | |
220 // value message (IndexedDBMsg_Value or one that includes it). | |
221 template <class IndexedDBMsgValueType> | |
222 static void PrepareWebValue(const IndexedDBMsgValueType& value, | |
223 WebIDBValue* web_value) { | |
224 if (value.bits.empty()) | |
225 return; | |
226 | |
227 web_value->data.assign(&*value.bits.begin(), value.bits.size()); | |
228 blink::WebVector<WebBlobInfo> local_blob_info(value.blob_or_file_info.size()); | |
229 for (size_t i = 0; i < value.blob_or_file_info.size(); ++i) { | |
230 const IndexedDBMsg_BlobOrFileInfo& info = value.blob_or_file_info[i]; | |
231 if (info.is_file) { | |
232 local_blob_info[i] = WebBlobInfo( | |
233 WebString::fromUTF8(info.uuid.c_str()), info.file_path, | |
234 info.file_name, info.mime_type, info.last_modified, info.size); | |
235 } else { | |
236 local_blob_info[i] = WebBlobInfo(WebString::fromUTF8(info.uuid.c_str()), | |
237 info.mime_type, info.size); | |
238 } | |
239 } | |
240 | |
241 web_value->webBlobInfo.swap(local_blob_info); | |
242 } | |
243 | |
244 static void PrepareReturnWebValue(const IndexedDBMsg_ReturnValue& value, | |
245 WebIDBValue* web_value) { | |
246 PrepareWebValue(value, web_value); | |
247 web_value->primaryKey = WebIDBKeyBuilder::Build(value.primary_key); | |
248 web_value->keyPath = WebIDBKeyPathBuilder::Build(value.key_path); | |
249 } | |
250 | |
251 void IndexedDBDispatcher::OnSuccessValue( | |
252 const IndexedDBMsg_CallbacksSuccessValue_Params& params) { | |
253 DCHECK_EQ(params.ipc_thread_id, CurrentWorkerId()); | |
254 WebIDBCallbacks* callbacks = | |
255 pending_callbacks_.Lookup(params.ipc_callbacks_id); | |
256 if (!callbacks) | |
257 return; | |
258 WebIDBValue web_value; | |
259 PrepareReturnWebValue(params.value, &web_value); | |
260 if (params.value.primary_key.IsValid()) { | |
261 web_value.primaryKey = WebIDBKeyBuilder::Build(params.value.primary_key); | |
262 web_value.keyPath = WebIDBKeyPathBuilder::Build(params.value.key_path); | |
263 } | |
264 callbacks->onSuccess(web_value); | |
265 pending_callbacks_.Remove(params.ipc_callbacks_id); | |
266 } | |
267 | |
268 void IndexedDBDispatcher::OnSuccessInteger(int32_t ipc_thread_id, | |
269 int32_t ipc_callbacks_id, | |
270 int64_t value) { | |
271 DCHECK_EQ(ipc_thread_id, CurrentWorkerId()); | |
272 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id); | |
273 if (!callbacks) | |
274 return; | |
275 callbacks->onSuccess(value); | |
276 pending_callbacks_.Remove(ipc_callbacks_id); | |
277 } | |
278 | |
279 void IndexedDBDispatcher::OnSuccessCursorContinue( | |
280 const IndexedDBMsg_CallbacksSuccessCursorContinue_Params& p) { | |
281 DCHECK_EQ(p.ipc_thread_id, CurrentWorkerId()); | |
282 int32_t ipc_callbacks_id = p.ipc_callbacks_id; | |
283 int32_t ipc_cursor_id = p.ipc_cursor_id; | |
284 const IndexedDBKey& key = p.key; | |
285 const IndexedDBKey& primary_key = p.primary_key; | |
286 | |
287 if (cursors_.find(ipc_cursor_id) == cursors_.end()) | |
288 return; | |
289 | |
290 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id); | |
291 if (!callbacks) | |
292 return; | |
293 | |
294 WebIDBValue web_value; | |
295 PrepareWebValue(p.value, &web_value); | |
296 callbacks->onSuccess(WebIDBKeyBuilder::Build(key), | |
297 WebIDBKeyBuilder::Build(primary_key), web_value); | |
298 | |
299 pending_callbacks_.Remove(ipc_callbacks_id); | |
300 } | |
301 | |
302 void IndexedDBDispatcher::OnSuccessCursorPrefetch( | |
303 const IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params& p) { | |
304 DCHECK_EQ(p.ipc_thread_id, CurrentWorkerId()); | |
305 int32_t ipc_callbacks_id = p.ipc_callbacks_id; | |
306 int32_t ipc_cursor_id = p.ipc_cursor_id; | |
307 std::vector<WebIDBValue> values(p.values.size()); | |
308 for (size_t i = 0; i < p.values.size(); ++i) | |
309 PrepareWebValue(p.values[i], &values[i]); | |
310 std::map<int32_t, WebIDBCursorImpl*>::const_iterator cur_iter = | |
311 cursors_.find(ipc_cursor_id); | |
312 if (cur_iter == cursors_.end()) | |
313 return; | |
314 | |
315 cur_iter->second->SetPrefetchData(p.keys, p.primary_keys, values); | |
316 | |
317 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id); | |
318 DCHECK(callbacks); | |
319 cur_iter->second->CachedContinue(callbacks); | |
320 pending_callbacks_.Remove(ipc_callbacks_id); | |
321 } | |
322 | |
323 void IndexedDBDispatcher::OnError(int32_t ipc_thread_id, | |
324 int32_t ipc_callbacks_id, | |
325 int code, | |
326 const base::string16& message) { | |
327 DCHECK_EQ(ipc_thread_id, CurrentWorkerId()); | |
328 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id); | |
329 if (!callbacks) | |
330 return; | |
331 if (message.empty()) | |
332 callbacks->onError(WebIDBDatabaseError(code)); | |
333 else | |
334 callbacks->onError(WebIDBDatabaseError(code, message)); | |
335 pending_callbacks_.Remove(ipc_callbacks_id); | |
336 } | |
337 | |
338 void IndexedDBDispatcher::OnDatabaseChanges( | 121 void IndexedDBDispatcher::OnDatabaseChanges( |
339 int32_t ipc_thread_id, | 122 int32_t ipc_thread_id, |
340 const IndexedDBMsg_ObserverChanges& changes) { | 123 const IndexedDBMsg_ObserverChanges& changes) { |
341 DCHECK_EQ(ipc_thread_id, CurrentWorkerId()); | 124 DCHECK_EQ(ipc_thread_id, CurrentWorkerId()); |
342 std::vector<WebIDBObservation> observations( | 125 std::vector<WebIDBObservation> observations( |
343 ConvertObservations(changes.observations)); | 126 ConvertObservations(changes.observations)); |
344 for (auto& it : changes.observation_index) { | 127 for (auto& it : changes.observation_index) { |
345 WebIDBObserver* observer = observers_.Lookup(it.first); | 128 WebIDBObserver* observer = observers_.Lookup(it.first); |
346 // An observer can be removed from the renderer, but still exist in the | 129 // An observer can be removed from the renderer, but still exist in the |
347 // backend. Moreover, observer might have recorded some changes before being | 130 // backend. Moreover, observer might have recorded some changes before being |
348 // removed from the backend and thus, have its id be present in changes. | 131 // removed from the backend and thus, have its id be present in changes. |
349 if (!observer) | 132 if (!observer) |
350 continue; | 133 continue; |
351 observer->onChange(observations, std::move(it.second)); | 134 observer->onChange(observations, std::move(it.second)); |
352 } | 135 } |
353 } | 136 } |
354 | 137 |
| 138 void IndexedDBDispatcher::RegisterCursor(WebIDBCursorImpl* cursor) { |
| 139 DCHECK(!base::ContainsValue(cursors_, cursor)); |
| 140 cursors_.insert(cursor); |
| 141 } |
| 142 |
| 143 void IndexedDBDispatcher::UnregisterCursor(WebIDBCursorImpl* cursor) { |
| 144 DCHECK(base::ContainsValue(cursors_, cursor)); |
| 145 cursors_.erase(cursor); |
| 146 } |
| 147 |
355 void IndexedDBDispatcher::ResetCursorPrefetchCaches( | 148 void IndexedDBDispatcher::ResetCursorPrefetchCaches( |
356 int64_t transaction_id, | 149 int64_t transaction_id, |
357 int32_t ipc_exception_cursor_id) { | 150 WebIDBCursorImpl* exception_cursor) { |
358 typedef std::map<int32_t, WebIDBCursorImpl*>::iterator Iterator; | 151 for (WebIDBCursorImpl* cursor : cursors_) { |
359 for (Iterator i = cursors_.begin(); i != cursors_.end(); ++i) { | 152 if (cursor != exception_cursor && |
360 if (i->first == ipc_exception_cursor_id || | 153 cursor->transaction_id() == transaction_id) |
361 i->second->transaction_id() != transaction_id) | 154 cursor->ResetPrefetchCache(); |
362 continue; | |
363 i->second->ResetPrefetchCache(); | |
364 } | 155 } |
365 } | 156 } |
366 | 157 |
367 } // namespace content | 158 } // namespace content |
OLD | NEW |