Home | History | Annotate | Download | only in indexed_db
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "content/browser/indexed_db/indexed_db_callbacks.h"
      6 
      7 #include <algorithm>
      8 
      9 #include "content/browser/indexed_db/indexed_db_connection.h"
     10 #include "content/browser/indexed_db/indexed_db_cursor.h"
     11 #include "content/browser/indexed_db/indexed_db_database_callbacks.h"
     12 #include "content/browser/indexed_db/indexed_db_database_error.h"
     13 #include "content/browser/indexed_db/indexed_db_metadata.h"
     14 #include "content/common/indexed_db/indexed_db_messages.h"
     15 #include "webkit/browser/quota/quota_manager.h"
     16 
     17 using WebKit::WebIDBCallbacks;
     18 
     19 namespace content {
     20 
     21 namespace {
     22 const int32 kNoCursor = -1;
     23 const int32 kNoDatabase = -1;
     24 const int32 kNoDatabaseCallbacks = -1;
     25 const int64 kNoTransaction = -1;
     26 }
     27 
     28 IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
     29                                        int32 ipc_thread_id,
     30                                        int32 ipc_callbacks_id)
     31     : dispatcher_host_(dispatcher_host),
     32       ipc_callbacks_id_(ipc_callbacks_id),
     33       ipc_thread_id_(ipc_thread_id),
     34       ipc_cursor_id_(kNoCursor),
     35       host_transaction_id_(kNoTransaction),
     36       ipc_database_id_(kNoDatabase),
     37       ipc_database_callbacks_id_(kNoDatabaseCallbacks) {}
     38 
     39 IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
     40                                        int32 ipc_thread_id,
     41                                        int32 ipc_callbacks_id,
     42                                        int32 ipc_cursor_id)
     43     : dispatcher_host_(dispatcher_host),
     44       ipc_callbacks_id_(ipc_callbacks_id),
     45       ipc_thread_id_(ipc_thread_id),
     46       ipc_cursor_id_(ipc_cursor_id),
     47       host_transaction_id_(kNoTransaction),
     48       ipc_database_id_(kNoDatabase),
     49       ipc_database_callbacks_id_(kNoDatabaseCallbacks) {}
     50 
     51 IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
     52                                        int32 ipc_thread_id,
     53                                        int32 ipc_callbacks_id,
     54                                        int32 ipc_database_callbacks_id,
     55                                        int64 host_transaction_id,
     56                                        const GURL& origin_url)
     57     : dispatcher_host_(dispatcher_host),
     58       ipc_callbacks_id_(ipc_callbacks_id),
     59       ipc_thread_id_(ipc_thread_id),
     60       ipc_cursor_id_(kNoCursor),
     61       host_transaction_id_(host_transaction_id),
     62       origin_url_(origin_url),
     63       ipc_database_id_(kNoDatabase),
     64       ipc_database_callbacks_id_(ipc_database_callbacks_id) {}
     65 
     66 IndexedDBCallbacks::~IndexedDBCallbacks() {}
     67 
     68 void IndexedDBCallbacks::OnError(const IndexedDBDatabaseError& error) {
     69   DCHECK(dispatcher_host_.get());
     70 
     71   dispatcher_host_->Send(new IndexedDBMsg_CallbacksError(
     72       ipc_thread_id_, ipc_callbacks_id_, error.code(), error.message()));
     73   dispatcher_host_ = NULL;
     74 }
     75 
     76 void IndexedDBCallbacks::OnSuccess(const std::vector<string16>& value) {
     77   DCHECK(dispatcher_host_.get());
     78 
     79   DCHECK_EQ(kNoCursor, ipc_cursor_id_);
     80   DCHECK_EQ(kNoTransaction, host_transaction_id_);
     81   DCHECK_EQ(kNoDatabase, ipc_database_id_);
     82   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
     83 
     84   std::vector<string16> list;
     85   for (unsigned i = 0; i < value.size(); ++i)
     86     list.push_back(value[i]);
     87 
     88   dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessStringList(
     89       ipc_thread_id_, ipc_callbacks_id_, list));
     90   dispatcher_host_ = NULL;
     91 }
     92 
     93 void IndexedDBCallbacks::OnBlocked(int64 existing_version) {
     94   DCHECK(dispatcher_host_.get());
     95 
     96   DCHECK_EQ(kNoCursor, ipc_cursor_id_);
     97   // No transaction/db callbacks for DeleteDatabase.
     98   DCHECK_EQ(kNoTransaction == host_transaction_id_,
     99             kNoDatabaseCallbacks == ipc_database_callbacks_id_);
    100   DCHECK_EQ(kNoDatabase, ipc_database_id_);
    101 
    102   dispatcher_host_->Send(new IndexedDBMsg_CallbacksIntBlocked(
    103       ipc_thread_id_, ipc_callbacks_id_, existing_version));
    104 }
    105 
    106 void IndexedDBCallbacks::OnUpgradeNeeded(
    107     int64 old_version,
    108     scoped_ptr<IndexedDBConnection> connection,
    109     const IndexedDBDatabaseMetadata& metadata,
    110     WebIDBCallbacks::DataLoss data_loss) {
    111   DCHECK(dispatcher_host_.get());
    112 
    113   DCHECK_EQ(kNoCursor, ipc_cursor_id_);
    114   DCHECK_NE(kNoTransaction, host_transaction_id_);
    115   DCHECK_EQ(kNoDatabase, ipc_database_id_);
    116   DCHECK_NE(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
    117 
    118   dispatcher_host_->RegisterTransactionId(host_transaction_id_, origin_url_);
    119   int32 ipc_database_id =
    120       dispatcher_host_->Add(connection.release(), ipc_thread_id_, origin_url_);
    121   if (ipc_database_id < 0)
    122     return;
    123   ipc_database_id_ = ipc_database_id;
    124   IndexedDBMsg_CallbacksUpgradeNeeded_Params params;
    125   params.ipc_thread_id = ipc_thread_id_;
    126   params.ipc_callbacks_id = ipc_callbacks_id_;
    127   params.ipc_database_id = ipc_database_id;
    128   params.ipc_database_callbacks_id = ipc_database_callbacks_id_;
    129   params.old_version = old_version;
    130   params.idb_metadata = IndexedDBDispatcherHost::ConvertMetadata(metadata);
    131   params.data_loss = data_loss;
    132   dispatcher_host_->Send(new IndexedDBMsg_CallbacksUpgradeNeeded(params));
    133 }
    134 
    135 void IndexedDBCallbacks::OnSuccess(scoped_ptr<IndexedDBConnection> connection,
    136                                    const IndexedDBDatabaseMetadata& metadata) {
    137   DCHECK(dispatcher_host_.get());
    138 
    139   DCHECK_EQ(kNoCursor, ipc_cursor_id_);
    140   DCHECK_NE(kNoTransaction, host_transaction_id_);
    141   DCHECK_NE(ipc_database_id_ == kNoDatabase, !connection);
    142   DCHECK_NE(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
    143 
    144   scoped_refptr<IndexedDBCallbacks> self(this);
    145 
    146   int32 ipc_object_id = ipc_database_id_;
    147   if (ipc_object_id == kNoDatabase) {
    148     ipc_object_id = dispatcher_host_->Add(
    149         connection.release(), ipc_thread_id_, origin_url_);
    150   }
    151 
    152   dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIDBDatabase(
    153       ipc_thread_id_,
    154       ipc_callbacks_id_,
    155       ipc_database_callbacks_id_,
    156       ipc_object_id,
    157       IndexedDBDispatcherHost::ConvertMetadata(metadata)));
    158   dispatcher_host_ = NULL;
    159 }
    160 
    161 void IndexedDBCallbacks::OnSuccess(scoped_refptr<IndexedDBCursor> cursor,
    162                                    const IndexedDBKey& key,
    163                                    const IndexedDBKey& primary_key,
    164                                    std::string* value) {
    165   DCHECK(dispatcher_host_.get());
    166 
    167   DCHECK_EQ(kNoCursor, ipc_cursor_id_);
    168   DCHECK_EQ(kNoTransaction, host_transaction_id_);
    169   DCHECK_EQ(kNoDatabase, ipc_database_id_);
    170   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
    171 
    172   int32 ipc_object_id = dispatcher_host_->Add(cursor.get());
    173   IndexedDBMsg_CallbacksSuccessIDBCursor_Params params;
    174   params.ipc_thread_id = ipc_thread_id_;
    175   params.ipc_callbacks_id = ipc_callbacks_id_;
    176   params.ipc_cursor_id = ipc_object_id;
    177   params.key = key;
    178   params.primary_key = primary_key;
    179   if (value && !value->empty())
    180     std::swap(params.value, *value);
    181   // TODO(alecflett): Avoid a copy here: the whole params object is
    182   // being copied into the message.
    183   dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIDBCursor(params));
    184 
    185   dispatcher_host_ = NULL;
    186 }
    187 
    188 void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& key,
    189                                    const IndexedDBKey& primary_key,
    190                                    std::string* value) {
    191   DCHECK(dispatcher_host_.get());
    192 
    193   DCHECK_NE(kNoCursor, ipc_cursor_id_);
    194   DCHECK_EQ(kNoTransaction, host_transaction_id_);
    195   DCHECK_EQ(kNoDatabase, ipc_database_id_);
    196   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
    197 
    198   IndexedDBCursor* idb_cursor =
    199       dispatcher_host_->GetCursorFromId(ipc_cursor_id_);
    200 
    201   DCHECK(idb_cursor);
    202   if (!idb_cursor)
    203     return;
    204   IndexedDBMsg_CallbacksSuccessCursorContinue_Params params;
    205   params.ipc_thread_id = ipc_thread_id_;
    206   params.ipc_callbacks_id = ipc_callbacks_id_;
    207   params.ipc_cursor_id = ipc_cursor_id_;
    208   params.key = key;
    209   params.primary_key = primary_key;
    210   if (value && !value->empty())
    211     std::swap(params.value, *value);
    212   // TODO(alecflett): Avoid a copy here: the whole params object is
    213   // being copied into the message.
    214   dispatcher_host_->Send(
    215       new IndexedDBMsg_CallbacksSuccessCursorContinue(params));
    216   dispatcher_host_ = NULL;
    217 }
    218 
    219 void IndexedDBCallbacks::OnSuccessWithPrefetch(
    220     const std::vector<IndexedDBKey>& keys,
    221     const std::vector<IndexedDBKey>& primary_keys,
    222     const std::vector<std::string>& values) {
    223   DCHECK_EQ(keys.size(), primary_keys.size());
    224   DCHECK_EQ(keys.size(), values.size());
    225 
    226   DCHECK(dispatcher_host_.get());
    227 
    228   DCHECK_NE(kNoCursor, ipc_cursor_id_);
    229   DCHECK_EQ(kNoTransaction, host_transaction_id_);
    230   DCHECK_EQ(kNoDatabase, ipc_database_id_);
    231   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
    232 
    233   std::vector<IndexedDBKey> msgKeys;
    234   std::vector<IndexedDBKey> msgPrimaryKeys;
    235 
    236   for (size_t i = 0; i < keys.size(); ++i) {
    237     msgKeys.push_back(keys[i]);
    238     msgPrimaryKeys.push_back(primary_keys[i]);
    239   }
    240 
    241   IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params params;
    242   params.ipc_thread_id = ipc_thread_id_;
    243   params.ipc_callbacks_id = ipc_callbacks_id_;
    244   params.ipc_cursor_id = ipc_cursor_id_;
    245   params.keys = msgKeys;
    246   params.primary_keys = msgPrimaryKeys;
    247   params.values = values;
    248   dispatcher_host_->Send(
    249       new IndexedDBMsg_CallbacksSuccessCursorPrefetch(params));
    250   dispatcher_host_ = NULL;
    251 }
    252 
    253 void IndexedDBCallbacks::OnSuccess(std::string* value,
    254                                    const IndexedDBKey& key,
    255                                    const IndexedDBKeyPath& key_path) {
    256   DCHECK(dispatcher_host_.get());
    257 
    258   DCHECK_EQ(kNoCursor, ipc_cursor_id_);
    259   DCHECK_EQ(kNoTransaction, host_transaction_id_);
    260   DCHECK_EQ(kNoDatabase, ipc_database_id_);
    261   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
    262 
    263   std::string value_copy;
    264   if (value && !value->empty())
    265     std::swap(value_copy, *value);
    266 
    267   dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessValueWithKey(
    268       ipc_thread_id_,
    269       ipc_callbacks_id_,
    270       // TODO(alecflett): Avoid a copy here.
    271       value_copy,
    272       key,
    273       key_path));
    274   dispatcher_host_ = NULL;
    275 }
    276 
    277 void IndexedDBCallbacks::OnSuccess(std::string* value) {
    278   DCHECK(dispatcher_host_.get());
    279 
    280   DCHECK(kNoCursor == ipc_cursor_id_ || value == NULL);
    281   DCHECK_EQ(kNoTransaction, host_transaction_id_);
    282   DCHECK_EQ(kNoDatabase, ipc_database_id_);
    283   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
    284 
    285   std::string value_copy;
    286   if (value && !value->empty())
    287     std::swap(value_copy, *value);
    288 
    289   dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessValue(
    290       ipc_thread_id_,
    291       ipc_callbacks_id_,
    292       // TODO(alecflett): avoid a copy here.
    293       value_copy));
    294   dispatcher_host_ = NULL;
    295 }
    296 
    297 void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& value) {
    298   DCHECK(dispatcher_host_.get());
    299 
    300   DCHECK_EQ(kNoCursor, ipc_cursor_id_);
    301   DCHECK_EQ(kNoTransaction, host_transaction_id_);
    302   DCHECK_EQ(kNoDatabase, ipc_database_id_);
    303   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
    304 
    305   dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIndexedDBKey(
    306       ipc_thread_id_, ipc_callbacks_id_, value));
    307   dispatcher_host_ = NULL;
    308 }
    309 
    310 void IndexedDBCallbacks::OnSuccess(int64 value) {
    311   DCHECK(dispatcher_host_.get());
    312 
    313   DCHECK_EQ(kNoCursor, ipc_cursor_id_);
    314   DCHECK_EQ(kNoTransaction, host_transaction_id_);
    315   DCHECK_EQ(kNoDatabase, ipc_database_id_);
    316   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
    317 
    318   dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessInteger(
    319       ipc_thread_id_, ipc_callbacks_id_, value));
    320   dispatcher_host_ = NULL;
    321 }
    322 
    323 void IndexedDBCallbacks::OnSuccess() {
    324   DCHECK(dispatcher_host_.get());
    325 
    326   DCHECK_EQ(kNoCursor, ipc_cursor_id_);
    327   DCHECK_EQ(kNoTransaction, host_transaction_id_);
    328   DCHECK_EQ(kNoDatabase, ipc_database_id_);
    329   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
    330 
    331   dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessUndefined(
    332       ipc_thread_id_, ipc_callbacks_id_));
    333   dispatcher_host_ = NULL;
    334 }
    335 
    336 }  // namespace content
    337