component_installer_unittest.cc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. // Copyright 2016 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 <iterator>
  5. #include <memory>
  6. #include <string>
  7. #include <utility>
  8. #include <vector>
  9. #include "base/bind.h"
  10. #include "base/callback.h"
  11. #include "base/callback_helpers.h"
  12. #include "base/files/file_path.h"
  13. #include "base/files/file_util.h"
  14. #include "base/memory/raw_ptr.h"
  15. #include "base/memory/ref_counted.h"
  16. #include "base/path_service.h"
  17. #include "base/run_loop.h"
  18. #include "base/sequence_checker.h"
  19. #include "base/test/bind.h"
  20. #include "base/test/scoped_path_override.h"
  21. #include "base/test/task_environment.h"
  22. #include "base/threading/thread_task_runner_handle.h"
  23. #include "base/version.h"
  24. #include "components/component_updater/component_installer.h"
  25. #include "components/component_updater/component_updater_paths.h"
  26. #include "components/component_updater/component_updater_service.h"
  27. #include "components/component_updater/component_updater_service_internal.h"
  28. #include "components/crx_file/crx_verifier.h"
  29. #include "components/prefs/testing_pref_service.h"
  30. #include "components/update_client/component_unpacker.h"
  31. #include "components/update_client/crx_update_item.h"
  32. #include "components/update_client/patcher.h"
  33. #include "components/update_client/test_configurator.h"
  34. #include "components/update_client/unzipper.h"
  35. #include "components/update_client/update_client.h"
  36. #include "components/update_client/update_client_errors.h"
  37. #include "testing/gmock/include/gmock/gmock.h"
  38. #include "testing/gtest/include/gtest/gtest.h"
  39. using ComponentUnpacker = update_client::ComponentUnpacker;
  40. using Configurator = update_client::Configurator;
  41. using CrxUpdateItem = update_client::CrxUpdateItem;
  42. using TestConfigurator = update_client::TestConfigurator;
  43. using UpdateClient = update_client::UpdateClient;
  44. using ::testing::_;
  45. using ::testing::Invoke;
  46. namespace component_updater {
  47. namespace {
  48. // This hash corresponds to jebgalgnebhfojomionfpkfelancnnkf.crx.
  49. const uint8_t kSha256Hash[] = {0x94, 0x16, 0x0b, 0x6d, 0x41, 0x75, 0xe9, 0xec,
  50. 0x8e, 0xd5, 0xfa, 0x54, 0xb0, 0xd2, 0xdd, 0xa5,
  51. 0x6e, 0x05, 0x6b, 0xe8, 0x73, 0x47, 0xf6, 0xc4,
  52. 0x11, 0x9f, 0xbc, 0xb3, 0x09, 0xb3, 0x5b, 0x40};
  53. constexpr base::FilePath::CharType relative_install_dir[] =
  54. FILE_PATH_LITERAL("fake");
  55. base::FilePath test_file(const char* file) {
  56. base::FilePath path;
  57. base::PathService::Get(base::DIR_SOURCE_ROOT, &path);
  58. return path.AppendASCII("components")
  59. .AppendASCII("test")
  60. .AppendASCII("data")
  61. .AppendASCII("update_client")
  62. .AppendASCII(file);
  63. }
  64. class MockUpdateClient : public UpdateClient {
  65. public:
  66. MockUpdateClient() = default;
  67. base::RepeatingClosure Install(
  68. const std::string& id,
  69. CrxDataCallback crx_data_callback,
  70. CrxStateChangeCallback crx_state_change_callback,
  71. Callback callback) override {
  72. DoInstall(id, std::move(crx_data_callback));
  73. std::move(callback).Run(update_client::Error::NONE);
  74. return base::DoNothing();
  75. }
  76. void Update(const std::vector<std::string>& ids,
  77. CrxDataCallback crx_data_callback,
  78. CrxStateChangeCallback crx_state_change_callback,
  79. bool is_foreground,
  80. Callback callback) override {
  81. DoUpdate(ids, std::move(crx_data_callback));
  82. std::move(callback).Run(update_client::Error::NONE);
  83. }
  84. void SendUninstallPing(const CrxComponent& crx_component,
  85. int reason,
  86. Callback callback) override {
  87. DoSendUninstallPing(crx_component, reason);
  88. std::move(callback).Run(update_client::Error::NONE);
  89. }
  90. MOCK_METHOD1(AddObserver, void(Observer* observer));
  91. MOCK_METHOD1(RemoveObserver, void(Observer* observer));
  92. MOCK_METHOD2(DoInstall,
  93. void(const std::string& id,
  94. const CrxDataCallback& crx_data_callback));
  95. MOCK_METHOD2(DoUpdate,
  96. void(const std::vector<std::string>& ids,
  97. const CrxDataCallback& crx_data_callback));
  98. MOCK_CONST_METHOD2(GetCrxUpdateState,
  99. bool(const std::string& id, CrxUpdateItem* update_item));
  100. MOCK_CONST_METHOD1(IsUpdating, bool(const std::string& id));
  101. MOCK_METHOD0(Stop, void());
  102. MOCK_METHOD2(DoSendUninstallPing,
  103. void(const CrxComponent& crx_component, int reason));
  104. private:
  105. ~MockUpdateClient() override = default;
  106. };
  107. class MockInstallerPolicy : public ComponentInstallerPolicy {
  108. public:
  109. using ComponentReadyCallback =
  110. base::OnceCallback<void(const base::Version& version,
  111. const base::FilePath& install_dir,
  112. base::Value manifest)>;
  113. explicit MockInstallerPolicy(
  114. ComponentReadyCallback component_ready_cb = ComponentReadyCallback())
  115. : component_ready_cb_(std::move(component_ready_cb)) {}
  116. ~MockInstallerPolicy() override = default;
  117. bool VerifyInstallation(const base::Value& manifest,
  118. const base::FilePath& dir) const override {
  119. return true;
  120. }
  121. bool SupportsGroupPolicyEnabledComponentUpdates() const override {
  122. return true;
  123. }
  124. bool RequiresNetworkEncryption() const override { return true; }
  125. update_client::CrxInstaller::Result OnCustomInstall(
  126. const base::Value& manifest,
  127. const base::FilePath& install_dir) override {
  128. return update_client::CrxInstaller::Result(0);
  129. }
  130. void OnCustomUninstall() override {}
  131. void ComponentReady(const base::Version& version,
  132. const base::FilePath& install_dir,
  133. base::Value manifest) override {
  134. if (component_ready_cb_) {
  135. std::move(component_ready_cb_)
  136. .Run(version, install_dir, std::move(manifest));
  137. }
  138. }
  139. base::FilePath GetRelativeInstallDir() const override {
  140. return base::FilePath(relative_install_dir);
  141. }
  142. void GetHash(std::vector<uint8_t>* hash) const override { GetPkHash(hash); }
  143. std::string GetName() const override { return "fake name"; }
  144. update_client::InstallerAttributes GetInstallerAttributes() const override {
  145. update_client::InstallerAttributes installer_attributes;
  146. installer_attributes["ap"] = "fake-ap";
  147. installer_attributes["is-enterprise"] = "1";
  148. return installer_attributes;
  149. }
  150. private:
  151. static void GetPkHash(std::vector<uint8_t>* hash) {
  152. hash->assign(std::begin(kSha256Hash), std::end(kSha256Hash));
  153. }
  154. ComponentReadyCallback component_ready_cb_;
  155. };
  156. class MockUpdateScheduler : public UpdateScheduler {
  157. public:
  158. MOCK_METHOD4(Schedule,
  159. void(const base::TimeDelta& initial_delay,
  160. const base::TimeDelta& delay,
  161. const UserTask& user_task,
  162. const OnStopTaskCallback& on_stop));
  163. MOCK_METHOD0(Stop, void());
  164. };
  165. class ComponentInstallerTest : public testing::Test {
  166. public:
  167. ComponentInstallerTest();
  168. ~ComponentInstallerTest() override;
  169. MockUpdateClient& update_client() { return *update_client_; }
  170. ComponentUpdateService* component_updater() {
  171. return component_updater_.get();
  172. }
  173. scoped_refptr<TestConfigurator> configurator() const { return config_; }
  174. base::OnceClosure quit_closure() { return runloop_.QuitClosure(); }
  175. MockUpdateScheduler& scheduler() { return *scheduler_; }
  176. protected:
  177. void RunThreads();
  178. void Unpack(const base::FilePath& crx_path);
  179. ComponentUnpacker::Result result() const { return result_; }
  180. base::test::TaskEnvironment task_environment_;
  181. private:
  182. void UnpackComplete(const ComponentUnpacker::Result& result);
  183. void Schedule(const base::TimeDelta& initial_delay,
  184. const base::TimeDelta& delay,
  185. const UpdateScheduler::UserTask& user_task,
  186. const UpdateScheduler::OnStopTaskCallback& on_stop);
  187. const scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_ =
  188. base::ThreadTaskRunnerHandle::Get();
  189. base::RunLoop runloop_;
  190. std::unique_ptr<TestingPrefServiceSimple> pref_ =
  191. std::make_unique<TestingPrefServiceSimple>();
  192. scoped_refptr<TestConfigurator> config_ =
  193. base::MakeRefCounted<TestConfigurator>(pref_.get());
  194. raw_ptr<MockUpdateScheduler> scheduler_ = nullptr;
  195. scoped_refptr<MockUpdateClient> update_client_ =
  196. base::MakeRefCounted<MockUpdateClient>();
  197. std::unique_ptr<ComponentUpdateService> component_updater_;
  198. ComponentUnpacker::Result result_;
  199. };
  200. ComponentInstallerTest::ComponentInstallerTest() {
  201. EXPECT_CALL(update_client(), AddObserver(_)).Times(1);
  202. auto scheduler = std::make_unique<MockUpdateScheduler>();
  203. scheduler_ = scheduler.get();
  204. ON_CALL(*scheduler_, Schedule(_, _, _, _))
  205. .WillByDefault(Invoke(this, &ComponentInstallerTest::Schedule));
  206. component_updater_ = std::make_unique<CrxUpdateService>(
  207. config_, std::move(scheduler), update_client_, "");
  208. RegisterComponentUpdateServicePrefs(pref_->registry());
  209. }
  210. ComponentInstallerTest::~ComponentInstallerTest() {
  211. EXPECT_CALL(update_client(), RemoveObserver(_)).Times(1);
  212. component_updater_.reset();
  213. }
  214. void ComponentInstallerTest::RunThreads() {
  215. runloop_.Run();
  216. }
  217. void ComponentInstallerTest::Unpack(const base::FilePath& crx_path) {
  218. auto config = base::MakeRefCounted<TestConfigurator>();
  219. auto component_unpacker = base::MakeRefCounted<ComponentUnpacker>(
  220. std::vector<uint8_t>(std::begin(kSha256Hash), std::end(kSha256Hash)),
  221. crx_path, nullptr, config->GetUnzipperFactory()->Create(),
  222. config->GetPatcherFactory()->Create(), crx_file::VerifierFormat::CRX3);
  223. component_unpacker->Unpack(base::BindOnce(
  224. &ComponentInstallerTest::UnpackComplete, base::Unretained(this)));
  225. RunThreads();
  226. }
  227. void ComponentInstallerTest::UnpackComplete(
  228. const ComponentUnpacker::Result& result) {
  229. result_ = result;
  230. EXPECT_EQ(update_client::UnpackerError::kNone, result_.error);
  231. EXPECT_EQ(0, result_.extended_error);
  232. main_thread_task_runner_->PostTask(FROM_HERE, quit_closure());
  233. }
  234. void ComponentInstallerTest::Schedule(
  235. const base::TimeDelta& initial_delay,
  236. const base::TimeDelta& delay,
  237. const UpdateScheduler::UserTask& user_task,
  238. const UpdateScheduler::OnStopTaskCallback& on_stop) {
  239. user_task.Run(base::DoNothing());
  240. }
  241. } // namespace
  242. // Tests that the component metadata is propagated from the component installer
  243. // and its component policy, through the instance of the CrxComponent, to the
  244. // component updater service.
  245. TEST_F(ComponentInstallerTest, RegisterComponent) {
  246. class LoopHandler {
  247. public:
  248. LoopHandler(int max_cnt, base::OnceClosure quit_closure)
  249. : max_cnt_(max_cnt), quit_closure_(std::move(quit_closure)) {}
  250. void OnUpdate(const std::vector<std::string>& ids,
  251. const UpdateClient::CrxDataCallback& crx_data_callback) {
  252. static int cnt = 0;
  253. ++cnt;
  254. if (cnt >= max_cnt_)
  255. std::move(quit_closure_).Run();
  256. }
  257. private:
  258. const int max_cnt_;
  259. base::OnceClosure quit_closure_;
  260. };
  261. base::ScopedPathOverride scoped_path_override(DIR_COMPONENT_USER);
  262. const std::string id("jebgalgnebhfojomionfpkfelancnnkf");
  263. // Quit after one update check has been fired.
  264. LoopHandler loop_handler(1, quit_closure());
  265. EXPECT_CALL(update_client(), DoUpdate(_, _))
  266. .WillRepeatedly(Invoke(&loop_handler, &LoopHandler::OnUpdate));
  267. EXPECT_CALL(update_client(), GetCrxUpdateState(id, _)).Times(1);
  268. EXPECT_CALL(update_client(), Stop()).Times(1);
  269. EXPECT_CALL(scheduler(), Schedule(_, _, _, _)).Times(1);
  270. EXPECT_CALL(scheduler(), Stop()).Times(1);
  271. auto installer = base::MakeRefCounted<ComponentInstaller>(
  272. std::make_unique<MockInstallerPolicy>());
  273. installer->Register(component_updater(), base::OnceClosure());
  274. RunThreads();
  275. CrxUpdateItem item;
  276. EXPECT_TRUE(component_updater()->GetComponentDetails(id, &item));
  277. ASSERT_TRUE(item.component);
  278. const CrxComponent& component = *item.component;
  279. update_client::InstallerAttributes expected_attrs;
  280. expected_attrs["ap"] = "fake-ap";
  281. expected_attrs["is-enterprise"] = "1";
  282. EXPECT_EQ(
  283. std::vector<uint8_t>(std::begin(kSha256Hash), std::end(kSha256Hash)),
  284. component.pk_hash);
  285. EXPECT_EQ(base::Version("0.0.0.0"), component.version);
  286. EXPECT_TRUE(component.fingerprint.empty());
  287. EXPECT_STREQ("fake name", component.name.c_str());
  288. EXPECT_EQ(expected_attrs, component.installer_attributes);
  289. EXPECT_TRUE(component.requires_network_encryption);
  290. }
  291. // Tests that `ComponentInstallerPolicy::ComponentReady` and the completion
  292. // callback of `ComponentInstaller::Register` are called in sequence.
  293. TEST_F(ComponentInstallerTest, InstallerRegister_CheckSequence) {
  294. class RegisterHandler {
  295. public:
  296. virtual ~RegisterHandler() = default;
  297. virtual void ComponentReady() = 0;
  298. virtual void RegisterComplete() = 0;
  299. };
  300. // Allows defining call expectations on its functions when the functions
  301. // are invoked by callbacks posted from `ComponentInstaller::Register`.
  302. class MockRegisterHandler : public RegisterHandler {
  303. public:
  304. MockRegisterHandler() {
  305. ON_CALL(*this, ComponentReady)
  306. .WillByDefault(Invoke(this, &MockRegisterHandler::CheckSequence));
  307. ON_CALL(*this, RegisterComplete)
  308. .WillByDefault(Invoke(this, &MockRegisterHandler::CheckSequence));
  309. }
  310. MOCK_METHOD(void, ComponentReady, (), (override));
  311. MOCK_METHOD(void, RegisterComplete, (), (override));
  312. private:
  313. void CheckSequence() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker); }
  314. SEQUENCE_CHECKER(sequence_checker);
  315. };
  316. base::ScopedPathOverride scoped_path_override(DIR_COMPONENT_USER);
  317. // Install a CRX component so that `ComponentInstallerPolicy::ComponentReady`
  318. // can be invoked later on.
  319. {
  320. base::RunLoop run_loop;
  321. auto installer = base::MakeRefCounted<ComponentInstaller>(
  322. std::make_unique<MockInstallerPolicy>());
  323. Unpack(test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
  324. ASSERT_EQ(result().error, update_client::UnpackerError::kNone);
  325. base::FilePath base_dir;
  326. ASSERT_TRUE(base::PathService::Get(DIR_COMPONENT_USER, &base_dir));
  327. base_dir = base_dir.Append(relative_install_dir);
  328. ASSERT_TRUE(base::CreateDirectory(base_dir));
  329. installer->Install(
  330. result().unpack_path, update_client::jebg_public_key, nullptr,
  331. base::DoNothing(),
  332. base::BindLambdaForTesting(
  333. [&run_loop](const update_client::CrxInstaller::Result& result) {
  334. ASSERT_EQ(result.error, 0);
  335. run_loop.QuitClosure().Run();
  336. }));
  337. run_loop.Run();
  338. }
  339. base::RunLoop run_loop;
  340. EXPECT_CALL(update_client(), DoUpdate(_, _)).WillOnce(Invoke([&run_loop]() {
  341. run_loop.QuitClosure().Run();
  342. }));
  343. // Set up expectations for uninteresting calls on the mocks due to component
  344. // updater waking up after the component is registered.
  345. EXPECT_CALL(scheduler(), Schedule(_, _, _, _)).Times(1);
  346. EXPECT_CALL(scheduler(), Stop()).Times(1);
  347. EXPECT_CALL(update_client(), Stop()).Times(1);
  348. MockRegisterHandler mock_register_handler;
  349. {
  350. ::testing::InSequence seq;
  351. EXPECT_CALL(mock_register_handler, ComponentReady()).Times(1);
  352. EXPECT_CALL(mock_register_handler, RegisterComplete()).Times(1);
  353. }
  354. auto installer_policy =
  355. std::make_unique<MockInstallerPolicy>(base::BindLambdaForTesting(
  356. [&mock_register_handler](const base::Version& version,
  357. const base::FilePath& install_dir,
  358. base::Value manifest) {
  359. EXPECT_EQ(version.GetString(), "1.0");
  360. mock_register_handler.ComponentReady();
  361. }));
  362. auto installer =
  363. base::MakeRefCounted<ComponentInstaller>(std::move(installer_policy));
  364. installer->Register(component_updater(),
  365. base::BindLambdaForTesting([&mock_register_handler]() {
  366. mock_register_handler.RegisterComplete();
  367. }));
  368. run_loop.Run();
  369. }
  370. // Tests that the unpack path is removed when the install succeeded.
  371. TEST_F(ComponentInstallerTest, UnpackPathInstallSuccess) {
  372. auto installer = base::MakeRefCounted<ComponentInstaller>(
  373. std::make_unique<MockInstallerPolicy>());
  374. Unpack(test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
  375. const auto unpack_path = result().unpack_path;
  376. EXPECT_TRUE(base::DirectoryExists(unpack_path));
  377. EXPECT_EQ(update_client::jebg_public_key, result().public_key);
  378. base::ScopedPathOverride scoped_path_override(DIR_COMPONENT_USER);
  379. base::FilePath base_dir;
  380. EXPECT_TRUE(base::PathService::Get(DIR_COMPONENT_USER, &base_dir));
  381. base_dir = base_dir.Append(relative_install_dir);
  382. EXPECT_TRUE(base::CreateDirectory(base_dir));
  383. installer->Install(
  384. unpack_path, update_client::jebg_public_key, nullptr, base::DoNothing(),
  385. base::BindOnce([](const update_client::CrxInstaller::Result& result) {
  386. EXPECT_EQ(0, result.error);
  387. }));
  388. task_environment_.RunUntilIdle();
  389. EXPECT_FALSE(base::PathExists(unpack_path));
  390. EXPECT_CALL(update_client(), Stop()).Times(1);
  391. EXPECT_CALL(scheduler(), Stop()).Times(1);
  392. }
  393. // Tests that the unpack path is removed when the install failed.
  394. TEST_F(ComponentInstallerTest, UnpackPathInstallError) {
  395. auto installer = base::MakeRefCounted<ComponentInstaller>(
  396. std::make_unique<MockInstallerPolicy>());
  397. Unpack(test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
  398. const auto unpack_path = result().unpack_path;
  399. EXPECT_TRUE(base::DirectoryExists(unpack_path));
  400. // Test the precondition that DIR_COMPONENT_USER is not registered with
  401. // the path service.
  402. base::FilePath base_dir;
  403. EXPECT_FALSE(base::PathService::Get(DIR_COMPONENT_USER, &base_dir));
  404. // Calling |Install| fails since DIR_COMPONENT_USER does not exist.
  405. installer->Install(
  406. unpack_path, update_client::jebg_public_key, nullptr, base::DoNothing(),
  407. base::BindOnce([](const update_client::CrxInstaller::Result& result) {
  408. EXPECT_EQ(static_cast<int>(
  409. update_client::InstallError::NO_DIR_COMPONENT_USER),
  410. result.error);
  411. }));
  412. task_environment_.RunUntilIdle();
  413. EXPECT_FALSE(base::PathExists(unpack_path));
  414. EXPECT_CALL(update_client(), Stop()).Times(1);
  415. EXPECT_CALL(scheduler(), Stop()).Times(1);
  416. }
  417. } // namespace component_updater