consent_auditor_impl_unittest.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. // Copyright 2018 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/consent_auditor/consent_auditor_impl.h"
  5. #include <array>
  6. #include <memory>
  7. #include <string>
  8. #include <utility>
  9. #include <vector>
  10. #include "base/hash/sha1.h"
  11. #include "base/memory/raw_ptr.h"
  12. #include "base/memory/weak_ptr.h"
  13. #include "base/test/simple_test_clock.h"
  14. #include "base/time/default_clock.h"
  15. #include "base/time/time.h"
  16. #include "components/consent_auditor/pref_names.h"
  17. #include "components/prefs/testing_pref_service.h"
  18. #include "components/sync/protocol/user_consent_specifics.pb.h"
  19. #include "components/sync/test/fake_model_type_controller_delegate.h"
  20. #include "testing/gmock/include/gmock/gmock.h"
  21. #include "testing/gtest/include/gtest/gtest.h"
  22. using ArcPlayTermsOfServiceConsent =
  23. sync_pb::UserConsentTypes::ArcPlayTermsOfServiceConsent;
  24. using AssistantActivityControlConsent =
  25. sync_pb::UserConsentTypes::AssistantActivityControlConsent;
  26. using AutofillAssistantConsent =
  27. sync_pb::UserConsentTypes::AutofillAssistantConsent;
  28. using SyncConsent = sync_pb::UserConsentTypes::SyncConsent;
  29. using sync_pb::UserConsentSpecifics;
  30. using sync_pb::UserConsentTypes;
  31. using ::testing::ElementsAreArray;
  32. namespace consent_auditor {
  33. namespace {
  34. constexpr char kLocalConsentDescriptionKey[] = "description";
  35. constexpr char kLocalConsentConfirmationKey[] = "confirmation";
  36. constexpr char kLocalConsentVersionKey[] = "version";
  37. constexpr char kLocalConsentLocaleKey[] = "locale";
  38. // Fake product version for testing.
  39. constexpr char kCurrentAppVersion[] = "1.2.3.4";
  40. constexpr char kCurrentAppLocale[] = "en-US";
  41. // Fake message ids.
  42. constexpr std::array<int, 3> kDescriptionMessageIds = {12, 37, 42};
  43. constexpr int kConfirmationMessageId = 47;
  44. // A helper function to load the |description|, |confirmation|, |version|,
  45. // and |locale|, in that order, from a record for the |feature| in
  46. // the |consents| dictionary.
  47. void LoadEntriesFromLocalConsentRecord(const base::Value* consents,
  48. const std::string& feature,
  49. std::string* description,
  50. std::string* confirmation,
  51. std::string* version,
  52. std::string* locale) {
  53. SCOPED_TRACE(::testing::Message() << "|feature| = " << feature);
  54. const base::Value* record =
  55. consents->FindKeyOfType(feature, base::Value::Type::DICTIONARY);
  56. ASSERT_TRUE(record);
  57. SCOPED_TRACE(::testing::Message() << "|record| = " << record);
  58. const base::Value* description_entry =
  59. record->FindKey(kLocalConsentDescriptionKey);
  60. const base::Value* confirmation_entry =
  61. record->FindKey(kLocalConsentConfirmationKey);
  62. const base::Value* version_entry = record->FindKey(kLocalConsentVersionKey);
  63. const base::Value* locale_entry = record->FindKey(kLocalConsentLocaleKey);
  64. ASSERT_TRUE(description_entry);
  65. ASSERT_TRUE(confirmation_entry);
  66. ASSERT_TRUE(version_entry);
  67. ASSERT_TRUE(locale_entry);
  68. *description = description_entry->GetString();
  69. *confirmation = confirmation_entry->GetString();
  70. *version = version_entry->GetString();
  71. *locale = locale_entry->GetString();
  72. }
  73. class FakeConsentSyncBridge : public ConsentSyncBridge {
  74. public:
  75. ~FakeConsentSyncBridge() override = default;
  76. // ConsentSyncBridge implementation.
  77. void RecordConsent(
  78. std::unique_ptr<sync_pb::UserConsentSpecifics> specifics) override {
  79. DCHECK(specifics);
  80. recorded_user_consents_.push_back(*specifics);
  81. }
  82. base::WeakPtr<syncer::ModelTypeControllerDelegate> GetControllerDelegate()
  83. override {
  84. return delegate_;
  85. }
  86. // Fake methods.
  87. void SetControllerDelegate(
  88. base::WeakPtr<syncer::ModelTypeControllerDelegate> delegate) {
  89. delegate_ = delegate;
  90. }
  91. const std::vector<UserConsentSpecifics>& GetRecordedUserConsents() const {
  92. return recorded_user_consents_;
  93. }
  94. private:
  95. base::WeakPtr<syncer::ModelTypeControllerDelegate> delegate_;
  96. std::vector<UserConsentSpecifics> recorded_user_consents_;
  97. };
  98. } // namespace
  99. class ConsentAuditorImplTest : public testing::Test {
  100. public:
  101. // Fake account ID for testing.
  102. const CoreAccountId kAccountId;
  103. ConsentAuditorImplTest() : kAccountId("testing_account_id") {}
  104. void SetUp() override {
  105. pref_service_ = std::make_unique<TestingPrefServiceSimple>();
  106. ConsentAuditorImpl::RegisterProfilePrefs(pref_service_->registry());
  107. CreateConsentAuditorImpl(std::make_unique<FakeConsentSyncBridge>());
  108. }
  109. void CreateConsentAuditorImpl(
  110. std::unique_ptr<FakeConsentSyncBridge> bridge,
  111. const std::string& app_version = kCurrentAppVersion,
  112. const std::string& app_locale = kCurrentAppLocale) {
  113. consent_sync_bridge_ = bridge.get();
  114. consent_auditor_ = std::make_unique<ConsentAuditorImpl>(
  115. pref_service_.get(), std::move(bridge), app_version, app_locale,
  116. clock());
  117. }
  118. base::SimpleTestClock* clock() { return &test_clock_; }
  119. ConsentAuditorImpl* consent_auditor() { return consent_auditor_.get(); }
  120. FakeConsentSyncBridge* consent_sync_bridge() {
  121. return consent_sync_bridge_.get();
  122. }
  123. PrefService* pref_service() const { return pref_service_.get(); }
  124. private:
  125. // Test helpers.
  126. std::unique_ptr<TestingPrefServiceSimple> pref_service_;
  127. base::SimpleTestClock test_clock_;
  128. raw_ptr<FakeConsentSyncBridge> consent_sync_bridge_ = nullptr;
  129. // Test object to be tested.
  130. std::unique_ptr<ConsentAuditorImpl> consent_auditor_;
  131. };
  132. TEST_F(ConsentAuditorImplTest, LocalConsentPrefRepresentation) {
  133. // No consents are written at first.
  134. EXPECT_FALSE(pref_service()->HasPrefPath(prefs::kLocalConsentsDictionary));
  135. // Record a consent and check that it appears in the prefs.
  136. const std::string kFeature1Description = "This will enable feature 1.";
  137. const std::string kFeature1Confirmation = "OK.";
  138. consent_auditor()->RecordLocalConsent("feature1", kFeature1Description,
  139. kFeature1Confirmation);
  140. ASSERT_TRUE(pref_service()->HasPrefPath(prefs::kLocalConsentsDictionary));
  141. const base::Value* consents =
  142. pref_service()->GetDictionary(prefs::kLocalConsentsDictionary);
  143. ASSERT_TRUE(consents);
  144. std::string description, confirmation, version, locale;
  145. LoadEntriesFromLocalConsentRecord(consents, "feature1", &description,
  146. &confirmation, &version, &locale);
  147. EXPECT_EQ(kFeature1Description, description);
  148. EXPECT_EQ(kFeature1Confirmation, confirmation);
  149. EXPECT_EQ(kCurrentAppVersion, version);
  150. EXPECT_EQ(kCurrentAppLocale, locale);
  151. // Do the same for another feature.
  152. const std::string kFeature2Description = "Enable feature 2?";
  153. const std::string kFeature2Confirmation = "Yes.";
  154. consent_auditor()->RecordLocalConsent("feature2", kFeature2Description,
  155. kFeature2Confirmation);
  156. LoadEntriesFromLocalConsentRecord(consents, "feature2", &description,
  157. &confirmation, &version, &locale);
  158. EXPECT_EQ(kFeature2Description, description);
  159. EXPECT_EQ(kFeature2Confirmation, confirmation);
  160. EXPECT_EQ(kCurrentAppVersion, version);
  161. EXPECT_EQ(kCurrentAppLocale, locale);
  162. // They are two separate records; the latter did not overwrite the former.
  163. EXPECT_EQ(2u, consents->DictSize());
  164. EXPECT_TRUE(
  165. consents->FindKeyOfType("feature1", base::Value::Type::DICTIONARY));
  166. // Overwrite an existing consent, this time use a different product version
  167. // and a different locale.
  168. const std::string kFeature2NewDescription = "Re-enable feature 2?";
  169. const std::string kFeature2NewConfirmation = "Yes again.";
  170. const std::string kFeature2NewAppVersion = "5.6.7.8";
  171. const std::string kFeature2NewAppLocale = "de";
  172. // We rebuild consent auditor to emulate restarting Chrome. This is the only
  173. // way to change app version or app locale.
  174. CreateConsentAuditorImpl(std::make_unique<FakeConsentSyncBridge>(),
  175. kFeature2NewAppVersion, kFeature2NewAppLocale);
  176. consent_auditor()->RecordLocalConsent("feature2", kFeature2NewDescription,
  177. kFeature2NewConfirmation);
  178. LoadEntriesFromLocalConsentRecord(consents, "feature2", &description,
  179. &confirmation, &version, &locale);
  180. EXPECT_EQ(kFeature2NewDescription, description);
  181. EXPECT_EQ(kFeature2NewConfirmation, confirmation);
  182. EXPECT_EQ(kFeature2NewAppVersion, version);
  183. EXPECT_EQ(kFeature2NewAppLocale, locale);
  184. // We still have two records.
  185. EXPECT_EQ(2u, consents->DictSize());
  186. }
  187. TEST_F(ConsentAuditorImplTest, RecordGaiaConsentAsUserConsent) {
  188. base::Time now;
  189. ASSERT_TRUE(base::Time::FromUTCString("2017-11-14T15:15:38Z", &now));
  190. clock()->SetNow(now);
  191. SyncConsent sync_consent;
  192. sync_consent.set_status(UserConsentTypes::GIVEN);
  193. sync_consent.set_confirmation_grd_id(kConfirmationMessageId);
  194. for (int id : kDescriptionMessageIds) {
  195. sync_consent.add_description_grd_ids(id);
  196. }
  197. consent_auditor()->RecordSyncConsent(kAccountId, sync_consent);
  198. std::vector<UserConsentSpecifics> consents =
  199. consent_sync_bridge()->GetRecordedUserConsents();
  200. ASSERT_EQ(1U, consents.size());
  201. const UserConsentSpecifics& consent = consents[0];
  202. EXPECT_EQ(now.since_origin().InMicroseconds(),
  203. consent.client_consent_time_usec());
  204. EXPECT_EQ(kAccountId.ToString(), consent.account_id());
  205. EXPECT_EQ(kCurrentAppLocale, consent.locale());
  206. EXPECT_TRUE(consent.has_sync_consent());
  207. const SyncConsent& actual_sync_consent = consent.sync_consent();
  208. EXPECT_THAT(actual_sync_consent.description_grd_ids(),
  209. ElementsAreArray(kDescriptionMessageIds));
  210. EXPECT_EQ(actual_sync_consent.confirmation_grd_id(), kConfirmationMessageId);
  211. }
  212. TEST_F(ConsentAuditorImplTest, RecordArcPlayConsentRevocation) {
  213. base::Time now;
  214. ASSERT_TRUE(base::Time::FromUTCString("2017-11-14T15:15:38Z", &now));
  215. clock()->SetNow(now);
  216. ArcPlayTermsOfServiceConsent play_consent;
  217. play_consent.set_status(UserConsentTypes::NOT_GIVEN);
  218. play_consent.set_confirmation_grd_id(kConfirmationMessageId);
  219. for (int id : kDescriptionMessageIds) {
  220. play_consent.add_description_grd_ids(id);
  221. }
  222. play_consent.set_consent_flow(ArcPlayTermsOfServiceConsent::SETTING_CHANGE);
  223. consent_auditor()->RecordArcPlayConsent(kAccountId, play_consent);
  224. const std::vector<UserConsentSpecifics> consents =
  225. consent_sync_bridge()->GetRecordedUserConsents();
  226. ASSERT_EQ(1U, consents.size());
  227. const UserConsentSpecifics& consent = consents[0];
  228. EXPECT_EQ(kAccountId.ToString(), consent.account_id());
  229. EXPECT_EQ(kCurrentAppLocale, consent.locale());
  230. EXPECT_TRUE(consent.has_arc_play_terms_of_service_consent());
  231. const ArcPlayTermsOfServiceConsent& actual_play_consent =
  232. consent.arc_play_terms_of_service_consent();
  233. EXPECT_EQ(UserConsentTypes::NOT_GIVEN, actual_play_consent.status());
  234. EXPECT_EQ(ArcPlayTermsOfServiceConsent::SETTING_CHANGE,
  235. actual_play_consent.consent_flow());
  236. EXPECT_THAT(actual_play_consent.description_grd_ids(),
  237. ElementsAreArray(kDescriptionMessageIds));
  238. EXPECT_EQ(kConfirmationMessageId, actual_play_consent.confirmation_grd_id());
  239. }
  240. TEST_F(ConsentAuditorImplTest, RecordArcPlayConsent) {
  241. base::Time now;
  242. ASSERT_TRUE(base::Time::FromUTCString("2017-11-14T15:15:38Z", &now));
  243. clock()->SetNow(now);
  244. ArcPlayTermsOfServiceConsent play_consent;
  245. play_consent.set_status(UserConsentTypes::GIVEN);
  246. play_consent.set_confirmation_grd_id(kConfirmationMessageId);
  247. play_consent.set_consent_flow(ArcPlayTermsOfServiceConsent::SETUP);
  248. // Verify the hash: 2fd4e1c6 7a2d28fc ed849ee1 bb76e739 1b93eb12.
  249. const uint8_t play_tos_hash[] = {0x2f, 0xd4, 0xe1, 0xc6, 0x7a, 0x2d, 0x28,
  250. 0xfc, 0xed, 0x84, 0x9e, 0xe1, 0xbb, 0x76,
  251. 0xe7, 0x39, 0x1b, 0x93, 0xeb, 0x12};
  252. play_consent.set_play_terms_of_service_hash(std::string(
  253. reinterpret_cast<const char*>(play_tos_hash), base::kSHA1Length));
  254. play_consent.set_play_terms_of_service_text_length(7);
  255. consent_auditor()->RecordArcPlayConsent(kAccountId, play_consent);
  256. const std::vector<UserConsentSpecifics> consents =
  257. consent_sync_bridge()->GetRecordedUserConsents();
  258. ASSERT_EQ(1U, consents.size());
  259. const UserConsentSpecifics& consent = consents[0];
  260. EXPECT_EQ(kAccountId.ToString(), consent.account_id());
  261. EXPECT_EQ(kCurrentAppLocale, consent.locale());
  262. EXPECT_TRUE(consent.has_arc_play_terms_of_service_consent());
  263. const ArcPlayTermsOfServiceConsent& actual_play_consent =
  264. consent.arc_play_terms_of_service_consent();
  265. EXPECT_EQ(7, actual_play_consent.play_terms_of_service_text_length());
  266. EXPECT_EQ(std::string(reinterpret_cast<const char*>(play_tos_hash),
  267. base::kSHA1Length),
  268. actual_play_consent.play_terms_of_service_hash());
  269. EXPECT_EQ(kConfirmationMessageId, actual_play_consent.confirmation_grd_id());
  270. EXPECT_EQ(ArcPlayTermsOfServiceConsent::SETUP,
  271. actual_play_consent.consent_flow());
  272. EXPECT_EQ(UserConsentTypes::GIVEN, actual_play_consent.status());
  273. }
  274. TEST_F(ConsentAuditorImplTest, ShouldReturnSyncDelegateWhenBridgePresent) {
  275. auto fake_bridge = std::make_unique<FakeConsentSyncBridge>();
  276. syncer::FakeModelTypeControllerDelegate fake_delegate(
  277. syncer::ModelType::USER_CONSENTS);
  278. auto expected_delegate_ptr = fake_delegate.GetWeakPtr();
  279. DCHECK(expected_delegate_ptr);
  280. fake_bridge->SetControllerDelegate(expected_delegate_ptr);
  281. CreateConsentAuditorImpl(std::move(fake_bridge));
  282. // There is a bridge (i.e. separate sync type for consents is enabled), thus,
  283. // there should be a delegate as well.
  284. EXPECT_EQ(expected_delegate_ptr.get(),
  285. consent_auditor()->GetControllerDelegate().get());
  286. }
  287. TEST_F(ConsentAuditorImplTest, RecordAssistantActivityControlConsent) {
  288. constexpr char ui_audit_key[] = {0x67, 0x23, 0x78};
  289. AssistantActivityControlConsent assistant_consent;
  290. assistant_consent.set_status(UserConsentTypes::GIVEN);
  291. assistant_consent.set_ui_audit_key(std::string(ui_audit_key, 3));
  292. assistant_consent.set_setting_type(AssistantActivityControlConsent::ALL);
  293. consent_auditor()->RecordAssistantActivityControlConsent(kAccountId,
  294. assistant_consent);
  295. std::vector<UserConsentSpecifics> consents =
  296. consent_sync_bridge()->GetRecordedUserConsents();
  297. ASSERT_EQ(consents.size(), 1u);
  298. const UserConsentSpecifics& consent = consents[0];
  299. EXPECT_EQ(kAccountId.ToString(), consent.account_id());
  300. EXPECT_EQ(kCurrentAppLocale, consent.locale());
  301. EXPECT_TRUE(consent.has_assistant_activity_control_consent());
  302. EXPECT_EQ(UserConsentTypes::GIVEN,
  303. consent.assistant_activity_control_consent().status());
  304. EXPECT_EQ(std::string(ui_audit_key, 3),
  305. consent.assistant_activity_control_consent().ui_audit_key());
  306. EXPECT_EQ(AssistantActivityControlConsent::ALL,
  307. consent.assistant_activity_control_consent().setting_type());
  308. }
  309. TEST_F(ConsentAuditorImplTest, RecordAutofillAssistantAssistantConsent) {
  310. AutofillAssistantConsent assistant_consent;
  311. assistant_consent.set_status(UserConsentTypes::GIVEN);
  312. assistant_consent.set_confirmation_grd_id(kConfirmationMessageId);
  313. for (int id : kDescriptionMessageIds) {
  314. assistant_consent.add_description_grd_ids(id);
  315. }
  316. consent_auditor()->RecordAutofillAssistantConsent(kAccountId,
  317. assistant_consent);
  318. const std::vector<UserConsentSpecifics> consents =
  319. consent_sync_bridge()->GetRecordedUserConsents();
  320. ASSERT_EQ(consents.size(), 1u);
  321. const UserConsentSpecifics& consent = consents[0];
  322. EXPECT_EQ(consent.account_id(), kAccountId.ToString());
  323. EXPECT_EQ(consent.locale(), kCurrentAppLocale);
  324. EXPECT_TRUE(consent.has_autofill_assistant_consent());
  325. const AutofillAssistantConsent& actual_consent =
  326. consent.autofill_assistant_consent();
  327. EXPECT_THAT(actual_consent.description_grd_ids(),
  328. ElementsAreArray(kDescriptionMessageIds));
  329. EXPECT_EQ(actual_consent.confirmation_grd_id(), kConfirmationMessageId);
  330. EXPECT_EQ(actual_consent.status(), UserConsentTypes::GIVEN);
  331. }
  332. } // namespace consent_auditor