Upstream version 10.39.225.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/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