Home | History | Annotate | Download | only in indexed_db
      1 // Copyright (c) 2012 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/browser/indexed_db/indexed_db_callbacks.h"
      6 
      7 #include <algorithm>
      8 
      9 #include "base/guid.h"
     10 #include "base/strings/utf_string_conversions.h"
     11 #include "base/time/time.h"
     12 #include "content/browser/child_process_security_policy_impl.h"
     13 #include "content/browser/fileapi/fileapi_message_filter.h"
     14 #include "content/browser/indexed_db/indexed_db_blob_info.h"
     15 #include "content/browser/indexed_db/indexed_db_connection.h"
     16 #include "content/browser/indexed_db/indexed_db_context_impl.h"
     17 #include "content/browser/indexed_db/indexed_db_cursor.h"
     18 #include "content/browser/indexed_db/indexed_db_database_callbacks.h"
     19 #include "content/browser/indexed_db/indexed_db_database_error.h"
     20 #include "content/browser/indexed_db/indexed_db_metadata.h"
     21 #include "content/browser/indexed_db/indexed_db_value.h"
     22 #include "content/common/indexed_db/indexed_db_constants.h"
     23 #include "content/common/indexed_db/indexed_db_messages.h"
     24 #include "webkit/browser/blob/blob_storage_context.h"
     25 #include "webkit/browser/quota/quota_manager.h"
     26 #include "webkit/common/blob/blob_data.h"
     27 #include "webkit/common/blob/shareable_file_reference.h"
     28 
     29 using webkit_blob::ShareableFileReference;
     30 
     31 namespace content {
     32 
     33 namespace {
     34 const int32 kNoCursor = -1;
     35 const int32 kNoDatabaseCallbacks = -1;
     36 const int64 kNoTransaction = -1;
     37 }
     38 
     39 IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
     40                                        int32 ipc_thread_id,
     41                                        int32 ipc_callbacks_id)
     42     : dispatcher_host_(dispatcher_host),
     43       ipc_callbacks_id_(ipc_callbacks_id),
     44       ipc_thread_id_(ipc_thread_id),
     45       ipc_cursor_id_(kNoCursor),
     46       host_transaction_id_(kNoTransaction),
     47       ipc_database_id_(kNoDatabase),
     48       ipc_database_callbacks_id_(kNoDatabaseCallbacks),
     49       data_loss_(blink::WebIDBDataLossNone) {}
     50 
     51 IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
     52                                        int32 ipc_thread_id,
     53                                        int32 ipc_callbacks_id,
     54                                        int32 ipc_cursor_id)
     55     : dispatcher_host_(dispatcher_host),
     56       ipc_callbacks_id_(ipc_callbacks_id),
     57       ipc_thread_id_(ipc_thread_id),
     58       ipc_cursor_id_(ipc_cursor_id),
     59       host_transaction_id_(kNoTransaction),
     60       ipc_database_id_(kNoDatabase),
     61       ipc_database_callbacks_id_(kNoDatabaseCallbacks),
     62       data_loss_(blink::WebIDBDataLossNone) {}
     63 
     64 IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
     65                                        int32 ipc_thread_id,
     66                                        int32 ipc_callbacks_id,
     67                                        int32 ipc_database_callbacks_id,
     68                                        int64 host_transaction_id,
     69                                        const GURL& origin_url)
     70     : dispatcher_host_(dispatcher_host),
     71       ipc_callbacks_id_(ipc_callbacks_id),
     72       ipc_thread_id_(ipc_thread_id),
     73       ipc_cursor_id_(kNoCursor),
     74       host_transaction_id_(host_transaction_id),
     75       origin_url_(origin_url),
     76       ipc_database_id_(kNoDatabase),
     77       ipc_database_callbacks_id_(ipc_database_callbacks_id),
     78       data_loss_(blink::WebIDBDataLossNone) {}
     79 
     80 IndexedDBCallbacks::~IndexedDBCallbacks() {}
     81 
     82 void IndexedDBCallbacks::OnError(const IndexedDBDatabaseError& error) {
     83   DCHECK(dispatcher_host_.get());
     84 
     85   dispatcher_host_->Send(new IndexedDBMsg_CallbacksError(
     86       ipc_thread_id_, ipc_callbacks_id_, error.code(), error.message()));
     87   dispatcher_host_ = NULL;
     88 }
     89 
     90 void IndexedDBCallbacks::OnSuccess(const std::vector<base::string16>& value) {
     91   DCHECK(dispatcher_host_.get());
     92 
     93   DCHECK_EQ(kNoCursor, ipc_cursor_id_);
     94   DCHECK_EQ(kNoTransaction, host_transaction_id_);
     95   DCHECK_EQ(kNoDatabase, ipc_database_id_);
     96   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
     97   DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
     98 
     99   std::vector<base::string16> list;
    100   for (unsigned i = 0; i < value.size(); ++i)
    101     list.push_back(value[i]);
    102 
    103   dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessStringList(
    104       ipc_thread_id_, ipc_callbacks_id_, list));
    105   dispatcher_host_ = NULL;
    106 }
    107 
    108 void IndexedDBCallbacks::OnBlocked(int64 existing_version) {
    109   DCHECK(dispatcher_host_.get());
    110 
    111   DCHECK_EQ(kNoCursor, ipc_cursor_id_);
    112   // No transaction/db callbacks for DeleteDatabase.
    113   DCHECK_EQ(kNoTransaction == host_transaction_id_,
    114             kNoDatabaseCallbacks == ipc_database_callbacks_id_);
    115   DCHECK_EQ(kNoDatabase, ipc_database_id_);
    116 
    117   dispatcher_host_->Send(new IndexedDBMsg_CallbacksIntBlocked(
    118       ipc_thread_id_, ipc_callbacks_id_, existing_version));
    119 }
    120 
    121 void IndexedDBCallbacks::OnDataLoss(blink::WebIDBDataLoss data_loss,
    122                                     std::string data_loss_message) {
    123   DCHECK_NE(blink::WebIDBDataLossNone, data_loss);
    124   data_loss_ = data_loss;
    125   data_loss_message_ = data_loss_message;
    126 }
    127 
    128 void IndexedDBCallbacks::OnUpgradeNeeded(
    129     int64 old_version,
    130     scoped_ptr<IndexedDBConnection> connection,
    131     const IndexedDBDatabaseMetadata& metadata) {
    132   DCHECK(dispatcher_host_.get());
    133 
    134   DCHECK_EQ(kNoCursor, ipc_cursor_id_);
    135   DCHECK_NE(kNoTransaction, host_transaction_id_);
    136   DCHECK_EQ(kNoDatabase, ipc_database_id_);
    137   DCHECK_NE(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
    138 
    139   dispatcher_host_->RegisterTransactionId(host_transaction_id_, origin_url_);
    140   int32 ipc_database_id =
    141       dispatcher_host_->Add(connection.release(), ipc_thread_id_, origin_url_);
    142   if (ipc_database_id < 0)
    143     return;
    144   ipc_database_id_ = ipc_database_id;
    145   IndexedDBMsg_CallbacksUpgradeNeeded_Params params;
    146   params.ipc_thread_id = ipc_thread_id_;
    147   params.ipc_callbacks_id = ipc_callbacks_id_;
    148   params.ipc_database_id = ipc_database_id;
    149   params.ipc_database_callbacks_id = ipc_database_callbacks_id_;
    150   params.old_version = old_version;
    151   params.idb_metadata = IndexedDBDispatcherHost::ConvertMetadata(metadata);
    152   params.data_loss = data_loss_;
    153   params.data_loss_message = data_loss_message_;
    154   dispatcher_host_->Send(new IndexedDBMsg_CallbacksUpgradeNeeded(params));
    155 }
    156 
    157 void IndexedDBCallbacks::OnSuccess(scoped_ptr<IndexedDBConnection> connection,
    158                                    const IndexedDBDatabaseMetadata& metadata) {
    159   DCHECK(dispatcher_host_.get());
    160 
    161   DCHECK_EQ(kNoCursor, ipc_cursor_id_);
    162   DCHECK_NE(kNoTransaction, host_transaction_id_);
    163   DCHECK_NE(ipc_database_id_ == kNoDatabase, !connection);
    164   DCHECK_NE(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
    165 
    166   scoped_refptr<IndexedDBCallbacks> self(this);
    167 
    168   int32 ipc_object_id = kNoDatabase;
    169   // Only register if the connection was not previously sent in OnUpgradeNeeded.
    170   if (ipc_database_id_ == kNoDatabase) {
    171     ipc_object_id = dispatcher_host_->Add(
    172         connection.release(), ipc_thread_id_, origin_url_);
    173   }
    174 
    175   dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIDBDatabase(
    176       ipc_thread_id_,
    177       ipc_callbacks_id_,
    178       ipc_database_callbacks_id_,
    179       ipc_object_id,
    180       IndexedDBDispatcherHost::ConvertMetadata(metadata)));
    181   dispatcher_host_ = NULL;
    182 }
    183 
    184 static std::string CreateBlobData(
    185     const IndexedDBBlobInfo& blob_info,
    186     scoped_refptr<IndexedDBDispatcherHost> dispatcher_host,
    187     webkit_blob::BlobStorageContext* blob_storage_context,
    188     base::TaskRunner* task_runner) {
    189   std::string uuid = blob_info.uuid();
    190   if (!uuid.empty()) {
    191     // We're sending back a live blob, not a reference into our backing store.
    192     scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle(
    193         blob_storage_context->GetBlobDataFromUUID(uuid));
    194     dispatcher_host->HoldBlobDataHandle(uuid, blob_data_handle);
    195     return uuid;
    196   }
    197   scoped_refptr<ShareableFileReference> shareable_file =
    198       ShareableFileReference::Get(blob_info.file_path());
    199   if (!shareable_file.get()) {
    200     shareable_file = ShareableFileReference::GetOrCreate(
    201         blob_info.file_path(),
    202         ShareableFileReference::DONT_DELETE_ON_FINAL_RELEASE,
    203         task_runner);
    204     if (!blob_info.release_callback().is_null())
    205       shareable_file->AddFinalReleaseCallback(blob_info.release_callback());
    206   }
    207 
    208   uuid = base::GenerateGUID();
    209   scoped_refptr<webkit_blob::BlobData> blob_data =
    210       new webkit_blob::BlobData(uuid);
    211   blob_data->AppendFile(
    212       blob_info.file_path(), 0, blob_info.size(), blob_info.last_modified());
    213   scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle(
    214       blob_storage_context->AddFinishedBlob(blob_data.get()));
    215   dispatcher_host->HoldBlobDataHandle(uuid, blob_data_handle);
    216 
    217   return uuid;
    218 }
    219 
    220 static bool CreateAllBlobs(
    221     const std::vector<IndexedDBBlobInfo>& blob_info,
    222     std::vector<IndexedDBMsg_BlobOrFileInfo>* blob_or_file_info,
    223     scoped_refptr<IndexedDBDispatcherHost> dispatcher_host) {
    224   DCHECK_EQ(blob_info.size(), blob_or_file_info->size());
    225   size_t i;
    226   if (!dispatcher_host->blob_storage_context())
    227     return false;
    228   for (i = 0; i < blob_info.size(); ++i) {
    229     (*blob_or_file_info)[i].uuid =
    230         CreateBlobData(blob_info[i],
    231                        dispatcher_host,
    232                        dispatcher_host->blob_storage_context(),
    233                        dispatcher_host->Context()->TaskRunner());
    234   }
    235   return true;
    236 }
    237 
    238 template <class ParamType, class MsgType>
    239 static void CreateBlobsAndSend(
    240     ParamType* params,
    241     scoped_refptr<IndexedDBDispatcherHost> dispatcher_host,
    242     const std::vector<IndexedDBBlobInfo>& blob_info,
    243     std::vector<IndexedDBMsg_BlobOrFileInfo>* blob_or_file_info) {
    244   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    245   if (CreateAllBlobs(blob_info, blob_or_file_info, dispatcher_host))
    246     dispatcher_host->Send(new MsgType(*params));
    247 }
    248 
    249 static void BlobLookupForCursorPrefetch(
    250     IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params* params,
    251     scoped_refptr<IndexedDBDispatcherHost> dispatcher_host,
    252     const std::vector<IndexedDBValue>& values) {
    253   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    254   DCHECK_EQ(values.size(), params->blob_or_file_infos.size());
    255 
    256   std::vector<IndexedDBValue>::const_iterator value_iter;
    257   std::vector<std::vector<IndexedDBMsg_BlobOrFileInfo> >::iterator blob_iter;
    258   for (value_iter = values.begin(), blob_iter =
    259        params->blob_or_file_infos.begin(); value_iter != values.end();
    260        ++value_iter, ++blob_iter) {
    261     if (!CreateAllBlobs(value_iter->blob_info, &*blob_iter, dispatcher_host))
    262       return;
    263   }
    264   dispatcher_host->Send(
    265       new IndexedDBMsg_CallbacksSuccessCursorPrefetch(*params));
    266 }
    267 
    268 static void FillInBlobData(
    269     const std::vector<IndexedDBBlobInfo>& blob_info,
    270     std::vector<IndexedDBMsg_BlobOrFileInfo>* blob_or_file_info) {
    271   for (std::vector<IndexedDBBlobInfo>::const_iterator iter = blob_info.begin();
    272        iter != blob_info.end();
    273        ++iter) {
    274     if (iter->is_file()) {
    275       IndexedDBMsg_BlobOrFileInfo info;
    276       info.is_file = true;
    277       info.mime_type = iter->type();
    278       info.file_name = iter->file_name();
    279       info.file_path = iter->file_path().AsUTF16Unsafe();
    280       info.size = iter->size();
    281       info.last_modified = iter->last_modified().ToDoubleT();
    282       blob_or_file_info->push_back(info);
    283     } else {
    284       IndexedDBMsg_BlobOrFileInfo info;
    285       info.mime_type = iter->type();
    286       info.size = iter->size();
    287       blob_or_file_info->push_back(info);
    288     }
    289   }
    290 }
    291 
    292 void IndexedDBCallbacks::RegisterBlobsAndSend(
    293     const std::vector<IndexedDBBlobInfo>& blob_info,
    294     const base::Closure& callback) {
    295   std::vector<IndexedDBBlobInfo>::const_iterator iter;
    296   for (iter = blob_info.begin(); iter != blob_info.end(); ++iter) {
    297     if (!iter->mark_used_callback().is_null())
    298       iter->mark_used_callback().Run();
    299   }
    300   DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
    301   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, callback);
    302 }
    303 
    304 void IndexedDBCallbacks::OnSuccess(scoped_refptr<IndexedDBCursor> cursor,
    305                                    const IndexedDBKey& key,
    306                                    const IndexedDBKey& primary_key,
    307                                    IndexedDBValue* value) {
    308   DCHECK(dispatcher_host_.get());
    309 
    310   DCHECK_EQ(kNoCursor, ipc_cursor_id_);
    311   DCHECK_EQ(kNoTransaction, host_transaction_id_);
    312   DCHECK_EQ(kNoDatabase, ipc_database_id_);
    313   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
    314   DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
    315 
    316   int32 ipc_object_id = dispatcher_host_->Add(cursor.get());
    317   scoped_ptr<IndexedDBMsg_CallbacksSuccessIDBCursor_Params> params(
    318       new IndexedDBMsg_CallbacksSuccessIDBCursor_Params());
    319   params->ipc_thread_id = ipc_thread_id_;
    320   params->ipc_callbacks_id = ipc_callbacks_id_;
    321   params->ipc_cursor_id = ipc_object_id;
    322   params->key = key;
    323   params->primary_key = primary_key;
    324   if (value && !value->empty())
    325     std::swap(params->value, value->bits);
    326   // TODO(alecflett): Avoid a copy here: the whole params object is
    327   // being copied into the message.
    328   if (!value || value->blob_info.empty()) {
    329     dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIDBCursor(*params));
    330   } else {
    331     IndexedDBMsg_CallbacksSuccessIDBCursor_Params* p = params.get();
    332     FillInBlobData(value->blob_info, &p->blob_or_file_info);
    333     RegisterBlobsAndSend(
    334         value->blob_info,
    335         base::Bind(
    336             CreateBlobsAndSend<IndexedDBMsg_CallbacksSuccessIDBCursor_Params,
    337                                IndexedDBMsg_CallbacksSuccessIDBCursor>,
    338             base::Owned(params.release()),
    339             dispatcher_host_,
    340             value->blob_info,
    341             base::Unretained(&p->blob_or_file_info)));
    342   }
    343   dispatcher_host_ = NULL;
    344 }
    345 
    346 void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& key,
    347                                    const IndexedDBKey& primary_key,
    348                                    IndexedDBValue* value) {
    349   DCHECK(dispatcher_host_.get());
    350 
    351   DCHECK_NE(kNoCursor, ipc_cursor_id_);
    352   DCHECK_EQ(kNoTransaction, host_transaction_id_);
    353   DCHECK_EQ(kNoDatabase, ipc_database_id_);
    354   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
    355   DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
    356 
    357   IndexedDBCursor* idb_cursor =
    358       dispatcher_host_->GetCursorFromId(ipc_cursor_id_);
    359 
    360   DCHECK(idb_cursor);
    361   if (!idb_cursor)
    362     return;
    363 
    364   scoped_ptr<IndexedDBMsg_CallbacksSuccessCursorContinue_Params> params(
    365       new IndexedDBMsg_CallbacksSuccessCursorContinue_Params());
    366   params->ipc_thread_id = ipc_thread_id_;
    367   params->ipc_callbacks_id = ipc_callbacks_id_;
    368   params->ipc_cursor_id = ipc_cursor_id_;
    369   params->key = key;
    370   params->primary_key = primary_key;
    371   if (value && !value->empty())
    372     std::swap(params->value, value->bits);
    373   // TODO(alecflett): Avoid a copy here: the whole params object is
    374   // being copied into the message.
    375   if (!value || value->blob_info.empty()) {
    376     dispatcher_host_->Send(
    377         new IndexedDBMsg_CallbacksSuccessCursorContinue(*params));
    378   } else {
    379     IndexedDBMsg_CallbacksSuccessCursorContinue_Params* p = params.get();
    380     FillInBlobData(value->blob_info, &p->blob_or_file_info);
    381     RegisterBlobsAndSend(
    382         value->blob_info,
    383         base::Bind(CreateBlobsAndSend<
    384                        IndexedDBMsg_CallbacksSuccessCursorContinue_Params,
    385                        IndexedDBMsg_CallbacksSuccessCursorContinue>,
    386                    base::Owned(params.release()),
    387                    dispatcher_host_,
    388                    value->blob_info,
    389                    base::Unretained(&p->blob_or_file_info)));
    390   }
    391   dispatcher_host_ = NULL;
    392 }
    393 
    394 void IndexedDBCallbacks::OnSuccessWithPrefetch(
    395     const std::vector<IndexedDBKey>& keys,
    396     const std::vector<IndexedDBKey>& primary_keys,
    397     std::vector<IndexedDBValue>& values) {
    398   DCHECK_EQ(keys.size(), primary_keys.size());
    399   DCHECK_EQ(keys.size(), values.size());
    400 
    401   DCHECK(dispatcher_host_.get());
    402 
    403   DCHECK_NE(kNoCursor, ipc_cursor_id_);
    404   DCHECK_EQ(kNoTransaction, host_transaction_id_);
    405   DCHECK_EQ(kNoDatabase, ipc_database_id_);
    406   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
    407   DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
    408 
    409   std::vector<IndexedDBKey> msgKeys;
    410   std::vector<IndexedDBKey> msgPrimaryKeys;
    411 
    412   for (size_t i = 0; i < keys.size(); ++i) {
    413     msgKeys.push_back(keys[i]);
    414     msgPrimaryKeys.push_back(primary_keys[i]);
    415   }
    416 
    417   scoped_ptr<IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params> params(
    418       new IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params());
    419   params->ipc_thread_id = ipc_thread_id_;
    420   params->ipc_callbacks_id = ipc_callbacks_id_;
    421   params->ipc_cursor_id = ipc_cursor_id_;
    422   params->keys = msgKeys;
    423   params->primary_keys = msgPrimaryKeys;
    424   std::vector<std::string>& values_bits = params->values;
    425   values_bits.resize(values.size());
    426   std::vector<std::vector<IndexedDBMsg_BlobOrFileInfo> >& values_blob_infos =
    427       params->blob_or_file_infos;
    428   values_blob_infos.resize(values.size());
    429 
    430   bool found_blob_info = false;
    431   std::vector<IndexedDBValue>::iterator iter = values.begin();
    432   for (size_t i = 0; iter != values.end(); ++iter, ++i) {
    433     values_bits[i].swap(iter->bits);
    434     if (iter->blob_info.size()) {
    435       found_blob_info = true;
    436       FillInBlobData(iter->blob_info, &values_blob_infos[i]);
    437       std::vector<IndexedDBBlobInfo>::const_iterator blob_iter;
    438       for (blob_iter = iter->blob_info.begin();
    439            blob_iter != iter->blob_info.end();
    440            ++blob_iter) {
    441         if (!blob_iter->mark_used_callback().is_null())
    442           blob_iter->mark_used_callback().Run();
    443       }
    444     }
    445   }
    446 
    447   if (found_blob_info) {
    448     BrowserThread::PostTask(
    449         BrowserThread::IO,
    450         FROM_HERE,
    451         base::Bind(BlobLookupForCursorPrefetch,
    452                    base::Owned(params.release()),
    453                    dispatcher_host_,
    454                    values));
    455   } else {
    456     dispatcher_host_->Send(
    457         new IndexedDBMsg_CallbacksSuccessCursorPrefetch(*params.get()));
    458   }
    459   dispatcher_host_ = NULL;
    460 }
    461 
    462 void IndexedDBCallbacks::OnSuccess(IndexedDBValue* value,
    463                                    const IndexedDBKey& key,
    464                                    const IndexedDBKeyPath& key_path) {
    465   DCHECK(dispatcher_host_.get());
    466 
    467   DCHECK_EQ(kNoCursor, ipc_cursor_id_);
    468   DCHECK_EQ(kNoTransaction, host_transaction_id_);
    469   DCHECK_EQ(kNoDatabase, ipc_database_id_);
    470   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
    471   DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
    472 
    473   scoped_ptr<IndexedDBMsg_CallbacksSuccessValueWithKey_Params> params(
    474       new IndexedDBMsg_CallbacksSuccessValueWithKey_Params());
    475   params->ipc_thread_id = ipc_thread_id_;
    476   params->ipc_callbacks_id = ipc_callbacks_id_;
    477   params->primary_key = key;
    478   params->key_path = key_path;
    479   if (value && !value->empty())
    480     std::swap(params->value, value->bits);
    481   if (!value || value->blob_info.empty()) {
    482     dispatcher_host_->Send(
    483         new IndexedDBMsg_CallbacksSuccessValueWithKey(*params));
    484   } else {
    485     IndexedDBMsg_CallbacksSuccessValueWithKey_Params* p = params.get();
    486     FillInBlobData(value->blob_info, &p->blob_or_file_info);
    487     RegisterBlobsAndSend(
    488         value->blob_info,
    489         base::Bind(
    490             CreateBlobsAndSend<IndexedDBMsg_CallbacksSuccessValueWithKey_Params,
    491                                IndexedDBMsg_CallbacksSuccessValueWithKey>,
    492             base::Owned(params.release()),
    493             dispatcher_host_,
    494             value->blob_info,
    495             base::Unretained(&p->blob_or_file_info)));
    496   }
    497   dispatcher_host_ = NULL;
    498 }
    499 
    500 void IndexedDBCallbacks::OnSuccess(IndexedDBValue* value) {
    501   DCHECK(dispatcher_host_.get());
    502   DCHECK(kNoCursor == ipc_cursor_id_ || value == NULL);
    503   DCHECK_EQ(kNoTransaction, host_transaction_id_);
    504   DCHECK_EQ(kNoDatabase, ipc_database_id_);
    505   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
    506   DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
    507 
    508   scoped_ptr<IndexedDBMsg_CallbacksSuccessValue_Params> params(
    509       new IndexedDBMsg_CallbacksSuccessValue_Params());
    510   params->ipc_thread_id = ipc_thread_id_;
    511   params->ipc_callbacks_id = ipc_callbacks_id_;
    512   if (value && !value->empty())
    513     std::swap(params->value, value->bits);
    514   if (!value || value->blob_info.empty()) {
    515     dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessValue(*params));
    516   } else {
    517     IndexedDBMsg_CallbacksSuccessValue_Params* p = params.get();
    518     FillInBlobData(value->blob_info, &p->blob_or_file_info);
    519     RegisterBlobsAndSend(
    520         value->blob_info,
    521         base::Bind(CreateBlobsAndSend<IndexedDBMsg_CallbacksSuccessValue_Params,
    522                                       IndexedDBMsg_CallbacksSuccessValue>,
    523                    base::Owned(params.release()),
    524                    dispatcher_host_,
    525                    value->blob_info,
    526                    base::Unretained(&p->blob_or_file_info)));
    527   }
    528   dispatcher_host_ = NULL;
    529 }
    530 
    531 void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& value) {
    532   DCHECK(dispatcher_host_.get());
    533 
    534   DCHECK_EQ(kNoCursor, ipc_cursor_id_);
    535   DCHECK_EQ(kNoTransaction, host_transaction_id_);
    536   DCHECK_EQ(kNoDatabase, ipc_database_id_);
    537   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
    538   DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
    539 
    540   dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIndexedDBKey(
    541       ipc_thread_id_, ipc_callbacks_id_, value));
    542   dispatcher_host_ = NULL;
    543 }
    544 
    545 void IndexedDBCallbacks::OnSuccess(int64 value) {
    546   DCHECK(dispatcher_host_.get());
    547 
    548   DCHECK_EQ(kNoCursor, ipc_cursor_id_);
    549   DCHECK_EQ(kNoTransaction, host_transaction_id_);
    550   DCHECK_EQ(kNoDatabase, ipc_database_id_);
    551   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
    552   DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
    553 
    554   dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessInteger(
    555       ipc_thread_id_, ipc_callbacks_id_, value));
    556   dispatcher_host_ = NULL;
    557 }
    558 
    559 void IndexedDBCallbacks::OnSuccess() {
    560   DCHECK(dispatcher_host_.get());
    561 
    562   DCHECK_EQ(kNoCursor, ipc_cursor_id_);
    563   DCHECK_EQ(kNoTransaction, host_transaction_id_);
    564   DCHECK_EQ(kNoDatabase, ipc_database_id_);
    565   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
    566   DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
    567 
    568   dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessUndefined(
    569       ipc_thread_id_, ipc_callbacks_id_));
    570   dispatcher_host_ = NULL;
    571 }
    572 
    573 }  // namespace content
    574