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