Upstream version 10.38.208.0
[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       sent_blocked_(false) {
51 }
52
53 IndexedDBCallbacks::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
68 IndexedDBCallbacks::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
86 IndexedDBCallbacks::~IndexedDBCallbacks() {}
87
88 void 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
96 void 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
114 void 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
131 void 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
138 void 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
167 void 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
194 static 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.Pass());
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->set_content_type(base::UTF16ToUTF8(blob_info.type()));
222   blob_data->AppendFile(
223       blob_info.file_path(), 0, blob_info.size(), blob_info.last_modified());
224   scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle(
225       blob_storage_context->AddFinishedBlob(blob_data.get()));
226   dispatcher_host->HoldBlobDataHandle(uuid, blob_data_handle.Pass());
227
228   return uuid;
229 }
230
231 static bool CreateAllBlobs(
232     const std::vector<IndexedDBBlobInfo>& blob_info,
233     std::vector<IndexedDBMsg_BlobOrFileInfo>* blob_or_file_info,
234     scoped_refptr<IndexedDBDispatcherHost> dispatcher_host) {
235   DCHECK_EQ(blob_info.size(), blob_or_file_info->size());
236   size_t i;
237   if (!dispatcher_host->blob_storage_context())
238     return false;
239   for (i = 0; i < blob_info.size(); ++i) {
240     (*blob_or_file_info)[i].uuid =
241         CreateBlobData(blob_info[i],
242                        dispatcher_host,
243                        dispatcher_host->blob_storage_context(),
244                        dispatcher_host->Context()->TaskRunner());
245   }
246   return true;
247 }
248
249 template <class ParamType, class MsgType>
250 static void CreateBlobsAndSend(
251     ParamType* params,
252     scoped_refptr<IndexedDBDispatcherHost> dispatcher_host,
253     const std::vector<IndexedDBBlobInfo>& blob_info,
254     std::vector<IndexedDBMsg_BlobOrFileInfo>* blob_or_file_info) {
255   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
256   if (CreateAllBlobs(blob_info, blob_or_file_info, dispatcher_host))
257     dispatcher_host->Send(new MsgType(*params));
258 }
259
260 static void BlobLookupForCursorPrefetch(
261     IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params* params,
262     scoped_refptr<IndexedDBDispatcherHost> dispatcher_host,
263     const std::vector<IndexedDBValue>& values) {
264   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
265   DCHECK_EQ(values.size(), params->blob_or_file_infos.size());
266
267   std::vector<IndexedDBValue>::const_iterator value_iter;
268   std::vector<std::vector<IndexedDBMsg_BlobOrFileInfo> >::iterator blob_iter;
269   for (value_iter = values.begin(), blob_iter =
270        params->blob_or_file_infos.begin(); value_iter != values.end();
271        ++value_iter, ++blob_iter) {
272     if (!CreateAllBlobs(value_iter->blob_info, &*blob_iter, dispatcher_host))
273       return;
274   }
275   dispatcher_host->Send(
276       new IndexedDBMsg_CallbacksSuccessCursorPrefetch(*params));
277 }
278
279 static void FillInBlobData(
280     const std::vector<IndexedDBBlobInfo>& blob_info,
281     std::vector<IndexedDBMsg_BlobOrFileInfo>* blob_or_file_info) {
282   for (std::vector<IndexedDBBlobInfo>::const_iterator iter = blob_info.begin();
283        iter != blob_info.end();
284        ++iter) {
285     if (iter->is_file()) {
286       IndexedDBMsg_BlobOrFileInfo info;
287       info.is_file = true;
288       info.mime_type = iter->type();
289       info.file_name = iter->file_name();
290       info.file_path = iter->file_path().AsUTF16Unsafe();
291       info.size = iter->size();
292       info.last_modified = iter->last_modified().ToDoubleT();
293       blob_or_file_info->push_back(info);
294     } else {
295       IndexedDBMsg_BlobOrFileInfo info;
296       info.mime_type = iter->type();
297       info.size = iter->size();
298       blob_or_file_info->push_back(info);
299     }
300   }
301 }
302
303 void IndexedDBCallbacks::RegisterBlobsAndSend(
304     const std::vector<IndexedDBBlobInfo>& blob_info,
305     const base::Closure& callback) {
306   std::vector<IndexedDBBlobInfo>::const_iterator iter;
307   for (iter = blob_info.begin(); iter != blob_info.end(); ++iter) {
308     if (!iter->mark_used_callback().is_null())
309       iter->mark_used_callback().Run();
310   }
311   DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
312   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, callback);
313 }
314
315 void IndexedDBCallbacks::OnSuccess(scoped_refptr<IndexedDBCursor> cursor,
316                                    const IndexedDBKey& key,
317                                    const IndexedDBKey& primary_key,
318                                    IndexedDBValue* value) {
319   DCHECK(dispatcher_host_.get());
320
321   DCHECK_EQ(kNoCursor, ipc_cursor_id_);
322   DCHECK_EQ(kNoTransaction, host_transaction_id_);
323   DCHECK_EQ(kNoDatabase, ipc_database_id_);
324   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
325   DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
326
327   int32 ipc_object_id = dispatcher_host_->Add(cursor.get());
328   scoped_ptr<IndexedDBMsg_CallbacksSuccessIDBCursor_Params> params(
329       new IndexedDBMsg_CallbacksSuccessIDBCursor_Params());
330   params->ipc_thread_id = ipc_thread_id_;
331   params->ipc_callbacks_id = ipc_callbacks_id_;
332   params->ipc_cursor_id = ipc_object_id;
333   params->key = key;
334   params->primary_key = primary_key;
335   if (value && !value->empty())
336     std::swap(params->value, value->bits);
337   // TODO(alecflett): Avoid a copy here: the whole params object is
338   // being copied into the message.
339   if (!value || value->blob_info.empty()) {
340     dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIDBCursor(*params));
341   } else {
342     IndexedDBMsg_CallbacksSuccessIDBCursor_Params* p = params.get();
343     FillInBlobData(value->blob_info, &p->blob_or_file_info);
344     RegisterBlobsAndSend(
345         value->blob_info,
346         base::Bind(
347             CreateBlobsAndSend<IndexedDBMsg_CallbacksSuccessIDBCursor_Params,
348                                IndexedDBMsg_CallbacksSuccessIDBCursor>,
349             base::Owned(params.release()),
350             dispatcher_host_,
351             value->blob_info,
352             base::Unretained(&p->blob_or_file_info)));
353   }
354   dispatcher_host_ = NULL;
355 }
356
357 void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& key,
358                                    const IndexedDBKey& primary_key,
359                                    IndexedDBValue* value) {
360   DCHECK(dispatcher_host_.get());
361
362   DCHECK_NE(kNoCursor, ipc_cursor_id_);
363   DCHECK_EQ(kNoTransaction, host_transaction_id_);
364   DCHECK_EQ(kNoDatabase, ipc_database_id_);
365   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
366   DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
367
368   IndexedDBCursor* idb_cursor =
369       dispatcher_host_->GetCursorFromId(ipc_cursor_id_);
370
371   DCHECK(idb_cursor);
372   if (!idb_cursor)
373     return;
374
375   scoped_ptr<IndexedDBMsg_CallbacksSuccessCursorContinue_Params> params(
376       new IndexedDBMsg_CallbacksSuccessCursorContinue_Params());
377   params->ipc_thread_id = ipc_thread_id_;
378   params->ipc_callbacks_id = ipc_callbacks_id_;
379   params->ipc_cursor_id = ipc_cursor_id_;
380   params->key = key;
381   params->primary_key = primary_key;
382   if (value && !value->empty())
383     std::swap(params->value, value->bits);
384   // TODO(alecflett): Avoid a copy here: the whole params object is
385   // being copied into the message.
386   if (!value || value->blob_info.empty()) {
387     dispatcher_host_->Send(
388         new IndexedDBMsg_CallbacksSuccessCursorContinue(*params));
389   } else {
390     IndexedDBMsg_CallbacksSuccessCursorContinue_Params* p = params.get();
391     FillInBlobData(value->blob_info, &p->blob_or_file_info);
392     RegisterBlobsAndSend(
393         value->blob_info,
394         base::Bind(CreateBlobsAndSend<
395                        IndexedDBMsg_CallbacksSuccessCursorContinue_Params,
396                        IndexedDBMsg_CallbacksSuccessCursorContinue>,
397                    base::Owned(params.release()),
398                    dispatcher_host_,
399                    value->blob_info,
400                    base::Unretained(&p->blob_or_file_info)));
401   }
402   dispatcher_host_ = NULL;
403 }
404
405 void IndexedDBCallbacks::OnSuccessWithPrefetch(
406     const std::vector<IndexedDBKey>& keys,
407     const std::vector<IndexedDBKey>& primary_keys,
408     std::vector<IndexedDBValue>* values) {
409   DCHECK_EQ(keys.size(), primary_keys.size());
410   DCHECK_EQ(keys.size(), values->size());
411
412   DCHECK(dispatcher_host_.get());
413
414   DCHECK_NE(kNoCursor, ipc_cursor_id_);
415   DCHECK_EQ(kNoTransaction, host_transaction_id_);
416   DCHECK_EQ(kNoDatabase, ipc_database_id_);
417   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
418   DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
419
420   std::vector<IndexedDBKey> msgKeys;
421   std::vector<IndexedDBKey> msgPrimaryKeys;
422
423   for (size_t i = 0; i < keys.size(); ++i) {
424     msgKeys.push_back(keys[i]);
425     msgPrimaryKeys.push_back(primary_keys[i]);
426   }
427
428   scoped_ptr<IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params> params(
429       new IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params());
430   params->ipc_thread_id = ipc_thread_id_;
431   params->ipc_callbacks_id = ipc_callbacks_id_;
432   params->ipc_cursor_id = ipc_cursor_id_;
433   params->keys = msgKeys;
434   params->primary_keys = msgPrimaryKeys;
435   std::vector<std::string>& values_bits = params->values;
436   values_bits.resize(values->size());
437   std::vector<std::vector<IndexedDBMsg_BlobOrFileInfo> >& values_blob_infos =
438       params->blob_or_file_infos;
439   values_blob_infos.resize(values->size());
440
441   bool found_blob_info = false;
442   std::vector<IndexedDBValue>::iterator iter = values->begin();
443   for (size_t i = 0; iter != values->end(); ++iter, ++i) {
444     values_bits[i].swap(iter->bits);
445     if (iter->blob_info.size()) {
446       found_blob_info = true;
447       FillInBlobData(iter->blob_info, &values_blob_infos[i]);
448       std::vector<IndexedDBBlobInfo>::const_iterator blob_iter;
449       for (blob_iter = iter->blob_info.begin();
450            blob_iter != iter->blob_info.end();
451            ++blob_iter) {
452         if (!blob_iter->mark_used_callback().is_null())
453           blob_iter->mark_used_callback().Run();
454       }
455     }
456   }
457
458   if (found_blob_info) {
459     BrowserThread::PostTask(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
472 void 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
510 void 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
541 void 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
555 void 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
569 void 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