• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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