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