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 void 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 StoreFileNameMap& store_file_name_map, | 25 const StoreFileNameMap& store_file_name_map, |
26 NewDatabaseReadyCallback callback) { | 26 NewDatabaseReadyCallback new_db_callback) { |
27 // Create the database, which may be a lengthy operation, on the | 27 DCHECK(base_path.IsAbsolute()); |
28 // db_task_runner, but once that is done, call the caller back on this | 28 DCHECK(!store_file_name_map.empty()); |
29 // thread. | 29 |
30 const scoped_refptr<base::SingleThreadTaskRunner>& callback_task_runner = | 30 const scoped_refptr<base::SingleThreadTaskRunner>& callback_task_runner = |
31 base::MessageLoop::current()->task_runner(); | 31 base::MessageLoop::current()->task_runner(); |
32 db_task_runner->PostTask( | 32 db_task_runner->PostTask( |
33 FROM_HERE, | 33 FROM_HERE, |
34 base::Bind(&V4Database::CreateOnTaskRunner, db_task_runner, base_path, | 34 base::Bind(&V4Database::CreateOnTaskRunner, db_task_runner, base_path, |
35 store_file_name_map, callback_task_runner, callback)); | 35 store_file_name_map, callback_task_runner, new_db_callback)); |
36 } | 36 } |
37 | 37 |
38 // static | 38 // static |
39 void V4Database::CreateOnTaskRunner( | 39 void V4Database::CreateOnTaskRunner( |
40 const scoped_refptr<base::SequencedTaskRunner>& db_task_runner, | 40 const scoped_refptr<base::SequencedTaskRunner>& db_task_runner, |
41 const base::FilePath& base_path, | 41 const base::FilePath& base_path, |
42 const StoreFileNameMap& store_file_name_map, | 42 const StoreFileNameMap& store_file_name_map, |
43 const scoped_refptr<base::SingleThreadTaskRunner>& callback_task_runner, | 43 const scoped_refptr<base::SingleThreadTaskRunner>& callback_task_runner, |
44 NewDatabaseReadyCallback callback) { | 44 NewDatabaseReadyCallback new_db_callback) { |
45 DCHECK(db_task_runner->RunsTasksOnCurrentThread()); | 45 DCHECK(db_task_runner->RunsTasksOnCurrentThread()); |
46 DCHECK(base_path.IsAbsolute()); | |
47 | 46 |
48 if (!factory_) { | 47 if (!factory_) { |
49 factory_ = new V4StoreFactory(); | 48 factory_ = new V4StoreFactory(); |
50 ANNOTATE_LEAKING_OBJECT_PTR(factory_); | 49 ANNOTATE_LEAKING_OBJECT_PTR(factory_); |
51 } | 50 } |
52 auto store_map = base::MakeUnique<StoreMap>(); | 51 |
| 52 std::unique_ptr<StoreMap> store_map = base::MakeUnique<StoreMap>(); |
53 for (const auto& store_info : store_file_name_map) { | 53 for (const auto& store_info : store_file_name_map) { |
54 const UpdateListIdentifier& update_list_identifier = store_info.first; | 54 const UpdateListIdentifier& update_list_identifier = store_info.first; |
55 const base::FilePath store_path = base_path.AppendASCII(store_info.second); | 55 const base::FilePath store_path = base_path.AppendASCII(store_info.second); |
56 (*store_map)[update_list_identifier].reset( | 56 (*store_map)[update_list_identifier].reset( |
57 factory_->CreateV4Store(db_task_runner, store_path)); | 57 factory_->CreateV4Store(db_task_runner, store_path)); |
58 } | 58 } |
59 std::unique_ptr<V4Database> v4_database( | 59 std::unique_ptr<V4Database> v4_database( |
60 new V4Database(db_task_runner, std::move(store_map))); | 60 new V4Database(db_task_runner, std::move(store_map))); |
61 | 61 |
62 // Database is done loading, pass it to the callback on the caller's thread. | 62 // Database is done loading, pass it to the new_db_callback on the caller's |
| 63 // thread. |
63 callback_task_runner->PostTask( | 64 callback_task_runner->PostTask( |
64 FROM_HERE, base::Bind(callback, base::Passed(&v4_database))); | 65 FROM_HERE, base::Bind(new_db_callback, base::Passed(&v4_database))); |
65 } | 66 } |
66 | 67 |
67 V4Database::V4Database( | 68 V4Database::V4Database( |
68 const scoped_refptr<base::SequencedTaskRunner>& db_task_runner, | 69 const scoped_refptr<base::SequencedTaskRunner>& db_task_runner, |
69 std::unique_ptr<StoreMap> store_map) | 70 std::unique_ptr<StoreMap> store_map) |
70 : db_task_runner_(db_task_runner), store_map_(std::move(store_map)) { | 71 : db_task_runner_(db_task_runner), |
| 72 store_map_(std::move(store_map)), |
| 73 pending_store_updates_(0) { |
71 DCHECK(db_task_runner->RunsTasksOnCurrentThread()); | 74 DCHECK(db_task_runner->RunsTasksOnCurrentThread()); |
72 // TODO(vakh): Implement skeleton | 75 // TODO(vakh): Implement skeleton |
73 } | 76 } |
74 | 77 |
75 // static | 78 // static |
76 void V4Database::Destroy(std::unique_ptr<V4Database> v4_database) { | 79 void V4Database::Destroy(std::unique_ptr<V4Database> v4_database) { |
77 V4Database* v4_database_raw = v4_database.release(); | 80 V4Database* v4_database_raw = v4_database.release(); |
78 if (v4_database_raw) { | 81 if (v4_database_raw) { |
79 v4_database_raw->db_task_runner_->DeleteSoon(FROM_HERE, v4_database_raw); | 82 v4_database_raw->db_task_runner_->DeleteSoon(FROM_HERE, v4_database_raw); |
80 } | 83 } |
81 } | 84 } |
82 | 85 |
83 V4Database::~V4Database() { | 86 V4Database::~V4Database() { |
84 DCHECK(db_task_runner_->RunsTasksOnCurrentThread()); | 87 DCHECK(db_task_runner_->RunsTasksOnCurrentThread()); |
85 } | 88 } |
86 | 89 |
| 90 void V4Database::ApplyUpdate(const std::vector<ListUpdateResponse>& responses, |
| 91 DatabaseUpdatedCallback db_updated_callback) { |
| 92 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 93 DCHECK(!pending_store_updates_); |
| 94 DCHECK(db_updated_callback_.is_null()); |
| 95 |
| 96 db_updated_callback_ = db_updated_callback; |
| 97 |
| 98 // Post the V4Store update task on the task runner but get the callback on the |
| 99 // current thread. |
| 100 const scoped_refptr<base::SingleThreadTaskRunner>& current_task_runner = |
| 101 base::MessageLoop::current()->task_runner(); |
| 102 for (const ListUpdateResponse& response : responses) { |
| 103 UpdateListIdentifier identifier(response); |
| 104 StoreMap::const_iterator iter = store_map_->find(identifier); |
| 105 if (iter != store_map_->end()) { |
| 106 const std::unique_ptr<V4Store>& old_store = iter->second; |
| 107 if (old_store->state() != response.new_client_state()) { |
| 108 // A different state implies there are updates to process. |
| 109 pending_store_updates_++; |
| 110 UpdatedStoreReadyCallback store_ready_callback = base::Bind( |
| 111 &V4Database::UpdatedStoreReady, base::Unretained(this), identifier); |
| 112 db_task_runner_->PostTask( |
| 113 FROM_HERE, |
| 114 base::Bind(&V4Store::ApplyUpdate, base::Unretained(old_store.get()), |
| 115 response, current_task_runner, store_ready_callback)); |
| 116 } |
| 117 } else { |
| 118 NOTREACHED() << "Got update for unexpected identifier: " << identifier; |
| 119 } |
| 120 } |
| 121 |
| 122 if (!pending_store_updates_) { |
| 123 current_task_runner->PostTask(FROM_HERE, db_updated_callback_); |
| 124 db_updated_callback_.Reset(); |
| 125 } |
| 126 } |
| 127 |
| 128 void V4Database::UpdatedStoreReady(UpdateListIdentifier identifier, |
| 129 std::unique_ptr<V4Store> new_store) { |
| 130 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 131 DCHECK(pending_store_updates_); |
| 132 (*store_map_)[identifier] = std::move(new_store); |
| 133 |
| 134 pending_store_updates_--; |
| 135 if (!pending_store_updates_) { |
| 136 db_updated_callback_.Run(); |
| 137 db_updated_callback_.Reset(); |
| 138 } |
| 139 } |
| 140 |
87 bool V4Database::ResetDatabase() { | 141 bool V4Database::ResetDatabase() { |
88 DCHECK(db_task_runner_->RunsTasksOnCurrentThread()); | 142 DCHECK(db_task_runner_->RunsTasksOnCurrentThread()); |
89 bool reset_success = true; | 143 bool reset_success = true; |
90 for (const auto& store_id_and_store : *store_map_) { | 144 for (const auto& store_map_iter : *store_map_) { |
91 if (!store_id_and_store.second->Reset()) { | 145 if (!store_map_iter.second->Reset()) { |
92 reset_success = false; | 146 reset_success = false; |
93 } | 147 } |
94 } | 148 } |
95 return reset_success; | 149 return reset_success; |
96 } | 150 } |
97 | 151 |
| 152 std::unique_ptr<StoreStateMap> V4Database::GetStoreStateMap() { |
| 153 std::unique_ptr<StoreStateMap> store_state_map = |
| 154 base::MakeUnique<StoreStateMap>(); |
| 155 for (const auto& store_map_iter : *store_map_) { |
| 156 (*store_state_map)[store_map_iter.first] = store_map_iter.second->state(); |
| 157 } |
| 158 return store_state_map; |
| 159 } |
| 160 |
98 } // namespace safe_browsing | 161 } // namespace safe_browsing |
OLD | NEW |