Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 <memory> | 5 #include <memory> |
| 6 | 6 |
| 7 #include "base/callback.h" | 7 #include "base/callback.h" |
| 8 #include "base/debug/leak_annotations.h" | 8 #include "base/debug/leak_annotations.h" |
| 9 #include "base/memory/ptr_util.h" | 9 #include "base/memory/ptr_util.h" |
| 10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
| 11 #include "components/safe_browsing_db/v4_database.h" | 11 #include "components/safe_browsing_db/v4_database.h" |
| 12 #include "content/public/browser/browser_thread.h" | 12 #include "content/public/browser/browser_thread.h" |
| 13 | 13 |
| 14 using content::BrowserThread; | 14 using content::BrowserThread; |
| 15 | 15 |
| 16 namespace safe_browsing { | 16 namespace safe_browsing { |
| 17 | 17 |
| 18 // static | 18 // static |
| 19 V4StoreFactory* V4Database::factory_ = NULL; | 19 V4StoreFactory* V4Database::factory_ = NULL; |
| 20 | 20 |
| 21 // static | 21 // static |
| 22 void V4Database::Create( | 22 bool V4Database::Create( |
| 23 const scoped_refptr<base::SequencedTaskRunner>& db_task_runner, | 23 const scoped_refptr<base::SequencedTaskRunner>& db_task_runner, |
| 24 const base::FilePath& base_path, | 24 const base::FilePath& base_path, |
| 25 const ListInfoMap& list_info_map, | 25 const StoreFileNameMap& store_file_name_map, |
| 26 NewDatabaseReadyCallback callback) { | 26 DatabaseUpdatedCallback db_updated_callback, |
| 27 NewDatabaseReadyCallback new_db_callback) { | |
| 27 // Create the database, which may be a lengthy operation, on the | 28 // Create the database, which may be a lengthy operation, on the |
| 28 // db_task_runner, but once that is done, call the caller back on this | 29 // db_task_runner, but once that is done, call the caller back on this |
| 29 // thread. | 30 // thread. |
| 31 if (!base_path.IsAbsolute() || store_file_name_map.empty()) { | |
|
Nathan Parker
2016/06/15 21:24:11
Could just dcheck on these, and then the caller do
vakh (use Gerrit instead)
2016/06/16 01:07:34
Done.
| |
| 32 return false; | |
| 33 } | |
| 34 | |
| 30 const scoped_refptr<base::SingleThreadTaskRunner>& callback_task_runner = | 35 const scoped_refptr<base::SingleThreadTaskRunner>& callback_task_runner = |
| 31 base::MessageLoop::current()->task_runner(); | 36 base::MessageLoop::current()->task_runner(); |
| 32 db_task_runner->PostTask( | 37 db_task_runner->PostTask( |
| 33 FROM_HERE, | 38 FROM_HERE, base::Bind(&V4Database::CreateOnTaskRunner, db_task_runner, |
| 34 base::Bind(&V4Database::CreateOnTaskRunner, db_task_runner, base_path, | 39 base_path, store_file_name_map, db_updated_callback, |
| 35 list_info_map, callback_task_runner, callback)); | 40 callback_task_runner, new_db_callback)); |
| 41 return true; | |
| 36 } | 42 } |
| 37 | 43 |
| 38 // static | 44 // static |
| 39 void V4Database::CreateOnTaskRunner( | 45 void V4Database::CreateOnTaskRunner( |
| 40 const scoped_refptr<base::SequencedTaskRunner>& db_task_runner, | 46 const scoped_refptr<base::SequencedTaskRunner>& db_task_runner, |
| 41 const base::FilePath& base_path, | 47 const base::FilePath& base_path, |
| 42 const ListInfoMap& list_info_map, | 48 const StoreFileNameMap& store_file_name_map, |
| 49 DatabaseUpdatedCallback db_updated_callback, | |
| 43 const scoped_refptr<base::SingleThreadTaskRunner>& callback_task_runner, | 50 const scoped_refptr<base::SingleThreadTaskRunner>& callback_task_runner, |
| 44 NewDatabaseReadyCallback callback) { | 51 NewDatabaseReadyCallback new_db_callback) { |
| 45 DCHECK(db_task_runner->RunsTasksOnCurrentThread()); | 52 DCHECK(db_task_runner->RunsTasksOnCurrentThread()); |
| 46 DCHECK(base_path.IsAbsolute()); | |
| 47 | 53 |
| 48 if (!factory_) { | 54 if (!factory_) { |
| 49 factory_ = new V4StoreFactory(); | 55 factory_ = new V4StoreFactory(); |
| 50 ANNOTATE_LEAKING_OBJECT_PTR(factory_); | 56 ANNOTATE_LEAKING_OBJECT_PTR(factory_); |
| 51 } | 57 } |
| 52 auto store_map = base::MakeUnique<StoreMap>(); | 58 auto store_map = base::MakeUnique<StoreMap>(); |
| 53 for (const auto& list_info : list_info_map) { | 59 for (const auto& store_info : store_file_name_map) { |
| 54 const UpdateListIdentifier& update_list_identifier = list_info.first; | 60 const UpdateListIdentifier& update_list_identifier = store_info.first; |
| 55 const base::FilePath store_path = base_path.AppendASCII(list_info.second); | 61 const base::FilePath store_path = base_path.AppendASCII(store_info.second); |
| 56 (*store_map)[update_list_identifier].reset( | 62 (*store_map)[update_list_identifier].reset( |
| 57 factory_->CreateV4Store(db_task_runner, store_path)); | 63 factory_->CreateV4Store(db_task_runner, store_path)); |
| 58 } | 64 } |
| 59 std::unique_ptr<V4Database> v4_database( | 65 std::unique_ptr<V4Database> v4_database(new V4Database( |
| 60 new V4Database(db_task_runner, std::move(store_map))); | 66 db_task_runner, std::move(store_map), db_updated_callback)); |
| 61 | 67 |
| 62 // Database is done loading, pass it to the callback on the caller's thread. | 68 // Database is done loading, pass it to the new_db_callback on the caller's |
| 69 // thread. | |
| 63 callback_task_runner->PostTask( | 70 callback_task_runner->PostTask( |
| 64 FROM_HERE, base::Bind(callback, base::Passed(&v4_database))); | 71 FROM_HERE, base::Bind(new_db_callback, base::Passed(&v4_database))); |
| 65 } | 72 } |
| 66 | 73 |
| 67 V4Database::V4Database( | 74 V4Database::V4Database( |
| 68 const scoped_refptr<base::SequencedTaskRunner>& db_task_runner, | 75 const scoped_refptr<base::SequencedTaskRunner>& db_task_runner, |
| 69 std::unique_ptr<StoreMap> store_map) | 76 std::unique_ptr<StoreMap> store_map, |
| 70 : db_task_runner_(db_task_runner), store_map_(std::move(store_map)) { | 77 DatabaseUpdatedCallback db_updated_callback) |
| 78 : db_task_runner_(db_task_runner), | |
| 79 store_map_(std::move(store_map)), | |
| 80 store_state_map_(base::MakeUnique<StoreStateMap>()), | |
| 81 db_updated_callback_(db_updated_callback), | |
| 82 pending_store_updates_(0) { | |
| 71 DCHECK(db_task_runner->RunsTasksOnCurrentThread()); | 83 DCHECK(db_task_runner->RunsTasksOnCurrentThread()); |
| 84 UpdateStoreStateMap(); | |
| 72 // TODO(vakh): Implement skeleton | 85 // TODO(vakh): Implement skeleton |
| 73 } | 86 } |
| 74 | 87 |
| 75 // static | 88 // static |
| 76 void V4Database::Destroy(std::unique_ptr<V4Database> v4_database) { | 89 void V4Database::Destroy(std::unique_ptr<V4Database> v4_database) { |
| 77 V4Database* v4_database_raw = v4_database.release(); | 90 V4Database* v4_database_raw = v4_database.release(); |
| 78 if (v4_database_raw) { | 91 if (v4_database_raw) { |
| 79 v4_database_raw->db_task_runner_->DeleteSoon(FROM_HERE, v4_database_raw); | 92 v4_database_raw->db_task_runner_->DeleteSoon(FROM_HERE, v4_database_raw); |
| 80 } | 93 } |
| 81 } | 94 } |
| 82 | 95 |
| 83 V4Database::~V4Database() { | 96 V4Database::~V4Database() { |
| 84 DCHECK(db_task_runner_->RunsTasksOnCurrentThread()); | 97 DCHECK(db_task_runner_->RunsTasksOnCurrentThread()); |
| 85 } | 98 } |
| 86 | 99 |
| 100 void V4Database::ApplyUpdate(const std::vector<ListUpdateResponse>& responses) { | |
| 101 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 102 DCHECK(!pending_store_updates_); | |
| 103 | |
| 104 // Post the V4Store update task on the task runner but get the callback on the | |
| 105 // current thread (IO thread). | |
| 106 const scoped_refptr<base::SingleThreadTaskRunner>& current_task_runner = | |
| 107 base::MessageLoop::current()->task_runner(); | |
| 108 for (const auto& response : responses) { | |
| 109 UpdateListIdentifier identifier(response); | |
| 110 StoreMap::const_iterator iter = store_map_->find(identifier); | |
| 111 if (iter != store_map_->end()) { | |
| 112 const auto& old_store = iter->second; | |
| 113 if (old_store->state() != response.new_client_state()) { | |
| 114 // A different state implies there are updates to process. | |
| 115 UpdatedStoreReadyCallback store_ready_callback = base::Bind( | |
| 116 &V4Database::UpdatedStoreReady, base::Unretained(this), identifier); | |
| 117 db_task_runner_->PostTask( | |
|
Nathan Parker
2016/06/15 21:24:11
Increment before posting, since otherwise the post
vakh (use Gerrit instead)
2016/06/16 01:07:34
Done. Though that's not a problem since the synchr
| |
| 118 FROM_HERE, | |
| 119 base::Bind(&V4Store::ApplyUpdate, base::Unretained(old_store.get()), | |
| 120 response, current_task_runner, store_ready_callback)); | |
| 121 pending_store_updates_++; | |
| 122 } | |
| 123 } else { | |
| 124 DVLOG(1) << "Got update for unexpected identifier: " << identifier; | |
|
Nathan Parker
2016/06/15 21:24:12
I'd say this is more severe, and could be a DCHECK
vakh (use Gerrit instead)
2016/06/16 01:07:35
Done.
| |
| 125 } | |
| 126 } | |
| 127 | |
| 128 if (!pending_store_updates_) { | |
| 129 db_updated_callback_.Run(); | |
| 130 } | |
| 131 } | |
| 132 | |
| 133 void V4Database::UpdatedStoreReady(UpdateListIdentifier identifier, | |
| 134 std::unique_ptr<V4Store> new_store) { | |
| 135 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 136 DCHECK(pending_store_updates_); | |
| 137 (*store_state_map_)[identifier] = new_store->state(); | |
| 138 (*store_map_)[identifier] = std::move(new_store); | |
| 139 | |
| 140 // Since this method is always called on the IO thread, there can't be a race | |
| 141 // condition in decrementing pending_store_updates_. | |
| 142 pending_store_updates_--; | |
| 143 if (!pending_store_updates_) { | |
| 144 db_updated_callback_.Run(); | |
| 145 } | |
| 146 } | |
| 147 | |
| 87 bool V4Database::ResetDatabase() { | 148 bool V4Database::ResetDatabase() { |
| 88 DCHECK(db_task_runner_->RunsTasksOnCurrentThread()); | 149 DCHECK(db_task_runner_->RunsTasksOnCurrentThread()); |
| 89 bool reset_success = true; | 150 bool reset_success = true; |
| 90 for (const auto& store_id_and_store : *store_map_) { | 151 for (const auto& store_map_iter : *store_map_) { |
| 91 if (!store_id_and_store.second->Reset()) { | 152 if (!store_map_iter.second->Reset()) { |
| 92 reset_success = false; | 153 reset_success = false; |
| 93 } | 154 } |
| 94 } | 155 } |
| 95 return reset_success; | 156 return reset_success; |
| 96 } | 157 } |
| 97 | 158 |
| 159 void V4Database::UpdateStoreStateMap() { | |
| 160 for (const auto& store_map_iter : *store_map_) { | |
| 161 (*store_state_map_)[store_map_iter.first] = store_map_iter.second->state(); | |
|
Nathan Parker
2016/06/15 21:24:13
I'm confused: is the store_state_map just a view i
vakh (use Gerrit instead)
2016/06/16 01:07:35
Yes, it is a view.
If we do not have a store_state
Nathan Parker
2016/06/17 21:34:19
What if you created this map on the heap only when
vakh (use Gerrit instead)
2016/06/21 00:29:36
Done. See patch 10.
| |
| 162 } | |
| 163 } | |
| 164 | |
| 98 } // namespace safe_browsing | 165 } // namespace safe_browsing |
| OLD | NEW |