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