1 // Copyright 2013 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/child/indexed_db/indexed_db_dispatcher.h" 6 7 #include "base/format_macros.h" 8 #include "base/lazy_instance.h" 9 #include "base/strings/stringprintf.h" 10 #include "base/threading/thread_local.h" 11 #include "content/child/indexed_db/indexed_db_key_builders.h" 12 #include "content/child/indexed_db/webidbcursor_impl.h" 13 #include "content/child/indexed_db/webidbdatabase_impl.h" 14 #include "content/child/thread_safe_sender.h" 15 #include "content/common/indexed_db/indexed_db_constants.h" 16 #include "content/common/indexed_db/indexed_db_messages.h" 17 #include "ipc/ipc_channel.h" 18 #include "third_party/WebKit/public/platform/WebIDBDatabaseCallbacks.h" 19 #include "third_party/WebKit/public/platform/WebIDBDatabaseError.h" 20 #include "third_party/WebKit/public/platform/WebIDBDatabaseException.h" 21 22 using blink::WebData; 23 using blink::WebIDBCallbacks; 24 using blink::WebIDBDatabase; 25 using blink::WebIDBDatabaseCallbacks; 26 using blink::WebIDBDatabaseError; 27 using blink::WebIDBKey; 28 using blink::WebIDBMetadata; 29 using blink::WebString; 30 using blink::WebVector; 31 using base::ThreadLocalPointer; 32 using webkit_glue::WorkerTaskRunner; 33 34 namespace content { 35 static base::LazyInstance<ThreadLocalPointer<IndexedDBDispatcher> >::Leaky 36 g_idb_dispatcher_tls = LAZY_INSTANCE_INITIALIZER; 37 38 namespace { 39 40 IndexedDBDispatcher* const kHasBeenDeleted = 41 reinterpret_cast<IndexedDBDispatcher*>(0x1); 42 43 } // unnamed namespace 44 45 const size_t kMaxIDBValueSizeInBytes = 64 * 1024 * 1024; 46 47 IndexedDBDispatcher::IndexedDBDispatcher(ThreadSafeSender* thread_safe_sender) 48 : thread_safe_sender_(thread_safe_sender) { 49 g_idb_dispatcher_tls.Pointer()->Set(this); 50 } 51 52 IndexedDBDispatcher::~IndexedDBDispatcher() { 53 // Clear any pending callbacks - which may result in dispatch requests - 54 // before marking the dispatcher as deleted. 55 pending_callbacks_.Clear(); 56 pending_database_callbacks_.Clear(); 57 58 DCHECK(pending_callbacks_.IsEmpty()); 59 DCHECK(pending_database_callbacks_.IsEmpty()); 60 61 g_idb_dispatcher_tls.Pointer()->Set(kHasBeenDeleted); 62 } 63 64 IndexedDBDispatcher* IndexedDBDispatcher::ThreadSpecificInstance( 65 ThreadSafeSender* thread_safe_sender) { 66 if (g_idb_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted) { 67 NOTREACHED() << "Re-instantiating TLS IndexedDBDispatcher."; 68 g_idb_dispatcher_tls.Pointer()->Set(NULL); 69 } 70 if (g_idb_dispatcher_tls.Pointer()->Get()) 71 return g_idb_dispatcher_tls.Pointer()->Get(); 72 73 IndexedDBDispatcher* dispatcher = new IndexedDBDispatcher(thread_safe_sender); 74 if (WorkerTaskRunner::Instance()->CurrentWorkerId()) 75 webkit_glue::WorkerTaskRunner::Instance()->AddStopObserver(dispatcher); 76 return dispatcher; 77 } 78 79 void IndexedDBDispatcher::OnWorkerRunLoopStopped() { delete this; } 80 81 WebIDBMetadata IndexedDBDispatcher::ConvertMetadata( 82 const IndexedDBDatabaseMetadata& idb_metadata) { 83 WebIDBMetadata web_metadata; 84 web_metadata.id = idb_metadata.id; 85 web_metadata.name = idb_metadata.name; 86 web_metadata.version = idb_metadata.version; 87 web_metadata.intVersion = idb_metadata.int_version; 88 web_metadata.maxObjectStoreId = idb_metadata.max_object_store_id; 89 web_metadata.objectStores = 90 WebVector<WebIDBMetadata::ObjectStore>(idb_metadata.object_stores.size()); 91 92 for (size_t i = 0; i < idb_metadata.object_stores.size(); ++i) { 93 const IndexedDBObjectStoreMetadata& idb_store_metadata = 94 idb_metadata.object_stores[i]; 95 WebIDBMetadata::ObjectStore& web_store_metadata = 96 web_metadata.objectStores[i]; 97 98 web_store_metadata.id = idb_store_metadata.id; 99 web_store_metadata.name = idb_store_metadata.name; 100 web_store_metadata.keyPath = 101 WebIDBKeyPathBuilder::Build(idb_store_metadata.keyPath); 102 web_store_metadata.autoIncrement = idb_store_metadata.autoIncrement; 103 web_store_metadata.maxIndexId = idb_store_metadata.max_index_id; 104 web_store_metadata.indexes = 105 WebVector<WebIDBMetadata::Index>(idb_store_metadata.indexes.size()); 106 107 for (size_t j = 0; j < idb_store_metadata.indexes.size(); ++j) { 108 const IndexedDBIndexMetadata& idb_index_metadata = 109 idb_store_metadata.indexes[j]; 110 WebIDBMetadata::Index& web_index_metadata = web_store_metadata.indexes[j]; 111 112 web_index_metadata.id = idb_index_metadata.id; 113 web_index_metadata.name = idb_index_metadata.name; 114 web_index_metadata.keyPath = 115 WebIDBKeyPathBuilder::Build(idb_index_metadata.keyPath); 116 web_index_metadata.unique = idb_index_metadata.unique; 117 web_index_metadata.multiEntry = idb_index_metadata.multiEntry; 118 } 119 } 120 121 return web_metadata; 122 } 123 124 void IndexedDBDispatcher::OnMessageReceived(const IPC::Message& msg) { 125 bool handled = true; 126 IPC_BEGIN_MESSAGE_MAP(IndexedDBDispatcher, msg) 127 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIDBCursor, 128 OnSuccessOpenCursor) 129 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorAdvance, 130 OnSuccessCursorContinue) 131 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorContinue, 132 OnSuccessCursorContinue) 133 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorPrefetch, 134 OnSuccessCursorPrefetch) 135 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIDBDatabase, 136 OnSuccessIDBDatabase) 137 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIndexedDBKey, 138 OnSuccessIndexedDBKey) 139 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessStringList, 140 OnSuccessStringList) 141 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessValue, OnSuccessValue) 142 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessValueWithKey, 143 OnSuccessValueWithKey) 144 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessInteger, OnSuccessInteger) 145 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessUndefined, 146 OnSuccessUndefined) 147 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksError, OnError) 148 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksIntBlocked, OnIntBlocked) 149 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksUpgradeNeeded, OnUpgradeNeeded) 150 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksForcedClose, 151 OnForcedClose) 152 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksIntVersionChange, 153 OnIntVersionChange) 154 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksAbort, OnAbort) 155 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksComplete, OnComplete) 156 IPC_MESSAGE_UNHANDLED(handled = false) 157 IPC_END_MESSAGE_MAP() 158 // If a message gets here, IndexedDBMessageFilter already determined that it 159 // is an IndexedDB message. 160 DCHECK(handled) << "Didn't handle a message defined at line " 161 << IPC_MESSAGE_ID_LINE(msg.type()); 162 } 163 164 bool IndexedDBDispatcher::Send(IPC::Message* msg) { 165 return thread_safe_sender_->Send(msg); 166 } 167 168 void IndexedDBDispatcher::RequestIDBCursorAdvance( 169 unsigned long count, 170 WebIDBCallbacks* callbacks_ptr, 171 int32 ipc_cursor_id) { 172 // Reset all cursor prefetch caches except for this cursor. 173 ResetCursorPrefetchCaches(ipc_cursor_id); 174 175 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); 176 177 int32 ipc_callbacks_id = pending_callbacks_.Add(callbacks.release()); 178 Send(new IndexedDBHostMsg_CursorAdvance( 179 ipc_cursor_id, CurrentWorkerId(), ipc_callbacks_id, count)); 180 } 181 182 void IndexedDBDispatcher::RequestIDBCursorContinue( 183 const IndexedDBKey& key, 184 const IndexedDBKey& primary_key, 185 WebIDBCallbacks* callbacks_ptr, 186 int32 ipc_cursor_id) { 187 // Reset all cursor prefetch caches except for this cursor. 188 ResetCursorPrefetchCaches(ipc_cursor_id); 189 190 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); 191 192 int32 ipc_callbacks_id = pending_callbacks_.Add(callbacks.release()); 193 Send(new IndexedDBHostMsg_CursorContinue( 194 ipc_cursor_id, CurrentWorkerId(), ipc_callbacks_id, key, primary_key)); 195 } 196 197 void IndexedDBDispatcher::RequestIDBCursorPrefetch( 198 int n, 199 WebIDBCallbacks* callbacks_ptr, 200 int32 ipc_cursor_id) { 201 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); 202 203 int32 ipc_callbacks_id = pending_callbacks_.Add(callbacks.release()); 204 Send(new IndexedDBHostMsg_CursorPrefetch( 205 ipc_cursor_id, CurrentWorkerId(), ipc_callbacks_id, n)); 206 } 207 208 void IndexedDBDispatcher::RequestIDBCursorPrefetchReset(int used_prefetches, 209 int unused_prefetches, 210 int32 ipc_cursor_id) { 211 Send(new IndexedDBHostMsg_CursorPrefetchReset( 212 ipc_cursor_id, used_prefetches, unused_prefetches)); 213 } 214 215 void IndexedDBDispatcher::RequestIDBFactoryOpen( 216 const base::string16& name, 217 int64 version, 218 int64 transaction_id, 219 WebIDBCallbacks* callbacks_ptr, 220 WebIDBDatabaseCallbacks* database_callbacks_ptr, 221 const std::string& database_identifier) { 222 ResetCursorPrefetchCaches(); 223 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); 224 scoped_ptr<WebIDBDatabaseCallbacks> database_callbacks( 225 database_callbacks_ptr); 226 227 IndexedDBHostMsg_FactoryOpen_Params params; 228 params.ipc_thread_id = CurrentWorkerId(); 229 params.ipc_callbacks_id = pending_callbacks_.Add(callbacks.release()); 230 params.ipc_database_callbacks_id = 231 pending_database_callbacks_.Add(database_callbacks.release()); 232 params.database_identifier = database_identifier; 233 params.name = name; 234 params.transaction_id = transaction_id; 235 params.version = version; 236 Send(new IndexedDBHostMsg_FactoryOpen(params)); 237 } 238 239 void IndexedDBDispatcher::RequestIDBFactoryGetDatabaseNames( 240 WebIDBCallbacks* callbacks_ptr, 241 const std::string& database_identifier) { 242 ResetCursorPrefetchCaches(); 243 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); 244 245 IndexedDBHostMsg_FactoryGetDatabaseNames_Params params; 246 params.ipc_thread_id = CurrentWorkerId(); 247 params.ipc_callbacks_id = pending_callbacks_.Add(callbacks.release()); 248 params.database_identifier = database_identifier; 249 Send(new IndexedDBHostMsg_FactoryGetDatabaseNames(params)); 250 } 251 252 void IndexedDBDispatcher::RequestIDBFactoryDeleteDatabase( 253 const base::string16& name, 254 WebIDBCallbacks* callbacks_ptr, 255 const std::string& database_identifier) { 256 ResetCursorPrefetchCaches(); 257 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); 258 259 IndexedDBHostMsg_FactoryDeleteDatabase_Params params; 260 params.ipc_thread_id = CurrentWorkerId(); 261 params.ipc_callbacks_id = pending_callbacks_.Add(callbacks.release()); 262 params.database_identifier = database_identifier; 263 params.name = name; 264 Send(new IndexedDBHostMsg_FactoryDeleteDatabase(params)); 265 } 266 267 void IndexedDBDispatcher::RequestIDBDatabaseClose( 268 int32 ipc_database_id, 269 int32 ipc_database_callbacks_id) { 270 ResetCursorPrefetchCaches(); 271 Send(new IndexedDBHostMsg_DatabaseClose(ipc_database_id)); 272 // There won't be pending database callbacks if the transaction was aborted in 273 // the initial upgradeneeded event handler. 274 if (pending_database_callbacks_.Lookup(ipc_database_callbacks_id)) 275 pending_database_callbacks_.Remove(ipc_database_callbacks_id); 276 } 277 278 void IndexedDBDispatcher::RequestIDBDatabaseCreateTransaction( 279 int32 ipc_database_id, 280 int64 transaction_id, 281 WebIDBDatabaseCallbacks* database_callbacks_ptr, 282 WebVector<long long> object_store_ids, 283 unsigned short mode) { 284 scoped_ptr<WebIDBDatabaseCallbacks> database_callbacks( 285 database_callbacks_ptr); 286 IndexedDBHostMsg_DatabaseCreateTransaction_Params params; 287 params.ipc_thread_id = CurrentWorkerId(); 288 params.ipc_database_id = ipc_database_id; 289 params.transaction_id = transaction_id; 290 params.ipc_database_callbacks_id = 291 pending_database_callbacks_.Add(database_callbacks.release()); 292 params.object_store_ids 293 .assign(object_store_ids.data(), 294 object_store_ids.data() + object_store_ids.size()); 295 params.mode = mode; 296 297 Send(new IndexedDBHostMsg_DatabaseCreateTransaction(params)); 298 } 299 300 void IndexedDBDispatcher::RequestIDBDatabaseGet( 301 int32 ipc_database_id, 302 int64 transaction_id, 303 int64 object_store_id, 304 int64 index_id, 305 const IndexedDBKeyRange& key_range, 306 bool key_only, 307 WebIDBCallbacks* callbacks) { 308 ResetCursorPrefetchCaches(); 309 IndexedDBHostMsg_DatabaseGet_Params params; 310 init_params(params, callbacks); 311 params.ipc_database_id = ipc_database_id; 312 params.transaction_id = transaction_id; 313 params.object_store_id = object_store_id; 314 params.index_id = index_id; 315 params.key_range = key_range; 316 params.key_only = key_only; 317 Send(new IndexedDBHostMsg_DatabaseGet(params)); 318 } 319 320 void IndexedDBDispatcher::RequestIDBDatabasePut( 321 int32 ipc_database_id, 322 int64 transaction_id, 323 int64 object_store_id, 324 const WebData& value, 325 const IndexedDBKey& key, 326 WebIDBDatabase::PutMode put_mode, 327 WebIDBCallbacks* callbacks, 328 const WebVector<long long>& index_ids, 329 const WebVector<WebVector<WebIDBKey> >& index_keys) { 330 331 if (value.size() > kMaxIDBValueSizeInBytes) { 332 callbacks->onError(WebIDBDatabaseError( 333 blink::WebIDBDatabaseExceptionUnknownError, 334 WebString::fromUTF8(base::StringPrintf( 335 "The serialized value is too large" 336 " (size=%" PRIuS " bytes, max=%" PRIuS " bytes).", 337 value.size(), 338 kMaxIDBValueSizeInBytes).c_str()))); 339 return; 340 } 341 342 ResetCursorPrefetchCaches(); 343 IndexedDBHostMsg_DatabasePut_Params params; 344 init_params(params, callbacks); 345 params.ipc_database_id = ipc_database_id; 346 params.transaction_id = transaction_id; 347 params.object_store_id = object_store_id; 348 349 params.value.assign(value.data(), value.data() + value.size()); 350 params.key = key; 351 params.put_mode = put_mode; 352 353 COMPILE_ASSERT(sizeof(params.index_ids[0]) == sizeof(index_ids[0]), 354 Cant_copy); 355 params.index_ids 356 .assign(index_ids.data(), index_ids.data() + index_ids.size()); 357 358 params.index_keys.resize(index_keys.size()); 359 for (size_t i = 0; i < index_keys.size(); ++i) { 360 params.index_keys[i].resize(index_keys[i].size()); 361 for (size_t j = 0; j < index_keys[i].size(); ++j) { 362 params.index_keys[i][j] = 363 IndexedDBKey(IndexedDBKeyBuilder::Build(index_keys[i][j])); 364 } 365 } 366 Send(new IndexedDBHostMsg_DatabasePut(params)); 367 } 368 369 void IndexedDBDispatcher::RequestIDBDatabaseOpenCursor( 370 int32 ipc_database_id, 371 int64 transaction_id, 372 int64 object_store_id, 373 int64 index_id, 374 const IndexedDBKeyRange& key_range, 375 unsigned short direction, 376 bool key_only, 377 WebIDBDatabase::TaskType task_type, 378 WebIDBCallbacks* callbacks) { 379 ResetCursorPrefetchCaches(); 380 IndexedDBHostMsg_DatabaseOpenCursor_Params params; 381 init_params(params, callbacks); 382 params.ipc_database_id = ipc_database_id; 383 params.transaction_id = transaction_id; 384 params.object_store_id = object_store_id; 385 params.index_id = index_id; 386 params.key_range = key_range; 387 params.direction = direction; 388 params.key_only = key_only; 389 params.task_type = task_type; 390 Send(new IndexedDBHostMsg_DatabaseOpenCursor(params)); 391 } 392 393 void IndexedDBDispatcher::RequestIDBDatabaseCount( 394 int32 ipc_database_id, 395 int64 transaction_id, 396 int64 object_store_id, 397 int64 index_id, 398 const IndexedDBKeyRange& key_range, 399 WebIDBCallbacks* callbacks) { 400 ResetCursorPrefetchCaches(); 401 IndexedDBHostMsg_DatabaseCount_Params params; 402 init_params(params, callbacks); 403 params.ipc_database_id = ipc_database_id; 404 params.transaction_id = transaction_id; 405 params.object_store_id = object_store_id; 406 params.index_id = index_id; 407 params.key_range = key_range; 408 Send(new IndexedDBHostMsg_DatabaseCount(params)); 409 } 410 411 void IndexedDBDispatcher::RequestIDBDatabaseDeleteRange( 412 int32 ipc_database_id, 413 int64 transaction_id, 414 int64 object_store_id, 415 const IndexedDBKeyRange& key_range, 416 WebIDBCallbacks* callbacks) { 417 ResetCursorPrefetchCaches(); 418 IndexedDBHostMsg_DatabaseDeleteRange_Params params; 419 init_params(params, callbacks); 420 params.ipc_database_id = ipc_database_id; 421 params.transaction_id = transaction_id; 422 params.object_store_id = object_store_id; 423 params.key_range = key_range; 424 Send(new IndexedDBHostMsg_DatabaseDeleteRange(params)); 425 } 426 427 void IndexedDBDispatcher::RequestIDBDatabaseClear( 428 int32 ipc_database_id, 429 int64 transaction_id, 430 int64 object_store_id, 431 WebIDBCallbacks* callbacks_ptr) { 432 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); 433 int32 ipc_callbacks_id = pending_callbacks_.Add(callbacks.release()); 434 Send(new IndexedDBHostMsg_DatabaseClear(CurrentWorkerId(), 435 ipc_callbacks_id, 436 ipc_database_id, 437 transaction_id, 438 object_store_id)); 439 } 440 441 void IndexedDBDispatcher::CursorDestroyed(int32 ipc_cursor_id) { 442 cursors_.erase(ipc_cursor_id); 443 } 444 445 void IndexedDBDispatcher::DatabaseDestroyed(int32 ipc_database_id) { 446 DCHECK_EQ(databases_.count(ipc_database_id), 1u); 447 databases_.erase(ipc_database_id); 448 } 449 450 void IndexedDBDispatcher::OnSuccessIDBDatabase( 451 int32 ipc_thread_id, 452 int32 ipc_callbacks_id, 453 int32 ipc_database_callbacks_id, 454 int32 ipc_object_id, 455 const IndexedDBDatabaseMetadata& idb_metadata) { 456 DCHECK_EQ(ipc_thread_id, CurrentWorkerId()); 457 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id); 458 if (!callbacks) 459 return; 460 WebIDBMetadata metadata(ConvertMetadata(idb_metadata)); 461 // If an upgrade was performed, count will be non-zero. 462 WebIDBDatabase* database = NULL; 463 464 // Back-end will send kNoDatabase if it was already sent in OnUpgradeNeeded. 465 // May already be deleted and removed from the table, but do not recreate.. 466 if (ipc_object_id != kNoDatabase) { 467 DCHECK(!databases_.count(ipc_object_id)); 468 database = databases_[ipc_object_id] = new WebIDBDatabaseImpl( 469 ipc_object_id, ipc_database_callbacks_id, thread_safe_sender_.get()); 470 } 471 472 callbacks->onSuccess(database, metadata); 473 pending_callbacks_.Remove(ipc_callbacks_id); 474 } 475 476 void IndexedDBDispatcher::OnSuccessIndexedDBKey(int32 ipc_thread_id, 477 int32 ipc_callbacks_id, 478 const IndexedDBKey& key) { 479 DCHECK_EQ(ipc_thread_id, CurrentWorkerId()); 480 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id); 481 if (!callbacks) 482 return; 483 callbacks->onSuccess(WebIDBKeyBuilder::Build(key)); 484 pending_callbacks_.Remove(ipc_callbacks_id); 485 } 486 487 void IndexedDBDispatcher::OnSuccessStringList( 488 int32 ipc_thread_id, 489 int32 ipc_callbacks_id, 490 const std::vector<base::string16>& value) { 491 DCHECK_EQ(ipc_thread_id, CurrentWorkerId()); 492 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id); 493 if (!callbacks) 494 return; 495 callbacks->onSuccess(WebVector<WebString>(value)); 496 pending_callbacks_.Remove(ipc_callbacks_id); 497 } 498 499 void IndexedDBDispatcher::OnSuccessValue(int32 ipc_thread_id, 500 int32 ipc_callbacks_id, 501 const std::string& value) { 502 DCHECK_EQ(ipc_thread_id, CurrentWorkerId()); 503 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id); 504 if (!callbacks) 505 return; 506 WebData web_value; 507 if (value.size()) 508 web_value.assign(&*value.begin(), value.size()); 509 callbacks->onSuccess(web_value); 510 pending_callbacks_.Remove(ipc_callbacks_id); 511 } 512 513 void IndexedDBDispatcher::OnSuccessValueWithKey( 514 int32 ipc_thread_id, 515 int32 ipc_callbacks_id, 516 const std::string& value, 517 const IndexedDBKey& primary_key, 518 const IndexedDBKeyPath& key_path) { 519 DCHECK_EQ(ipc_thread_id, CurrentWorkerId()); 520 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id); 521 if (!callbacks) 522 return; 523 WebData web_value; 524 if (value.size()) 525 web_value.assign(&*value.begin(), value.size()); 526 callbacks->onSuccess(web_value, 527 WebIDBKeyBuilder::Build(primary_key), 528 WebIDBKeyPathBuilder::Build(key_path)); 529 pending_callbacks_.Remove(ipc_callbacks_id); 530 } 531 532 void IndexedDBDispatcher::OnSuccessInteger(int32 ipc_thread_id, 533 int32 ipc_callbacks_id, 534 int64 value) { 535 DCHECK_EQ(ipc_thread_id, CurrentWorkerId()); 536 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id); 537 if (!callbacks) 538 return; 539 callbacks->onSuccess(value); 540 pending_callbacks_.Remove(ipc_callbacks_id); 541 } 542 543 void IndexedDBDispatcher::OnSuccessUndefined(int32 ipc_thread_id, 544 int32 ipc_callbacks_id) { 545 DCHECK_EQ(ipc_thread_id, CurrentWorkerId()); 546 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id); 547 if (!callbacks) 548 return; 549 callbacks->onSuccess(); 550 pending_callbacks_.Remove(ipc_callbacks_id); 551 } 552 553 void IndexedDBDispatcher::OnSuccessOpenCursor( 554 const IndexedDBMsg_CallbacksSuccessIDBCursor_Params& p) { 555 DCHECK_EQ(p.ipc_thread_id, CurrentWorkerId()); 556 int32 ipc_callbacks_id = p.ipc_callbacks_id; 557 int32 ipc_object_id = p.ipc_cursor_id; 558 const IndexedDBKey& key = p.key; 559 const IndexedDBKey& primary_key = p.primary_key; 560 WebData web_value; 561 if (p.value.size()) 562 web_value.assign(&*p.value.begin(), p.value.size()); 563 564 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id); 565 if (!callbacks) 566 return; 567 568 WebIDBCursorImpl* cursor = 569 new WebIDBCursorImpl(ipc_object_id, thread_safe_sender_.get()); 570 cursors_[ipc_object_id] = cursor; 571 callbacks->onSuccess(cursor, WebIDBKeyBuilder::Build(key), 572 WebIDBKeyBuilder::Build(primary_key), web_value); 573 574 pending_callbacks_.Remove(ipc_callbacks_id); 575 } 576 577 void IndexedDBDispatcher::OnSuccessCursorContinue( 578 const IndexedDBMsg_CallbacksSuccessCursorContinue_Params& p) { 579 DCHECK_EQ(p.ipc_thread_id, CurrentWorkerId()); 580 int32 ipc_callbacks_id = p.ipc_callbacks_id; 581 int32 ipc_cursor_id = p.ipc_cursor_id; 582 const IndexedDBKey& key = p.key; 583 const IndexedDBKey& primary_key = p.primary_key; 584 const std::string& value = p.value; 585 586 WebIDBCursorImpl* cursor = cursors_[ipc_cursor_id]; 587 DCHECK(cursor); 588 589 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id); 590 if (!callbacks) 591 return; 592 593 WebData web_value; 594 if (value.size()) 595 web_value.assign(&*value.begin(), value.size()); 596 callbacks->onSuccess(WebIDBKeyBuilder::Build(key), 597 WebIDBKeyBuilder::Build(primary_key), web_value); 598 599 pending_callbacks_.Remove(ipc_callbacks_id); 600 } 601 602 void IndexedDBDispatcher::OnSuccessCursorPrefetch( 603 const IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params& p) { 604 DCHECK_EQ(p.ipc_thread_id, CurrentWorkerId()); 605 int32 ipc_callbacks_id = p.ipc_callbacks_id; 606 int32 ipc_cursor_id = p.ipc_cursor_id; 607 const std::vector<IndexedDBKey>& keys = p.keys; 608 const std::vector<IndexedDBKey>& primary_keys = p.primary_keys; 609 std::vector<WebData> values(p.values.size()); 610 for (size_t i = 0; i < p.values.size(); ++i) { 611 if (p.values[i].size()) 612 values[i].assign(&*p.values[i].begin(), p.values[i].size()); 613 } 614 WebIDBCursorImpl* cursor = cursors_[ipc_cursor_id]; 615 DCHECK(cursor); 616 cursor->SetPrefetchData(keys, primary_keys, values); 617 618 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id); 619 DCHECK(callbacks); 620 cursor->CachedContinue(callbacks); 621 pending_callbacks_.Remove(ipc_callbacks_id); 622 } 623 624 void IndexedDBDispatcher::OnIntBlocked(int32 ipc_thread_id, 625 int32 ipc_callbacks_id, 626 int64 existing_version) { 627 DCHECK_EQ(ipc_thread_id, CurrentWorkerId()); 628 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id); 629 DCHECK(callbacks); 630 callbacks->onBlocked(existing_version); 631 } 632 633 void IndexedDBDispatcher::OnUpgradeNeeded( 634 const IndexedDBMsg_CallbacksUpgradeNeeded_Params& p) { 635 DCHECK_EQ(p.ipc_thread_id, CurrentWorkerId()); 636 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(p.ipc_callbacks_id); 637 DCHECK(callbacks); 638 WebIDBMetadata metadata(ConvertMetadata(p.idb_metadata)); 639 DCHECK(!databases_.count(p.ipc_database_id)); 640 databases_[p.ipc_database_id] = 641 new WebIDBDatabaseImpl(p.ipc_database_id, 642 p.ipc_database_callbacks_id, 643 thread_safe_sender_.get()); 644 callbacks->onUpgradeNeeded( 645 p.old_version, 646 databases_[p.ipc_database_id], 647 metadata, 648 static_cast<blink::WebIDBDataLoss>(p.data_loss), 649 WebString::fromUTF8(p.data_loss_message)); 650 } 651 652 void IndexedDBDispatcher::OnError(int32 ipc_thread_id, 653 int32 ipc_callbacks_id, 654 int code, 655 const base::string16& message) { 656 DCHECK_EQ(ipc_thread_id, CurrentWorkerId()); 657 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id); 658 if (!callbacks) 659 return; 660 if (message.empty()) 661 callbacks->onError(WebIDBDatabaseError(code)); 662 else 663 callbacks->onError(WebIDBDatabaseError(code, message)); 664 pending_callbacks_.Remove(ipc_callbacks_id); 665 } 666 667 void IndexedDBDispatcher::OnAbort(int32 ipc_thread_id, 668 int32 ipc_database_callbacks_id, 669 int64 transaction_id, 670 int code, 671 const base::string16& message) { 672 DCHECK_EQ(ipc_thread_id, CurrentWorkerId()); 673 WebIDBDatabaseCallbacks* callbacks = 674 pending_database_callbacks_.Lookup(ipc_database_callbacks_id); 675 if (!callbacks) 676 return; 677 if (message.empty()) 678 callbacks->onAbort(transaction_id, WebIDBDatabaseError(code)); 679 else 680 callbacks->onAbort(transaction_id, WebIDBDatabaseError(code, message)); 681 } 682 683 void IndexedDBDispatcher::OnComplete(int32 ipc_thread_id, 684 int32 ipc_database_callbacks_id, 685 int64 transaction_id) { 686 DCHECK_EQ(ipc_thread_id, CurrentWorkerId()); 687 WebIDBDatabaseCallbacks* callbacks = 688 pending_database_callbacks_.Lookup(ipc_database_callbacks_id); 689 if (!callbacks) 690 return; 691 callbacks->onComplete(transaction_id); 692 } 693 694 void IndexedDBDispatcher::OnForcedClose(int32 ipc_thread_id, 695 int32 ipc_database_callbacks_id) { 696 DCHECK_EQ(ipc_thread_id, CurrentWorkerId()); 697 WebIDBDatabaseCallbacks* callbacks = 698 pending_database_callbacks_.Lookup(ipc_database_callbacks_id); 699 if (!callbacks) 700 return; 701 callbacks->onForcedClose(); 702 } 703 704 void IndexedDBDispatcher::OnIntVersionChange(int32 ipc_thread_id, 705 int32 ipc_database_callbacks_id, 706 int64 old_version, 707 int64 new_version) { 708 DCHECK_EQ(ipc_thread_id, CurrentWorkerId()); 709 WebIDBDatabaseCallbacks* callbacks = 710 pending_database_callbacks_.Lookup(ipc_database_callbacks_id); 711 // callbacks would be NULL if a versionchange event is received after close 712 // has been called. 713 if (!callbacks) 714 return; 715 callbacks->onVersionChange(old_version, new_version); 716 } 717 718 void IndexedDBDispatcher::ResetCursorPrefetchCaches( 719 int32 ipc_exception_cursor_id) { 720 typedef std::map<int32, WebIDBCursorImpl*>::iterator Iterator; 721 for (Iterator i = cursors_.begin(); i != cursors_.end(); ++i) { 722 if (i->first == ipc_exception_cursor_id) 723 continue; 724 i->second->ResetPrefetchCache(); 725 } 726 } 727 728 } // namespace content 729