Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/indexed_db/indexed_db_dispatcher_host.h" | 5 #include "content/browser/indexed_db/indexed_db_dispatcher_host.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 11 #include "base/files/file_path.h" | 11 #include "base/files/file_path.h" |
| 12 #include "base/guid.h" | 12 #include "base/guid.h" |
| 13 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
| 14 #include "base/process/process.h" | 14 #include "base/process/process.h" |
| 15 #include "base/stl_util.h" | 15 #include "base/stl_util.h" |
| 16 #include "base/strings/utf_string_conversions.h" | 16 #include "base/strings/utf_string_conversions.h" |
| 17 #include "content/browser/bad_message.h" | 17 #include "content/browser/bad_message.h" |
| 18 #include "content/browser/indexed_db/indexed_db_callbacks.h" | 18 #include "content/browser/indexed_db/indexed_db_callbacks.h" |
| 19 #include "content/browser/indexed_db/indexed_db_connection.h" | 19 #include "content/browser/indexed_db/indexed_db_connection.h" |
| 20 #include "content/browser/indexed_db/indexed_db_context_impl.h" | 20 #include "content/browser/indexed_db/indexed_db_context_impl.h" |
| 21 #include "content/browser/indexed_db/indexed_db_cursor.h" | |
| 22 #include "content/browser/indexed_db/indexed_db_database_callbacks.h" | 21 #include "content/browser/indexed_db/indexed_db_database_callbacks.h" |
| 23 #include "content/browser/indexed_db/indexed_db_observation.h" | 22 #include "content/browser/indexed_db/indexed_db_observation.h" |
| 24 #include "content/browser/indexed_db/indexed_db_observer_changes.h" | 23 #include "content/browser/indexed_db/indexed_db_observer_changes.h" |
| 25 #include "content/browser/indexed_db/indexed_db_pending_connection.h" | 24 #include "content/browser/indexed_db/indexed_db_pending_connection.h" |
| 26 #include "content/browser/indexed_db/indexed_db_value.h" | 25 #include "content/browser/indexed_db/indexed_db_value.h" |
| 27 #include "content/browser/renderer_host/render_message_filter.h" | 26 #include "content/browser/renderer_host/render_message_filter.h" |
| 28 #include "content/common/indexed_db/indexed_db_messages.h" | 27 #include "content/common/indexed_db/indexed_db_messages.h" |
| 29 #include "content/common/indexed_db/indexed_db_metadata.h" | 28 #include "content/common/indexed_db/indexed_db_metadata.h" |
| 30 #include "content/public/browser/browser_thread.h" | 29 #include "content/public/browser/browser_thread.h" |
| 31 #include "content/public/browser/user_metrics.h" | 30 #include "content/public/browser/user_metrics.h" |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 56 IndexedDBDispatcherHost::IndexedDBDispatcherHost( | 55 IndexedDBDispatcherHost::IndexedDBDispatcherHost( |
| 57 int ipc_process_id, | 56 int ipc_process_id, |
| 58 net::URLRequestContextGetter* request_context_getter, | 57 net::URLRequestContextGetter* request_context_getter, |
| 59 IndexedDBContextImpl* indexed_db_context, | 58 IndexedDBContextImpl* indexed_db_context, |
| 60 ChromeBlobStorageContext* blob_storage_context) | 59 ChromeBlobStorageContext* blob_storage_context) |
| 61 : BrowserMessageFilter(IndexedDBMsgStart), | 60 : BrowserMessageFilter(IndexedDBMsgStart), |
| 62 BrowserAssociatedInterface(this, this), | 61 BrowserAssociatedInterface(this, this), |
| 63 request_context_getter_(request_context_getter), | 62 request_context_getter_(request_context_getter), |
| 64 indexed_db_context_(indexed_db_context), | 63 indexed_db_context_(indexed_db_context), |
| 65 blob_storage_context_(blob_storage_context), | 64 blob_storage_context_(blob_storage_context), |
| 66 cursor_dispatcher_host_(base::MakeUnique<CursorDispatcherHost>(this)), | |
| 67 ipc_process_id_(ipc_process_id) { | 65 ipc_process_id_(ipc_process_id) { |
| 68 DCHECK(indexed_db_context_.get()); | 66 DCHECK(indexed_db_context_.get()); |
| 69 } | 67 } |
| 70 | 68 |
| 71 IndexedDBDispatcherHost::~IndexedDBDispatcherHost() { | 69 IndexedDBDispatcherHost::~IndexedDBDispatcherHost() { |
| 72 // TODO(alecflett): uncomment these when we find the source of these leaks. | 70 // TODO(alecflett): uncomment these when we find the source of these leaks. |
| 73 // DCHECK(transaction_size_map_.empty()); | 71 // DCHECK(transaction_size_map_.empty()); |
| 74 // DCHECK(transaction_origin_map_.empty()); | 72 // DCHECK(transaction_origin_map_.empty()); |
| 75 } | 73 } |
| 76 | 74 |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 94 | 92 |
| 95 void IndexedDBDispatcherHost::ResetDispatcherHosts() { | 93 void IndexedDBDispatcherHost::ResetDispatcherHosts() { |
| 96 // It is important that the various *_dispatcher_host_ members are reset | 94 // It is important that the various *_dispatcher_host_ members are reset |
| 97 // on the IndexedDB thread, since there might be incoming messages on that | 95 // on the IndexedDB thread, since there might be incoming messages on that |
| 98 // thread, and we must not reset the dispatcher hosts until after those | 96 // thread, and we must not reset the dispatcher hosts until after those |
| 99 // messages are processed. | 97 // messages are processed. |
| 100 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | 98 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); |
| 101 | 99 |
| 102 // Prevent any pending connections from being processed. | 100 // Prevent any pending connections from being processed. |
| 103 is_open_ = false; | 101 is_open_ = false; |
| 104 | |
| 105 cursor_dispatcher_host_.reset(); | |
| 106 } | |
| 107 | |
| 108 base::TaskRunner* IndexedDBDispatcherHost::OverrideTaskRunnerForMessage( | |
| 109 const IPC::Message& message) { | |
| 110 if (IPC_MESSAGE_CLASS(message) != IndexedDBMsgStart) | |
| 111 return NULL; | |
| 112 | |
| 113 switch (message.type()) { | |
| 114 case IndexedDBHostMsg_AckReceivedBlobs::ID: | |
| 115 return NULL; | |
| 116 default: | |
| 117 return indexed_db_context_->TaskRunner(); | |
| 118 } | |
| 119 } | 102 } |
| 120 | 103 |
| 121 bool IndexedDBDispatcherHost::OnMessageReceived(const IPC::Message& message) { | 104 bool IndexedDBDispatcherHost::OnMessageReceived(const IPC::Message& message) { |
| 122 if (IPC_MESSAGE_CLASS(message) != IndexedDBMsgStart) | 105 return false; |
|
dcheng
2016/11/17 03:46:23
Does this still need to be a BrowserMessageFilter?
Reilly Grant (use Gerrit)
2016/11/17 20:04:52
It still needs to send one IPC message. My next pa
| |
| 123 return false; | |
| 124 | |
| 125 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread() || | |
| 126 message.type() == IndexedDBHostMsg_AckReceivedBlobs::ID); | |
| 127 | |
| 128 bool handled = cursor_dispatcher_host_->OnMessageReceived(message); | |
| 129 | |
| 130 if (!handled) { | |
| 131 handled = true; | |
| 132 IPC_BEGIN_MESSAGE_MAP(IndexedDBDispatcherHost, message) | |
| 133 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_AckReceivedBlobs, OnAckReceivedBlobs) | |
| 134 IPC_MESSAGE_UNHANDLED(handled = false) | |
| 135 IPC_END_MESSAGE_MAP() | |
| 136 } | |
| 137 return handled; | |
| 138 } | |
| 139 | |
| 140 int32_t IndexedDBDispatcherHost::Add(IndexedDBCursor* cursor) { | |
| 141 if (!cursor_dispatcher_host_) { | |
| 142 return 0; | |
| 143 } | |
| 144 return cursor_dispatcher_host_->map_.Add(cursor); | |
| 145 } | 106 } |
| 146 | 107 |
| 147 bool IndexedDBDispatcherHost::RegisterTransactionId(int64_t host_transaction_id, | 108 bool IndexedDBDispatcherHost::RegisterTransactionId(int64_t host_transaction_id, |
| 148 const url::Origin& origin) { | 109 const url::Origin& origin) { |
| 149 if (base::ContainsKey(transaction_size_map_, host_transaction_id)) | 110 if (base::ContainsKey(transaction_size_map_, host_transaction_id)) |
| 150 return false; | 111 return false; |
| 151 transaction_size_map_[host_transaction_id] = 0; | 112 transaction_size_map_[host_transaction_id] = 0; |
| 152 transaction_origin_map_[host_transaction_id] = origin; | 113 transaction_origin_map_[host_transaction_id] = origin; |
| 153 return true; | 114 return true; |
| 154 } | 115 } |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 239 blob_data_handle_map_.erase(iter); | 200 blob_data_handle_map_.erase(iter); |
| 240 else | 201 else |
| 241 --iter->second.second; | 202 --iter->second.second; |
| 242 } | 203 } |
| 243 | 204 |
| 244 bool IndexedDBDispatcherHost::IsOpen() const { | 205 bool IndexedDBDispatcherHost::IsOpen() const { |
| 245 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | 206 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); |
| 246 return is_open_; | 207 return is_open_; |
| 247 } | 208 } |
| 248 | 209 |
| 249 IndexedDBCursor* IndexedDBDispatcherHost::GetCursorFromId( | |
| 250 int32_t ipc_cursor_id) { | |
| 251 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 252 return cursor_dispatcher_host_->map_.Lookup(ipc_cursor_id); | |
| 253 } | |
| 254 | |
| 255 IndexedDBMsg_ObserverChanges IndexedDBDispatcherHost::ConvertObserverChanges( | 210 IndexedDBMsg_ObserverChanges IndexedDBDispatcherHost::ConvertObserverChanges( |
| 256 std::unique_ptr<IndexedDBObserverChanges> changes) { | 211 std::unique_ptr<IndexedDBObserverChanges> changes) { |
| 257 IndexedDBMsg_ObserverChanges idb_changes; | 212 IndexedDBMsg_ObserverChanges idb_changes; |
| 258 idb_changes.observation_index = changes->release_observation_indices_map(); | 213 idb_changes.observation_index = changes->release_observation_indices_map(); |
| 259 for (const auto& observation : changes->release_observations()) | 214 for (const auto& observation : changes->release_observations()) |
| 260 idb_changes.observations.push_back(ConvertObservation(observation.get())); | 215 idb_changes.observations.push_back(ConvertObservation(observation.get())); |
| 261 return idb_changes; | 216 return idb_changes; |
| 262 } | 217 } |
| 263 | 218 |
| 264 IndexedDBMsg_Observation IndexedDBDispatcherHost::ConvertObservation( | 219 IndexedDBMsg_Observation IndexedDBDispatcherHost::ConvertObservation( |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 378 const url::Origin& origin, | 333 const url::Origin& origin, |
| 379 const base::string16& name) { | 334 const base::string16& name) { |
| 380 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | 335 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); |
| 381 | 336 |
| 382 base::FilePath indexed_db_path = indexed_db_context_->data_path(); | 337 base::FilePath indexed_db_path = indexed_db_context_->data_path(); |
| 383 DCHECK(request_context_getter_); | 338 DCHECK(request_context_getter_); |
| 384 context()->GetIDBFactory()->DeleteDatabase( | 339 context()->GetIDBFactory()->DeleteDatabase( |
| 385 name, request_context_getter_, callbacks, origin, indexed_db_path); | 340 name, request_context_getter_, callbacks, origin, indexed_db_path); |
| 386 } | 341 } |
| 387 | 342 |
| 388 void IndexedDBDispatcherHost::OnAckReceivedBlobs( | |
| 389 const std::vector<std::string>& uuids) { | |
| 390 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 391 for (const auto& uuid : uuids) | |
| 392 DropBlobData(uuid); | |
| 393 } | |
| 394 | |
| 395 void IndexedDBDispatcherHost::FinishTransaction(int64_t host_transaction_id, | 343 void IndexedDBDispatcherHost::FinishTransaction(int64_t host_transaction_id, |
| 396 bool committed) { | 344 bool committed) { |
| 397 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | 345 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); |
| 398 if (committed) { | 346 if (committed) { |
| 399 context()->TransactionComplete( | 347 context()->TransactionComplete( |
| 400 transaction_origin_map_[host_transaction_id]); | 348 transaction_origin_map_[host_transaction_id]); |
| 401 } | 349 } |
| 402 transaction_origin_map_.erase(host_transaction_id); | 350 transaction_origin_map_.erase(host_transaction_id); |
| 403 transaction_size_map_.erase(host_transaction_id); | 351 transaction_size_map_.erase(host_transaction_id); |
| 404 } | 352 } |
| 405 | 353 |
| 406 ////////////////////////////////////////////////////////////////////// | |
| 407 // Helper templates. | |
| 408 // | |
| 409 | |
| 410 template <typename ObjectType> | |
| 411 ObjectType* IndexedDBDispatcherHost::GetOrTerminateProcess( | |
| 412 RefIDMap<ObjectType>* map, | |
| 413 int32_t ipc_return_object_id) { | |
| 414 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 415 ObjectType* return_object = map->Lookup(ipc_return_object_id); | |
| 416 if (!return_object) { | |
| 417 NOTREACHED() << "Uh oh, couldn't find object with id " | |
| 418 << ipc_return_object_id; | |
| 419 bad_message::ReceivedBadMessage(this, bad_message::IDBDH_GET_OR_TERMINATE); | |
| 420 } | |
| 421 return return_object; | |
| 422 } | |
| 423 | |
| 424 template <typename MapType> | |
| 425 void IndexedDBDispatcherHost::DestroyObject(MapType* map, | |
| 426 int32_t ipc_object_id) { | |
| 427 GetOrTerminateProcess(map, ipc_object_id); | |
| 428 map->Remove(ipc_object_id); | |
| 429 } | |
| 430 | |
| 431 ////////////////////////////////////////////////////////////////////// | |
| 432 // IndexedDBDispatcherHost::CursorDispatcherHost | |
| 433 // | |
| 434 | |
| 435 IndexedDBDispatcherHost::CursorDispatcherHost::CursorDispatcherHost( | |
| 436 IndexedDBDispatcherHost* parent) | |
| 437 : parent_(parent) { | |
| 438 } | |
| 439 | |
| 440 IndexedDBDispatcherHost::CursorDispatcherHost::~CursorDispatcherHost() {} | |
| 441 | |
| 442 bool IndexedDBDispatcherHost::CursorDispatcherHost::OnMessageReceived( | |
| 443 const IPC::Message& message) { | |
| 444 bool handled = true; | |
| 445 IPC_BEGIN_MESSAGE_MAP( | |
| 446 IndexedDBDispatcherHost::CursorDispatcherHost, message) | |
| 447 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorAdvance, OnAdvance) | |
| 448 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorContinue, OnContinue) | |
| 449 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorPrefetch, OnPrefetch) | |
| 450 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorPrefetchReset, OnPrefetchReset) | |
| 451 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorDestroyed, OnDestroyed) | |
| 452 IPC_MESSAGE_UNHANDLED(handled = false) | |
| 453 IPC_END_MESSAGE_MAP() | |
| 454 | |
| 455 DCHECK(!handled || | |
| 456 parent_->context()->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 457 | |
| 458 return handled; | |
| 459 } | |
| 460 | |
| 461 void IndexedDBDispatcherHost::CursorDispatcherHost::OnAdvance( | |
| 462 int32_t ipc_cursor_id, | |
| 463 int32_t ipc_thread_id, | |
| 464 int32_t ipc_callbacks_id, | |
| 465 uint32_t count) { | |
| 466 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 467 IndexedDBCursor* idb_cursor = | |
| 468 parent_->GetOrTerminateProcess(&map_, ipc_cursor_id); | |
| 469 if (!idb_cursor) | |
| 470 return; | |
| 471 | |
| 472 idb_cursor->Advance( | |
| 473 count, | |
| 474 new IndexedDBCallbacks( | |
| 475 parent_, ipc_thread_id, ipc_callbacks_id, ipc_cursor_id)); | |
| 476 } | |
| 477 | |
| 478 void IndexedDBDispatcherHost::CursorDispatcherHost::OnContinue( | |
| 479 int32_t ipc_cursor_id, | |
| 480 int32_t ipc_thread_id, | |
| 481 int32_t ipc_callbacks_id, | |
| 482 const IndexedDBKey& key, | |
| 483 const IndexedDBKey& primary_key) { | |
| 484 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 485 IndexedDBCursor* idb_cursor = | |
| 486 parent_->GetOrTerminateProcess(&map_, ipc_cursor_id); | |
| 487 if (!idb_cursor) | |
| 488 return; | |
| 489 | |
| 490 idb_cursor->Continue(key.IsValid() ? base::MakeUnique<IndexedDBKey>(key) | |
| 491 : std::unique_ptr<IndexedDBKey>(), | |
| 492 primary_key.IsValid() | |
| 493 ? base::MakeUnique<IndexedDBKey>(primary_key) | |
| 494 : std::unique_ptr<IndexedDBKey>(), | |
| 495 new IndexedDBCallbacks(parent_, ipc_thread_id, | |
| 496 ipc_callbacks_id, ipc_cursor_id)); | |
| 497 } | |
| 498 | |
| 499 void IndexedDBDispatcherHost::CursorDispatcherHost::OnPrefetch( | |
| 500 int32_t ipc_cursor_id, | |
| 501 int32_t ipc_thread_id, | |
| 502 int32_t ipc_callbacks_id, | |
| 503 int n) { | |
| 504 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 505 IndexedDBCursor* idb_cursor = | |
| 506 parent_->GetOrTerminateProcess(&map_, ipc_cursor_id); | |
| 507 if (!idb_cursor) | |
| 508 return; | |
| 509 | |
| 510 idb_cursor->PrefetchContinue( | |
| 511 n, | |
| 512 new IndexedDBCallbacks( | |
| 513 parent_, ipc_thread_id, ipc_callbacks_id, ipc_cursor_id)); | |
| 514 } | |
| 515 | |
| 516 void IndexedDBDispatcherHost::CursorDispatcherHost::OnPrefetchReset( | |
| 517 int32_t ipc_cursor_id, | |
| 518 int used_prefetches, | |
| 519 int unused_prefetches) { | |
| 520 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 521 IndexedDBCursor* idb_cursor = | |
| 522 parent_->GetOrTerminateProcess(&map_, ipc_cursor_id); | |
| 523 if (!idb_cursor) | |
| 524 return; | |
| 525 | |
| 526 leveldb::Status s = | |
| 527 idb_cursor->PrefetchReset(used_prefetches, unused_prefetches); | |
| 528 // TODO(cmumford): Handle this error (crbug.com/363397) | |
| 529 if (!s.ok()) | |
| 530 DLOG(ERROR) << "Unable to reset prefetch"; | |
| 531 } | |
| 532 | |
| 533 void IndexedDBDispatcherHost::CursorDispatcherHost::OnDestroyed( | |
| 534 int32_t ipc_object_id) { | |
| 535 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread()); | |
| 536 parent_->DestroyObject(&map_, ipc_object_id); | |
| 537 } | |
| 538 | |
| 539 } // namespace content | 354 } // namespace content |
| OLD | NEW |