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 DCHECK(base_path.IsAbsolute()); | |
32 DCHECK(!store_file_name_map.empty()); | |
33 | |
30 const scoped_refptr<base::SingleThreadTaskRunner>& callback_task_runner = | 34 const scoped_refptr<base::SingleThreadTaskRunner>& callback_task_runner = |
31 base::MessageLoop::current()->task_runner(); | 35 base::MessageLoop::current()->task_runner(); |
32 db_task_runner->PostTask( | 36 db_task_runner->PostTask( |
33 FROM_HERE, | 37 FROM_HERE, base::Bind(&V4Database::CreateOnTaskRunner, db_task_runner, |
34 base::Bind(&V4Database::CreateOnTaskRunner, db_task_runner, base_path, | 38 base_path, store_file_name_map, db_updated_callback, |
35 list_info_map, callback_task_runner, callback)); | 39 callback_task_runner, new_db_callback)); |
40 return true; | |
Scott Hess - ex-Googler
2016/06/17 22:53:42
This seems like it always returns true. Since it'
vakh (use Gerrit instead)
2016/06/20 22:28:42
I was initially returning false for the DCHECKS ab
| |
36 } | 41 } |
37 | 42 |
38 // static | 43 // static |
39 void V4Database::CreateOnTaskRunner( | 44 void V4Database::CreateOnTaskRunner( |
40 const scoped_refptr<base::SequencedTaskRunner>& db_task_runner, | 45 const scoped_refptr<base::SequencedTaskRunner>& db_task_runner, |
41 const base::FilePath& base_path, | 46 const base::FilePath& base_path, |
42 const ListInfoMap& list_info_map, | 47 const StoreFileNameMap& store_file_name_map, |
48 DatabaseUpdatedCallback db_updated_callback, | |
43 const scoped_refptr<base::SingleThreadTaskRunner>& callback_task_runner, | 49 const scoped_refptr<base::SingleThreadTaskRunner>& callback_task_runner, |
44 NewDatabaseReadyCallback callback) { | 50 NewDatabaseReadyCallback new_db_callback) { |
45 DCHECK(db_task_runner->RunsTasksOnCurrentThread()); | 51 DCHECK(db_task_runner->RunsTasksOnCurrentThread()); |
46 DCHECK(base_path.IsAbsolute()); | |
47 | 52 |
48 if (!factory_) { | 53 if (!factory_) { |
49 factory_ = new V4StoreFactory(); | 54 factory_ = new V4StoreFactory(); |
50 ANNOTATE_LEAKING_OBJECT_PTR(factory_); | 55 ANNOTATE_LEAKING_OBJECT_PTR(factory_); |
51 } | 56 } |
52 auto store_map = base::MakeUnique<StoreMap>(); | 57 auto store_map = base::MakeUnique<StoreMap>(); |
53 for (const auto& list_info : list_info_map) { | 58 for (const auto& store_info : store_file_name_map) { |
54 const UpdateListIdentifier& update_list_identifier = list_info.first; | 59 const UpdateListIdentifier& update_list_identifier = store_info.first; |
55 const base::FilePath store_path = base_path.AppendASCII(list_info.second); | 60 const base::FilePath store_path = base_path.AppendASCII(store_info.second); |
56 (*store_map)[update_list_identifier].reset( | 61 (*store_map)[update_list_identifier].reset( |
57 factory_->CreateV4Store(db_task_runner, store_path)); | 62 factory_->CreateV4Store(db_task_runner, store_path)); |
58 } | 63 } |
59 std::unique_ptr<V4Database> v4_database( | 64 std::unique_ptr<V4Database> v4_database(new V4Database( |
60 new V4Database(db_task_runner, std::move(store_map))); | 65 db_task_runner, std::move(store_map), db_updated_callback)); |
61 | 66 |
62 // Database is done loading, pass it to the callback on the caller's thread. | 67 // Database is done loading, pass it to the new_db_callback on the caller's |
68 // thread. | |
63 callback_task_runner->PostTask( | 69 callback_task_runner->PostTask( |
64 FROM_HERE, base::Bind(callback, base::Passed(&v4_database))); | 70 FROM_HERE, base::Bind(new_db_callback, base::Passed(&v4_database))); |
65 } | 71 } |
66 | 72 |
67 V4Database::V4Database( | 73 V4Database::V4Database( |
68 const scoped_refptr<base::SequencedTaskRunner>& db_task_runner, | 74 const scoped_refptr<base::SequencedTaskRunner>& db_task_runner, |
69 std::unique_ptr<StoreMap> store_map) | 75 std::unique_ptr<StoreMap> store_map, |
70 : db_task_runner_(db_task_runner), store_map_(std::move(store_map)) { | 76 DatabaseUpdatedCallback db_updated_callback) |
77 : db_task_runner_(db_task_runner), | |
78 store_map_(std::move(store_map)), | |
79 db_updated_callback_(db_updated_callback), | |
80 pending_store_updates_(0) { | |
71 DCHECK(db_task_runner->RunsTasksOnCurrentThread()); | 81 DCHECK(db_task_runner->RunsTasksOnCurrentThread()); |
82 UpdateStoreStateMap(); | |
72 // TODO(vakh): Implement skeleton | 83 // TODO(vakh): Implement skeleton |
73 } | 84 } |
74 | 85 |
75 // static | 86 // static |
76 void V4Database::Destroy(std::unique_ptr<V4Database> v4_database) { | 87 void V4Database::Destroy(std::unique_ptr<V4Database> v4_database) { |
77 V4Database* v4_database_raw = v4_database.release(); | 88 V4Database* v4_database_raw = v4_database.release(); |
78 if (v4_database_raw) { | 89 if (v4_database_raw) { |
79 v4_database_raw->db_task_runner_->DeleteSoon(FROM_HERE, v4_database_raw); | 90 v4_database_raw->db_task_runner_->DeleteSoon(FROM_HERE, v4_database_raw); |
80 } | 91 } |
81 } | 92 } |
82 | 93 |
83 V4Database::~V4Database() { | 94 V4Database::~V4Database() { |
84 DCHECK(db_task_runner_->RunsTasksOnCurrentThread()); | 95 DCHECK(db_task_runner_->RunsTasksOnCurrentThread()); |
85 } | 96 } |
86 | 97 |
98 void V4Database::ApplyUpdate(const std::vector<ListUpdateResponse>& responses) { | |
99 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
100 DCHECK(!pending_store_updates_); | |
101 | |
102 // Post the V4Store update task on the task runner but get the callback on the | |
103 // current thread (IO thread). | |
104 const scoped_refptr<base::SingleThreadTaskRunner>& current_task_runner = | |
105 base::MessageLoop::current()->task_runner(); | |
106 for (const auto& response : responses) { | |
107 UpdateListIdentifier identifier(response); | |
108 StoreMap::const_iterator iter = store_map_->find(identifier); | |
109 if (iter != store_map_->end()) { | |
110 const auto& old_store = iter->second; | |
111 if (old_store->state() != response.new_client_state()) { | |
Scott Hess - ex-Googler
2016/06/17 22:53:42
I'm not entirely liking the auto for |response| an
vakh (use Gerrit instead)
2016/06/20 22:28:42
"for (const auto& iter ...)" is a commonly used an
Scott Hess - ex-Googler
2016/06/21 21:03:44
Yeah, I'm just feeling like this case is not incre
vakh (use Gerrit instead)
2016/06/21 23:19:35
Fair enough. Done. Changed for response.
For the o
Scott Hess - ex-Googler
2016/06/24 23:01:18
Acknowledged. I feel like this looks less magical
| |
112 // A different state implies there are updates to process. | |
113 pending_store_updates_++; | |
114 UpdatedStoreReadyCallback store_ready_callback = base::Bind( | |
115 &V4Database::UpdatedStoreReady, base::Unretained(this), identifier); | |
116 db_task_runner_->PostTask( | |
117 FROM_HERE, | |
118 base::Bind(&V4Store::ApplyUpdate, base::Unretained(old_store.get()), | |
119 response, current_task_runner, store_ready_callback)); | |
Scott Hess - ex-Googler
2016/06/17 22:53:42
I'm slightly questioning whether this is better do
vakh (use Gerrit instead)
2016/06/20 22:28:42
Writing a store to disk is a long operation so the
Scott Hess - ex-Googler
2016/06/21 21:03:44
I wouldn't be upset about running long jobs on the
vakh (use Gerrit instead)
2016/06/23 06:23:49
If you feel strongly about making this change, I c
Scott Hess - ex-Googler
2016/06/24 23:01:18
OK, I do think it's a style thing rather than a re
vakh (use Gerrit instead)
2016/06/27 19:38:26
Acknowledged.
| |
120 } | |
121 } else { | |
122 DVLOG(1) << "Got update for unexpected identifier: " << identifier; | |
123 NOTREACHED(); | |
Scott Hess - ex-Googler
2016/06/17 22:53:42
The two lines just create a poor DCHECK, don't the
vakh (use Gerrit instead)
2016/06/20 22:28:42
Done.
| |
124 } | |
125 } | |
126 | |
127 if (!pending_store_updates_) { | |
128 db_updated_callback_.Run(); | |
129 } | |
Scott Hess - ex-Googler
2016/06/17 22:53:42
Should this be a post rather than a direct run, so
vakh (use Gerrit instead)
2016/06/20 22:28:42
Done.
| |
130 } | |
131 | |
132 void V4Database::UpdatedStoreReady(UpdateListIdentifier identifier, | |
133 std::unique_ptr<V4Store> new_store) { | |
134 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
135 DCHECK(pending_store_updates_); | |
136 store_state_map_[identifier] = new_store->state(); | |
137 (*store_map_)[identifier] = std::move(new_store); | |
138 | |
139 // Since this method is always called on the IO thread, there can't be a race | |
140 // condition in decrementing pending_store_updates_. | |
Scott Hess - ex-Googler
2016/06/17 22:53:42
Do we have any sort of thread annotations? This c
vakh (use Gerrit instead)
2016/06/20 22:28:42
Sorry, I'm not sure what you mean.
Scott Hess - ex-Googler
2016/06/21 21:03:43
In some systems (perhaps not Chromium), you can an
vakh (use Gerrit instead)
2016/06/21 23:19:35
Acknowledged. I've moved the comment next to the v
| |
141 pending_store_updates_--; | |
142 if (!pending_store_updates_) { | |
143 db_updated_callback_.Run(); | |
144 } | |
145 } | |
146 | |
87 bool V4Database::ResetDatabase() { | 147 bool V4Database::ResetDatabase() { |
88 DCHECK(db_task_runner_->RunsTasksOnCurrentThread()); | 148 DCHECK(db_task_runner_->RunsTasksOnCurrentThread()); |
89 bool reset_success = true; | 149 bool reset_success = true; |
90 for (const auto& store_id_and_store : *store_map_) { | 150 for (const auto& store_map_iter : *store_map_) { |
91 if (!store_id_and_store.second->Reset()) { | 151 if (!store_map_iter.second->Reset()) { |
92 reset_success = false; | 152 reset_success = false; |
93 } | 153 } |
94 } | 154 } |
95 return reset_success; | 155 return reset_success; |
96 } | 156 } |
97 | 157 |
158 void V4Database::UpdateStoreStateMap() { | |
159 for (const auto& store_map_iter : *store_map_) { | |
160 store_state_map_[store_map_iter.first] = store_map_iter.second->state(); | |
161 } | |
162 } | |
163 | |
98 } // namespace safe_browsing | 164 } // namespace safe_browsing |
OLD | NEW |