74a76fdce53de540f390fb177a45710e8cb6c95e
[platform/framework/web/crosswalk.git] / src / content / browser / indexed_db / indexed_db_callbacks.cc
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