Index: components/safe_browsing_db/v4_database.cc |
diff --git a/components/safe_browsing_db/v4_database.cc b/components/safe_browsing_db/v4_database.cc |
index 32d0494b457f710b69147514791eb9e90514127d..20711340207600c6affd40dba037259c81a88159 100644 |
--- a/components/safe_browsing_db/v4_database.cc |
+++ b/components/safe_browsing_db/v4_database.cc |
@@ -19,56 +19,67 @@ namespace safe_browsing { |
V4StoreFactory* V4Database::factory_ = NULL; |
// static |
-void V4Database::Create( |
+bool V4Database::Create( |
const scoped_refptr<base::SequencedTaskRunner>& db_task_runner, |
const base::FilePath& base_path, |
- const ListInfoMap& list_info_map, |
- NewDatabaseReadyCallback callback) { |
+ const StoreFileNameMap& store_file_name_map, |
+ DatabaseUpdatedCallback db_updated_callback, |
+ NewDatabaseReadyCallback new_db_callback) { |
// Create the database, which may be a lengthy operation, on the |
// db_task_runner, but once that is done, call the caller back on this |
// thread. |
+ DCHECK(base_path.IsAbsolute()); |
+ DCHECK(!store_file_name_map.empty()); |
+ |
const scoped_refptr<base::SingleThreadTaskRunner>& callback_task_runner = |
base::MessageLoop::current()->task_runner(); |
db_task_runner->PostTask( |
- FROM_HERE, |
- base::Bind(&V4Database::CreateOnTaskRunner, db_task_runner, base_path, |
- list_info_map, callback_task_runner, callback)); |
+ FROM_HERE, base::Bind(&V4Database::CreateOnTaskRunner, db_task_runner, |
+ base_path, store_file_name_map, db_updated_callback, |
+ callback_task_runner, new_db_callback)); |
+ 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
|
} |
// static |
void V4Database::CreateOnTaskRunner( |
const scoped_refptr<base::SequencedTaskRunner>& db_task_runner, |
const base::FilePath& base_path, |
- const ListInfoMap& list_info_map, |
+ const StoreFileNameMap& store_file_name_map, |
+ DatabaseUpdatedCallback db_updated_callback, |
const scoped_refptr<base::SingleThreadTaskRunner>& callback_task_runner, |
- NewDatabaseReadyCallback callback) { |
+ NewDatabaseReadyCallback new_db_callback) { |
DCHECK(db_task_runner->RunsTasksOnCurrentThread()); |
- DCHECK(base_path.IsAbsolute()); |
if (!factory_) { |
factory_ = new V4StoreFactory(); |
ANNOTATE_LEAKING_OBJECT_PTR(factory_); |
} |
auto store_map = base::MakeUnique<StoreMap>(); |
- for (const auto& list_info : list_info_map) { |
- const UpdateListIdentifier& update_list_identifier = list_info.first; |
- const base::FilePath store_path = base_path.AppendASCII(list_info.second); |
+ for (const auto& store_info : store_file_name_map) { |
+ const UpdateListIdentifier& update_list_identifier = store_info.first; |
+ const base::FilePath store_path = base_path.AppendASCII(store_info.second); |
(*store_map)[update_list_identifier].reset( |
factory_->CreateV4Store(db_task_runner, store_path)); |
} |
- std::unique_ptr<V4Database> v4_database( |
- new V4Database(db_task_runner, std::move(store_map))); |
+ std::unique_ptr<V4Database> v4_database(new V4Database( |
+ db_task_runner, std::move(store_map), db_updated_callback)); |
- // Database is done loading, pass it to the callback on the caller's thread. |
+ // Database is done loading, pass it to the new_db_callback on the caller's |
+ // thread. |
callback_task_runner->PostTask( |
- FROM_HERE, base::Bind(callback, base::Passed(&v4_database))); |
+ FROM_HERE, base::Bind(new_db_callback, base::Passed(&v4_database))); |
} |
V4Database::V4Database( |
const scoped_refptr<base::SequencedTaskRunner>& db_task_runner, |
- std::unique_ptr<StoreMap> store_map) |
- : db_task_runner_(db_task_runner), store_map_(std::move(store_map)) { |
+ std::unique_ptr<StoreMap> store_map, |
+ DatabaseUpdatedCallback db_updated_callback) |
+ : db_task_runner_(db_task_runner), |
+ store_map_(std::move(store_map)), |
+ db_updated_callback_(db_updated_callback), |
+ pending_store_updates_(0) { |
DCHECK(db_task_runner->RunsTasksOnCurrentThread()); |
+ UpdateStoreStateMap(); |
// TODO(vakh): Implement skeleton |
} |
@@ -84,15 +95,70 @@ V4Database::~V4Database() { |
DCHECK(db_task_runner_->RunsTasksOnCurrentThread()); |
} |
+void V4Database::ApplyUpdate(const std::vector<ListUpdateResponse>& responses) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ DCHECK(!pending_store_updates_); |
+ |
+ // Post the V4Store update task on the task runner but get the callback on the |
+ // current thread (IO thread). |
+ const scoped_refptr<base::SingleThreadTaskRunner>& current_task_runner = |
+ base::MessageLoop::current()->task_runner(); |
+ for (const auto& response : responses) { |
+ UpdateListIdentifier identifier(response); |
+ StoreMap::const_iterator iter = store_map_->find(identifier); |
+ if (iter != store_map_->end()) { |
+ const auto& old_store = iter->second; |
+ 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
|
+ // A different state implies there are updates to process. |
+ pending_store_updates_++; |
+ UpdatedStoreReadyCallback store_ready_callback = base::Bind( |
+ &V4Database::UpdatedStoreReady, base::Unretained(this), identifier); |
+ db_task_runner_->PostTask( |
+ FROM_HERE, |
+ base::Bind(&V4Store::ApplyUpdate, base::Unretained(old_store.get()), |
+ 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.
|
+ } |
+ } else { |
+ DVLOG(1) << "Got update for unexpected identifier: " << identifier; |
+ 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.
|
+ } |
+ } |
+ |
+ if (!pending_store_updates_) { |
+ db_updated_callback_.Run(); |
+ } |
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.
|
+} |
+ |
+void V4Database::UpdatedStoreReady(UpdateListIdentifier identifier, |
+ std::unique_ptr<V4Store> new_store) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ DCHECK(pending_store_updates_); |
+ store_state_map_[identifier] = new_store->state(); |
+ (*store_map_)[identifier] = std::move(new_store); |
+ |
+ // Since this method is always called on the IO thread, there can't be a race |
+ // 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
|
+ pending_store_updates_--; |
+ if (!pending_store_updates_) { |
+ db_updated_callback_.Run(); |
+ } |
+} |
+ |
bool V4Database::ResetDatabase() { |
DCHECK(db_task_runner_->RunsTasksOnCurrentThread()); |
bool reset_success = true; |
- for (const auto& store_id_and_store : *store_map_) { |
- if (!store_id_and_store.second->Reset()) { |
+ for (const auto& store_map_iter : *store_map_) { |
+ if (!store_map_iter.second->Reset()) { |
reset_success = false; |
} |
} |
return reset_success; |
} |
+void V4Database::UpdateStoreStateMap() { |
+ for (const auto& store_map_iter : *store_map_) { |
+ store_state_map_[store_map_iter.first] = store_map_iter.second->state(); |
+ } |
+} |
+ |
} // namespace safe_browsing |