component_loader_policy_unittests.cc 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  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 "base/memory/raw_ptr.h"
  5. #include "components/component_updater/android/component_loader_policy.h"
  6. #include <fcntl.h>
  7. #include <jni.h>
  8. #include <stdint.h>
  9. #include <iterator>
  10. #include <memory>
  11. #include <string>
  12. #include <utility>
  13. #include <vector>
  14. #include "base/android/jni_android.h"
  15. #include "base/android/jni_array.h"
  16. #include "base/android/jni_string.h"
  17. #include "base/android/scoped_java_ref.h"
  18. #include "base/callback.h"
  19. #include "base/callback_helpers.h"
  20. #include "base/containers/flat_map.h"
  21. #include "base/files/file_path.h"
  22. #include "base/files/file_util.h"
  23. #include "base/files/scoped_file.h"
  24. #include "base/files/scoped_temp_dir.h"
  25. #include "base/run_loop.h"
  26. #include "base/test/bind.h"
  27. #include "base/test/metrics/histogram_tester.h"
  28. #include "base/test/task_environment.h"
  29. #include "base/values.h"
  30. #include "base/version.h"
  31. #include "testing/gtest/include/gtest/gtest.h"
  32. namespace component_updater {
  33. namespace {
  34. constexpr char kComponentId[] = "jebgalgnebhfojomionfpkfelancnnkf";
  35. // This hash corresponds to kComponentId.
  36. constexpr uint8_t kSha256Hash[] = {
  37. 0x94, 0x16, 0x0b, 0x6d, 0x41, 0x75, 0xe9, 0xec, 0x8e, 0xd5, 0xfa,
  38. 0x54, 0xb0, 0xd2, 0xdd, 0xa5, 0x6e, 0x05, 0x6b, 0xe8, 0x73, 0x47,
  39. 0xf6, 0xc4, 0x11, 0x9f, 0xbc, 0xb3, 0x09, 0xb3, 0x5b, 0x40};
  40. constexpr char kMockComponentHistogramName[] =
  41. "ComponentUpdater.AndroidComponentLoader.LoadStatus.MockComponent";
  42. void GetPkHash(std::vector<uint8_t>* hash) {
  43. hash->assign(std::begin(kSha256Hash), std::end(kSha256Hash));
  44. }
  45. std::vector<int> OpenFileFds(const base::FilePath& base,
  46. const std::vector<std::string>& files) {
  47. std::vector<int> fds;
  48. for (const std::string& file : files) {
  49. base::FilePath path = base.AppendASCII(file);
  50. fds.push_back(open(path.MaybeAsASCII().c_str(), O_RDONLY));
  51. }
  52. return fds;
  53. }
  54. using OnLoadedTestCallBack =
  55. base::OnceCallback<void(const base::Version&,
  56. base::flat_map<std::string, base::ScopedFD>&,
  57. std::unique_ptr<base::DictionaryValue>)>;
  58. using OnFailedTestCallBack = base::OnceCallback<void(ComponentLoadResult)>;
  59. class MockLoaderPolicy : public ComponentLoaderPolicy {
  60. public:
  61. explicit MockLoaderPolicy(OnLoadedTestCallBack on_loaded,
  62. OnFailedTestCallBack on_failed)
  63. : on_loaded_(std::move(on_loaded)), on_failed_(std::move(on_failed)) {}
  64. MockLoaderPolicy()
  65. : on_loaded_(base::DoNothing()), on_failed_(base::DoNothing()) {}
  66. ~MockLoaderPolicy() override = default;
  67. MockLoaderPolicy(const MockLoaderPolicy&) = delete;
  68. MockLoaderPolicy& operator=(const MockLoaderPolicy&) = delete;
  69. void ComponentLoaded(
  70. const base::Version& version,
  71. base::flat_map<std::string, base::ScopedFD>& fd_map,
  72. std::unique_ptr<base::DictionaryValue> manifest) override {
  73. std::move(on_loaded_).Run(version, fd_map, std::move(manifest));
  74. }
  75. void ComponentLoadFailed(ComponentLoadResult error) override {
  76. std::move(on_failed_).Run(error);
  77. }
  78. void GetHash(std::vector<uint8_t>* hash) const override { GetPkHash(hash); }
  79. std::string GetMetricsSuffix() const override { return "MockComponent"; }
  80. private:
  81. OnLoadedTestCallBack on_loaded_;
  82. OnFailedTestCallBack on_failed_;
  83. };
  84. void VerifyComponentLoaded(base::OnceClosure on_done,
  85. const base::Version& version,
  86. base::flat_map<std::string, base::ScopedFD>& fd_map,
  87. std::unique_ptr<base::DictionaryValue> manifest) {
  88. EXPECT_EQ(version.GetString(), "123.456.789");
  89. EXPECT_EQ(fd_map.size(), 2u);
  90. EXPECT_NE(fd_map.find("file1.txt"), fd_map.end());
  91. EXPECT_NE(fd_map.find("file2.txt"), fd_map.end());
  92. std::move(on_done).Run();
  93. }
  94. } // namespace
  95. class AndroidComponentLoaderPolicyTest : public testing::Test {
  96. public:
  97. AndroidComponentLoaderPolicyTest() = default;
  98. ~AndroidComponentLoaderPolicyTest() override = default;
  99. AndroidComponentLoaderPolicyTest(const AndroidComponentLoaderPolicyTest&) =
  100. delete;
  101. AndroidComponentLoaderPolicyTest& operator=(
  102. const AndroidComponentLoaderPolicyTest&) = delete;
  103. void SetUp() override {
  104. env_ = base::android::AttachCurrentThread();
  105. ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
  106. }
  107. protected:
  108. void WriteFile(const std::string& file_name, const std::string& content) {
  109. ASSERT_TRUE(
  110. base::WriteFile(temp_dir_.GetPath().AppendASCII(file_name), content));
  111. files_.push_back(file_name);
  112. }
  113. std::vector<int> GetFileFds() const {
  114. return OpenFileFds(temp_dir_.GetPath(), files_);
  115. }
  116. raw_ptr<JNIEnv> env_ = nullptr;
  117. std::vector<std::string> files_;
  118. base::HistogramTester histogram_tester_;
  119. private:
  120. base::ScopedTempDir temp_dir_;
  121. };
  122. TEST_F(AndroidComponentLoaderPolicyTest, TestValidManifest) {
  123. base::test::TaskEnvironment task_environment;
  124. WriteFile("file1.txt", "1");
  125. WriteFile("file2.txt", "2");
  126. WriteFile("manifest.json",
  127. "{\n\"manifest_version\": 2,\n\"version\": \"123.456.789\"\n}");
  128. base::RunLoop run_loop;
  129. auto* android_policy =
  130. new AndroidComponentLoaderPolicy(std::make_unique<MockLoaderPolicy>(
  131. base::BindOnce(&VerifyComponentLoaded, run_loop.QuitClosure()),
  132. base::BindOnce([](ComponentLoadResult) { FAIL(); })));
  133. android_policy->ComponentLoaded(
  134. env_, base::android::ToJavaArrayOfStrings(env_, files_),
  135. base::android::ToJavaIntArray(env_, GetFileFds()));
  136. run_loop.Run();
  137. histogram_tester_.ExpectBucketCount(kMockComponentHistogramName,
  138. ComponentLoadResult::kComponentLoaded, 1);
  139. histogram_tester_.ExpectTotalCount(kMockComponentHistogramName, 1);
  140. }
  141. TEST_F(AndroidComponentLoaderPolicyTest, TestMissingManifest) {
  142. base::test::TaskEnvironment task_environment;
  143. WriteFile("file.txt", "test");
  144. base::RunLoop run_loop;
  145. auto* android_policy =
  146. new AndroidComponentLoaderPolicy(std::make_unique<MockLoaderPolicy>(
  147. base::BindOnce(
  148. [](const base::Version& version,
  149. base::flat_map<std::string, base::ScopedFD>& fd_map,
  150. std::unique_ptr<base::DictionaryValue> manifest) { FAIL(); }),
  151. base::BindLambdaForTesting([&](ComponentLoadResult error) {
  152. ASSERT_EQ(error, ComponentLoadResult::kMissingManifest);
  153. run_loop.Quit();
  154. })));
  155. android_policy->ComponentLoaded(
  156. env_, base::android::ToJavaArrayOfStrings(env_, files_),
  157. base::android::ToJavaIntArray(env_, GetFileFds()));
  158. run_loop.Run();
  159. histogram_tester_.ExpectBucketCount(kMockComponentHistogramName,
  160. ComponentLoadResult::kMissingManifest, 1);
  161. histogram_tester_.ExpectTotalCount(kMockComponentHistogramName, 1);
  162. }
  163. TEST_F(AndroidComponentLoaderPolicyTest, TestInvalidVersion) {
  164. base::test::TaskEnvironment task_environment;
  165. WriteFile("file.txt", "test");
  166. WriteFile("manifest.json",
  167. "{\n\"manifest_version\": 2,\n\"version\": \"\"\n}");
  168. base::RunLoop run_loop;
  169. auto* android_policy =
  170. new AndroidComponentLoaderPolicy(std::make_unique<MockLoaderPolicy>(
  171. base::BindOnce(
  172. [](const base::Version& version,
  173. base::flat_map<std::string, base::ScopedFD>& fd_map,
  174. std::unique_ptr<base::DictionaryValue> manifest) { FAIL(); }),
  175. base::BindLambdaForTesting([&](ComponentLoadResult error) {
  176. ASSERT_EQ(error, ComponentLoadResult::kInvalidVersion);
  177. run_loop.Quit();
  178. })));
  179. android_policy->ComponentLoaded(
  180. env_, base::android::ToJavaArrayOfStrings(env_, files_),
  181. base::android::ToJavaIntArray(env_, GetFileFds()));
  182. run_loop.Run();
  183. histogram_tester_.ExpectBucketCount(kMockComponentHistogramName,
  184. ComponentLoadResult::kInvalidVersion, 1);
  185. histogram_tester_.ExpectTotalCount(kMockComponentHistogramName, 1);
  186. }
  187. TEST_F(AndroidComponentLoaderPolicyTest, TestInvalidManifest) {
  188. base::test::TaskEnvironment task_environment;
  189. WriteFile("file.txt", "test");
  190. WriteFile("manifest.json", "{\n\"manifest_version\":}");
  191. base::RunLoop run_loop;
  192. auto* android_policy =
  193. new AndroidComponentLoaderPolicy(std::make_unique<MockLoaderPolicy>(
  194. base::BindOnce(
  195. [](const base::Version& version,
  196. base::flat_map<std::string, base::ScopedFD>& fd_map,
  197. std::unique_ptr<base::DictionaryValue> manifest) { FAIL(); }),
  198. base::BindLambdaForTesting([&](ComponentLoadResult error) {
  199. ASSERT_EQ(error, ComponentLoadResult::kMalformedManifest);
  200. run_loop.Quit();
  201. })));
  202. android_policy->ComponentLoaded(
  203. env_, base::android::ToJavaArrayOfStrings(env_, files_),
  204. base::android::ToJavaIntArray(env_, GetFileFds()));
  205. run_loop.Run();
  206. histogram_tester_.ExpectBucketCount(
  207. kMockComponentHistogramName, ComponentLoadResult::kMalformedManifest, 1);
  208. histogram_tester_.ExpectTotalCount(kMockComponentHistogramName, 1);
  209. }
  210. TEST_F(AndroidComponentLoaderPolicyTest, TestGetComponentId) {
  211. base::test::TaskEnvironment task_environment;
  212. auto* android_policy =
  213. new AndroidComponentLoaderPolicy(std::make_unique<MockLoaderPolicy>());
  214. base::android::ScopedJavaLocalRef<jstring> jcomponentId =
  215. android_policy->GetComponentId(env_);
  216. EXPECT_EQ(base::android::ConvertJavaStringToUTF8(jcomponentId), kComponentId);
  217. }
  218. } // namespace component_updater