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