aw_component_update_service_test.cc 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  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 "android_webview/nonembedded/component_updater/aw_component_update_service.h"
  5. #include <stdint.h>
  6. #include <iterator>
  7. #include <memory>
  8. #include <utility>
  9. #include "android_webview/common/aw_paths.h"
  10. #include "android_webview/nonembedded/component_updater/aw_component_updater_configurator.h"
  11. #include "base/android/path_utils.h"
  12. #include "base/callback.h"
  13. #include "base/callback_helpers.h"
  14. #include "base/command_line.h"
  15. #include "base/files/file_path.h"
  16. #include "base/files/file_util.h"
  17. #include "base/json/json_reader.h"
  18. #include "base/memory/raw_ptr.h"
  19. #include "base/test/android/url_utils.h"
  20. #include "base/test/task_environment.h"
  21. #include "base/values.h"
  22. #include "base/version.h"
  23. #include "components/component_updater/component_installer.h"
  24. #include "components/component_updater/component_updater_paths.h"
  25. #include "components/component_updater/component_updater_service.h"
  26. #include "components/prefs/testing_pref_service.h"
  27. #include "components/update_client/network.h"
  28. #include "components/update_client/update_client.h"
  29. #include "testing/gtest/include/gtest/gtest.h"
  30. #include "third_party/abseil-cpp/absl/types/optional.h"
  31. #include "url/gurl.h"
  32. namespace android_webview {
  33. namespace {
  34. // Size of android_webview/test/data/components/fake_component.crx.
  35. constexpr size_t kCrxContentLength = 3902;
  36. constexpr char kComponentId[] = "llkgjffcdpffmhiakmfcdcblohccpfmo";
  37. // This hash corresponds to kComponentId.
  38. constexpr uint8_t kSha256Hash[] = {
  39. 0xbb, 0xa6, 0x95, 0x52, 0x3f, 0x55, 0xc7, 0x80, 0xac, 0x52, 0x32,
  40. 0x1b, 0xe7, 0x22, 0xf5, 0xce, 0x6a, 0xfd, 0x9c, 0x9e, 0xa9, 0x2a,
  41. 0x0b, 0x50, 0x60, 0x2b, 0x7f, 0x6c, 0x64, 0x80, 0x09, 0x04};
  42. constexpr char kTestVersion[] = "1.0.0.6";
  43. base::FilePath GetTestFile(const std::string& file_name) {
  44. return base::android::GetIsolatedTestRoot()
  45. .AppendASCII("android_webview/test/data/components")
  46. .AppendASCII(file_name);
  47. }
  48. void CreateTestFiles(const base::FilePath& install_dir) {
  49. base::CreateDirectory(install_dir);
  50. ASSERT_TRUE(base::WriteFile(install_dir.AppendASCII("file1.txt"), "1"));
  51. ASSERT_TRUE(base::CopyFile(GetTestFile("fake_component_manifest.json"),
  52. install_dir.AppendASCII("manifest.json")));
  53. }
  54. void AssertOnDemandRequest(bool on_demand, std::string post_data) {
  55. const auto root = base::JSONReader::Read(post_data);
  56. ASSERT_TRUE(root);
  57. const auto* request = root->FindKey("request");
  58. ASSERT_TRUE(request);
  59. const auto& app = request->FindKey("app")->GetListDeprecated()[0];
  60. if (on_demand) {
  61. EXPECT_EQ("ondemand", app.FindKey("installsource")->GetString());
  62. } else {
  63. EXPECT_EQ(nullptr, app.FindKey("installsource"));
  64. }
  65. }
  66. class FailingNetworkFetcher : public update_client::NetworkFetcher {
  67. public:
  68. FailingNetworkFetcher() = default;
  69. ~FailingNetworkFetcher() override = default;
  70. FailingNetworkFetcher(const FailingNetworkFetcher&) = delete;
  71. FailingNetworkFetcher& operator=(const FailingNetworkFetcher&) = delete;
  72. // NetworkFetcher overrides.
  73. void PostRequest(
  74. const GURL& url,
  75. const std::string& post_data,
  76. const std::string& content_type,
  77. const base::flat_map<std::string, std::string>& post_additional_headers,
  78. ResponseStartedCallback response_started_callback,
  79. ProgressCallback progress_callback,
  80. PostRequestCompleteCallback post_request_complete_callback) override {
  81. AssertOnDemandRequest(false, post_data);
  82. std::move(post_request_complete_callback)
  83. .Run(/* response_body= */ std::make_unique<std::string>(""),
  84. /* network_error= */ -2,
  85. /* header_etag= */ "",
  86. /* header_x_cup_server_proof= */ "",
  87. /* x_header_retry_after_sec= */ 0ll);
  88. }
  89. void DownloadToFile(const GURL& url,
  90. const base::FilePath& file_path,
  91. ResponseStartedCallback response_started_callback,
  92. ProgressCallback progress_callback,
  93. DownloadToFileCompleteCallback
  94. download_to_file_complete_callback) override {
  95. std::move(download_to_file_complete_callback)
  96. .Run(
  97. /* network_error= */ -2,
  98. /* content_size= */ 0);
  99. }
  100. };
  101. // This inspects that param onDemandUpdate gets passed down the call stack.
  102. class OnDemandNetworkFetcher : public update_client::NetworkFetcher {
  103. public:
  104. OnDemandNetworkFetcher() = default;
  105. ~OnDemandNetworkFetcher() override = default;
  106. OnDemandNetworkFetcher(const OnDemandNetworkFetcher&) = delete;
  107. OnDemandNetworkFetcher& operator=(const OnDemandNetworkFetcher&) = delete;
  108. // NetworkFetcher overrides.
  109. void PostRequest(
  110. const GURL& url,
  111. const std::string& post_data,
  112. const std::string& content_type,
  113. const base::flat_map<std::string, std::string>& post_additional_headers,
  114. ResponseStartedCallback response_started_callback,
  115. ProgressCallback progress_callback,
  116. PostRequestCompleteCallback post_request_complete_callback) override {
  117. AssertOnDemandRequest(true, post_data);
  118. std::move(post_request_complete_callback)
  119. .Run(/* response_body= */ std::make_unique<std::string>(""),
  120. /* network_error= */ -2,
  121. /* header_etag= */ "",
  122. /* header_x_cup_server_proof= */ "",
  123. /* x_header_retry_after_sec= */ 0ll);
  124. }
  125. void DownloadToFile(const GURL& url,
  126. const base::FilePath& file_path,
  127. ResponseStartedCallback response_started_callback,
  128. ProgressCallback progress_callback,
  129. DownloadToFileCompleteCallback
  130. download_to_file_complete_callback) override {
  131. std::move(download_to_file_complete_callback)
  132. .Run(
  133. /* network_error= */ -2,
  134. /* content_size= */ 0);
  135. }
  136. };
  137. // A NetworkFetcher that fakes downloading a CRX file.
  138. // TODO(crbug.com/1190310) use EmbeddedTestServer instead of Mocking the
  139. // NetworkFetcher.
  140. class FakeCrxNetworkFetcher : public update_client::NetworkFetcher {
  141. public:
  142. FakeCrxNetworkFetcher() = default;
  143. ~FakeCrxNetworkFetcher() override = default;
  144. FakeCrxNetworkFetcher(const FakeCrxNetworkFetcher&) = delete;
  145. FakeCrxNetworkFetcher& operator=(const FakeCrxNetworkFetcher&) = delete;
  146. // NetworkFetcher overrides.
  147. void PostRequest(
  148. const GURL& url,
  149. const std::string& post_data,
  150. const std::string& content_type,
  151. const base::flat_map<std::string, std::string>& post_additional_headers,
  152. ResponseStartedCallback response_started_callback,
  153. ProgressCallback progress_callback,
  154. PostRequestCompleteCallback post_request_complete_callback) override {
  155. AssertOnDemandRequest(false, post_data);
  156. std::move(response_started_callback)
  157. .Run(/* responseCode= */ 200, /* content_size= */ 0);
  158. std::string response_body;
  159. int network_error = 0;
  160. if (post_data.find("updatecheck") != std::string::npos) {
  161. ASSERT_TRUE(base::ReadFileToString(
  162. GetTestFile("fake_component_update_response.json"), &response_body));
  163. } else if (post_data.find("eventtype") != std::string::npos) {
  164. ASSERT_TRUE(base::ReadFileToString(
  165. GetTestFile("fake_component_ping_response.json"), &response_body));
  166. } else { // error post request not a ping nor update.
  167. network_error = -2;
  168. }
  169. std::move(post_request_complete_callback)
  170. .Run(/* response_body= */ std::make_unique<std::string>(response_body),
  171. /* network_error= */ network_error,
  172. /* header_etag= */ "",
  173. /* header_x_cup_server_proof= */ "",
  174. /* x_header_retry_after_sec= */ 0ll);
  175. }
  176. void DownloadToFile(const GURL& url,
  177. const base::FilePath& file_path,
  178. ResponseStartedCallback response_started_callback,
  179. ProgressCallback progress_callback,
  180. DownloadToFileCompleteCallback
  181. download_to_file_complete_callback) override {
  182. ASSERT_TRUE(base::CopyFile(GetTestFile("fake_component.crx"), file_path));
  183. std::move(response_started_callback)
  184. .Run(/* responseCode= */ 200, /* content_size= */ kCrxContentLength);
  185. std::move(download_to_file_complete_callback)
  186. .Run(
  187. /* network_error= */ 0,
  188. /* content_size= */ kCrxContentLength);
  189. }
  190. };
  191. template <typename T>
  192. class MockNetworkFetcherFactory : public update_client::NetworkFetcherFactory {
  193. public:
  194. MockNetworkFetcherFactory() = default;
  195. MockNetworkFetcherFactory(const MockNetworkFetcherFactory&) = delete;
  196. MockNetworkFetcherFactory& operator=(const MockNetworkFetcherFactory&) =
  197. delete;
  198. std::unique_ptr<update_client::NetworkFetcher> Create() const override {
  199. return std::make_unique<T>();
  200. }
  201. protected:
  202. ~MockNetworkFetcherFactory() override = default;
  203. };
  204. class MockConfigurator : public AwComponentUpdaterConfigurator {
  205. public:
  206. explicit MockConfigurator(PrefService* pref_service,
  207. scoped_refptr<update_client::NetworkFetcherFactory>
  208. network_fetcher_factory)
  209. : AwComponentUpdaterConfigurator(base::CommandLine::ForCurrentProcess(),
  210. pref_service),
  211. network_fetcher_factory_(std::move(network_fetcher_factory)) {}
  212. scoped_refptr<update_client::NetworkFetcherFactory> GetNetworkFetcherFactory()
  213. override {
  214. return network_fetcher_factory_;
  215. }
  216. // Disable CUP signing so we can inject the fake CRX.
  217. bool EnabledCupSigning() const override { return false; }
  218. protected:
  219. ~MockConfigurator() override = default;
  220. private:
  221. scoped_refptr<update_client::NetworkFetcherFactory> network_fetcher_factory_;
  222. };
  223. class MockInstallerPolicy : public component_updater::ComponentInstallerPolicy {
  224. public:
  225. MockInstallerPolicy() = default;
  226. ~MockInstallerPolicy() override = default;
  227. MockInstallerPolicy(const MockInstallerPolicy&) = delete;
  228. MockInstallerPolicy& operator=(const MockInstallerPolicy&) = delete;
  229. // Overridden ComponentInstallerPolicy methods
  230. bool SupportsGroupPolicyEnabledComponentUpdates() const override {
  231. return false;
  232. }
  233. bool RequiresNetworkEncryption() const override { return false; }
  234. update_client::CrxInstaller::Result OnCustomInstall(
  235. const base::Value& manifest,
  236. const base::FilePath& install_dir) override {
  237. return update_client::CrxInstaller::Result(0);
  238. }
  239. void OnCustomUninstall() override { FAIL(); }
  240. void ComponentReady(const base::Version& version,
  241. const base::FilePath& install_dir,
  242. base::Value manifest) override {
  243. version_ = version;
  244. install_dir_ = install_dir;
  245. manifest_ = std::move(manifest);
  246. }
  247. bool VerifyInstallation(const base::Value& manifest,
  248. const base::FilePath& install_dir) const override {
  249. return true;
  250. }
  251. base::FilePath GetRelativeInstallDir() const override {
  252. return base::FilePath(FILE_PATH_LITERAL(kComponentId));
  253. }
  254. void GetHash(std::vector<uint8_t>* hash) const override {
  255. hash->assign(std::begin(kSha256Hash), std::end(kSha256Hash));
  256. }
  257. std::string GetName() const override { return kComponentId; }
  258. update_client::InstallerAttributes GetInstallerAttributes() const override {
  259. return update_client::InstallerAttributes();
  260. }
  261. bool IsComponentReadyInvoked() { return !!manifest_; }
  262. base::Value& GetManifest() { return *manifest_; }
  263. base::FilePath GetInstallDir() const { return install_dir_; }
  264. base::Version GetVersion() const { return version_; }
  265. private:
  266. absl::optional<base::Value> manifest_;
  267. base::FilePath install_dir_;
  268. base::Version version_;
  269. };
  270. } // namespace
  271. class TestAwComponentUpdateService : public AwComponentUpdateService {
  272. public:
  273. explicit TestAwComponentUpdateService(
  274. scoped_refptr<update_client::Configurator> configurator)
  275. : AwComponentUpdateService(configurator) {}
  276. ~TestAwComponentUpdateService() override = default;
  277. MockInstallerPolicy* GetMockPolicy() { return mock_policy_; }
  278. protected:
  279. void RegisterComponents(RegisterComponentsCallback register_callback,
  280. base::OnceClosure on_finished) override {
  281. auto policy = std::make_unique<MockInstallerPolicy>();
  282. mock_policy_ = policy.get();
  283. base::MakeRefCounted<component_updater::ComponentInstaller>(
  284. std::move(policy))
  285. ->Register(std::move(register_callback), std::move(on_finished));
  286. }
  287. private:
  288. raw_ptr<MockInstallerPolicy> mock_policy_;
  289. };
  290. class AwComponentUpdateServiceTest : public testing::Test {
  291. public:
  292. AwComponentUpdateServiceTest() = default;
  293. ~AwComponentUpdateServiceTest() override = default;
  294. AwComponentUpdateServiceTest(const AwComponentUpdateServiceTest&) = delete;
  295. AwComponentUpdateServiceTest& operator=(const AwComponentUpdateServiceTest&) =
  296. delete;
  297. static void SetUpTestSuite() {
  298. RegisterPathProvider();
  299. component_updater::RegisterPathProvider(
  300. /*components_system_root_key=*/android_webview::DIR_COMPONENTS_ROOT,
  301. /*components_system_root_key_alt=*/android_webview::DIR_COMPONENTS_ROOT,
  302. /*components_user_root_key=*/android_webview::DIR_COMPONENTS_ROOT);
  303. }
  304. // Override from testing::Test
  305. void SetUp() override {
  306. update_client::RegisterPrefs(test_pref_->registry());
  307. ASSERT_TRUE(base::android::GetDataDirectory(&component_install_dir_));
  308. component_install_dir_ = component_install_dir_.AppendASCII("components")
  309. .AppendASCII("cus")
  310. .AppendASCII(kComponentId);
  311. }
  312. void TearDown() override {
  313. if (base::PathExists(component_install_dir_))
  314. ASSERT_TRUE(base::DeletePathRecursively(component_install_dir_));
  315. }
  316. protected:
  317. base::FilePath component_install_dir_;
  318. std::unique_ptr<TestingPrefServiceSimple> test_pref_ =
  319. std::make_unique<TestingPrefServiceSimple>();
  320. private:
  321. base::test::TaskEnvironment task_environment_;
  322. };
  323. TEST_F(AwComponentUpdateServiceTest, TestComponentReadyWhenOffline) {
  324. CreateTestFiles(component_install_dir_.AppendASCII(kTestVersion));
  325. base::RunLoop run_loop;
  326. TestAwComponentUpdateService service(base::MakeRefCounted<MockConfigurator>(
  327. test_pref_.get(),
  328. base::MakeRefCounted<
  329. MockNetworkFetcherFactory<FailingNetworkFetcher>>()));
  330. base::OnceClosure closure = run_loop.QuitClosure();
  331. service.StartComponentUpdateService(
  332. base::BindOnce(
  333. [](base::OnceClosure closure, int) { std::move(closure).Run(); },
  334. std::move(closure)),
  335. false);
  336. run_loop.Run();
  337. ASSERT_TRUE(service.GetMockPolicy()->IsComponentReadyInvoked());
  338. EXPECT_EQ(service.GetMockPolicy()->GetVersion().GetString(), kTestVersion);
  339. EXPECT_EQ(service.GetMockPolicy()->GetInstallDir(),
  340. component_install_dir_.AppendASCII(kTestVersion));
  341. }
  342. TEST_F(AwComponentUpdateServiceTest, TestFreshDownloadingFakeApk) {
  343. base::RunLoop run_loop;
  344. TestAwComponentUpdateService service(base::MakeRefCounted<MockConfigurator>(
  345. test_pref_.get(),
  346. base::MakeRefCounted<
  347. MockNetworkFetcherFactory<FakeCrxNetworkFetcher>>()));
  348. base::OnceClosure closure = run_loop.QuitClosure();
  349. service.StartComponentUpdateService(
  350. base::BindOnce(
  351. [](base::OnceClosure closure, int) { std::move(closure).Run(); },
  352. std::move(closure)),
  353. false);
  354. run_loop.Run();
  355. ASSERT_TRUE(service.GetMockPolicy()->IsComponentReadyInvoked());
  356. EXPECT_EQ(service.GetMockPolicy()->GetVersion().GetString(), kTestVersion);
  357. EXPECT_EQ(service.GetMockPolicy()->GetInstallDir(),
  358. component_install_dir_.AppendASCII(kTestVersion));
  359. // Assert that the manifest is valid by asserting a field in it other than
  360. // version.
  361. std::string* minimum_chrome_version =
  362. service.GetMockPolicy()->GetManifest().FindStringKey(
  363. "minimum_chrome_version");
  364. ASSERT_TRUE(minimum_chrome_version);
  365. EXPECT_EQ(*minimum_chrome_version, "50");
  366. }
  367. TEST_F(AwComponentUpdateServiceTest, TestOnDemandUpdateRequest) {
  368. CreateTestFiles(component_install_dir_.AppendASCII(kTestVersion));
  369. base::RunLoop run_loop;
  370. TestAwComponentUpdateService service(base::MakeRefCounted<MockConfigurator>(
  371. test_pref_.get(),
  372. base::MakeRefCounted<
  373. MockNetworkFetcherFactory<OnDemandNetworkFetcher>>()));
  374. base::OnceClosure closure = run_loop.QuitClosure();
  375. service.StartComponentUpdateService(
  376. base::BindOnce(
  377. [](base::OnceClosure closure, int) { std::move(closure).Run(); },
  378. std::move(closure)),
  379. true);
  380. run_loop.Run();
  381. ASSERT_TRUE(service.GetMockPolicy()->IsComponentReadyInvoked());
  382. EXPECT_EQ(service.GetMockPolicy()->GetVersion().GetString(), kTestVersion);
  383. EXPECT_EQ(service.GetMockPolicy()->GetInstallDir(),
  384. component_install_dir_.AppendASCII(kTestVersion));
  385. }
  386. } // namespace android_webview