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