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