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 |