| // Copyright 2018 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/leveldb_proto/shared_proto_database_client.h" |
| |
| #include "base/strings/strcat.h" |
| #include "components/leveldb_proto/proto_leveldb_wrapper.h" |
| #include "components/leveldb_proto/shared_proto_database.h" |
| #include "components/leveldb_proto/shared_proto_database_client_list.h" |
| |
| namespace leveldb_proto { |
| namespace { |
| const char* const* g_obsolete_client_list_for_testing = nullptr; |
| |
| // Holds the db wrapper alive and callback is called at destruction. This class |
| // is used to post multiple update tasks on |db_wrapper| and keep the instance |
| // alive till all the callbacks are returned. |
| class ObsoleteClientsDbHolder |
| : public base::RefCounted<ObsoleteClientsDbHolder> { |
| public: |
| ObsoleteClientsDbHolder(std::unique_ptr<ProtoLevelDBWrapper> db_wrapper, |
| Callbacks::UpdateCallback callback) |
| : success_(true), |
| owned_db_wrapper_(std::move(db_wrapper)), |
| callback_(std::move(callback)) {} |
| |
| void set_success(bool success) { success_ &= success; } |
| |
| private: |
| friend class RefCounted<ObsoleteClientsDbHolder>; |
| ~ObsoleteClientsDbHolder() { std::move(callback_).Run(success_); } |
| |
| bool success_; |
| std::unique_ptr<ProtoLevelDBWrapper> owned_db_wrapper_; |
| Callbacks::UpdateCallback callback_; |
| }; |
| |
| } // namespace |
| |
| std::string StripPrefix(const std::string& key, const std::string& prefix) { |
| return base::StartsWith(key, prefix, base::CompareCase::SENSITIVE) |
| ? key.substr(prefix.length()) |
| : key; |
| } |
| |
| std::unique_ptr<std::vector<std::string>> PrefixStrings( |
| std::unique_ptr<std::vector<std::string>> strings, |
| const std::string& prefix) { |
| for (auto& str : *strings) |
| str.assign(base::StrCat({prefix, str})); |
| return strings; |
| } |
| |
| bool KeyFilterStripPrefix(const LevelDB::KeyFilter& key_filter, |
| const std::string& prefix, |
| const std::string& key) { |
| if (key_filter.is_null()) |
| return true; |
| return key_filter.Run(StripPrefix(key, prefix)); |
| } |
| |
| void GetSharedDatabaseInitStatusAsync( |
| const std::string& client_name, |
| const scoped_refptr<SharedProtoDatabase>& shared_db, |
| Callbacks::InitStatusCallback callback) { |
| shared_db->GetDatabaseInitStatusAsync(client_name, std::move(callback)); |
| } |
| |
| void UpdateClientCorruptAsync( |
| const scoped_refptr<SharedProtoDatabase>& shared_db, |
| const std::string& client_name, |
| ClientCorruptCallback callback) { |
| shared_db->UpdateClientCorruptAsync(client_name, std::move(callback)); |
| } |
| |
| void DestroyObsoleteSharedProtoDatabaseClients( |
| std::unique_ptr<ProtoLevelDBWrapper> db_wrapper, |
| Callbacks::UpdateCallback callback) { |
| ProtoLevelDBWrapper* db_wrapper_ptr = db_wrapper.get(); |
| scoped_refptr<ObsoleteClientsDbHolder> db_holder = |
| new ObsoleteClientsDbHolder(std::move(db_wrapper), std::move(callback)); |
| |
| const char* const* list = g_obsolete_client_list_for_testing |
| ? g_obsolete_client_list_for_testing |
| : kObsoleteSharedProtoDatabaseClients; |
| for (size_t i = 0; list[i] != nullptr; ++i) { |
| // Callback keeps a ref pointer to db_holder alive till the changes are |
| // done. |db_holder| will be destroyed once all the RemoveKeys() calls |
| // return. |
| Callbacks::UpdateCallback callback_wrapper = |
| base::BindOnce([](scoped_refptr<ObsoleteClientsDbHolder> db_holder, |
| bool success) { db_holder->set_success(success); }, |
| db_holder); |
| // Remove all type prefixes for the client. |
| // TODO(ssid): Support cleanup of namespaces for clients. This code assumes |
| // the prefix contains the client namespace at the beginning. |
| db_wrapper_ptr->RemoveKeys( |
| base::BindRepeating([](const std::string& key) { return true; }), |
| list[i], std::move(callback_wrapper)); |
| } |
| } |
| |
| void SetObsoleteClientListForTesting(const char* const* list) { |
| g_obsolete_client_list_for_testing = list; |
| } |
| |
| } // namespace leveldb_proto |