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