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
3 // found in the LICENSE file.
4
5 #include "content/child/indexed_db/indexed_db_dispatcher.h"
6
7 #include "base/format_macros.h"
8 #include "base/lazy_instance.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/threading/thread_local.h"
11 #include "content/child/indexed_db/indexed_db_key_builders.h"
12 #include "content/child/indexed_db/webidbcursor_impl.h"
13 #include "content/child/indexed_db/webidbdatabase_impl.h"
14 #include "content/child/thread_safe_sender.h"
15 #include "content/common/indexed_db/indexed_db_constants.h"
16 #include "content/common/indexed_db/indexed_db_messages.h"
17 #include "ipc/ipc_channel.h"
18 #include "third_party/WebKit/public/platform/WebIDBDatabaseCallbacks.h"
19 #include "third_party/WebKit/public/platform/WebIDBDatabaseError.h"
20 #include "third_party/WebKit/public/platform/WebIDBDatabaseException.h"
21
22 using blink::WebData;
23 using blink::WebIDBCallbacks;
24 using blink::WebIDBDatabase;
25 using blink::WebIDBDatabaseCallbacks;
26 using blink::WebIDBDatabaseError;
27 using blink::WebIDBKey;
28 using blink::WebIDBMetadata;
29 using blink::WebString;
30 using blink::WebVector;
31 using base::ThreadLocalPointer;
32 using webkit_glue::WorkerTaskRunner;
33
34 namespace content {
35 static base::LazyInstance<ThreadLocalPointer<IndexedDBDispatcher> >::Leaky
36 g_idb_dispatcher_tls = LAZY_INSTANCE_INITIALIZER;
37
38 namespace {
39
40 IndexedDBDispatcher* const kHasBeenDeleted =
41 reinterpret_cast<IndexedDBDispatcher*>(0x1);
42
43 } // unnamed namespace
44
45 const size_t kMaxIDBValueSizeInBytes = 64 * 1024 * 1024;
46
IndexedDBDispatcher(ThreadSafeSender * thread_safe_sender)47 IndexedDBDispatcher::IndexedDBDispatcher(ThreadSafeSender* thread_safe_sender)
48 : thread_safe_sender_(thread_safe_sender) {
49 g_idb_dispatcher_tls.Pointer()->Set(this);
50 }
51
~IndexedDBDispatcher()52 IndexedDBDispatcher::~IndexedDBDispatcher() {
53 // Clear any pending callbacks - which may result in dispatch requests -
54 // before marking the dispatcher as deleted.
55 pending_callbacks_.Clear();
56 pending_database_callbacks_.Clear();
57
58 DCHECK(pending_callbacks_.IsEmpty());
59 DCHECK(pending_database_callbacks_.IsEmpty());
60
61 g_idb_dispatcher_tls.Pointer()->Set(kHasBeenDeleted);
62 }
63
ThreadSpecificInstance(ThreadSafeSender * thread_safe_sender)64 IndexedDBDispatcher* IndexedDBDispatcher::ThreadSpecificInstance(
65 ThreadSafeSender* thread_safe_sender) {
66 if (g_idb_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted) {
67 NOTREACHED() << "Re-instantiating TLS IndexedDBDispatcher.";
68 g_idb_dispatcher_tls.Pointer()->Set(NULL);
69 }
70 if (g_idb_dispatcher_tls.Pointer()->Get())
71 return g_idb_dispatcher_tls.Pointer()->Get();
72
73 IndexedDBDispatcher* dispatcher = new IndexedDBDispatcher(thread_safe_sender);
74 if (WorkerTaskRunner::Instance()->CurrentWorkerId())
75 webkit_glue::WorkerTaskRunner::Instance()->AddStopObserver(dispatcher);
76 return dispatcher;
77 }
78
OnWorkerRunLoopStopped()79 void IndexedDBDispatcher::OnWorkerRunLoopStopped() { delete this; }
80
ConvertMetadata(const IndexedDBDatabaseMetadata & idb_metadata)81 WebIDBMetadata IndexedDBDispatcher::ConvertMetadata(
82 const IndexedDBDatabaseMetadata& idb_metadata) {
83 WebIDBMetadata web_metadata;
84 web_metadata.id = idb_metadata.id;
85 web_metadata.name = idb_metadata.name;
86 web_metadata.version = idb_metadata.version;
87 web_metadata.intVersion = idb_metadata.int_version;
88 web_metadata.maxObjectStoreId = idb_metadata.max_object_store_id;
89 web_metadata.objectStores =
90 WebVector<WebIDBMetadata::ObjectStore>(idb_metadata.object_stores.size());
91
92 for (size_t i = 0; i < idb_metadata.object_stores.size(); ++i) {
93 const IndexedDBObjectStoreMetadata& idb_store_metadata =
94 idb_metadata.object_stores[i];
95 WebIDBMetadata::ObjectStore& web_store_metadata =
96 web_metadata.objectStores[i];
97
98 web_store_metadata.id = idb_store_metadata.id;
99 web_store_metadata.name = idb_store_metadata.name;
100 web_store_metadata.keyPath =
101 WebIDBKeyPathBuilder::Build(idb_store_metadata.keyPath);
102 web_store_metadata.autoIncrement = idb_store_metadata.autoIncrement;
103 web_store_metadata.maxIndexId = idb_store_metadata.max_index_id;
104 web_store_metadata.indexes =
105 WebVector<WebIDBMetadata::Index>(idb_store_metadata.indexes.size());
106
107 for (size_t j = 0; j < idb_store_metadata.indexes.size(); ++j) {
108 const IndexedDBIndexMetadata& idb_index_metadata =
109 idb_store_metadata.indexes[j];
110 WebIDBMetadata::Index& web_index_metadata = web_store_metadata.indexes[j];
111
112 web_index_metadata.id = idb_index_metadata.id;
113 web_index_metadata.name = idb_index_metadata.name;
114 web_index_metadata.keyPath =
115 WebIDBKeyPathBuilder::Build(idb_index_metadata.keyPath);
116 web_index_metadata.unique = idb_index_metadata.unique;
117 web_index_metadata.multiEntry = idb_index_metadata.multiEntry;
118 }
119 }
120
121 return web_metadata;
122 }
123
OnMessageReceived(const IPC::Message & msg)124 void IndexedDBDispatcher::OnMessageReceived(const IPC::Message& msg) {
125 bool handled = true;
126 IPC_BEGIN_MESSAGE_MAP(IndexedDBDispatcher, msg)
127 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIDBCursor,
128 OnSuccessOpenCursor)
129 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorAdvance,
130 OnSuccessCursorContinue)
131 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorContinue,
132 OnSuccessCursorContinue)
133 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorPrefetch,
134 OnSuccessCursorPrefetch)
135 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIDBDatabase,
136 OnSuccessIDBDatabase)
137 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIndexedDBKey,
138 OnSuccessIndexedDBKey)
139 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessStringList,
140 OnSuccessStringList)
141 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessValue, OnSuccessValue)
142 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessValueWithKey,
143 OnSuccessValueWithKey)
144 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessInteger, OnSuccessInteger)
145 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessUndefined,
146 OnSuccessUndefined)
147 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksError, OnError)
148 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksIntBlocked, OnIntBlocked)
149 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksUpgradeNeeded, OnUpgradeNeeded)
150 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksForcedClose,
151 OnForcedClose)
152 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksIntVersionChange,
153 OnIntVersionChange)
154 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksAbort, OnAbort)
155 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksComplete, OnComplete)
156 IPC_MESSAGE_UNHANDLED(handled = false)
157 IPC_END_MESSAGE_MAP()
158 // If a message gets here, IndexedDBMessageFilter already determined that it
159 // is an IndexedDB message.
160 DCHECK(handled) << "Didn't handle a message defined at line "
161 << IPC_MESSAGE_ID_LINE(msg.type());
162 }
163
Send(IPC::Message * msg)164 bool IndexedDBDispatcher::Send(IPC::Message* msg) {
165 return thread_safe_sender_->Send(msg);
166 }
167
RequestIDBCursorAdvance(unsigned long count,WebIDBCallbacks * callbacks_ptr,int32 ipc_cursor_id)168 void IndexedDBDispatcher::RequestIDBCursorAdvance(
169 unsigned long count,
170 WebIDBCallbacks* callbacks_ptr,
171 int32 ipc_cursor_id) {
172 // Reset all cursor prefetch caches except for this cursor.
173 ResetCursorPrefetchCaches(ipc_cursor_id);
174
175 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
176
177 int32 ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
178 Send(new IndexedDBHostMsg_CursorAdvance(
179 ipc_cursor_id, CurrentWorkerId(), ipc_callbacks_id, count));
180 }
181
RequestIDBCursorContinue(const IndexedDBKey & key,const IndexedDBKey & primary_key,WebIDBCallbacks * callbacks_ptr,int32 ipc_cursor_id)182 void IndexedDBDispatcher::RequestIDBCursorContinue(
183 const IndexedDBKey& key,
184 const IndexedDBKey& primary_key,
185 WebIDBCallbacks* callbacks_ptr,
186 int32 ipc_cursor_id) {
187 // Reset all cursor prefetch caches except for this cursor.
188 ResetCursorPrefetchCaches(ipc_cursor_id);
189
190 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
191
192 int32 ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
193 Send(new IndexedDBHostMsg_CursorContinue(
194 ipc_cursor_id, CurrentWorkerId(), ipc_callbacks_id, key, primary_key));
195 }
196
RequestIDBCursorPrefetch(int n,WebIDBCallbacks * callbacks_ptr,int32 ipc_cursor_id)197 void IndexedDBDispatcher::RequestIDBCursorPrefetch(
198 int n,
199 WebIDBCallbacks* callbacks_ptr,
200 int32 ipc_cursor_id) {
201 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
202
203 int32 ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
204 Send(new IndexedDBHostMsg_CursorPrefetch(
205 ipc_cursor_id, CurrentWorkerId(), ipc_callbacks_id, n));
206 }
207
RequestIDBCursorPrefetchReset(int used_prefetches,int unused_prefetches,int32 ipc_cursor_id)208 void IndexedDBDispatcher::RequestIDBCursorPrefetchReset(int used_prefetches,
209 int unused_prefetches,
210 int32 ipc_cursor_id) {
211 Send(new IndexedDBHostMsg_CursorPrefetchReset(
212 ipc_cursor_id, used_prefetches, unused_prefetches));
213 }
214
RequestIDBFactoryOpen(const base::string16 & name,int64 version,int64 transaction_id,WebIDBCallbacks * callbacks_ptr,WebIDBDatabaseCallbacks * database_callbacks_ptr,const std::string & database_identifier)215 void IndexedDBDispatcher::RequestIDBFactoryOpen(
216 const base::string16& name,
217 int64 version,
218 int64 transaction_id,
219 WebIDBCallbacks* callbacks_ptr,
220 WebIDBDatabaseCallbacks* database_callbacks_ptr,
221 const std::string& database_identifier) {
222 ResetCursorPrefetchCaches();
223 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
224 scoped_ptr<WebIDBDatabaseCallbacks> database_callbacks(
225 database_callbacks_ptr);
226
227 IndexedDBHostMsg_FactoryOpen_Params params;
228 params.ipc_thread_id = CurrentWorkerId();
229 params.ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
230 params.ipc_database_callbacks_id =
231 pending_database_callbacks_.Add(database_callbacks.release());
232 params.database_identifier = database_identifier;
233 params.name = name;
234 params.transaction_id = transaction_id;
235 params.version = version;
236 Send(new IndexedDBHostMsg_FactoryOpen(params));
237 }
238
RequestIDBFactoryGetDatabaseNames(WebIDBCallbacks * callbacks_ptr,const std::string & database_identifier)239 void IndexedDBDispatcher::RequestIDBFactoryGetDatabaseNames(
240 WebIDBCallbacks* callbacks_ptr,
241 const std::string& database_identifier) {
242 ResetCursorPrefetchCaches();
243 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
244
245 IndexedDBHostMsg_FactoryGetDatabaseNames_Params params;
246 params.ipc_thread_id = CurrentWorkerId();
247 params.ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
248 params.database_identifier = database_identifier;
249 Send(new IndexedDBHostMsg_FactoryGetDatabaseNames(params));
250 }
251
RequestIDBFactoryDeleteDatabase(const base::string16 & name,WebIDBCallbacks * callbacks_ptr,const std::string & database_identifier)252 void IndexedDBDispatcher::RequestIDBFactoryDeleteDatabase(
253 const base::string16& name,
254 WebIDBCallbacks* callbacks_ptr,
255 const std::string& database_identifier) {
256 ResetCursorPrefetchCaches();
257 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
258
259 IndexedDBHostMsg_FactoryDeleteDatabase_Params params;
260 params.ipc_thread_id = CurrentWorkerId();
261 params.ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
262 params.database_identifier = database_identifier;
263 params.name = name;
264 Send(new IndexedDBHostMsg_FactoryDeleteDatabase(params));
265 }
266
RequestIDBDatabaseClose(int32 ipc_database_id,int32 ipc_database_callbacks_id)267 void IndexedDBDispatcher::RequestIDBDatabaseClose(
268 int32 ipc_database_id,
269 int32 ipc_database_callbacks_id) {
270 ResetCursorPrefetchCaches();
271 Send(new IndexedDBHostMsg_DatabaseClose(ipc_database_id));
272 // There won't be pending database callbacks if the transaction was aborted in
273 // the initial upgradeneeded event handler.
274 if (pending_database_callbacks_.Lookup(ipc_database_callbacks_id))
275 pending_database_callbacks_.Remove(ipc_database_callbacks_id);
276 }
277
RequestIDBDatabaseCreateTransaction(int32 ipc_database_id,int64 transaction_id,WebIDBDatabaseCallbacks * database_callbacks_ptr,WebVector<long long> object_store_ids,unsigned short mode)278 void IndexedDBDispatcher::RequestIDBDatabaseCreateTransaction(
279 int32 ipc_database_id,
280 int64 transaction_id,
281 WebIDBDatabaseCallbacks* database_callbacks_ptr,
282 WebVector<long long> object_store_ids,
283 unsigned short mode) {
284 scoped_ptr<WebIDBDatabaseCallbacks> database_callbacks(
285 database_callbacks_ptr);
286 IndexedDBHostMsg_DatabaseCreateTransaction_Params params;
287 params.ipc_thread_id = CurrentWorkerId();
288 params.ipc_database_id = ipc_database_id;
289 params.transaction_id = transaction_id;
290 params.ipc_database_callbacks_id =
291 pending_database_callbacks_.Add(database_callbacks.release());
292 params.object_store_ids
293 .assign(object_store_ids.data(),
294 object_store_ids.data() + object_store_ids.size());
295 params.mode = mode;
296
297 Send(new IndexedDBHostMsg_DatabaseCreateTransaction(params));
298 }
299
RequestIDBDatabaseGet(int32 ipc_database_id,int64 transaction_id,int64 object_store_id,int64 index_id,const IndexedDBKeyRange & key_range,bool key_only,WebIDBCallbacks * callbacks)300 void IndexedDBDispatcher::RequestIDBDatabaseGet(
301 int32 ipc_database_id,
302 int64 transaction_id,
303 int64 object_store_id,
304 int64 index_id,
305 const IndexedDBKeyRange& key_range,
306 bool key_only,
307 WebIDBCallbacks* callbacks) {
308 ResetCursorPrefetchCaches();
309 IndexedDBHostMsg_DatabaseGet_Params params;
310 init_params(params, callbacks);
311 params.ipc_database_id = ipc_database_id;
312 params.transaction_id = transaction_id;
313 params.object_store_id = object_store_id;
314 params.index_id = index_id;
315 params.key_range = key_range;
316 params.key_only = key_only;
317 Send(new IndexedDBHostMsg_DatabaseGet(params));
318 }
319
RequestIDBDatabasePut(int32 ipc_database_id,int64 transaction_id,int64 object_store_id,const WebData & value,const IndexedDBKey & key,WebIDBDatabase::PutMode put_mode,WebIDBCallbacks * callbacks,const WebVector<long long> & index_ids,const WebVector<WebVector<WebIDBKey>> & index_keys)320 void IndexedDBDispatcher::RequestIDBDatabasePut(
321 int32 ipc_database_id,
322 int64 transaction_id,
323 int64 object_store_id,
324 const WebData& value,
325 const IndexedDBKey& key,
326 WebIDBDatabase::PutMode put_mode,
327 WebIDBCallbacks* callbacks,
328 const WebVector<long long>& index_ids,
329 const WebVector<WebVector<WebIDBKey> >& index_keys) {
330
331 if (value.size() > kMaxIDBValueSizeInBytes) {
332 callbacks->onError(WebIDBDatabaseError(
333 blink::WebIDBDatabaseExceptionUnknownError,
334 WebString::fromUTF8(base::StringPrintf(
335 "The serialized value is too large"
336 " (size=%" PRIuS " bytes, max=%" PRIuS " bytes).",
337 value.size(),
338 kMaxIDBValueSizeInBytes).c_str())));
339 return;
340 }
341
342 ResetCursorPrefetchCaches();
343 IndexedDBHostMsg_DatabasePut_Params params;
344 init_params(params, callbacks);
345 params.ipc_database_id = ipc_database_id;
346 params.transaction_id = transaction_id;
347 params.object_store_id = object_store_id;
348
349 params.value.assign(value.data(), value.data() + value.size());
350 params.key = key;
351 params.put_mode = put_mode;
352
353 COMPILE_ASSERT(sizeof(params.index_ids[0]) == sizeof(index_ids[0]),
354 Cant_copy);
355 params.index_ids
356 .assign(index_ids.data(), index_ids.data() + index_ids.size());
357
358 params.index_keys.resize(index_keys.size());
359 for (size_t i = 0; i < index_keys.size(); ++i) {
360 params.index_keys[i].resize(index_keys[i].size());
361 for (size_t j = 0; j < index_keys[i].size(); ++j) {
362 params.index_keys[i][j] =
363 IndexedDBKey(IndexedDBKeyBuilder::Build(index_keys[i][j]));
364 }
365 }
366 Send(new IndexedDBHostMsg_DatabasePut(params));
367 }
368
RequestIDBDatabaseOpenCursor(int32 ipc_database_id,int64 transaction_id,int64 object_store_id,int64 index_id,const IndexedDBKeyRange & key_range,unsigned short direction,bool key_only,WebIDBDatabase::TaskType task_type,WebIDBCallbacks * callbacks)369 void IndexedDBDispatcher::RequestIDBDatabaseOpenCursor(
370 int32 ipc_database_id,
371 int64 transaction_id,
372 int64 object_store_id,
373 int64 index_id,
374 const IndexedDBKeyRange& key_range,
375 unsigned short direction,
376 bool key_only,
377 WebIDBDatabase::TaskType task_type,
378 WebIDBCallbacks* callbacks) {
379 ResetCursorPrefetchCaches();
380 IndexedDBHostMsg_DatabaseOpenCursor_Params params;
381 init_params(params, callbacks);
382 params.ipc_database_id = ipc_database_id;
383 params.transaction_id = transaction_id;
384 params.object_store_id = object_store_id;
385 params.index_id = index_id;
386 params.key_range = key_range;
387 params.direction = direction;
388 params.key_only = key_only;
389 params.task_type = task_type;
390 Send(new IndexedDBHostMsg_DatabaseOpenCursor(params));
391 }
392
RequestIDBDatabaseCount(int32 ipc_database_id,int64 transaction_id,int64 object_store_id,int64 index_id,const IndexedDBKeyRange & key_range,WebIDBCallbacks * callbacks)393 void IndexedDBDispatcher::RequestIDBDatabaseCount(
394 int32 ipc_database_id,
395 int64 transaction_id,
396 int64 object_store_id,
397 int64 index_id,
398 const IndexedDBKeyRange& key_range,
399 WebIDBCallbacks* callbacks) {
400 ResetCursorPrefetchCaches();
401 IndexedDBHostMsg_DatabaseCount_Params params;
402 init_params(params, callbacks);
403 params.ipc_database_id = ipc_database_id;
404 params.transaction_id = transaction_id;
405 params.object_store_id = object_store_id;
406 params.index_id = index_id;
407 params.key_range = key_range;
408 Send(new IndexedDBHostMsg_DatabaseCount(params));
409 }
410
RequestIDBDatabaseDeleteRange(int32 ipc_database_id,int64 transaction_id,int64 object_store_id,const IndexedDBKeyRange & key_range,WebIDBCallbacks * callbacks)411 void IndexedDBDispatcher::RequestIDBDatabaseDeleteRange(
412 int32 ipc_database_id,
413 int64 transaction_id,
414 int64 object_store_id,
415 const IndexedDBKeyRange& key_range,
416 WebIDBCallbacks* callbacks) {
417 ResetCursorPrefetchCaches();
418 IndexedDBHostMsg_DatabaseDeleteRange_Params params;
419 init_params(params, callbacks);
420 params.ipc_database_id = ipc_database_id;
421 params.transaction_id = transaction_id;
422 params.object_store_id = object_store_id;
423 params.key_range = key_range;
424 Send(new IndexedDBHostMsg_DatabaseDeleteRange(params));
425 }
426
RequestIDBDatabaseClear(int32 ipc_database_id,int64 transaction_id,int64 object_store_id,WebIDBCallbacks * callbacks_ptr)427 void IndexedDBDispatcher::RequestIDBDatabaseClear(
428 int32 ipc_database_id,
429 int64 transaction_id,
430 int64 object_store_id,
431 WebIDBCallbacks* callbacks_ptr) {
432 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
433 int32 ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
434 Send(new IndexedDBHostMsg_DatabaseClear(CurrentWorkerId(),
435 ipc_callbacks_id,
436 ipc_database_id,
437 transaction_id,
438 object_store_id));
439 }
440
CursorDestroyed(int32 ipc_cursor_id)441 void IndexedDBDispatcher::CursorDestroyed(int32 ipc_cursor_id) {
442 cursors_.erase(ipc_cursor_id);
443 }
444
DatabaseDestroyed(int32 ipc_database_id)445 void IndexedDBDispatcher::DatabaseDestroyed(int32 ipc_database_id) {
446 DCHECK_EQ(databases_.count(ipc_database_id), 1u);
447 databases_.erase(ipc_database_id);
448 }
449
OnSuccessIDBDatabase(int32 ipc_thread_id,int32 ipc_callbacks_id,int32 ipc_database_callbacks_id,int32 ipc_object_id,const IndexedDBDatabaseMetadata & idb_metadata)450 void IndexedDBDispatcher::OnSuccessIDBDatabase(
451 int32 ipc_thread_id,
452 int32 ipc_callbacks_id,
453 int32 ipc_database_callbacks_id,
454 int32 ipc_object_id,
455 const IndexedDBDatabaseMetadata& idb_metadata) {
456 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
457 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
458 if (!callbacks)
459 return;
460 WebIDBMetadata metadata(ConvertMetadata(idb_metadata));
461 // If an upgrade was performed, count will be non-zero.
462 WebIDBDatabase* database = NULL;
463
464 // Back-end will send kNoDatabase if it was already sent in OnUpgradeNeeded.
465 // May already be deleted and removed from the table, but do not recreate..
466 if (ipc_object_id != kNoDatabase) {
467 DCHECK(!databases_.count(ipc_object_id));
468 database = databases_[ipc_object_id] = new WebIDBDatabaseImpl(
469 ipc_object_id, ipc_database_callbacks_id, thread_safe_sender_.get());
470 }
471
472 callbacks->onSuccess(database, metadata);
473 pending_callbacks_.Remove(ipc_callbacks_id);
474 }
475
OnSuccessIndexedDBKey(int32 ipc_thread_id,int32 ipc_callbacks_id,const IndexedDBKey & key)476 void IndexedDBDispatcher::OnSuccessIndexedDBKey(int32 ipc_thread_id,
477 int32 ipc_callbacks_id,
478 const IndexedDBKey& key) {
479 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
480 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
481 if (!callbacks)
482 return;
483 callbacks->onSuccess(WebIDBKeyBuilder::Build(key));
484 pending_callbacks_.Remove(ipc_callbacks_id);
485 }
486
OnSuccessStringList(int32 ipc_thread_id,int32 ipc_callbacks_id,const std::vector<base::string16> & value)487 void IndexedDBDispatcher::OnSuccessStringList(
488 int32 ipc_thread_id,
489 int32 ipc_callbacks_id,
490 const std::vector<base::string16>& value) {
491 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
492 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
493 if (!callbacks)
494 return;
495 callbacks->onSuccess(WebVector<WebString>(value));
496 pending_callbacks_.Remove(ipc_callbacks_id);
497 }
498
OnSuccessValue(int32 ipc_thread_id,int32 ipc_callbacks_id,const std::string & value)499 void IndexedDBDispatcher::OnSuccessValue(int32 ipc_thread_id,
500 int32 ipc_callbacks_id,
501 const std::string& value) {
502 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
503 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
504 if (!callbacks)
505 return;
506 WebData web_value;
507 if (value.size())
508 web_value.assign(&*value.begin(), value.size());
509 callbacks->onSuccess(web_value);
510 pending_callbacks_.Remove(ipc_callbacks_id);
511 }
512
OnSuccessValueWithKey(int32 ipc_thread_id,int32 ipc_callbacks_id,const std::string & value,const IndexedDBKey & primary_key,const IndexedDBKeyPath & key_path)513 void IndexedDBDispatcher::OnSuccessValueWithKey(
514 int32 ipc_thread_id,
515 int32 ipc_callbacks_id,
516 const std::string& value,
517 const IndexedDBKey& primary_key,
518 const IndexedDBKeyPath& key_path) {
519 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
520 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
521 if (!callbacks)
522 return;
523 WebData web_value;
524 if (value.size())
525 web_value.assign(&*value.begin(), value.size());
526 callbacks->onSuccess(web_value,
527 WebIDBKeyBuilder::Build(primary_key),
528 WebIDBKeyPathBuilder::Build(key_path));
529 pending_callbacks_.Remove(ipc_callbacks_id);
530 }
531
OnSuccessInteger(int32 ipc_thread_id,int32 ipc_callbacks_id,int64 value)532 void IndexedDBDispatcher::OnSuccessInteger(int32 ipc_thread_id,
533 int32 ipc_callbacks_id,
534 int64 value) {
535 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
536 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
537 if (!callbacks)
538 return;
539 callbacks->onSuccess(value);
540 pending_callbacks_.Remove(ipc_callbacks_id);
541 }
542
OnSuccessUndefined(int32 ipc_thread_id,int32 ipc_callbacks_id)543 void IndexedDBDispatcher::OnSuccessUndefined(int32 ipc_thread_id,
544 int32 ipc_callbacks_id) {
545 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
546 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
547 if (!callbacks)
548 return;
549 callbacks->onSuccess();
550 pending_callbacks_.Remove(ipc_callbacks_id);
551 }
552
OnSuccessOpenCursor(const IndexedDBMsg_CallbacksSuccessIDBCursor_Params & p)553 void IndexedDBDispatcher::OnSuccessOpenCursor(
554 const IndexedDBMsg_CallbacksSuccessIDBCursor_Params& p) {
555 DCHECK_EQ(p.ipc_thread_id, CurrentWorkerId());
556 int32 ipc_callbacks_id = p.ipc_callbacks_id;
557 int32 ipc_object_id = p.ipc_cursor_id;
558 const IndexedDBKey& key = p.key;
559 const IndexedDBKey& primary_key = p.primary_key;
560 WebData web_value;
561 if (p.value.size())
562 web_value.assign(&*p.value.begin(), p.value.size());
563
564 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
565 if (!callbacks)
566 return;
567
568 WebIDBCursorImpl* cursor =
569 new WebIDBCursorImpl(ipc_object_id, thread_safe_sender_.get());
570 cursors_[ipc_object_id] = cursor;
571 callbacks->onSuccess(cursor, WebIDBKeyBuilder::Build(key),
572 WebIDBKeyBuilder::Build(primary_key), web_value);
573
574 pending_callbacks_.Remove(ipc_callbacks_id);
575 }
576
OnSuccessCursorContinue(const IndexedDBMsg_CallbacksSuccessCursorContinue_Params & p)577 void IndexedDBDispatcher::OnSuccessCursorContinue(
578 const IndexedDBMsg_CallbacksSuccessCursorContinue_Params& p) {
579 DCHECK_EQ(p.ipc_thread_id, CurrentWorkerId());
580 int32 ipc_callbacks_id = p.ipc_callbacks_id;
581 int32 ipc_cursor_id = p.ipc_cursor_id;
582 const IndexedDBKey& key = p.key;
583 const IndexedDBKey& primary_key = p.primary_key;
584 const std::string& value = p.value;
585
586 WebIDBCursorImpl* cursor = cursors_[ipc_cursor_id];
587 DCHECK(cursor);
588
589 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
590 if (!callbacks)
591 return;
592
593 WebData web_value;
594 if (value.size())
595 web_value.assign(&*value.begin(), value.size());
596 callbacks->onSuccess(WebIDBKeyBuilder::Build(key),
597 WebIDBKeyBuilder::Build(primary_key), web_value);
598
599 pending_callbacks_.Remove(ipc_callbacks_id);
600 }
601
OnSuccessCursorPrefetch(const IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params & p)602 void IndexedDBDispatcher::OnSuccessCursorPrefetch(
603 const IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params& p) {
604 DCHECK_EQ(p.ipc_thread_id, CurrentWorkerId());
605 int32 ipc_callbacks_id = p.ipc_callbacks_id;
606 int32 ipc_cursor_id = p.ipc_cursor_id;
607 const std::vector<IndexedDBKey>& keys = p.keys;
608 const std::vector<IndexedDBKey>& primary_keys = p.primary_keys;
609 std::vector<WebData> values(p.values.size());
610 for (size_t i = 0; i < p.values.size(); ++i) {
611 if (p.values[i].size())
612 values[i].assign(&*p.values[i].begin(), p.values[i].size());
613 }
614 WebIDBCursorImpl* cursor = cursors_[ipc_cursor_id];
615 DCHECK(cursor);
616 cursor->SetPrefetchData(keys, primary_keys, values);
617
618 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
619 DCHECK(callbacks);
620 cursor->CachedContinue(callbacks);
621 pending_callbacks_.Remove(ipc_callbacks_id);
622 }
623
OnIntBlocked(int32 ipc_thread_id,int32 ipc_callbacks_id,int64 existing_version)624 void IndexedDBDispatcher::OnIntBlocked(int32 ipc_thread_id,
625 int32 ipc_callbacks_id,
626 int64 existing_version) {
627 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
628 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
629 DCHECK(callbacks);
630 callbacks->onBlocked(existing_version);
631 }
632
OnUpgradeNeeded(const IndexedDBMsg_CallbacksUpgradeNeeded_Params & p)633 void IndexedDBDispatcher::OnUpgradeNeeded(
634 const IndexedDBMsg_CallbacksUpgradeNeeded_Params& p) {
635 DCHECK_EQ(p.ipc_thread_id, CurrentWorkerId());
636 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(p.ipc_callbacks_id);
637 DCHECK(callbacks);
638 WebIDBMetadata metadata(ConvertMetadata(p.idb_metadata));
639 DCHECK(!databases_.count(p.ipc_database_id));
640 databases_[p.ipc_database_id] =
641 new WebIDBDatabaseImpl(p.ipc_database_id,
642 p.ipc_database_callbacks_id,
643 thread_safe_sender_.get());
644 callbacks->onUpgradeNeeded(
645 p.old_version,
646 databases_[p.ipc_database_id],
647 metadata,
648 static_cast<blink::WebIDBDataLoss>(p.data_loss),
649 WebString::fromUTF8(p.data_loss_message));
650 }
651
OnError(int32 ipc_thread_id,int32 ipc_callbacks_id,int code,const base::string16 & message)652 void IndexedDBDispatcher::OnError(int32 ipc_thread_id,
653 int32 ipc_callbacks_id,
654 int code,
655 const base::string16& message) {
656 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
657 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
658 if (!callbacks)
659 return;
660 if (message.empty())
661 callbacks->onError(WebIDBDatabaseError(code));
662 else
663 callbacks->onError(WebIDBDatabaseError(code, message));
664 pending_callbacks_.Remove(ipc_callbacks_id);
665 }
666
OnAbort(int32 ipc_thread_id,int32 ipc_database_callbacks_id,int64 transaction_id,int code,const base::string16 & message)667 void IndexedDBDispatcher::OnAbort(int32 ipc_thread_id,
668 int32 ipc_database_callbacks_id,
669 int64 transaction_id,
670 int code,
671 const base::string16& message) {
672 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
673 WebIDBDatabaseCallbacks* callbacks =
674 pending_database_callbacks_.Lookup(ipc_database_callbacks_id);
675 if (!callbacks)
676 return;
677 if (message.empty())
678 callbacks->onAbort(transaction_id, WebIDBDatabaseError(code));
679 else
680 callbacks->onAbort(transaction_id, WebIDBDatabaseError(code, message));
681 }
682
OnComplete(int32 ipc_thread_id,int32 ipc_database_callbacks_id,int64 transaction_id)683 void IndexedDBDispatcher::OnComplete(int32 ipc_thread_id,
684 int32 ipc_database_callbacks_id,
685 int64 transaction_id) {
686 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
687 WebIDBDatabaseCallbacks* callbacks =
688 pending_database_callbacks_.Lookup(ipc_database_callbacks_id);
689 if (!callbacks)
690 return;
691 callbacks->onComplete(transaction_id);
692 }
693
OnForcedClose(int32 ipc_thread_id,int32 ipc_database_callbacks_id)694 void IndexedDBDispatcher::OnForcedClose(int32 ipc_thread_id,
695 int32 ipc_database_callbacks_id) {
696 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
697 WebIDBDatabaseCallbacks* callbacks =
698 pending_database_callbacks_.Lookup(ipc_database_callbacks_id);
699 if (!callbacks)
700 return;
701 callbacks->onForcedClose();
702 }
703
OnIntVersionChange(int32 ipc_thread_id,int32 ipc_database_callbacks_id,int64 old_version,int64 new_version)704 void IndexedDBDispatcher::OnIntVersionChange(int32 ipc_thread_id,
705 int32 ipc_database_callbacks_id,
706 int64 old_version,
707 int64 new_version) {
708 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
709 WebIDBDatabaseCallbacks* callbacks =
710 pending_database_callbacks_.Lookup(ipc_database_callbacks_id);
711 // callbacks would be NULL if a versionchange event is received after close
712 // has been called.
713 if (!callbacks)
714 return;
715 callbacks->onVersionChange(old_version, new_version);
716 }
717
ResetCursorPrefetchCaches(int32 ipc_exception_cursor_id)718 void IndexedDBDispatcher::ResetCursorPrefetchCaches(
719 int32 ipc_exception_cursor_id) {
720 typedef std::map<int32, WebIDBCursorImpl*>::iterator Iterator;
721 for (Iterator i = cursors_.begin(); i != cursors_.end(); ++i) {
722 if (i->first == ipc_exception_cursor_id)
723 continue;
724 i->second->ResetPrefetchCache();
725 }
726 }
727
728 } // namespace content
729