blob: 09581bf0bb2892dba85ce8885aea8e276d4107e3 [file] [log] [blame]
// Copyright 2017 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/consent_auditor/consent_auditor.h"
#include <memory>
#include "components/consent_auditor/pref_names.h"
#include "components/prefs/testing_pref_service.h"
#include "components/sync/user_events/fake_user_event_service.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace consent_auditor {
namespace {
const char kLocalConsentDescriptionKey[] = "description";
const char kLocalConsentConfirmationKey[] = "confirmation";
const char kLocalConsentVersionKey[] = "version";
const char kLocalConsentLocaleKey[] = "locale";
// Fake product version for testing.
const char kCurrentAppVersion[] = "1.2.3.4";
const char kCurrentAppLocale[] = "en-US";
// A helper function to load the |description|, |confirmation|, |version|,
// and |locale|, in that order, from a record for the |feature| in
// the |consents| dictionary.
void LoadEntriesFromLocalConsentRecord(const base::Value* consents,
const std::string& feature,
std::string* description,
std::string* confirmation,
std::string* version,
std::string* locale) {
SCOPED_TRACE(::testing::Message() << "|feature| = " << feature);
const base::Value* record =
consents->FindKeyOfType(feature, base::Value::Type::DICTIONARY);
ASSERT_TRUE(record);
SCOPED_TRACE(::testing::Message() << "|record| = " << record);
const base::Value* description_entry =
record->FindKey(kLocalConsentDescriptionKey);
const base::Value* confirmation_entry =
record->FindKey(kLocalConsentConfirmationKey);
const base::Value* version_entry = record->FindKey(kLocalConsentVersionKey);
const base::Value* locale_entry = record->FindKey(kLocalConsentLocaleKey);
ASSERT_TRUE(description_entry);
ASSERT_TRUE(confirmation_entry);
ASSERT_TRUE(version_entry);
ASSERT_TRUE(locale_entry);
*description = description_entry->GetString();
*confirmation = confirmation_entry->GetString();
*version = version_entry->GetString();
*locale = locale_entry->GetString();
}
} // namespace
class ConsentAuditorTest : public testing::Test {
public:
void SetUp() override {
pref_service_ = base::MakeUnique<TestingPrefServiceSimple>();
user_event_service_ = base::MakeUnique<syncer::FakeUserEventService>();
ConsentAuditor::RegisterProfilePrefs(pref_service_->registry());
consent_auditor_ = base::MakeUnique<ConsentAuditor>(
pref_service_.get(), user_event_service_.get(), kCurrentAppVersion,
kCurrentAppLocale);
}
void UpdateAppVersionAndLocale(const std::string& new_product_version,
const std::string& new_app_locale) {
// We'll have to recreate |consent_auditor| in order to update the version
// and locale. This is not a problem, as in reality we'd have to restart
// Chrome to update both, let alone just recreate this class.
consent_auditor_ = base::MakeUnique<ConsentAuditor>(
pref_service_.get(), user_event_service_.get(), new_product_version,
new_app_locale);
}
ConsentAuditor* consent_auditor() { return consent_auditor_.get(); }
PrefService* pref_service() const { return pref_service_.get(); }
private:
std::unique_ptr<ConsentAuditor> consent_auditor_;
std::unique_ptr<TestingPrefServiceSimple> pref_service_;
std::unique_ptr<syncer::FakeUserEventService> user_event_service_;
};
TEST_F(ConsentAuditorTest, LocalConsentPrefRepresentation) {
// No consents are written at first.
EXPECT_FALSE(pref_service()->HasPrefPath(prefs::kLocalConsentsDictionary));
// Record a consent and check that it appears in the prefs.
const std::string kFeature1Description = "This will enable feature 1.";
const std::string kFeature1Confirmation = "OK.";
consent_auditor()->RecordLocalConsent("feature1", kFeature1Description,
kFeature1Confirmation);
ASSERT_TRUE(pref_service()->HasPrefPath(prefs::kLocalConsentsDictionary));
const base::DictionaryValue* consents =
pref_service()->GetDictionary(prefs::kLocalConsentsDictionary);
ASSERT_TRUE(consents);
std::string description;
std::string confirmation;
std::string version;
std::string locale;
LoadEntriesFromLocalConsentRecord(consents, "feature1", &description,
&confirmation, &version, &locale);
EXPECT_EQ(kFeature1Description, description);
EXPECT_EQ(kFeature1Confirmation, confirmation);
EXPECT_EQ(kCurrentAppVersion, version);
EXPECT_EQ(kCurrentAppLocale, locale);
// Do the same for another feature.
const std::string kFeature2Description = "Enable feature 2?";
const std::string kFeature2Confirmation = "Yes.";
consent_auditor()->RecordLocalConsent("feature2", kFeature2Description,
kFeature2Confirmation);
LoadEntriesFromLocalConsentRecord(consents, "feature2", &description,
&confirmation, &version, &locale);
EXPECT_EQ(kFeature2Description, description);
EXPECT_EQ(kFeature2Confirmation, confirmation);
EXPECT_EQ(kCurrentAppVersion, version);
EXPECT_EQ(kCurrentAppLocale, locale);
// They are two separate records; the latter did not overwrite the former.
EXPECT_EQ(2u, consents->size());
EXPECT_TRUE(
consents->FindKeyOfType("feature1", base::Value::Type::DICTIONARY));
// Overwrite an existing consent, this time use a different product version
// and a different locale.
const std::string kFeature2NewDescription = "Re-enable feature 2?";
const std::string kFeature2NewConfirmation = "Yes again.";
const std::string kFeature2NewAppVersion = "5.6.7.8";
const std::string kFeature2NewAppLocale = "de";
UpdateAppVersionAndLocale(kFeature2NewAppVersion, kFeature2NewAppLocale);
consent_auditor()->RecordLocalConsent("feature2", kFeature2NewDescription,
kFeature2NewConfirmation);
LoadEntriesFromLocalConsentRecord(consents, "feature2", &description,
&confirmation, &version, &locale);
EXPECT_EQ(kFeature2NewDescription, description);
EXPECT_EQ(kFeature2NewConfirmation, confirmation);
EXPECT_EQ(kFeature2NewAppVersion, version);
EXPECT_EQ(kFeature2NewAppLocale, locale);
// We still have two records.
EXPECT_EQ(2u, consents->size());
}
} // namespace consent_auditor