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