Home | History | Annotate | Download | only in indexed_db
      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 
     47 IndexedDBDispatcher::IndexedDBDispatcher(ThreadSafeSender* thread_safe_sender)
     48     : thread_safe_sender_(thread_safe_sender) {
     49   g_idb_dispatcher_tls.Pointer()->Set(this);
     50 }
     51 
     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 
     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 
     79 void IndexedDBDispatcher::OnWorkerRunLoopStopped() { delete this; }
     80 
     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 
    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 
    164 bool IndexedDBDispatcher::Send(IPC::Message* msg) {
    165   return thread_safe_sender_->Send(msg);
    166 }
    167 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    441 void IndexedDBDispatcher::CursorDestroyed(int32 ipc_cursor_id) {
    442   cursors_.erase(ipc_cursor_id);
    443 }
    444 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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