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