[Chromeshine] Persist token mappings to LevelDB.
Implement the Set- and GetAllTokenMappings functions for UsageStatsDatabase.
Bug: 902570
Change-Id: I619f1bf152566792f6046001ea14022b69e1aad5
Reviewed-on: https://chromium-review.googlesource.com/c/1423622
Commit-Queue: Natalie Chouinard <chouinard@chromium.org>
Reviewed-by: Patrick Noland <pnoland@chromium.org>
Cr-Commit-Position: refs/heads/master@{#624876}
diff --git a/chrome/browser/android/usage_stats/usage_stats_database.cc b/chrome/browser/android/usage_stats/usage_stats_database.cc
index 3ca66fe..46d50db9 100644
--- a/chrome/browser/android/usage_stats/usage_stats_database.cc
+++ b/chrome/browser/android/usage_stats/usage_stats_database.cc
@@ -16,8 +16,8 @@
const char kNamespace[] = "usage_stats";
const char kTypePrefix[] = "usage_stats";
-const char kKeySeparator = '.';
-const char kSuspensionPrefix[] = "suspension";
+const char kSuspensionPrefix[] = "suspension_";
+const char kTokenMappingPrefix[] = "token_mapping_";
UsageStatsDatabase::UsageStatsDatabase(Profile* profile)
: weak_ptr_factory_(this) {
@@ -71,7 +71,7 @@
for (std::string domain : domains) {
// Prepend prefix to form key.
- std::string key = std::string(kSuspensionPrefix) + kKeySeparator + domain;
+ std::string key = kSuspensionPrefix + domain;
keys.emplace_back(key);
@@ -88,10 +88,55 @@
proto_db_->UpdateEntriesWithRemoveFilter(
std::move(entries),
base::BindRepeating(&DoesNotContainFilter, std::move(key_set)),
- base::BindOnce(&UsageStatsDatabase::OnUpdateEntriesForSetSuspensions,
+ base::BindOnce(&UsageStatsDatabase::OnUpdateEntries,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
+void UsageStatsDatabase::GetAllTokenMappings(TokenMappingsCallback callback) {
+ // Load all UsageStats with the token mapping prefix.
+ proto_db_->LoadEntriesWithFilter(
+ leveldb_proto::KeyFilter(), leveldb::ReadOptions(), kTokenMappingPrefix,
+ base::BindOnce(&UsageStatsDatabase::OnLoadEntriesForGetAllTokenMappings,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void UsageStatsDatabase::SetTokenMappings(TokenMap mappings,
+ StatusCallback callback) {
+ std::vector<std::string> keys;
+ keys.reserve(mappings.size());
+
+ auto entries = std::make_unique<
+ leveldb_proto::ProtoDatabase<UsageStat>::KeyEntryVector>();
+
+ for (const auto& mapping : mappings) {
+ // Prepend prefix to token to form key.
+ std::string key = kTokenMappingPrefix + mapping.first;
+
+ keys.emplace_back(key);
+
+ UsageStat value;
+ TokenMapping* token_mapping = value.mutable_token_mapping();
+ token_mapping->set_token(mapping.first);
+ token_mapping->set_fqdn(mapping.second);
+
+ entries->emplace_back(key, value);
+ }
+
+ auto key_set = base::flat_set<std::string>(keys);
+
+ // Add all entries created from map, remove all entries not in the map.
+ proto_db_->UpdateEntriesWithRemoveFilter(
+ std::move(entries),
+ base::BindRepeating(&DoesNotContainFilter, std::move(key_set)),
+ base::BindOnce(&UsageStatsDatabase::OnUpdateEntries,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void UsageStatsDatabase::OnUpdateEntries(StatusCallback callback,
+ bool success) {
+ std::move(callback).Run(ToError(success));
+}
+
void UsageStatsDatabase::OnLoadEntriesForGetAllSuspensions(
SuspensionCallback callback,
bool success,
@@ -108,10 +153,20 @@
std::move(callback).Run(ToError(success), std::move(results));
}
-void UsageStatsDatabase::OnUpdateEntriesForSetSuspensions(
- StatusCallback callback,
- bool success) {
- std::move(callback).Run(ToError(success));
+void UsageStatsDatabase::OnLoadEntriesForGetAllTokenMappings(
+ TokenMappingsCallback callback,
+ bool success,
+ std::unique_ptr<std::vector<UsageStat>> stats) {
+ TokenMap results;
+
+ if (stats) {
+ for (UsageStat stat : *stats) {
+ TokenMapping mapping = stat.token_mapping();
+ results.emplace(mapping.token(), mapping.fqdn());
+ }
+ }
+
+ std::move(callback).Run(ToError(success), std::move(results));
}
} // namespace usage_stats
diff --git a/chrome/browser/android/usage_stats/usage_stats_database.h b/chrome/browser/android/usage_stats/usage_stats_database.h
index 35dbf3d..76390f7 100644
--- a/chrome/browser/android/usage_stats/usage_stats_database.h
+++ b/chrome/browser/android/usage_stats/usage_stats_database.h
@@ -31,8 +31,8 @@
using SuspensionCallback =
base::OnceCallback<void(Error, std::vector<std::string>)>;
- using TokenMappingsCallback =
- base::OnceCallback<void(Error, std::map<std::string, std::string>)>;
+ using TokenMap = std::map<std::string, std::string>;
+ using TokenMappingsCallback = base::OnceCallback<void(Error, TokenMap)>;
using StatusCallback = base::OnceCallback<void(Error)>;
@@ -73,16 +73,20 @@
// Persists all the mappings in |mappings| and deletes any mappings *not* in
// |mappings|. The map's key is the token, and its value is the FQDN.
- void SetTokenMappings(std::map<std::string, std::string> mappings,
- StatusCallback callback);
+ void SetTokenMappings(TokenMap mappings, StatusCallback callback);
private:
+ void OnUpdateEntries(StatusCallback callback, bool success);
+
void OnLoadEntriesForGetAllSuspensions(
SuspensionCallback callback,
bool success,
- std::unique_ptr<std::vector<UsageStat>> suspensions);
+ std::unique_ptr<std::vector<UsageStat>> stats);
- void OnUpdateEntriesForSetSuspensions(StatusCallback callback, bool success);
+ void OnLoadEntriesForGetAllTokenMappings(
+ TokenMappingsCallback callback,
+ bool success,
+ std::unique_ptr<std::vector<UsageStat>> stats);
std::unique_ptr<leveldb_proto::ProtoDatabase<UsageStat>> proto_db_;
diff --git a/chrome/browser/android/usage_stats/usage_stats_database_unittest.cc b/chrome/browser/android/usage_stats/usage_stats_database_unittest.cc
index 144e1239..5086ad7 100644
--- a/chrome/browser/android/usage_stats/usage_stats_database_unittest.cc
+++ b/chrome/browser/android/usage_stats/usage_stats_database_unittest.cc
@@ -19,6 +19,9 @@
const char kFqdn1[] = "foo.com";
const char kFqdn2[] = "bar.org";
+const char kToken1[] = "token1";
+const char kToken2[] = "token2";
+
} // namespace
class UsageStatsDatabaseTest : public testing::Test {
@@ -39,9 +42,11 @@
FakeDB<UsageStat>* fake_db() { return fake_db_unowned_; }
- MOCK_METHOD1(OnSetSuspensionsDone, void(UsageStatsDatabase::Error));
+ MOCK_METHOD1(OnUpdateDone, void(UsageStatsDatabase::Error));
MOCK_METHOD2(OnGetAllSuspensionsDone,
void(UsageStatsDatabase::Error, std::vector<std::string>));
+ MOCK_METHOD2(OnGetAllTokenMappingsDone,
+ void(UsageStatsDatabase::Error, UsageStatsDatabase::TokenMap));
private:
std::map<std::string, UsageStat> fake_db_unowned_store_;
@@ -56,13 +61,15 @@
ASSERT_NE(nullptr, fake_db());
}
+// Suspension Tests
+
TEST_F(UsageStatsDatabaseTest, SetSuspensionsSuccess) {
base::flat_set<std::string> domains({kFqdn1, kFqdn2});
- EXPECT_CALL(*this, OnSetSuspensionsDone(UsageStatsDatabase::Error::kNoError));
+ EXPECT_CALL(*this, OnUpdateDone(UsageStatsDatabase::Error::kNoError));
usage_stats_database()->SetSuspensions(
- domains, base::BindOnce(&UsageStatsDatabaseTest::OnSetSuspensionsDone,
+ domains, base::BindOnce(&UsageStatsDatabaseTest::OnUpdateDone,
base::Unretained(this)));
fake_db()->UpdateCallback(true);
@@ -71,11 +78,10 @@
TEST_F(UsageStatsDatabaseTest, SetSuspensionsFailure) {
base::flat_set<std::string> domains({kFqdn1, kFqdn2});
- EXPECT_CALL(*this,
- OnSetSuspensionsDone(UsageStatsDatabase::Error::kUnknownError));
+ EXPECT_CALL(*this, OnUpdateDone(UsageStatsDatabase::Error::kUnknownError));
usage_stats_database()->SetSuspensions(
- domains, base::BindOnce(&UsageStatsDatabaseTest::OnSetSuspensionsDone,
+ domains, base::BindOnce(&UsageStatsDatabaseTest::OnUpdateDone,
base::Unretained(this)));
fake_db()->UpdateCallback(false);
@@ -111,10 +117,10 @@
// Insert 1 suspension.
base::flat_set<std::string> domains({kFqdn1});
- EXPECT_CALL(*this, OnSetSuspensionsDone(UsageStatsDatabase::Error::kNoError));
+ EXPECT_CALL(*this, OnUpdateDone(UsageStatsDatabase::Error::kNoError));
usage_stats_database()->SetSuspensions(
- domains, base::BindOnce(&UsageStatsDatabaseTest::OnSetSuspensionsDone,
+ domains, base::BindOnce(&UsageStatsDatabaseTest::OnUpdateDone,
base::Unretained(this)));
fake_db()->UpdateCallback(true);
@@ -136,10 +142,10 @@
// Insert 2 suspensions.
base::flat_set<std::string> domains1({kFqdn1, kFqdn2});
- EXPECT_CALL(*this, OnSetSuspensionsDone(UsageStatsDatabase::Error::kNoError));
+ EXPECT_CALL(*this, OnUpdateDone(UsageStatsDatabase::Error::kNoError));
usage_stats_database()->SetSuspensions(
- domains1, base::BindOnce(&UsageStatsDatabaseTest::OnSetSuspensionsDone,
+ domains1, base::BindOnce(&UsageStatsDatabaseTest::OnUpdateDone,
base::Unretained(this)));
fake_db()->UpdateCallback(true);
@@ -147,10 +153,10 @@
// Insert 1 suspension, and remove the other.
base::flat_set<std::string> domains2({kFqdn1});
- EXPECT_CALL(*this, OnSetSuspensionsDone(UsageStatsDatabase::Error::kNoError));
+ EXPECT_CALL(*this, OnUpdateDone(UsageStatsDatabase::Error::kNoError));
usage_stats_database()->SetSuspensions(
- domains2, base::BindOnce(&UsageStatsDatabaseTest::OnSetSuspensionsDone,
+ domains2, base::BindOnce(&UsageStatsDatabaseTest::OnUpdateDone,
base::Unretained(this)));
fake_db()->UpdateCallback(true);
@@ -168,4 +174,113 @@
fake_db()->LoadCallback(true);
}
+// Token Mapping Tests
+
+TEST_F(UsageStatsDatabaseTest, SetTokenMappingsSuccess) {
+ UsageStatsDatabase::TokenMap mappings({{kToken1, kFqdn1}, {kToken2, kFqdn2}});
+
+ EXPECT_CALL(*this, OnUpdateDone(UsageStatsDatabase::Error::kNoError));
+
+ usage_stats_database()->SetTokenMappings(
+ mappings, base::BindOnce(&UsageStatsDatabaseTest::OnUpdateDone,
+ base::Unretained(this)));
+
+ fake_db()->UpdateCallback(true);
+}
+
+TEST_F(UsageStatsDatabaseTest, SetTokenMappingsFailure) {
+ UsageStatsDatabase::TokenMap mappings({{kToken1, kFqdn1}, {kToken2, kFqdn2}});
+
+ EXPECT_CALL(*this, OnUpdateDone(UsageStatsDatabase::Error::kUnknownError));
+
+ usage_stats_database()->SetTokenMappings(
+ mappings, base::BindOnce(&UsageStatsDatabaseTest::OnUpdateDone,
+ base::Unretained(this)));
+
+ fake_db()->UpdateCallback(false);
+}
+
+TEST_F(UsageStatsDatabaseTest, GetAllTokenMappingsSuccess) {
+ UsageStatsDatabase::TokenMap expected;
+
+ EXPECT_CALL(*this, OnGetAllTokenMappingsDone(
+ UsageStatsDatabase::Error::kNoError, expected));
+
+ usage_stats_database()->GetAllTokenMappings(
+ base::BindOnce(&UsageStatsDatabaseTest::OnGetAllTokenMappingsDone,
+ base::Unretained(this)));
+
+ fake_db()->LoadCallback(true);
+}
+
+TEST_F(UsageStatsDatabaseTest, GetAllTokenMappingsFailure) {
+ UsageStatsDatabase::TokenMap expected;
+
+ EXPECT_CALL(*this, OnGetAllTokenMappingsDone(
+ UsageStatsDatabase::Error::kUnknownError, expected));
+
+ usage_stats_database()->GetAllTokenMappings(
+ base::BindOnce(&UsageStatsDatabaseTest::OnGetAllTokenMappingsDone,
+ base::Unretained(this)));
+
+ fake_db()->LoadCallback(false);
+}
+
+TEST_F(UsageStatsDatabaseTest, SetAndGetTokenMapping) {
+ UsageStatsDatabase::TokenMap mapping({{kToken1, kFqdn1}});
+
+ // Insert 1 token mapping.
+ EXPECT_CALL(*this, OnUpdateDone(UsageStatsDatabase::Error::kNoError));
+
+ usage_stats_database()->SetTokenMappings(
+ mapping, base::BindOnce(&UsageStatsDatabaseTest::OnUpdateDone,
+ base::Unretained(this)));
+
+ fake_db()->UpdateCallback(true);
+
+ // Get 1 token mapping.
+ EXPECT_CALL(*this, OnGetAllTokenMappingsDone(
+ UsageStatsDatabase::Error::kNoError, mapping));
+
+ usage_stats_database()->GetAllTokenMappings(
+ base::BindOnce(&UsageStatsDatabaseTest::OnGetAllTokenMappingsDone,
+ base::Unretained(this)));
+
+ fake_db()->LoadCallback(true);
+}
+
+TEST_F(UsageStatsDatabaseTest, SetRemoveAndGetTokenMapping) {
+ // Insert 2 token mappings.
+ UsageStatsDatabase::TokenMap mappings1(
+ {{kToken1, kFqdn1}, {kToken2, kFqdn2}});
+
+ EXPECT_CALL(*this, OnUpdateDone(UsageStatsDatabase::Error::kNoError));
+
+ usage_stats_database()->SetTokenMappings(
+ mappings1, base::BindOnce(&UsageStatsDatabaseTest::OnUpdateDone,
+ base::Unretained(this)));
+
+ fake_db()->UpdateCallback(true);
+
+ // Re-insert 1 token mapping, and remove the other.apping) {
+ UsageStatsDatabase::TokenMap mappings2({{kToken1, kFqdn1}});
+
+ EXPECT_CALL(*this, OnUpdateDone(UsageStatsDatabase::Error::kNoError));
+
+ usage_stats_database()->SetTokenMappings(
+ mappings2, base::BindOnce(&UsageStatsDatabaseTest::OnUpdateDone,
+ base::Unretained(this)));
+
+ fake_db()->UpdateCallback(true);
+
+ // Get 1 remaining token mapping.
+ EXPECT_CALL(*this, OnGetAllTokenMappingsDone(
+ UsageStatsDatabase::Error::kNoError, mappings2));
+
+ usage_stats_database()->GetAllTokenMappings(
+ base::BindOnce(&UsageStatsDatabaseTest::OnGetAllTokenMappingsDone,
+ base::Unretained(this)));
+
+ fake_db()->LoadCallback(true);
+}
} // namespace usage_stats