blob: afebb3d43026833c388f8ea2d97b3e4892b4ae9f [file] [log] [blame]
sorin6a57db92016-06-27 22:28:151// 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
5#include <iterator>
Gyuyoung Kim6afb5082018-01-19 13:35:576#include <memory>
sorin6a57db92016-06-27 22:28:157#include <string>
waffles77255cc2016-08-02 17:25:128#include <utility>
sorin6a57db92016-06-27 22:28:159#include <vector>
10
Sorin Jianuf40ab4b32017-10-06 22:53:4111#include "base/bind.h"
sorin6a57db92016-06-27 22:28:1512#include "base/callback.h"
Sorin Jianu316232a2017-05-26 20:22:3013#include "base/files/file_path.h"
14#include "base/files/file_util.h"
sorin6a57db92016-06-27 22:28:1515#include "base/macros.h"
sorin6a57db92016-06-27 22:28:1516#include "base/memory/ref_counted.h"
Sorin Jianu316232a2017-05-26 20:22:3017#include "base/path_service.h"
sorin6a57db92016-06-27 22:28:1518#include "base/run_loop.h"
Gabriel Charette44db1422018-08-06 11:19:3319#include "base/task/post_task.h"
Sorin Jianu316232a2017-05-26 20:22:3020#include "base/test/scoped_path_override.h"
fdorayb26583c2017-05-16 18:47:0121#include "base/test/scoped_task_environment.h"
22#include "base/threading/thread_task_runner_handle.h"
sorin6a57db92016-06-27 22:28:1523#include "base/version.h"
Sorin Jianu08f92b3c2017-09-25 16:17:1224#include "components/component_updater/component_installer.h"
Sorin Jianu316232a2017-05-26 20:22:3025#include "components/component_updater/component_updater_paths.h"
sorin6a57db92016-06-27 22:28:1526#include "components/component_updater/component_updater_service.h"
27#include "components/component_updater/component_updater_service_internal.h"
Joshua Pawlickif4b33f382018-08-17 17:36:5128#include "components/crx_file/crx_verifier.h"
Sorin Jianu316232a2017-05-26 20:22:3029#include "components/update_client/component_unpacker.h"
sorin6a57db92016-06-27 22:28:1530#include "components/update_client/crx_update_item.h"
31#include "components/update_client/test_configurator.h"
32#include "components/update_client/update_client.h"
sorin7b8650522016-11-02 18:23:4133#include "components/update_client/update_client_errors.h"
Jay Civelli29f9b942017-11-08 20:07:2634#include "services/service_manager/public/cpp/connector.h"
sorin6a57db92016-06-27 22:28:1535#include "testing/gmock/include/gmock/gmock.h"
36#include "testing/gtest/include/gtest/gtest.h"
37
Sorin Jianu316232a2017-05-26 20:22:3038using ComponentUnpacker = update_client::ComponentUnpacker;
sorin6a57db92016-06-27 22:28:1539using Configurator = update_client::Configurator;
40using CrxUpdateItem = update_client::CrxUpdateItem;
41using TestConfigurator = update_client::TestConfigurator;
42using UpdateClient = update_client::UpdateClient;
43
44using ::testing::_;
45using ::testing::Invoke;
46
47namespace component_updater {
48
49namespace {
50
51// This hash corresponds to jebgalgnebhfojomionfpkfelancnnkf.crx.
52const uint8_t kSha256Hash[] = {0x94, 0x16, 0x0b, 0x6d, 0x41, 0x75, 0xe9, 0xec,
53 0x8e, 0xd5, 0xfa, 0x54, 0xb0, 0xd2, 0xdd, 0xa5,
54 0x6e, 0x05, 0x6b, 0xe8, 0x73, 0x47, 0xf6, 0xc4,
55 0x11, 0x9f, 0xbc, 0xb3, 0x09, 0xb3, 0x5b, 0x40};
56
Sorin Jianu316232a2017-05-26 20:22:3057constexpr base::FilePath::CharType relative_install_dir[] =
58 FILE_PATH_LITERAL("fake");
59
60base::FilePath test_file(const char* file) {
61 base::FilePath path;
Avi Drissmanf617d012018-05-02 18:48:5362 base::PathService::Get(base::DIR_SOURCE_ROOT, &path);
Sorin Jianu316232a2017-05-26 20:22:3063 return path.AppendASCII("components")
64 .AppendASCII("test")
65 .AppendASCII("data")
66 .AppendASCII("update_client")
67 .AppendASCII(file);
68}
69
sorin6a57db92016-06-27 22:28:1570class MockUpdateClient : public UpdateClient {
71 public:
sorin2adb2ca2016-06-29 01:44:3572 MockUpdateClient() {}
Vladislav Kuzkokov12eca792017-10-20 12:45:3873
74 void Install(const std::string& id,
Sorin Jianua8ef73d2017-11-02 16:55:1775 CrxDataCallback crx_data_callback,
Daniel Cheng67848522018-04-27 22:04:4176 Callback callback) override {
Sorin Jianua8ef73d2017-11-02 16:55:1777 DoInstall(id, std::move(crx_data_callback));
Vladislav Kuzkokov12eca792017-10-20 12:45:3878 std::move(callback).Run(update_client::Error::NONE);
79 }
80
81 void Update(const std::vector<std::string>& ids,
Sorin Jianua8ef73d2017-11-02 16:55:1782 CrxDataCallback crx_data_callback,
Sorin Jianub41a592a2018-03-02 16:30:2783 bool is_foreground,
Daniel Cheng67848522018-04-27 22:04:4184 Callback callback) override {
Sorin Jianua8ef73d2017-11-02 16:55:1785 DoUpdate(ids, std::move(crx_data_callback));
Vladislav Kuzkokov12eca792017-10-20 12:45:3886 std::move(callback).Run(update_client::Error::NONE);
87 }
88
89 void SendUninstallPing(const std::string& id,
90 const base::Version& version,
91 int reason,
Daniel Cheng67848522018-04-27 22:04:4192 Callback callback) override {
Vladislav Kuzkokov12eca792017-10-20 12:45:3893 DoSendUninstallPing(id, version, reason);
94 std::move(callback).Run(update_client::Error::NONE);
95 }
96
sorin6a57db92016-06-27 22:28:1597 MOCK_METHOD1(AddObserver, void(Observer* observer));
98 MOCK_METHOD1(RemoveObserver, void(Observer* observer));
Vladislav Kuzkokov12eca792017-10-20 12:45:3899 MOCK_METHOD2(DoInstall,
sorin6a57db92016-06-27 22:28:15100 void(const std::string& id,
Vladislav Kuzkokov12eca792017-10-20 12:45:38101 const CrxDataCallback& crx_data_callback));
102 MOCK_METHOD2(DoUpdate,
sorin6a57db92016-06-27 22:28:15103 void(const std::vector<std::string>& ids,
Vladislav Kuzkokov12eca792017-10-20 12:45:38104 const CrxDataCallback& crx_data_callback));
sorin6a57db92016-06-27 22:28:15105 MOCK_CONST_METHOD2(GetCrxUpdateState,
106 bool(const std::string& id, CrxUpdateItem* update_item));
107 MOCK_CONST_METHOD1(IsUpdating, bool(const std::string& id));
108 MOCK_METHOD0(Stop, void());
Vladislav Kuzkokov12eca792017-10-20 12:45:38109 MOCK_METHOD3(DoSendUninstallPing,
sorin8037ac8c2017-04-19 16:28:00110 void(const std::string& id,
111 const base::Version& version,
Vladislav Kuzkokov12eca792017-10-20 12:45:38112 int reason));
sorin6a57db92016-06-27 22:28:15113
114 private:
sorin2adb2ca2016-06-29 01:44:35115 ~MockUpdateClient() override {}
sorin6a57db92016-06-27 22:28:15116};
117
Sorin Jianua8926bf2018-03-09 21:02:53118class MockInstallerPolicy : public ComponentInstallerPolicy {
sorin6a57db92016-06-27 22:28:15119 public:
Sorin Jianua8926bf2018-03-09 21:02:53120 MockInstallerPolicy() {}
121 ~MockInstallerPolicy() override {}
sorin6a57db92016-06-27 22:28:15122
123 bool VerifyInstallation(const base::DictionaryValue& manifest,
124 const base::FilePath& dir) const override {
125 return true;
126 }
127
sorin3574ef92016-08-03 16:46:01128 bool SupportsGroupPolicyEnabledComponentUpdates() const override {
sorin098a4a72016-08-30 04:43:24129 return true;
sorin3574ef92016-08-03 16:46:01130 }
sorin6a57db92016-06-27 22:28:15131
132 bool RequiresNetworkEncryption() const override { return true; }
133
sorin2892f7212016-11-07 18:59:43134 update_client::CrxInstaller::Result OnCustomInstall(
135 const base::DictionaryValue& manifest,
136 const base::FilePath& install_dir) override {
137 return update_client::CrxInstaller::Result(0);
sorin6a57db92016-06-27 22:28:15138 }
139
Xiaochu Liu1e306a32017-11-08 18:57:34140 void OnCustomUninstall() override {}
141
sorin6a57db92016-06-27 22:28:15142 void ComponentReady(
143 const base::Version& version,
144 const base::FilePath& install_dir,
145 std::unique_ptr<base::DictionaryValue> manifest) override {}
146
147 base::FilePath GetRelativeInstallDir() const override {
Sorin Jianu316232a2017-05-26 20:22:30148 return base::FilePath(relative_install_dir);
sorin6a57db92016-06-27 22:28:15149 }
150
151 void GetHash(std::vector<uint8_t>* hash) const override { GetPkHash(hash); }
152
153 std::string GetName() const override { return "fake name"; }
154
sorin2adb2ca2016-06-29 01:44:35155 update_client::InstallerAttributes GetInstallerAttributes() const override {
156 update_client::InstallerAttributes installer_attributes;
157 installer_attributes["ap"] = "fake-ap";
158 installer_attributes["is-enterprise"] = "1";
159 return installer_attributes;
160 }
sorin6a57db92016-06-27 22:28:15161
waffles77255cc2016-08-02 17:25:12162 std::vector<std::string> GetMimeTypes() const override {
163 return std::vector<std::string>();
164 }
165
sorin6a57db92016-06-27 22:28:15166 private:
167 static void GetPkHash(std::vector<uint8_t>* hash) {
168 hash->assign(std::begin(kSha256Hash), std::end(kSha256Hash));
169 }
170};
171
Tibor Goldschwendt5f173cb2018-06-21 22:50:40172class MockUpdateScheduler : public UpdateScheduler {
173 public:
174 MOCK_METHOD4(Schedule,
175 void(const base::TimeDelta& initial_delay,
176 const base::TimeDelta& delay,
177 const UserTask& user_task,
178 const OnStopTaskCallback& on_stop));
179 MOCK_METHOD0(Stop, void());
180};
181
Sorin Jianu08f92b3c2017-09-25 16:17:12182class ComponentInstallerTest : public testing::Test {
sorin6a57db92016-06-27 22:28:15183 public:
Sorin Jianu08f92b3c2017-09-25 16:17:12184 ComponentInstallerTest();
185 ~ComponentInstallerTest() override;
sorin6a57db92016-06-27 22:28:15186
187 MockUpdateClient& update_client() { return *update_client_; }
188 ComponentUpdateService* component_updater() {
189 return component_updater_.get();
190 }
191 scoped_refptr<TestConfigurator> configurator() const { return config_; }
Sorin Jianua8ef73d2017-11-02 16:55:17192 base::OnceClosure quit_closure() { return runloop_.QuitClosure(); }
Tibor Goldschwendt5f173cb2018-06-21 22:50:40193 MockUpdateScheduler& scheduler() { return *scheduler_; }
sorin6a57db92016-06-27 22:28:15194
195 protected:
196 void RunThreads();
Sorin Jianu316232a2017-05-26 20:22:30197 void Unpack(const base::FilePath& crx_path);
198 ComponentUnpacker::Result result() const { return result_; }
sorin6a57db92016-06-27 22:28:15199
Sorin Jianuf40ab4b32017-10-06 22:53:41200 base::test::ScopedTaskEnvironment scoped_task_environment_;
201
sorin6a57db92016-06-27 22:28:15202 private:
Sorin Jianu316232a2017-05-26 20:22:30203 void UnpackComplete(const ComponentUnpacker::Result& result);
Tibor Goldschwendt5f173cb2018-06-21 22:50:40204 void Schedule(const base::TimeDelta& initial_delay,
205 const base::TimeDelta& delay,
206 const UpdateScheduler::UserTask& user_task,
207 const UpdateScheduler::OnStopTaskCallback& on_stop);
Sorin Jianu316232a2017-05-26 20:22:30208
Sorin Jianu316232a2017-05-26 20:22:30209 const scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_ =
210 base::ThreadTaskRunnerHandle::Get();
sorin6a57db92016-06-27 22:28:15211 base::RunLoop runloop_;
sorin6a57db92016-06-27 22:28:15212
Sorin Jianucc048f892017-07-26 02:05:54213 scoped_refptr<TestConfigurator> config_ =
214 base::MakeRefCounted<TestConfigurator>();
Tibor Goldschwendt5f173cb2018-06-21 22:50:40215 MockUpdateScheduler* scheduler_ = nullptr;
Sorin Jianucc048f892017-07-26 02:05:54216 scoped_refptr<MockUpdateClient> update_client_ =
217 base::MakeRefCounted<MockUpdateClient>();
sorin6a57db92016-06-27 22:28:15218 std::unique_ptr<ComponentUpdateService> component_updater_;
Sorin Jianu316232a2017-05-26 20:22:30219 ComponentUnpacker::Result result_;
sorin6a57db92016-06-27 22:28:15220};
221
Sorin Jianu08f92b3c2017-09-25 16:17:12222ComponentInstallerTest::ComponentInstallerTest() {
sorin6a57db92016-06-27 22:28:15223 EXPECT_CALL(update_client(), AddObserver(_)).Times(1);
Tibor Goldschwendt5f173cb2018-06-21 22:50:40224 auto scheduler = std::make_unique<MockUpdateScheduler>();
225 scheduler_ = scheduler.get();
226 ON_CALL(*scheduler_, Schedule(_, _, _, _))
227 .WillByDefault(Invoke(this, &ComponentInstallerTest::Schedule));
228 component_updater_ = std::make_unique<CrxUpdateService>(
229 config_, std::move(scheduler), update_client_);
sorin6a57db92016-06-27 22:28:15230}
231
Sorin Jianu08f92b3c2017-09-25 16:17:12232ComponentInstallerTest::~ComponentInstallerTest() {
sorin6a57db92016-06-27 22:28:15233 EXPECT_CALL(update_client(), RemoveObserver(_)).Times(1);
234 component_updater_.reset();
235}
236
Sorin Jianu08f92b3c2017-09-25 16:17:12237void ComponentInstallerTest::RunThreads() {
sorin6a57db92016-06-27 22:28:15238 runloop_.Run();
239}
240
Sorin Jianu08f92b3c2017-09-25 16:17:12241void ComponentInstallerTest::Unpack(const base::FilePath& crx_path) {
Joshua Pawlicki6d764422018-02-21 15:23:10242 auto config = base::MakeRefCounted<TestConfigurator>();
Sorin Jianu316232a2017-05-26 20:22:30243 auto component_unpacker = base::MakeRefCounted<ComponentUnpacker>(
244 std::vector<uint8_t>(std::begin(kSha256Hash), std::end(kSha256Hash)),
Joshua Pawlickif4b33f382018-08-17 17:36:51245 crx_path, nullptr, config->CreateServiceManagerConnector(),
246 crx_file::VerifierFormat::CRX2_OR_CRX3);
Sorin Jianua8ef73d2017-11-02 16:55:17247 component_unpacker->Unpack(base::BindOnce(
248 &ComponentInstallerTest::UnpackComplete, base::Unretained(this)));
Sorin Jianu316232a2017-05-26 20:22:30249 RunThreads();
250}
251
Sorin Jianu08f92b3c2017-09-25 16:17:12252void ComponentInstallerTest::UnpackComplete(
Sorin Jianu316232a2017-05-26 20:22:30253 const ComponentUnpacker::Result& result) {
254 result_ = result;
255
256 EXPECT_EQ(update_client::UnpackerError::kNone, result_.error);
257 EXPECT_EQ(0, result_.extended_error);
258
Sorin Jianua8ef73d2017-11-02 16:55:17259 main_thread_task_runner_->PostTask(FROM_HERE, quit_closure());
Sorin Jianu316232a2017-05-26 20:22:30260}
261
Tibor Goldschwendt5f173cb2018-06-21 22:50:40262void ComponentInstallerTest::Schedule(
263 const base::TimeDelta& initial_delay,
264 const base::TimeDelta& delay,
265 const UpdateScheduler::UserTask& user_task,
266 const UpdateScheduler::OnStopTaskCallback& on_stop) {
267 user_task.Run(base::DoNothing());
268}
269
sorin6a57db92016-06-27 22:28:15270} // namespace
271
Sorin Jianu08f92b3c2017-09-25 16:17:12272// Tests that the component metadata is propagated from the component installer
273// and its component policy, through the instance of the CrxComponent, to the
274// component updater service.
275TEST_F(ComponentInstallerTest, RegisterComponent) {
sorin6a57db92016-06-27 22:28:15276 class LoopHandler {
277 public:
Sorin Jianua8ef73d2017-11-02 16:55:17278 LoopHandler(int max_cnt, base::OnceClosure quit_closure)
279 : max_cnt_(max_cnt), quit_closure_(std::move(quit_closure)) {}
sorin6a57db92016-06-27 22:28:15280
281 void OnUpdate(const std::vector<std::string>& ids,
Vladislav Kuzkokov12eca792017-10-20 12:45:38282 const UpdateClient::CrxDataCallback& crx_data_callback) {
sorin6a57db92016-06-27 22:28:15283 static int cnt = 0;
284 ++cnt;
285 if (cnt >= max_cnt_)
Sorin Jianua8ef73d2017-11-02 16:55:17286 std::move(quit_closure_).Run();
sorin6a57db92016-06-27 22:28:15287 }
288
289 private:
290 const int max_cnt_;
Sorin Jianua8ef73d2017-11-02 16:55:17291 base::OnceClosure quit_closure_;
sorin6a57db92016-06-27 22:28:15292 };
293
Sorin Jianu0bf4bd3f2017-06-01 23:42:32294 base::ScopedPathOverride scoped_path_override(DIR_COMPONENT_USER);
295
sorin6a57db92016-06-27 22:28:15296 const std::string id("jebgalgnebhfojomionfpkfelancnnkf");
297
298 // Quit after one update check has been fired.
299 LoopHandler loop_handler(1, quit_closure());
Vladislav Kuzkokov12eca792017-10-20 12:45:38300 EXPECT_CALL(update_client(), DoUpdate(_, _))
sorin6a57db92016-06-27 22:28:15301 .WillRepeatedly(Invoke(&loop_handler, &LoopHandler::OnUpdate));
302
303 EXPECT_CALL(update_client(), GetCrxUpdateState(id, _)).Times(1);
304 EXPECT_CALL(update_client(), Stop()).Times(1);
Tibor Goldschwendt5f173cb2018-06-21 22:50:40305 EXPECT_CALL(scheduler(), Schedule(_, _, _, _)).Times(1);
306 EXPECT_CALL(scheduler(), Stop()).Times(1);
sorin6a57db92016-06-27 22:28:15307
Sorin Jianu08f92b3c2017-09-25 16:17:12308 auto installer = base::MakeRefCounted<ComponentInstaller>(
Sorin Jianua8926bf2018-03-09 21:02:53309 std::make_unique<MockInstallerPolicy>());
Sorin Jianua8ef73d2017-11-02 16:55:17310 installer->Register(component_updater(), base::OnceClosure());
sorin6a57db92016-06-27 22:28:15311
312 RunThreads();
313
314 CrxUpdateItem item;
315 EXPECT_TRUE(component_updater()->GetComponentDetails(id, &item));
Sorin Jianu73900242018-08-17 01:11:53316 ASSERT_TRUE(item.component);
317 const CrxComponent& component = *item.component;
sorin2adb2ca2016-06-29 01:44:35318
319 update_client::InstallerAttributes expected_attrs;
320 expected_attrs["ap"] = "fake-ap";
321 expected_attrs["is-enterprise"] = "1";
322
sorin6a57db92016-06-27 22:28:15323 EXPECT_EQ(
324 std::vector<uint8_t>(std::begin(kSha256Hash), std::end(kSha256Hash)),
325 component.pk_hash);
326 EXPECT_EQ(base::Version("0.0.0.0"), component.version);
327 EXPECT_TRUE(component.fingerprint.empty());
328 EXPECT_STREQ("fake name", component.name.c_str());
sorin2adb2ca2016-06-29 01:44:35329 EXPECT_EQ(expected_attrs, component.installer_attributes);
sorin6a57db92016-06-27 22:28:15330 EXPECT_TRUE(component.requires_network_encryption);
sorin098a4a72016-08-30 04:43:24331 EXPECT_TRUE(component.supports_group_policy_enable_component_updates);
sorin6a57db92016-06-27 22:28:15332}
333
Sorin Jianu316232a2017-05-26 20:22:30334// Tests that the unpack path is removed when the install succeeded.
Sorin Jianu08f92b3c2017-09-25 16:17:12335TEST_F(ComponentInstallerTest, UnpackPathInstallSuccess) {
336 auto installer = base::MakeRefCounted<ComponentInstaller>(
Sorin Jianua8926bf2018-03-09 21:02:53337 std::make_unique<MockInstallerPolicy>());
Sorin Jianu316232a2017-05-26 20:22:30338
339 Unpack(test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
340
341 const auto unpack_path = result().unpack_path;
342 EXPECT_TRUE(base::DirectoryExists(unpack_path));
Minh X. Nguyenaafd7632017-10-19 21:12:35343 EXPECT_EQ(update_client::jebg_public_key, result().public_key);
Sorin Jianu316232a2017-05-26 20:22:30344
Sorin Jianu316232a2017-05-26 20:22:30345 base::ScopedPathOverride scoped_path_override(DIR_COMPONENT_USER);
346 base::FilePath base_dir;
Avi Drissmanf617d012018-05-02 18:48:53347 EXPECT_TRUE(base::PathService::Get(DIR_COMPONENT_USER, &base_dir));
Sorin Jianu316232a2017-05-26 20:22:30348 base_dir = base_dir.Append(relative_install_dir);
349 EXPECT_TRUE(base::CreateDirectory(base_dir));
Sorin Jianuf40ab4b32017-10-06 22:53:41350 installer->Install(
Sorin Jianuea5534e92017-10-27 01:40:28351 unpack_path, update_client::jebg_public_key,
Sorin Jianua8ef73d2017-11-02 16:55:17352 base::BindOnce([](const update_client::CrxInstaller::Result& result) {
Sorin Jianuf40ab4b32017-10-06 22:53:41353 EXPECT_EQ(0, result.error);
354 }));
Sorin Jianu316232a2017-05-26 20:22:30355
Sorin Jianuf40ab4b32017-10-06 22:53:41356 scoped_task_environment_.RunUntilIdle();
357
358 EXPECT_FALSE(base::PathExists(unpack_path));
Sorin Jianu316232a2017-05-26 20:22:30359 EXPECT_CALL(update_client(), Stop()).Times(1);
Tibor Goldschwendt5f173cb2018-06-21 22:50:40360 EXPECT_CALL(scheduler(), Stop()).Times(1);
Sorin Jianu316232a2017-05-26 20:22:30361}
362
363// Tests that the unpack path is removed when the install failed.
Sorin Jianu08f92b3c2017-09-25 16:17:12364TEST_F(ComponentInstallerTest, UnpackPathInstallError) {
365 auto installer = base::MakeRefCounted<ComponentInstaller>(
Sorin Jianua8926bf2018-03-09 21:02:53366 std::make_unique<MockInstallerPolicy>());
Sorin Jianu316232a2017-05-26 20:22:30367
368 Unpack(test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
369
370 const auto unpack_path = result().unpack_path;
371 EXPECT_TRUE(base::DirectoryExists(unpack_path));
372
Sorin Jianu316232a2017-05-26 20:22:30373 // Test the precondition that DIR_COMPONENT_USER is not registered with
374 // the path service.
375 base::FilePath base_dir;
Avi Drissmanea15ea02018-05-07 18:55:12376 EXPECT_FALSE(base::PathService::Get(DIR_COMPONENT_USER, &base_dir));
Sorin Jianu316232a2017-05-26 20:22:30377
378 // Calling |Install| fails since DIR_COMPONENT_USER does not exist.
Sorin Jianuf40ab4b32017-10-06 22:53:41379 installer->Install(
Sorin Jianuea5534e92017-10-27 01:40:28380 unpack_path, update_client::jebg_public_key,
Sorin Jianua8ef73d2017-11-02 16:55:17381 base::BindOnce([](const update_client::CrxInstaller::Result& result) {
Sorin Jianuf40ab4b32017-10-06 22:53:41382 EXPECT_EQ(static_cast<int>(
383 update_client::InstallError::NO_DIR_COMPONENT_USER),
384 result.error);
385 }));
Sorin Jianu316232a2017-05-26 20:22:30386
Sorin Jianuf40ab4b32017-10-06 22:53:41387 scoped_task_environment_.RunUntilIdle();
388
389 EXPECT_FALSE(base::PathExists(unpack_path));
Sorin Jianu316232a2017-05-26 20:22:30390 EXPECT_CALL(update_client(), Stop()).Times(1);
Tibor Goldschwendt5f173cb2018-06-21 22:50:40391 EXPECT_CALL(scheduler(), Stop()).Times(1);
Sorin Jianu316232a2017-05-26 20:22:30392}
393
sorin6a57db92016-06-27 22:28:15394} // namespace component_updater