component_updater_utils_unittest.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. // Copyright 2021 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/embedder_support/origin_trials/component_updater_utils.h"
  5. #include <string>
  6. #include <utility>
  7. #include "base/files/scoped_temp_dir.h"
  8. #include "base/values.h"
  9. #include "base/version.h"
  10. #include "components/component_updater/installer_policies/origin_trials_component_installer.h"
  11. #include "components/embedder_support/origin_trials/origin_trial_prefs.h"
  12. #include "components/embedder_support/origin_trials/pref_names.h"
  13. #include "components/prefs/scoped_user_pref_update.h"
  14. #include "components/prefs/testing_pref_service.h"
  15. #include "testing/gtest/include/gtest/gtest.h"
  16. #include "testing/platform_test.h"
  17. namespace {
  18. // Mirror the constants used in the component installer. Do not share the
  19. // constants, as want to catch inadvertent changes in the tests. The keys will
  20. // will be generated server-side, so any changes need to be intentional and
  21. // coordinated.
  22. static const char kManifestOriginTrialsKey[] = "origin-trials";
  23. static const char kManifestPublicKeyPath[] = "origin-trials.public-key";
  24. static const char kManifestDisabledFeaturesPath[] =
  25. "origin-trials.disabled-features";
  26. static const char kManifestDisabledTokensPath[] =
  27. "origin-trials.disabled-tokens";
  28. static const char kManifestDisabledTokenSignaturesPath[] =
  29. "origin-trials.disabled-tokens.signatures";
  30. static const char kExistingPublicKey[] = "existing public key";
  31. static const char kNewPublicKey[] = "new public key";
  32. static const char kExistingDisabledFeature[] = "already disabled";
  33. static const std::vector<std::string> kExistingDisabledFeatures = {
  34. kExistingDisabledFeature};
  35. static const char kNewDisabledFeature1[] = "newly disabled 1";
  36. static const char kNewDisabledFeature2[] = "newly disabled 2";
  37. static const std::vector<std::string> kNewDisabledFeatures = {
  38. kNewDisabledFeature1, kNewDisabledFeature2};
  39. static const char kExistingDisabledToken[] = "already disabled token";
  40. static const std::vector<std::string> kExistingDisabledTokens = {
  41. kExistingDisabledToken};
  42. static const char kNewDisabledToken1[] = "newly disabled token 1";
  43. static const char kNewDisabledToken2[] = "newly disabled token 2";
  44. static const std::vector<std::string> kNewDisabledTokens = {kNewDisabledToken1,
  45. kNewDisabledToken2};
  46. } // namespace
  47. namespace component_updater {
  48. class OriginTrialsComponentInstallerTest : public PlatformTest {
  49. public:
  50. OriginTrialsComponentInstallerTest() = default;
  51. OriginTrialsComponentInstallerTest(
  52. const OriginTrialsComponentInstallerTest&) = delete;
  53. OriginTrialsComponentInstallerTest& operator=(
  54. const OriginTrialsComponentInstallerTest&) = delete;
  55. void SetUp() override {
  56. PlatformTest::SetUp();
  57. ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
  58. embedder_support::OriginTrialPrefs::RegisterPrefs(local_state_.registry());
  59. policy_ = std::make_unique<OriginTrialsComponentInstallerPolicy>();
  60. }
  61. void LoadUpdates(base::Value manifest) {
  62. if (manifest.DictEmpty()) {
  63. manifest.SetKey(kManifestOriginTrialsKey, base::Value());
  64. }
  65. ASSERT_TRUE(policy_->VerifyInstallation(manifest, temp_dir_.GetPath()));
  66. embedder_support::ReadOriginTrialsConfigAndPopulateLocalState(
  67. local_state(), std::move(manifest));
  68. }
  69. void AddDisabledFeaturesToPrefs(const std::vector<std::string>& features) {
  70. base::Value disabled_feature_list(base::Value::Type::LIST);
  71. for (const std::string& feature : features) {
  72. disabled_feature_list.Append(feature);
  73. }
  74. ListPrefUpdate update(
  75. local_state(), embedder_support::prefs::kOriginTrialDisabledFeatures);
  76. *update = std::move(disabled_feature_list);
  77. }
  78. void CheckDisabledFeaturesPrefs(const std::vector<std::string>& features) {
  79. ASSERT_FALSE(features.empty());
  80. ASSERT_TRUE(local_state()->HasPrefPath(
  81. embedder_support::prefs::kOriginTrialDisabledFeatures));
  82. const base::Value::List& disabled_feature_list =
  83. local_state()->GetValueList(
  84. embedder_support::prefs::kOriginTrialDisabledFeatures);
  85. ASSERT_EQ(features.size(), disabled_feature_list.size());
  86. for (size_t i = 0; i < features.size(); ++i) {
  87. const std::string* disabled_feature =
  88. disabled_feature_list[i].GetIfString();
  89. if (!disabled_feature) {
  90. ADD_FAILURE() << "Entry not found or not a string at index " << i;
  91. continue;
  92. }
  93. EXPECT_EQ(features[i], *disabled_feature)
  94. << "Feature lists differ at index " << i;
  95. }
  96. }
  97. void AddDisabledTokensToPrefs(const std::vector<std::string>& tokens) {
  98. base::Value disabled_token_list(base::Value::Type::LIST);
  99. for (const std::string& token : tokens) {
  100. disabled_token_list.Append(token);
  101. }
  102. ListPrefUpdate update(local_state(),
  103. embedder_support::prefs::kOriginTrialDisabledTokens);
  104. *update = std::move(disabled_token_list);
  105. }
  106. void CheckDisabledTokensPrefs(const std::vector<std::string>& tokens) {
  107. ASSERT_FALSE(tokens.empty());
  108. ASSERT_TRUE(local_state()->HasPrefPath(
  109. embedder_support::prefs::kOriginTrialDisabledTokens));
  110. const base::Value::List& disabled_token_list = local_state()->GetValueList(
  111. embedder_support::prefs::kOriginTrialDisabledTokens);
  112. ASSERT_EQ(tokens.size(), disabled_token_list.size());
  113. for (size_t i = 0; i < tokens.size(); ++i) {
  114. const std::string* disabled_token = disabled_token_list[i].GetIfString();
  115. if (!disabled_token) {
  116. ADD_FAILURE() << "Entry not found or not a string at index " << i;
  117. continue;
  118. }
  119. EXPECT_EQ(tokens[i], *disabled_token)
  120. << "Token lists differ at index " << i;
  121. }
  122. }
  123. PrefService* local_state() { return &local_state_; }
  124. protected:
  125. base::ScopedTempDir temp_dir_;
  126. TestingPrefServiceSimple local_state_;
  127. std::unique_ptr<ComponentInstallerPolicy> policy_;
  128. };
  129. TEST_F(OriginTrialsComponentInstallerTest,
  130. PublicKeyResetToDefaultWhenOverrideMissing) {
  131. local_state()->SetString(embedder_support::prefs::kOriginTrialPublicKey,
  132. kExistingPublicKey);
  133. ASSERT_EQ(
  134. kExistingPublicKey,
  135. local_state()->GetString(embedder_support::prefs::kOriginTrialPublicKey));
  136. // Load with empty section in manifest
  137. LoadUpdates(base::Value(base::Value::Type::DICTIONARY));
  138. EXPECT_FALSE(local_state()->HasPrefPath(
  139. embedder_support::prefs::kOriginTrialPublicKey));
  140. }
  141. TEST_F(OriginTrialsComponentInstallerTest, PublicKeySetWhenOverrideExists) {
  142. ASSERT_FALSE(local_state()->HasPrefPath(
  143. embedder_support::prefs::kOriginTrialPublicKey));
  144. base::Value manifest(base::Value::Type::DICTIONARY);
  145. manifest.SetStringPath(kManifestPublicKeyPath, kNewPublicKey);
  146. LoadUpdates(std::move(manifest));
  147. EXPECT_EQ(kNewPublicKey, local_state()->GetString(
  148. embedder_support::prefs::kOriginTrialPublicKey));
  149. }
  150. TEST_F(OriginTrialsComponentInstallerTest,
  151. DisabledFeaturesResetToDefaultWhenListMissing) {
  152. AddDisabledFeaturesToPrefs(kExistingDisabledFeatures);
  153. ASSERT_TRUE(local_state()->HasPrefPath(
  154. embedder_support::prefs::kOriginTrialDisabledFeatures));
  155. // Load with empty section in manifest
  156. LoadUpdates(base::Value(base::Value::Type::DICTIONARY));
  157. EXPECT_FALSE(local_state()->HasPrefPath(
  158. embedder_support::prefs::kOriginTrialDisabledFeatures));
  159. }
  160. TEST_F(OriginTrialsComponentInstallerTest,
  161. DisabledFeaturesResetToDefaultWhenListEmpty) {
  162. AddDisabledFeaturesToPrefs(kExistingDisabledFeatures);
  163. ASSERT_TRUE(local_state()->HasPrefPath(
  164. embedder_support::prefs::kOriginTrialDisabledFeatures));
  165. base::Value manifest(base::Value::Type::DICTIONARY);
  166. base::ListValue disabled_feature_list;
  167. manifest.SetPath(kManifestDisabledFeaturesPath,
  168. std::move(disabled_feature_list));
  169. LoadUpdates(std::move(manifest));
  170. EXPECT_FALSE(local_state()->HasPrefPath(
  171. embedder_support::prefs::kOriginTrialDisabledFeatures));
  172. }
  173. TEST_F(OriginTrialsComponentInstallerTest, DisabledFeaturesSetWhenListExists) {
  174. ASSERT_FALSE(local_state()->HasPrefPath(
  175. embedder_support::prefs::kOriginTrialDisabledFeatures));
  176. base::Value manifest(base::Value::Type::DICTIONARY);
  177. base::ListValue disabled_feature_list;
  178. disabled_feature_list.Append(kNewDisabledFeature1);
  179. manifest.SetPath(kManifestDisabledFeaturesPath,
  180. std::move(disabled_feature_list));
  181. LoadUpdates(std::move(manifest));
  182. std::vector<std::string> features = {kNewDisabledFeature1};
  183. CheckDisabledFeaturesPrefs(features);
  184. }
  185. TEST_F(OriginTrialsComponentInstallerTest,
  186. DisabledFeaturesReplacedWhenListExists) {
  187. AddDisabledFeaturesToPrefs(kExistingDisabledFeatures);
  188. ASSERT_TRUE(local_state()->HasPrefPath(
  189. embedder_support::prefs::kOriginTrialDisabledFeatures));
  190. base::Value manifest(base::Value::Type::DICTIONARY);
  191. base::ListValue disabled_feature_list;
  192. for (const std::string& feature : kNewDisabledFeatures) {
  193. disabled_feature_list.Append(feature);
  194. }
  195. manifest.SetPath(kManifestDisabledFeaturesPath,
  196. std::move(disabled_feature_list));
  197. LoadUpdates(std::move(manifest));
  198. CheckDisabledFeaturesPrefs(kNewDisabledFeatures);
  199. }
  200. TEST_F(OriginTrialsComponentInstallerTest,
  201. DisabledTokensResetToDefaultWhenListMissing) {
  202. AddDisabledTokensToPrefs(kExistingDisabledTokens);
  203. ASSERT_TRUE(local_state()->HasPrefPath(
  204. embedder_support::prefs::kOriginTrialDisabledTokens));
  205. // Load with empty section in manifest
  206. LoadUpdates(base::Value(base::Value::Type::DICTIONARY));
  207. EXPECT_FALSE(local_state()->HasPrefPath(
  208. embedder_support::prefs::kOriginTrialDisabledTokens));
  209. }
  210. TEST_F(OriginTrialsComponentInstallerTest,
  211. DisabledTokensResetToDefaultWhenKeyExistsAndListMissing) {
  212. AddDisabledTokensToPrefs(kExistingDisabledTokens);
  213. ASSERT_TRUE(local_state()->HasPrefPath(
  214. embedder_support::prefs::kOriginTrialDisabledTokens));
  215. // Load with disabled tokens key in manifest, but no list values
  216. base::Value manifest(base::Value::Type::DICTIONARY);
  217. manifest.SetPath(kManifestDisabledTokensPath, base::Value());
  218. LoadUpdates(std::move(manifest));
  219. EXPECT_FALSE(local_state()->HasPrefPath(
  220. embedder_support::prefs::kOriginTrialDisabledTokens));
  221. }
  222. TEST_F(OriginTrialsComponentInstallerTest,
  223. DisabledTokensResetToDefaultWhenListEmpty) {
  224. AddDisabledTokensToPrefs(kExistingDisabledTokens);
  225. ASSERT_TRUE(local_state()->HasPrefPath(
  226. embedder_support::prefs::kOriginTrialDisabledTokens));
  227. base::Value manifest(base::Value::Type::DICTIONARY);
  228. base::ListValue disabled_token_list;
  229. manifest.SetPath(kManifestDisabledTokenSignaturesPath,
  230. std::move(disabled_token_list));
  231. LoadUpdates(std::move(manifest));
  232. EXPECT_FALSE(local_state()->HasPrefPath(
  233. embedder_support::prefs::kOriginTrialDisabledTokens));
  234. }
  235. TEST_F(OriginTrialsComponentInstallerTest, DisabledTokensSetWhenListExists) {
  236. ASSERT_FALSE(local_state()->HasPrefPath(
  237. embedder_support::prefs::kOriginTrialDisabledTokens));
  238. base::Value manifest(base::Value::Type::DICTIONARY);
  239. base::ListValue disabled_token_list;
  240. disabled_token_list.Append(kNewDisabledToken1);
  241. manifest.SetPath(kManifestDisabledTokenSignaturesPath,
  242. std::move(disabled_token_list));
  243. LoadUpdates(std::move(manifest));
  244. std::vector<std::string> tokens = {kNewDisabledToken1};
  245. CheckDisabledTokensPrefs(tokens);
  246. }
  247. TEST_F(OriginTrialsComponentInstallerTest,
  248. DisabledTokensReplacedWhenListExists) {
  249. AddDisabledTokensToPrefs(kExistingDisabledTokens);
  250. ASSERT_TRUE(local_state()->HasPrefPath(
  251. embedder_support::prefs::kOriginTrialDisabledTokens));
  252. base::Value manifest(base::Value::Type::DICTIONARY);
  253. base::ListValue disabled_token_list;
  254. for (const std::string& token : kNewDisabledTokens) {
  255. disabled_token_list.Append(token);
  256. }
  257. manifest.SetPath(kManifestDisabledTokenSignaturesPath,
  258. std::move(disabled_token_list));
  259. LoadUpdates(std::move(manifest));
  260. CheckDisabledTokensPrefs(kNewDisabledTokens);
  261. }
  262. } // namespace component_updater