blob: 43ec49e91c5495471772aa88853f36c0c9301947 [file] [log] [blame]
sorin9797aba2015-04-17 17:15:031// Copyright 2015 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
dchengd0fc6aa92016-04-22 18:03:125#include <memory>
dcheng51ace48a2015-12-26 22:45:176#include <utility>
7
sorin9797aba2015-04-17 17:15:038#include "base/bind.h"
Sorin Jianuc303bf42018-09-07 16:19:339#include "base/containers/flat_map.h"
sorin9797aba2015-04-17 17:15:0310#include "base/files/file_path.h"
11#include "base/files/file_util.h"
12#include "base/location.h"
avi5dd91f82015-12-25 22:30:4613#include "base/macros.h"
sorin9797aba2015-04-17 17:15:0314#include "base/memory/ref_counted.h"
Sorin Jianu888ec292018-06-01 15:35:4215#include "base/optional.h"
sorin9797aba2015-04-17 17:15:0316#include "base/path_service.h"
17#include "base/run_loop.h"
Sorin Jianucb4431a2018-04-30 20:59:2418#include "base/stl_util.h"
Gabriel Charette44db1422018-08-06 11:19:3319#include "base/task/post_task.h"
20#include "base/task/task_traits.h"
Sorin Jianu4ab7c292017-06-15 18:40:2121#include "base/test/scoped_path_override.h"
fdoray03349c12017-05-17 18:06:5122#include "base/test/scoped_task_environment.h"
gab7966d312016-05-11 20:35:0123#include "base/threading/thread_task_runner_handle.h"
sorin9797aba2015-04-17 17:15:0324#include "base/values.h"
25#include "base/version.h"
Sorin Jianu188907072018-01-22 18:42:2226#include "build/build_config.h"
Joshua Pawlickif4b33f382018-08-17 17:36:5127#include "components/crx_file/crx_verifier.h"
wafflesd2d9a332016-04-09 01:59:5728#include "components/prefs/testing_pref_service.h"
Sorin Jianu4ab7c292017-06-15 18:40:2129#include "components/update_client/component_unpacker.h"
sorin9797aba2015-04-17 17:15:0330#include "components/update_client/crx_update_item.h"
wafflesd2d9a332016-04-09 01:59:5731#include "components/update_client/persisted_data.h"
sorin9797aba2015-04-17 17:15:0332#include "components/update_client/ping_manager.h"
sorin7cff6e52017-05-17 16:37:2333#include "components/update_client/protocol_parser.h"
sorinb120440b2015-04-27 16:34:1534#include "components/update_client/test_configurator.h"
35#include "components/update_client/test_installer.h"
sorin9797aba2015-04-17 17:15:0336#include "components/update_client/update_checker.h"
sorin7b8650522016-11-02 18:23:4137#include "components/update_client/update_client_errors.h"
sorin9797aba2015-04-17 17:15:0338#include "components/update_client/update_client_internal.h"
sorin9797aba2015-04-17 17:15:0339#include "testing/gmock/include/gmock/gmock.h"
40#include "testing/gtest/include/gtest/gtest.h"
41#include "url/gurl.h"
42
43namespace update_client {
44
45namespace {
46
47using base::FilePath;
48
49// Makes a copy of the file specified by |from_path| in a temporary directory
50// and returns the path of the copy. Returns true if successful. Cleans up if
51// there was an error creating the copy.
52bool MakeTestFile(const FilePath& from_path, FilePath* to_path) {
53 FilePath temp_dir;
54 bool result =
55 CreateNewTempDirectory(FILE_PATH_LITERAL("update_client"), &temp_dir);
56 if (!result)
57 return false;
58
59 FilePath temp_file;
60 result = CreateTemporaryFileInDir(temp_dir, &temp_file);
61 if (!result)
62 return false;
63
64 result = CopyFile(from_path, temp_file);
65 if (!result) {
66 DeleteFile(temp_file, false);
67 return false;
68 }
69
70 *to_path = temp_file;
71 return true;
72}
73
74using Events = UpdateClient::Observer::Events;
75
76class MockObserver : public UpdateClient::Observer {
77 public:
78 MOCK_METHOD2(OnEvent, void(Events event, const std::string&));
79};
80
sorin30474f02017-04-27 00:45:4881} // namespace
sorin7c717622015-05-26 19:59:0982
sorin30474f02017-04-27 00:45:4883using ::testing::_;
84using ::testing::AtLeast;
85using ::testing::AnyNumber;
86using ::testing::DoAll;
87using ::testing::InSequence;
88using ::testing::Invoke;
89using ::testing::Mock;
90using ::testing::Return;
sorin7c717622015-05-26 19:59:0991
sorin30474f02017-04-27 00:45:4892using std::string;
sorin7c717622015-05-26 19:59:0993
Sorin Jianua8926bf2018-03-09 21:02:5394class MockPingManagerImpl : public PingManager {
sorin9797aba2015-04-17 17:15:0395 public:
sorin30474f02017-04-27 00:45:4896 struct PingData {
97 std::string id;
98 base::Version previous_version;
99 base::Version next_version;
Minh X. Nguyena4640cb2018-05-23 21:29:10100 ErrorCategory error_category = ErrorCategory::kNone;
sorin30474f02017-04-27 00:45:48101 int error_code = 0;
102 int extra_code1 = 0;
Minh X. Nguyena4640cb2018-05-23 21:29:10103 ErrorCategory diff_error_category = ErrorCategory::kNone;
sorin30474f02017-04-27 00:45:48104 int diff_error_code = 0;
105 bool diff_update_failed = false;
106 };
107
Sorin Jianua8926bf2018-03-09 21:02:53108 explicit MockPingManagerImpl(scoped_refptr<Configurator> config);
sorin9797aba2015-04-17 17:15:03109
Sorin Jianu560d5022018-02-12 23:11:54110 void SendPing(const Component& component, Callback callback) override;
sorin9797aba2015-04-17 17:15:03111
sorin30474f02017-04-27 00:45:48112 const std::vector<PingData>& ping_data() const;
sorin9797aba2015-04-17 17:15:03113
Sorin Jianu039032b2018-10-12 21:48:13114 const std::vector<base::Value>& events() const;
Sorin Jianu4ab7c292017-06-15 18:40:21115
Sorin Jianu560d5022018-02-12 23:11:54116 protected:
Sorin Jianua8926bf2018-03-09 21:02:53117 ~MockPingManagerImpl() override;
Sorin Jianu560d5022018-02-12 23:11:54118
sorin9797aba2015-04-17 17:15:03119 private:
sorin30474f02017-04-27 00:45:48120 std::vector<PingData> ping_data_;
Sorin Jianu039032b2018-10-12 21:48:13121 std::vector<base::Value> events_;
Sorin Jianua8926bf2018-03-09 21:02:53122 DISALLOW_COPY_AND_ASSIGN(MockPingManagerImpl);
sorin9797aba2015-04-17 17:15:03123};
124
Sorin Jianua8926bf2018-03-09 21:02:53125MockPingManagerImpl::MockPingManagerImpl(scoped_refptr<Configurator> config)
sorin958b5d32016-01-09 02:00:20126 : PingManager(config) {}
sorin9797aba2015-04-17 17:15:03127
Sorin Jianua8926bf2018-03-09 21:02:53128MockPingManagerImpl::~MockPingManagerImpl() {}
sorin9797aba2015-04-17 17:15:03129
Sorin Jianua8926bf2018-03-09 21:02:53130void MockPingManagerImpl::SendPing(const Component& component,
Sorin Jianu560d5022018-02-12 23:11:54131 Callback callback) {
sorin30474f02017-04-27 00:45:48132 PingData ping_data;
133 ping_data.id = component.id_;
134 ping_data.previous_version = component.previous_version_;
135 ping_data.next_version = component.next_version_;
136 ping_data.error_category = component.error_category_;
137 ping_data.error_code = component.error_code_;
138 ping_data.extra_code1 = component.extra_code1_;
139 ping_data.diff_error_category = component.diff_error_category_;
140 ping_data.diff_error_code = component.diff_error_code_;
141 ping_data.diff_update_failed = component.diff_update_failed();
142 ping_data_.push_back(ping_data);
Sorin Jianu4ab7c292017-06-15 18:40:21143
Sorin Jianu039032b2018-10-12 21:48:13144 events_ = component.GetEvents();
Sorin Jianu4ab7c292017-06-15 18:40:21145
Sorin Jianu560d5022018-02-12 23:11:54146 std::move(callback).Run(0, "");
sorin9797aba2015-04-17 17:15:03147}
148
Sorin Jianua8926bf2018-03-09 21:02:53149const std::vector<MockPingManagerImpl::PingData>&
150MockPingManagerImpl::ping_data() const {
sorin30474f02017-04-27 00:45:48151 return ping_data_;
sorin9797aba2015-04-17 17:15:03152}
153
Sorin Jianu039032b2018-10-12 21:48:13154const std::vector<base::Value>& MockPingManagerImpl::events() const {
Sorin Jianu4ab7c292017-06-15 18:40:21155 return events_;
156}
157
sorin9797aba2015-04-17 17:15:03158class UpdateClientTest : public testing::Test {
159 public:
160 UpdateClientTest();
161 ~UpdateClientTest() override;
162
sorin9797aba2015-04-17 17:15:03163 protected:
164 void RunThreads();
165
166 // Returns the full path to a test file.
167 static base::FilePath TestFilePath(const char* file);
168
sorine84ff702016-08-04 01:22:02169 scoped_refptr<update_client::TestConfigurator> config() { return config_; }
wafflese7dff732016-04-15 23:51:49170 update_client::PersistedData* metadata() { return metadata_.get(); }
sorin9797aba2015-04-17 17:15:03171
Sorin Jianua8ef73d2017-11-02 16:55:17172 base::OnceClosure quit_closure() { return runloop_.QuitClosure(); }
sorinf9f4834d2015-04-28 17:15:02173
174 private:
sorin30474f02017-04-27 00:45:48175 static constexpr int kNumWorkerThreads_ = 2;
sorinf9f4834d2015-04-28 17:15:02176
fdoray03349c12017-05-17 18:06:51177 base::test::ScopedTaskEnvironment scoped_task_environment_;
sorin9797aba2015-04-17 17:15:03178 base::RunLoop runloop_;
sorin9797aba2015-04-17 17:15:03179
Sorin Jianucc048f892017-07-26 02:05:54180 scoped_refptr<update_client::TestConfigurator> config_ =
181 base::MakeRefCounted<TestConfigurator>();
182 std::unique_ptr<TestingPrefServiceSimple> pref_ =
Jinho Bangda4e4282018-01-03 13:21:23183 std::make_unique<TestingPrefServiceSimple>();
wafflesd2d9a332016-04-09 01:59:57184 std::unique_ptr<update_client::PersistedData> metadata_;
sorinf9f4834d2015-04-28 17:15:02185
sorin9797aba2015-04-17 17:15:03186 DISALLOW_COPY_AND_ASSIGN(UpdateClientTest);
187};
188
sorin30474f02017-04-27 00:45:48189constexpr int UpdateClientTest::kNumWorkerThreads_;
190
Sorin Jianucc048f892017-07-26 02:05:54191UpdateClientTest::UpdateClientTest() {
wafflesd2d9a332016-04-09 01:59:57192 PersistedData::RegisterPrefs(pref_->registry());
Jinho Bangda4e4282018-01-03 13:21:23193 metadata_ = std::make_unique<PersistedData>(pref_.get(), nullptr);
sorin9797aba2015-04-17 17:15:03194}
195
196UpdateClientTest::~UpdateClientTest() {
sorin9797aba2015-04-17 17:15:03197}
198
199void UpdateClientTest::RunThreads() {
200 runloop_.Run();
Sorin Jianuf40ab4b32017-10-06 22:53:41201 scoped_task_environment_.RunUntilIdle();
sorin9797aba2015-04-17 17:15:03202}
203
204base::FilePath UpdateClientTest::TestFilePath(const char* file) {
205 base::FilePath path;
Avi Drissmanf617d012018-05-02 18:48:53206 base::PathService::Get(base::DIR_SOURCE_ROOT, &path);
sorin9797aba2015-04-17 17:15:03207 return path.AppendASCII("components")
208 .AppendASCII("test")
209 .AppendASCII("data")
210 .AppendASCII("update_client")
211 .AppendASCII(file);
212}
213
214// Tests the scenario where one update check is done for one CRX. The CRX
215// has no update.
216TEST_F(UpdateClientTest, OneCrxNoUpdate) {
Sorin Jianua8926bf2018-03-09 21:02:53217 class DataCallbackMock {
sorin9797aba2015-04-17 17:15:03218 public:
Sorin Jianu73900242018-08-17 01:11:53219 static std::vector<base::Optional<CrxComponent>> Callback(
Sorin Jianu7c22795b2018-04-26 22:16:52220 const std::vector<std::string>& ids) {
Sorin Jianu73900242018-08-17 01:11:53221 CrxComponent crx;
222 crx.name = "test_jebg";
223 crx.pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
224 crx.version = base::Version("0.9");
225 crx.installer = base::MakeRefCounted<TestInstaller>();
Joshua Pawlickif4b33f382018-08-17 17:36:51226 crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
Sorin Jianu73900242018-08-17 01:11:53227 std::vector<base::Optional<CrxComponent>> component = {crx};
Sorin Jianu7c22795b2018-04-26 22:16:52228 return component;
sorin9797aba2015-04-17 17:15:03229 }
230 };
231
Sorin Jianua8926bf2018-03-09 21:02:53232 class CompletionCallbackMock {
sorin9797aba2015-04-17 17:15:03233 public:
Sorin Jianua8ef73d2017-11-02 16:55:17234 static void Callback(base::OnceClosure quit_closure, Error error) {
sorin7b8650522016-11-02 18:23:41235 EXPECT_EQ(Error::NONE, error);
Sorin Jianua8ef73d2017-11-02 16:55:17236 std::move(quit_closure).Run();
sorin9797aba2015-04-17 17:15:03237 }
238 };
239
Sorin Jianua8926bf2018-03-09 21:02:53240 class MockUpdateChecker : public UpdateChecker {
sorin9797aba2015-04-17 17:15:03241 public:
dchengd0fc6aa92016-04-22 18:03:12242 static std::unique_ptr<UpdateChecker> Create(
Sorin Jianu49126332018-02-13 17:07:42243 scoped_refptr<Configurator> config,
wafflese7dff732016-04-15 23:51:49244 PersistedData* metadata) {
Sorin Jianua8926bf2018-03-09 21:02:53245 return std::make_unique<MockUpdateChecker>();
sorin9797aba2015-04-17 17:15:03246 }
247
Sorin Jianuc303bf42018-09-07 16:19:33248 void CheckForUpdates(
249 const std::string& session_id,
250 const std::vector<std::string>& ids_to_check,
251 const IdToComponentPtrMap& components,
252 const base::flat_map<std::string, std::string>& additional_attributes,
253 bool enabled_component_updates,
254 UpdateCheckCallback update_check_callback) override {
Sorin Jianud69d4372018-02-07 19:44:22255 EXPECT_FALSE(session_id.empty());
sorin590921d2016-08-11 23:48:36256 EXPECT_TRUE(enabled_component_updates);
sorin30474f02017-04-27 00:45:48257 EXPECT_EQ(1u, ids_to_check.size());
258 const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
259 EXPECT_EQ(id, ids_to_check.front());
260 EXPECT_EQ(1u, components.count(id));
261
262 auto& component = components.at(id);
263
Sorin Jianub41a592a2018-03-02 16:30:27264 EXPECT_TRUE(component->is_foreground());
sorin30474f02017-04-27 00:45:48265
sorin7cff6e52017-05-17 16:37:23266 ProtocolParser::Result result;
sorin30474f02017-04-27 00:45:48267 result.extension_id = id;
268 result.status = "noupdate";
Sorin Jianu888ec292018-06-01 15:35:42269
270 ProtocolParser::Results results;
271 results.list.push_back(result);
sorin30474f02017-04-27 00:45:48272
sorin9797aba2015-04-17 17:15:03273 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianuaa4165532018-06-08 19:46:46274 FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
275 ErrorCategory::kNone, 0, 0));
sorin9797aba2015-04-17 17:15:03276 }
277 };
278
Sorin Jianua8926bf2018-03-09 21:02:53279 class MockCrxDownloader : public CrxDownloader {
sorin9797aba2015-04-17 17:15:03280 public:
dchengd0fc6aa92016-04-22 18:03:12281 static std::unique_ptr<CrxDownloader> Create(
sorin9797aba2015-04-17 17:15:03282 bool is_background_download,
Antonio Gomes0807dd62018-08-10 14:28:47283 scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
Sorin Jianua8926bf2018-03-09 21:02:53284 return std::make_unique<MockCrxDownloader>();
sorin9797aba2015-04-17 17:15:03285 }
286
Sorin Jianua8926bf2018-03-09 21:02:53287 MockCrxDownloader() : CrxDownloader(nullptr) {}
sorin9797aba2015-04-17 17:15:03288
sorin30474f02017-04-27 00:45:48289 private:
sorin9797aba2015-04-17 17:15:03290 void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); }
291 };
292
Sorin Jianua8926bf2018-03-09 21:02:53293 class MockPingManager : public MockPingManagerImpl {
sorin9797aba2015-04-17 17:15:03294 public:
Sorin Jianua8926bf2018-03-09 21:02:53295 explicit MockPingManager(scoped_refptr<Configurator> config)
296 : MockPingManagerImpl(config) {}
Sorin Jianu560d5022018-02-12 23:11:54297
298 protected:
Sorin Jianua8926bf2018-03-09 21:02:53299 ~MockPingManager() override { EXPECT_TRUE(ping_data().empty()); }
sorin9797aba2015-04-17 17:15:03300 };
301
sorin30474f02017-04-27 00:45:48302 scoped_refptr<UpdateClient> update_client =
Taiju Tsuiki36c517d2017-05-18 06:45:43303 base::MakeRefCounted<UpdateClientImpl>(
Sorin Jianua8926bf2018-03-09 21:02:53304 config(), base::MakeRefCounted<MockPingManager>(config()),
305 &MockUpdateChecker::Create, &MockCrxDownloader::Create);
sorin7c717622015-05-26 19:59:09306
sorin9797aba2015-04-17 17:15:03307 MockObserver observer;
308 InSequence seq;
309 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
310 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
311 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED,
312 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
313
314 update_client->AddObserver(&observer);
315
sorin30474f02017-04-27 00:45:48316 const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf"};
sorin9797aba2015-04-17 17:15:03317 update_client->Update(
Sorin Jianua8926bf2018-03-09 21:02:53318 ids, base::BindOnce(&DataCallbackMock::Callback), true,
319 base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
sorin9797aba2015-04-17 17:15:03320
321 RunThreads();
322
323 update_client->RemoveObserver(&observer);
324}
325
326// Tests the scenario where two CRXs are checked for updates. On CRX has
327// an update, the other CRX does not.
328TEST_F(UpdateClientTest, TwoCrxUpdateNoUpdate) {
Sorin Jianua8926bf2018-03-09 21:02:53329 class DataCallbackMock {
sorin9797aba2015-04-17 17:15:03330 public:
Sorin Jianu73900242018-08-17 01:11:53331 static std::vector<base::Optional<CrxComponent>> Callback(
Sorin Jianu7c22795b2018-04-26 22:16:52332 const std::vector<std::string>& ids) {
Sorin Jianu73900242018-08-17 01:11:53333 CrxComponent crx1;
334 crx1.name = "test_jebg";
335 crx1.pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
336 crx1.version = base::Version("0.9");
337 crx1.installer = base::MakeRefCounted<TestInstaller>();
Joshua Pawlickif4b33f382018-08-17 17:36:51338 crx1.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
sorin9797aba2015-04-17 17:15:03339
Sorin Jianu73900242018-08-17 01:11:53340 CrxComponent crx2;
341 crx2.name = "test_abag";
342 crx2.pk_hash.assign(abag_hash, abag_hash + base::size(abag_hash));
343 crx2.version = base::Version("2.2");
344 crx2.installer = base::MakeRefCounted<TestInstaller>();
Joshua Pawlickif4b33f382018-08-17 17:36:51345 crx2.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
sorin9797aba2015-04-17 17:15:03346
Sorin Jianu73900242018-08-17 01:11:53347 return {crx1, crx2};
sorin9797aba2015-04-17 17:15:03348 }
349 };
350
Sorin Jianua8926bf2018-03-09 21:02:53351 class CompletionCallbackMock {
sorin9797aba2015-04-17 17:15:03352 public:
Sorin Jianua8ef73d2017-11-02 16:55:17353 static void Callback(base::OnceClosure quit_closure, Error error) {
sorin7b8650522016-11-02 18:23:41354 EXPECT_EQ(Error::NONE, error);
Sorin Jianua8ef73d2017-11-02 16:55:17355 std::move(quit_closure).Run();
sorin9797aba2015-04-17 17:15:03356 }
357 };
358
Sorin Jianua8926bf2018-03-09 21:02:53359 class MockUpdateChecker : public UpdateChecker {
sorin9797aba2015-04-17 17:15:03360 public:
dchengd0fc6aa92016-04-22 18:03:12361 static std::unique_ptr<UpdateChecker> Create(
Sorin Jianu49126332018-02-13 17:07:42362 scoped_refptr<Configurator> config,
wafflese7dff732016-04-15 23:51:49363 PersistedData* metadata) {
Sorin Jianua8926bf2018-03-09 21:02:53364 return std::make_unique<MockUpdateChecker>();
sorin9797aba2015-04-17 17:15:03365 }
366
Sorin Jianuc303bf42018-09-07 16:19:33367 void CheckForUpdates(
368 const std::string& session_id,
369 const std::vector<std::string>& ids_to_check,
370 const IdToComponentPtrMap& components,
371 const base::flat_map<std::string, std::string>& additional_attributes,
372 bool enabled_component_updates,
373 UpdateCheckCallback update_check_callback) override {
sorin9797aba2015-04-17 17:15:03374 /*
Sorin Jianua8926bf2018-03-09 21:02:53375 Mock the following response:
sorin9797aba2015-04-17 17:15:03376
377 <?xml version='1.0' encoding='UTF-8'?>
sorin39852802017-05-01 22:46:28378 <response protocol='3.1'>
sorin9797aba2015-04-17 17:15:03379 <app appid='jebgalgnebhfojomionfpkfelancnnkf'>
380 <updatecheck status='ok'>
381 <urls>
382 <url codebase='http://localhost/download/'/>
383 </urls>
384 <manifest version='1.0' prodversionmin='11.0.1.0'>
385 <packages>
sorin74e70672016-02-03 03:13:10386 <package name='jebgalgnebhfojomionfpkfelancnnkf.crx'
387 hash_sha256='6fc4b93fd11134de1300c2c0bb88c12b644a4ec0fd
388 7c9b12cb7cc067667bde87'/>
sorin9797aba2015-04-17 17:15:03389 </packages>
390 </manifest>
391 </updatecheck>
392 </app>
Sorin Jianu888ec292018-06-01 15:35:42393 <app appid='abagagagagagagagagagagagagagagag'>
394 <updatecheck status='noupdate'/>
395 </app>
sorin9797aba2015-04-17 17:15:03396 </response>
397 */
Sorin Jianud69d4372018-02-07 19:44:22398 EXPECT_FALSE(session_id.empty());
sorin30474f02017-04-27 00:45:48399 EXPECT_TRUE(enabled_component_updates);
400 EXPECT_EQ(2u, ids_to_check.size());
sorin9797aba2015-04-17 17:15:03401
Sorin Jianu888ec292018-06-01 15:35:42402 ProtocolParser::Results results;
sorin30474f02017-04-27 00:45:48403 {
404 const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
405 EXPECT_EQ(id, ids_to_check[0]);
406 EXPECT_EQ(1u, components.count(id));
407
sorin7cff6e52017-05-17 16:37:23408 ProtocolParser::Result::Manifest::Package package;
sorin30474f02017-04-27 00:45:48409 package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
410 package.hash_sha256 =
411 "6fc4b93fd11134de1300c2c0bb88c12b644a4ec0fd7c9b12cb7cc067667bde87";
412
sorin7cff6e52017-05-17 16:37:23413 ProtocolParser::Result result;
sorin30474f02017-04-27 00:45:48414 result.extension_id = "jebgalgnebhfojomionfpkfelancnnkf";
415 result.status = "ok";
416 result.crx_urls.push_back(GURL("http://localhost/download/"));
417 result.manifest.version = "1.0";
418 result.manifest.browser_min_version = "11.0.1.0";
419 result.manifest.packages.push_back(package);
Sorin Jianu888ec292018-06-01 15:35:42420 results.list.push_back(result);
sorin30474f02017-04-27 00:45:48421
Sorin Jianu888ec292018-06-01 15:35:42422 EXPECT_FALSE(components.at(id)->is_foreground());
sorin30474f02017-04-27 00:45:48423 }
424
425 {
426 const std::string id = "abagagagagagagagagagagagagagagag";
427 EXPECT_EQ(id, ids_to_check[1]);
428 EXPECT_EQ(1u, components.count(id));
429
sorin7cff6e52017-05-17 16:37:23430 ProtocolParser::Result result;
sorin30474f02017-04-27 00:45:48431 result.extension_id = id;
432 result.status = "noupdate";
Sorin Jianu888ec292018-06-01 15:35:42433 results.list.push_back(result);
sorin30474f02017-04-27 00:45:48434
Sorin Jianu888ec292018-06-01 15:35:42435 EXPECT_FALSE(components.at(id)->is_foreground());
sorin30474f02017-04-27 00:45:48436 }
sorin9797aba2015-04-17 17:15:03437
438 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianuaa4165532018-06-08 19:46:46439 FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
440 ErrorCategory::kNone, 0, 0));
sorin9797aba2015-04-17 17:15:03441 }
442 };
443
Sorin Jianua8926bf2018-03-09 21:02:53444 class MockCrxDownloader : public CrxDownloader {
sorin9797aba2015-04-17 17:15:03445 public:
dchengd0fc6aa92016-04-22 18:03:12446 static std::unique_ptr<CrxDownloader> Create(
sorin9797aba2015-04-17 17:15:03447 bool is_background_download,
Antonio Gomes0807dd62018-08-10 14:28:47448 scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
Sorin Jianua8926bf2018-03-09 21:02:53449 return std::make_unique<MockCrxDownloader>();
sorin9797aba2015-04-17 17:15:03450 }
451
Sorin Jianua8926bf2018-03-09 21:02:53452 MockCrxDownloader() : CrxDownloader(nullptr) {}
sorin9797aba2015-04-17 17:15:03453
sorin30474f02017-04-27 00:45:48454 private:
sorin9797aba2015-04-17 17:15:03455 void DoStartDownload(const GURL& url) override {
456 DownloadMetrics download_metrics;
457 download_metrics.url = url;
458 download_metrics.downloader = DownloadMetrics::kNone;
459 download_metrics.error = 0;
460 download_metrics.downloaded_bytes = 1843;
461 download_metrics.total_bytes = 1843;
462 download_metrics.download_time_ms = 1000;
463
464 FilePath path;
465 EXPECT_TRUE(MakeTestFile(
466 TestFilePath("jebgalgnebhfojomionfpkfelancnnkf.crx"), &path));
467
468 Result result;
469 result.error = 0;
470 result.response = path;
sorin9797aba2015-04-17 17:15:03471
472 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianua8926bf2018-03-09 21:02:53473 FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadProgress,
Antonio Gomes31237fb2018-08-27 19:11:03474 base::Unretained(this)));
sorin9797aba2015-04-17 17:15:03475
476 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianua8926bf2018-03-09 21:02:53477 FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadComplete,
Sorin Jianuebd652462017-07-23 02:00:58478 base::Unretained(this), true, result,
479 download_metrics));
sorin9797aba2015-04-17 17:15:03480 }
481 };
482
Sorin Jianua8926bf2018-03-09 21:02:53483 class MockPingManager : public MockPingManagerImpl {
sorin9797aba2015-04-17 17:15:03484 public:
Sorin Jianua8926bf2018-03-09 21:02:53485 explicit MockPingManager(scoped_refptr<Configurator> config)
486 : MockPingManagerImpl(config) {}
Sorin Jianu560d5022018-02-12 23:11:54487
488 protected:
Sorin Jianua8926bf2018-03-09 21:02:53489 ~MockPingManager() override {
490 const auto ping_data = MockPingManagerImpl::ping_data();
sorin30474f02017-04-27 00:45:48491 EXPECT_EQ(1u, ping_data.size());
492 EXPECT_EQ("jebgalgnebhfojomionfpkfelancnnkf", ping_data[0].id);
493 EXPECT_EQ(base::Version("0.9"), ping_data[0].previous_version);
494 EXPECT_EQ(base::Version("1.0"), ping_data[0].next_version);
Minh X. Nguyena4640cb2018-05-23 21:29:10495 EXPECT_EQ(0, static_cast<int>(ping_data[0].error_category));
sorin30474f02017-04-27 00:45:48496 EXPECT_EQ(0, ping_data[0].error_code);
sorin9797aba2015-04-17 17:15:03497 }
498 };
499
sorin30474f02017-04-27 00:45:48500 scoped_refptr<UpdateClient> update_client =
Taiju Tsuiki36c517d2017-05-18 06:45:43501 base::MakeRefCounted<UpdateClientImpl>(
Sorin Jianua8926bf2018-03-09 21:02:53502 config(), base::MakeRefCounted<MockPingManager>(config()),
503 &MockUpdateChecker::Create, &MockCrxDownloader::Create);
sorin9797aba2015-04-17 17:15:03504
505 MockObserver observer;
506 {
507 InSequence seq;
508 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
509 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
510 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
511 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
512 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
sorin30474f02017-04-27 00:45:48513 "jebgalgnebhfojomionfpkfelancnnkf"))
514 .Times(AtLeast(1));
sorin9797aba2015-04-17 17:15:03515 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
516 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
517 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED,
518 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
519 }
520 {
521 InSequence seq;
522 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
523 "abagagagagagagagagagagagagagagag")).Times(1);
524 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED,
525 "abagagagagagagagagagagagagagagag")).Times(1);
526 }
527
528 update_client->AddObserver(&observer);
529
sorin30474f02017-04-27 00:45:48530 const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf",
531 "abagagagagagagagagagagagagagagag"};
sorin9797aba2015-04-17 17:15:03532 update_client->Update(
Sorin Jianua8926bf2018-03-09 21:02:53533 ids, base::BindOnce(&DataCallbackMock::Callback), false,
534 base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
sorin9797aba2015-04-17 17:15:03535
536 RunThreads();
537
538 update_client->RemoveObserver(&observer);
539}
540
Sorin Jianu888ec292018-06-01 15:35:42541// Tests the scenario where two CRXs are checked for updates. One CRX has
542// an update but the server ignores the second CRX and returns no response for
543// it. The second component gets an |UPDATE_RESPONSE_NOT_FOUND| error and
544// transitions to the error state.
545TEST_F(UpdateClientTest, TwoCrxUpdateFirstServerIgnoresSecond) {
546 class DataCallbackMock {
547 public:
Sorin Jianu73900242018-08-17 01:11:53548 static std::vector<base::Optional<CrxComponent>> Callback(
Sorin Jianu888ec292018-06-01 15:35:42549 const std::vector<std::string>& ids) {
Sorin Jianu73900242018-08-17 01:11:53550 CrxComponent crx1;
551 crx1.name = "test_jebg";
552 crx1.pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
553 crx1.version = base::Version("0.9");
554 crx1.installer = base::MakeRefCounted<TestInstaller>();
Joshua Pawlickif4b33f382018-08-17 17:36:51555 crx1.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
Sorin Jianu888ec292018-06-01 15:35:42556
Sorin Jianu73900242018-08-17 01:11:53557 CrxComponent crx2;
558 crx2.name = "test_abag";
559 crx2.pk_hash.assign(abag_hash, abag_hash + base::size(abag_hash));
560 crx2.version = base::Version("2.2");
561 crx2.installer = base::MakeRefCounted<TestInstaller>();
Joshua Pawlickif4b33f382018-08-17 17:36:51562 crx2.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
Sorin Jianu888ec292018-06-01 15:35:42563
Sorin Jianu73900242018-08-17 01:11:53564 return {crx1, crx2};
Sorin Jianu888ec292018-06-01 15:35:42565 }
566 };
567
568 class CompletionCallbackMock {
569 public:
570 static void Callback(base::OnceClosure quit_closure, Error error) {
571 EXPECT_EQ(Error::NONE, error);
572 std::move(quit_closure).Run();
573 }
574 };
575
576 class MockUpdateChecker : public UpdateChecker {
577 public:
578 static std::unique_ptr<UpdateChecker> Create(
579 scoped_refptr<Configurator> config,
580 PersistedData* metadata) {
581 return std::make_unique<MockUpdateChecker>();
582 }
583
Sorin Jianuc303bf42018-09-07 16:19:33584 void CheckForUpdates(
585 const std::string& session_id,
586 const std::vector<std::string>& ids_to_check,
587 const IdToComponentPtrMap& components,
588 const base::flat_map<std::string, std::string>& additional_attributes,
589 bool enabled_component_updates,
590 UpdateCheckCallback update_check_callback) override {
Sorin Jianu888ec292018-06-01 15:35:42591 /*
592 Mock the following response:
593
594 <?xml version='1.0' encoding='UTF-8'?>
595 <response protocol='3.1'>
596 <app appid='jebgalgnebhfojomionfpkfelancnnkf'>
597 <updatecheck status='ok'>
598 <urls>
599 <url codebase='http://localhost/download/'/>
600 </urls>
601 <manifest version='1.0' prodversionmin='11.0.1.0'>
602 <packages>
603 <package name='jebgalgnebhfojomionfpkfelancnnkf.crx'
604 hash_sha256='6fc4b93fd11134de1300c2c0bb88c12b644a4ec0fd
605 7c9b12cb7cc067667bde87'/>
606 </packages>
607 </manifest>
608 </updatecheck>
609 </app>
610 </response>
611 */
612 EXPECT_FALSE(session_id.empty());
613 EXPECT_TRUE(enabled_component_updates);
614 EXPECT_EQ(2u, ids_to_check.size());
615
616 ProtocolParser::Results results;
617 {
618 const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
619 EXPECT_EQ(id, ids_to_check[0]);
620 EXPECT_EQ(1u, components.count(id));
621
622 ProtocolParser::Result::Manifest::Package package;
623 package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
624 package.hash_sha256 =
625 "6fc4b93fd11134de1300c2c0bb88c12b644a4ec0fd7c9b12cb7cc067667bde87";
626
627 ProtocolParser::Result result;
628 result.extension_id = "jebgalgnebhfojomionfpkfelancnnkf";
629 result.status = "ok";
630 result.crx_urls.push_back(GURL("http://localhost/download/"));
631 result.manifest.version = "1.0";
632 result.manifest.browser_min_version = "11.0.1.0";
633 result.manifest.packages.push_back(package);
634 results.list.push_back(result);
635
636 EXPECT_FALSE(components.at(id)->is_foreground());
637 }
638
639 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianuaa4165532018-06-08 19:46:46640 FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
641 ErrorCategory::kNone, 0, 0));
Sorin Jianu888ec292018-06-01 15:35:42642 }
643 };
644
645 class MockCrxDownloader : public CrxDownloader {
646 public:
647 static std::unique_ptr<CrxDownloader> Create(
648 bool is_background_download,
Antonio Gomes0807dd62018-08-10 14:28:47649 scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
Sorin Jianu888ec292018-06-01 15:35:42650 return std::make_unique<MockCrxDownloader>();
651 }
652
653 MockCrxDownloader() : CrxDownloader(nullptr) {}
654
655 private:
656 void DoStartDownload(const GURL& url) override {
657 DownloadMetrics download_metrics;
658 download_metrics.url = url;
659 download_metrics.downloader = DownloadMetrics::kNone;
660 download_metrics.error = 0;
661 download_metrics.downloaded_bytes = 1843;
662 download_metrics.total_bytes = 1843;
663 download_metrics.download_time_ms = 1000;
664
665 FilePath path;
666 EXPECT_TRUE(MakeTestFile(
667 TestFilePath("jebgalgnebhfojomionfpkfelancnnkf.crx"), &path));
668
669 Result result;
670 result.error = 0;
671 result.response = path;
Sorin Jianu888ec292018-06-01 15:35:42672
673 base::ThreadTaskRunnerHandle::Get()->PostTask(
674 FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadProgress,
Antonio Gomes31237fb2018-08-27 19:11:03675 base::Unretained(this)));
Sorin Jianu888ec292018-06-01 15:35:42676
677 base::ThreadTaskRunnerHandle::Get()->PostTask(
678 FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadComplete,
679 base::Unretained(this), true, result,
680 download_metrics));
681 }
682 };
683
684 class MockPingManager : public MockPingManagerImpl {
685 public:
686 explicit MockPingManager(scoped_refptr<Configurator> config)
687 : MockPingManagerImpl(config) {}
688
689 protected:
690 ~MockPingManager() override {
691 const auto ping_data = MockPingManagerImpl::ping_data();
692 EXPECT_EQ(1u, ping_data.size());
693 EXPECT_EQ("jebgalgnebhfojomionfpkfelancnnkf", ping_data[0].id);
694 EXPECT_EQ(base::Version("0.9"), ping_data[0].previous_version);
695 EXPECT_EQ(base::Version("1.0"), ping_data[0].next_version);
696 EXPECT_EQ(0, static_cast<int>(ping_data[0].error_category));
697 EXPECT_EQ(0, ping_data[0].error_code);
698 }
699 };
700
701 scoped_refptr<UpdateClient> update_client =
702 base::MakeRefCounted<UpdateClientImpl>(
703 config(), base::MakeRefCounted<MockPingManager>(config()),
704 &MockUpdateChecker::Create, &MockCrxDownloader::Create);
705
706 MockObserver observer;
707 {
708 InSequence seq;
709 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
710 "jebgalgnebhfojomionfpkfelancnnkf"))
711 .Times(1);
712 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
713 "jebgalgnebhfojomionfpkfelancnnkf"))
714 .Times(1);
715 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
716 "jebgalgnebhfojomionfpkfelancnnkf"))
717 .Times(AtLeast(1));
718 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
719 "jebgalgnebhfojomionfpkfelancnnkf"))
720 .Times(1);
721 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED,
722 "jebgalgnebhfojomionfpkfelancnnkf"))
723 .Times(1);
724 }
725 {
726 InSequence seq;
727 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
728 "abagagagagagagagagagagagagagagag"))
729 .Times(1);
730 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
731 "abagagagagagagagagagagagagagagag"))
732 .Times(1)
733 .WillOnce(Invoke([&update_client](Events event, const std::string& id) {
734 CrxUpdateItem item;
Sorin Jianu73900242018-08-17 01:11:53735 EXPECT_TRUE(update_client->GetCrxUpdateState(id, &item));
Sorin Jianu888ec292018-06-01 15:35:42736 EXPECT_EQ(ComponentState::kUpdateError, item.state);
737 EXPECT_EQ(5, static_cast<int>(item.error_category));
738 EXPECT_EQ(-10004, item.error_code);
739 EXPECT_EQ(0, item.extra_code1);
740 }));
741 }
742
743 update_client->AddObserver(&observer);
744
745 const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf",
746 "abagagagagagagagagagagagagagagag"};
747 update_client->Update(
748 ids, base::BindOnce(&DataCallbackMock::Callback), false,
749 base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
750
751 RunThreads();
752
753 update_client->RemoveObserver(&observer);
754}
755
Sorin Jianucb4431a2018-04-30 20:59:24756// Tests the update check for two CRXs scenario when the second CRX does not
757// provide a CrxComponent instance. In this case, the update is handled as
758// if only one component were provided as an argument to the |Update| call
759// with the exception that the second component still fires an event such as
760// |COMPONENT_UPDATE_ERROR|.
761TEST_F(UpdateClientTest, TwoCrxUpdateNoCrxComponentData) {
Sorin Jianua8926bf2018-03-09 21:02:53762 class DataCallbackMock {
sorin9797aba2015-04-17 17:15:03763 public:
Sorin Jianu73900242018-08-17 01:11:53764 static std::vector<base::Optional<CrxComponent>> Callback(
Sorin Jianu7c22795b2018-04-26 22:16:52765 const std::vector<std::string>& ids) {
Sorin Jianu73900242018-08-17 01:11:53766 CrxComponent crx;
767 crx.name = "test_jebg";
768 crx.pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
769 crx.version = base::Version("0.9");
770 crx.installer = base::MakeRefCounted<TestInstaller>();
Joshua Pawlickif4b33f382018-08-17 17:36:51771 crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
Sorin Jianu73900242018-08-17 01:11:53772 return {crx, base::nullopt};
sorin9797aba2015-04-17 17:15:03773 }
774 };
775
Sorin Jianua8926bf2018-03-09 21:02:53776 class CompletionCallbackMock {
sorin9797aba2015-04-17 17:15:03777 public:
Sorin Jianua8ef73d2017-11-02 16:55:17778 static void Callback(base::OnceClosure quit_closure, Error error) {
sorin7b8650522016-11-02 18:23:41779 EXPECT_EQ(Error::NONE, error);
Sorin Jianua8ef73d2017-11-02 16:55:17780 std::move(quit_closure).Run();
sorin9797aba2015-04-17 17:15:03781 }
782 };
783
Sorin Jianua8926bf2018-03-09 21:02:53784 class MockUpdateChecker : public UpdateChecker {
sorin9797aba2015-04-17 17:15:03785 public:
dchengd0fc6aa92016-04-22 18:03:12786 static std::unique_ptr<UpdateChecker> Create(
Sorin Jianu49126332018-02-13 17:07:42787 scoped_refptr<Configurator> config,
wafflese7dff732016-04-15 23:51:49788 PersistedData* metadata) {
Sorin Jianua8926bf2018-03-09 21:02:53789 return std::make_unique<MockUpdateChecker>();
sorin9797aba2015-04-17 17:15:03790 }
791
Sorin Jianuc303bf42018-09-07 16:19:33792 void CheckForUpdates(
793 const std::string& session_id,
794 const std::vector<std::string>& ids_to_check,
795 const IdToComponentPtrMap& components,
796 const base::flat_map<std::string, std::string>& additional_attributes,
797 bool enabled_component_updates,
798 UpdateCheckCallback update_check_callback) override {
sorin9797aba2015-04-17 17:15:03799 /*
Sorin Jianua8926bf2018-03-09 21:02:53800 Mock the following response:
sorin9797aba2015-04-17 17:15:03801
802 <?xml version='1.0' encoding='UTF-8'?>
sorin39852802017-05-01 22:46:28803 <response protocol='3.1'>
sorin9797aba2015-04-17 17:15:03804 <app appid='jebgalgnebhfojomionfpkfelancnnkf'>
805 <updatecheck status='ok'>
806 <urls>
807 <url codebase='http://localhost/download/'/>
808 </urls>
809 <manifest version='1.0' prodversionmin='11.0.1.0'>
810 <packages>
sorin74e70672016-02-03 03:13:10811 <package name='jebgalgnebhfojomionfpkfelancnnkf.crx'
812 hash_sha256='6fc4b93fd11134de1300c2c0bb88c12b644a4ec0fd
813 7c9b12cb7cc067667bde87'/>
sorin9797aba2015-04-17 17:15:03814 </packages>
815 </manifest>
816 </updatecheck>
817 </app>
sorin9797aba2015-04-17 17:15:03818 </response>
819 */
Sorin Jianud69d4372018-02-07 19:44:22820 EXPECT_FALSE(session_id.empty());
sorin30474f02017-04-27 00:45:48821 EXPECT_TRUE(enabled_component_updates);
Sorin Jianucb4431a2018-04-30 20:59:24822 EXPECT_EQ(1u, ids_to_check.size());
sorin9797aba2015-04-17 17:15:03823
Sorin Jianu888ec292018-06-01 15:35:42824 ProtocolParser::Results results;
sorin30474f02017-04-27 00:45:48825 {
826 const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
827 EXPECT_EQ(id, ids_to_check[0]);
828 EXPECT_EQ(1u, components.count(id));
sorin9797aba2015-04-17 17:15:03829
sorin7cff6e52017-05-17 16:37:23830 ProtocolParser::Result::Manifest::Package package;
sorin30474f02017-04-27 00:45:48831 package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
832 package.hash_sha256 =
833 "6fc4b93fd11134de1300c2c0bb88c12b644a4ec0fd7c9b12cb7cc067667bde87";
sorin9797aba2015-04-17 17:15:03834
sorin7cff6e52017-05-17 16:37:23835 ProtocolParser::Result result;
sorin30474f02017-04-27 00:45:48836 result.extension_id = id;
837 result.status = "ok";
838 result.crx_urls.push_back(GURL("http://localhost/download/"));
839 result.manifest.version = "1.0";
840 result.manifest.browser_min_version = "11.0.1.0";
841 result.manifest.packages.push_back(package);
Sorin Jianu888ec292018-06-01 15:35:42842 results.list.push_back(result);
sorin9797aba2015-04-17 17:15:03843
Sorin Jianu888ec292018-06-01 15:35:42844 EXPECT_FALSE(components.at(id)->is_foreground());
sorin30474f02017-04-27 00:45:48845 }
846
sorin9797aba2015-04-17 17:15:03847 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianuaa4165532018-06-08 19:46:46848 FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
849 ErrorCategory::kNone, 0, 0));
sorin9797aba2015-04-17 17:15:03850 }
851 };
852
Sorin Jianua8926bf2018-03-09 21:02:53853 class MockCrxDownloader : public CrxDownloader {
sorin9797aba2015-04-17 17:15:03854 public:
dchengd0fc6aa92016-04-22 18:03:12855 static std::unique_ptr<CrxDownloader> Create(
sorin9797aba2015-04-17 17:15:03856 bool is_background_download,
Antonio Gomes0807dd62018-08-10 14:28:47857 scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
Sorin Jianua8926bf2018-03-09 21:02:53858 return std::make_unique<MockCrxDownloader>();
sorin9797aba2015-04-17 17:15:03859 }
860
Sorin Jianua8926bf2018-03-09 21:02:53861 MockCrxDownloader() : CrxDownloader(nullptr) {}
sorin9797aba2015-04-17 17:15:03862
sorin30474f02017-04-27 00:45:48863 private:
sorin9797aba2015-04-17 17:15:03864 void DoStartDownload(const GURL& url) override {
865 DownloadMetrics download_metrics;
866 FilePath path;
867 Result result;
868 if (url.path() == "/download/jebgalgnebhfojomionfpkfelancnnkf.crx") {
869 download_metrics.url = url;
870 download_metrics.downloader = DownloadMetrics::kNone;
871 download_metrics.error = 0;
872 download_metrics.downloaded_bytes = 1843;
873 download_metrics.total_bytes = 1843;
874 download_metrics.download_time_ms = 1000;
875
876 EXPECT_TRUE(MakeTestFile(
877 TestFilePath("jebgalgnebhfojomionfpkfelancnnkf.crx"), &path));
878
879 result.error = 0;
880 result.response = path;
sorin9797aba2015-04-17 17:15:03881 } else {
882 NOTREACHED();
883 }
884
885 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianua8926bf2018-03-09 21:02:53886 FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadProgress,
Antonio Gomes31237fb2018-08-27 19:11:03887 base::Unretained(this)));
sorin9797aba2015-04-17 17:15:03888
889 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianua8926bf2018-03-09 21:02:53890 FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadComplete,
Sorin Jianua8ef73d2017-11-02 16:55:17891 base::Unretained(this), true, result,
892 download_metrics));
sorin9797aba2015-04-17 17:15:03893 }
894 };
895
Sorin Jianua8926bf2018-03-09 21:02:53896 class MockPingManager : public MockPingManagerImpl {
sorin9797aba2015-04-17 17:15:03897 public:
Sorin Jianua8926bf2018-03-09 21:02:53898 explicit MockPingManager(scoped_refptr<Configurator> config)
899 : MockPingManagerImpl(config) {}
Sorin Jianu560d5022018-02-12 23:11:54900
901 protected:
Sorin Jianua8926bf2018-03-09 21:02:53902 ~MockPingManager() override {
903 const auto ping_data = MockPingManagerImpl::ping_data();
Sorin Jianucb4431a2018-04-30 20:59:24904 EXPECT_EQ(1u, ping_data.size());
sorin30474f02017-04-27 00:45:48905 EXPECT_EQ("jebgalgnebhfojomionfpkfelancnnkf", ping_data[0].id);
906 EXPECT_EQ(base::Version("0.9"), ping_data[0].previous_version);
907 EXPECT_EQ(base::Version("1.0"), ping_data[0].next_version);
Minh X. Nguyena4640cb2018-05-23 21:29:10908 EXPECT_EQ(0, static_cast<int>(ping_data[0].error_category));
sorin30474f02017-04-27 00:45:48909 EXPECT_EQ(0, ping_data[0].error_code);
sorin9797aba2015-04-17 17:15:03910 }
911 };
912
sorin30474f02017-04-27 00:45:48913 scoped_refptr<UpdateClient> update_client =
Taiju Tsuiki36c517d2017-05-18 06:45:43914 base::MakeRefCounted<UpdateClientImpl>(
Sorin Jianua8926bf2018-03-09 21:02:53915 config(), base::MakeRefCounted<MockPingManager>(config()),
916 &MockUpdateChecker::Create, &MockCrxDownloader::Create);
sorin9797aba2015-04-17 17:15:03917
918 MockObserver observer;
919 {
920 InSequence seq;
921 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
922 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
923 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
924 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
925 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
sorin30474f02017-04-27 00:45:48926 "jebgalgnebhfojomionfpkfelancnnkf"))
927 .Times(AtLeast(1));
sorin9797aba2015-04-17 17:15:03928 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
929 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
930 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED,
931 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
932 }
933 {
934 InSequence seq;
Sorin Jianucb4431a2018-04-30 20:59:24935 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
sorin30474f02017-04-27 00:45:48936 "ihfokbkgjpifnbbojhneepfflplebdkc"))
Sorin Jianucb4431a2018-04-30 20:59:24937 .Times(1);
938 }
939
940 update_client->AddObserver(&observer);
941
942 const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf",
943 "ihfokbkgjpifnbbojhneepfflplebdkc"};
944 update_client->Update(
945 ids, base::BindOnce(&DataCallbackMock::Callback), false,
946 base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
947
948 RunThreads();
949
950 update_client->RemoveObserver(&observer);
951}
952
953// Tests the update check for two CRXs scenario when no CrxComponent data is
954// provided for either component. In this case, no update check occurs, and
955// |COMPONENT_UPDATE_ERROR| event fires for both components.
956TEST_F(UpdateClientTest, TwoCrxUpdateNoCrxComponentDataAtAll) {
957 class DataCallbackMock {
958 public:
Sorin Jianu73900242018-08-17 01:11:53959 static std::vector<base::Optional<CrxComponent>> Callback(
Sorin Jianucb4431a2018-04-30 20:59:24960 const std::vector<std::string>& ids) {
Sorin Jianu73900242018-08-17 01:11:53961 return {base::nullopt, base::nullopt};
Sorin Jianucb4431a2018-04-30 20:59:24962 }
963 };
964
965 class CompletionCallbackMock {
966 public:
967 static void Callback(base::OnceClosure quit_closure, Error error) {
968 EXPECT_EQ(Error::NONE, error);
969 std::move(quit_closure).Run();
970 }
971 };
972
973 class MockUpdateChecker : public UpdateChecker {
974 public:
975 static std::unique_ptr<UpdateChecker> Create(
976 scoped_refptr<Configurator> config,
977 PersistedData* metadata) {
978 return std::make_unique<MockUpdateChecker>();
979 }
980
Sorin Jianuc303bf42018-09-07 16:19:33981 void CheckForUpdates(
982 const std::string& session_id,
983 const std::vector<std::string>& ids_to_check,
984 const IdToComponentPtrMap& components,
985 const base::flat_map<std::string, std::string>& additional_attributes,
986 bool enabled_component_updates,
987 UpdateCheckCallback update_check_callback) override {
Sorin Jianucb4431a2018-04-30 20:59:24988 NOTREACHED();
989 }
990 };
991
992 class MockCrxDownloader : public CrxDownloader {
993 public:
994 static std::unique_ptr<CrxDownloader> Create(
995 bool is_background_download,
Antonio Gomes0807dd62018-08-10 14:28:47996 scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
Sorin Jianucb4431a2018-04-30 20:59:24997 return std::make_unique<MockCrxDownloader>();
998 }
999
1000 MockCrxDownloader() : CrxDownloader(nullptr) {}
1001
1002 private:
1003 void DoStartDownload(const GURL& url) override { NOTREACHED(); }
1004 };
1005
1006 class MockPingManager : public MockPingManagerImpl {
1007 public:
1008 explicit MockPingManager(scoped_refptr<Configurator> config)
1009 : MockPingManagerImpl(config) {}
1010
1011 protected:
1012 ~MockPingManager() override {
1013 EXPECT_EQ(0u, MockPingManagerImpl::ping_data().size());
1014 }
1015 };
1016
1017 scoped_refptr<UpdateClient> update_client =
1018 base::MakeRefCounted<UpdateClientImpl>(
1019 config(), base::MakeRefCounted<MockPingManager>(config()),
1020 &MockUpdateChecker::Create, &MockCrxDownloader::Create);
1021
1022 MockObserver observer;
1023 {
1024 InSequence seq;
1025 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
1026 "jebgalgnebhfojomionfpkfelancnnkf"))
1027 .Times(1);
1028 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
1029 "ihfokbkgjpifnbbojhneepfflplebdkc"))
1030 .Times(1);
sorin9797aba2015-04-17 17:15:031031 }
1032
1033 update_client->AddObserver(&observer);
1034
sorin30474f02017-04-27 00:45:481035 const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf",
1036 "ihfokbkgjpifnbbojhneepfflplebdkc"};
sorin9797aba2015-04-17 17:15:031037 update_client->Update(
Sorin Jianua8926bf2018-03-09 21:02:531038 ids, base::BindOnce(&DataCallbackMock::Callback), false,
1039 base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
sorin9797aba2015-04-17 17:15:031040
1041 RunThreads();
1042
1043 update_client->RemoveObserver(&observer);
1044}
1045
sorin6bb8de42015-06-03 00:23:271046// Tests the scenario where there is a download timeout for the first
1047// CRX. The update for the first CRX fails. The update client waits before
1048// attempting the update for the second CRX. This update succeeds.
1049TEST_F(UpdateClientTest, TwoCrxUpdateDownloadTimeout) {
Sorin Jianua8926bf2018-03-09 21:02:531050 class DataCallbackMock {
sorin6bb8de42015-06-03 00:23:271051 public:
Sorin Jianu73900242018-08-17 01:11:531052 static std::vector<base::Optional<CrxComponent>> Callback(
Sorin Jianu7c22795b2018-04-26 22:16:521053 const std::vector<std::string>& ids) {
Sorin Jianu73900242018-08-17 01:11:531054 CrxComponent crx1;
1055 crx1.name = "test_jebg";
1056 crx1.pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
1057 crx1.version = base::Version("0.9");
1058 crx1.installer = base::MakeRefCounted<TestInstaller>();
Joshua Pawlickif4b33f382018-08-17 17:36:511059 crx1.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
sorin6bb8de42015-06-03 00:23:271060
Sorin Jianu73900242018-08-17 01:11:531061 CrxComponent crx2;
1062 crx2.name = "test_ihfo";
1063 crx2.pk_hash.assign(ihfo_hash, ihfo_hash + base::size(ihfo_hash));
1064 crx2.version = base::Version("0.8");
1065 crx2.installer = base::MakeRefCounted<TestInstaller>();
Joshua Pawlickif4b33f382018-08-17 17:36:511066 crx2.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
sorin6bb8de42015-06-03 00:23:271067
Sorin Jianu73900242018-08-17 01:11:531068 return {crx1, crx2};
sorin6bb8de42015-06-03 00:23:271069 }
1070 };
1071
Sorin Jianua8926bf2018-03-09 21:02:531072 class CompletionCallbackMock {
sorin6bb8de42015-06-03 00:23:271073 public:
Sorin Jianua8ef73d2017-11-02 16:55:171074 static void Callback(base::OnceClosure quit_closure, Error error) {
sorin7b8650522016-11-02 18:23:411075 EXPECT_EQ(Error::NONE, error);
Sorin Jianua8ef73d2017-11-02 16:55:171076 std::move(quit_closure).Run();
sorin6bb8de42015-06-03 00:23:271077 }
1078 };
1079
Sorin Jianua8926bf2018-03-09 21:02:531080 class MockUpdateChecker : public UpdateChecker {
sorin6bb8de42015-06-03 00:23:271081 public:
dchengd0fc6aa92016-04-22 18:03:121082 static std::unique_ptr<UpdateChecker> Create(
Sorin Jianu49126332018-02-13 17:07:421083 scoped_refptr<Configurator> config,
wafflese7dff732016-04-15 23:51:491084 PersistedData* metadata) {
Sorin Jianua8926bf2018-03-09 21:02:531085 return std::make_unique<MockUpdateChecker>();
sorin6bb8de42015-06-03 00:23:271086 }
1087
Sorin Jianuc303bf42018-09-07 16:19:331088 void CheckForUpdates(
1089 const std::string& session_id,
1090 const std::vector<std::string>& ids_to_check,
1091 const IdToComponentPtrMap& components,
1092 const base::flat_map<std::string, std::string>& additional_attributes,
1093 bool enabled_component_updates,
1094 UpdateCheckCallback update_check_callback) override {
sorin6bb8de42015-06-03 00:23:271095 /*
Sorin Jianua8926bf2018-03-09 21:02:531096 Mock the following response:
sorin6bb8de42015-06-03 00:23:271097
1098 <?xml version='1.0' encoding='UTF-8'?>
sorin39852802017-05-01 22:46:281099 <response protocol='3.1'>
sorin6bb8de42015-06-03 00:23:271100 <app appid='jebgalgnebhfojomionfpkfelancnnkf'>
1101 <updatecheck status='ok'>
1102 <urls>
1103 <url codebase='http://localhost/download/'/>
1104 </urls>
1105 <manifest version='1.0' prodversionmin='11.0.1.0'>
1106 <packages>
sorin74e70672016-02-03 03:13:101107 <package name='jebgalgnebhfojomionfpkfelancnnkf.crx'
1108 hash_sha256='6fc4b93fd11134de1300c2c0bb88c12b644a4ec0fd
1109 7c9b12cb7cc067667bde87'/>
sorin6bb8de42015-06-03 00:23:271110 </packages>
1111 </manifest>
1112 </updatecheck>
1113 </app>
1114 <app appid='ihfokbkgjpifnbbojhneepfflplebdkc'>
1115 <updatecheck status='ok'>
1116 <urls>
1117 <url codebase='http://localhost/download/'/>
1118 </urls>
1119 <manifest version='1.0' prodversionmin='11.0.1.0'>
1120 <packages>
sorin74e70672016-02-03 03:13:101121 <package name='ihfokbkgjpifnbbojhneepfflplebdkc_1.crx'
1122 hash_sha256='813c59747e139a608b3b5fc49633affc6db574373f
1123 309f156ea6d27229c0b3f9'/>
sorin6bb8de42015-06-03 00:23:271124 </packages>
1125 </manifest>
1126 </updatecheck>
1127 </app>
1128 </response>
1129 */
sorin6bb8de42015-06-03 00:23:271130
Sorin Jianud69d4372018-02-07 19:44:221131 EXPECT_FALSE(session_id.empty());
sorin30474f02017-04-27 00:45:481132 EXPECT_TRUE(enabled_component_updates);
1133 EXPECT_EQ(2u, ids_to_check.size());
sorin6bb8de42015-06-03 00:23:271134
Sorin Jianu888ec292018-06-01 15:35:421135 ProtocolParser::Results results;
sorin30474f02017-04-27 00:45:481136 {
1137 const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
1138 EXPECT_EQ(id, ids_to_check[0]);
1139 EXPECT_EQ(1u, components.count(id));
sorin6bb8de42015-06-03 00:23:271140
sorin7cff6e52017-05-17 16:37:231141 ProtocolParser::Result::Manifest::Package package;
sorin30474f02017-04-27 00:45:481142 package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
1143 package.hash_sha256 =
1144 "6fc4b93fd11134de1300c2c0bb88c12b644a4ec0fd7c9b12cb7cc067667bde87";
sorin6bb8de42015-06-03 00:23:271145
sorin7cff6e52017-05-17 16:37:231146 ProtocolParser::Result result;
sorin30474f02017-04-27 00:45:481147 result.extension_id = id;
1148 result.status = "ok";
1149 result.crx_urls.push_back(GURL("http://localhost/download/"));
1150 result.manifest.version = "1.0";
1151 result.manifest.browser_min_version = "11.0.1.0";
1152 result.manifest.packages.push_back(package);
Sorin Jianu888ec292018-06-01 15:35:421153 results.list.push_back(result);
sorin30474f02017-04-27 00:45:481154 }
1155
1156 {
1157 const std::string id = "ihfokbkgjpifnbbojhneepfflplebdkc";
1158 EXPECT_EQ(id, ids_to_check[1]);
1159 EXPECT_EQ(1u, components.count(id));
1160
sorin7cff6e52017-05-17 16:37:231161 ProtocolParser::Result::Manifest::Package package;
sorin30474f02017-04-27 00:45:481162 package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_1.crx";
1163 package.hash_sha256 =
1164 "813c59747e139a608b3b5fc49633affc6db574373f309f156ea6d27229c0b3f9";
1165
sorin7cff6e52017-05-17 16:37:231166 ProtocolParser::Result result;
sorin30474f02017-04-27 00:45:481167 result.extension_id = id;
1168 result.status = "ok";
1169 result.crx_urls.push_back(GURL("http://localhost/download/"));
1170 result.manifest.version = "1.0";
1171 result.manifest.browser_min_version = "11.0.1.0";
1172 result.manifest.packages.push_back(package);
Sorin Jianu888ec292018-06-01 15:35:421173 results.list.push_back(result);
sorin30474f02017-04-27 00:45:481174 }
sorin6bb8de42015-06-03 00:23:271175
1176 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianuaa4165532018-06-08 19:46:461177 FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
1178 ErrorCategory::kNone, 0, 0));
sorin6bb8de42015-06-03 00:23:271179 }
1180 };
1181
Sorin Jianua8926bf2018-03-09 21:02:531182 class MockCrxDownloader : public CrxDownloader {
sorin6bb8de42015-06-03 00:23:271183 public:
dchengd0fc6aa92016-04-22 18:03:121184 static std::unique_ptr<CrxDownloader> Create(
sorin6bb8de42015-06-03 00:23:271185 bool is_background_download,
Antonio Gomes0807dd62018-08-10 14:28:471186 scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
Sorin Jianua8926bf2018-03-09 21:02:531187 return std::make_unique<MockCrxDownloader>();
sorin6bb8de42015-06-03 00:23:271188 }
1189
Sorin Jianua8926bf2018-03-09 21:02:531190 MockCrxDownloader() : CrxDownloader(nullptr) {}
sorin6bb8de42015-06-03 00:23:271191
sorin30474f02017-04-27 00:45:481192 private:
sorin6bb8de42015-06-03 00:23:271193 void DoStartDownload(const GURL& url) override {
1194 DownloadMetrics download_metrics;
1195 FilePath path;
1196 Result result;
1197 if (url.path() == "/download/jebgalgnebhfojomionfpkfelancnnkf.crx") {
1198 download_metrics.url = url;
1199 download_metrics.downloader = DownloadMetrics::kNone;
1200 download_metrics.error = -118;
1201 download_metrics.downloaded_bytes = 0;
1202 download_metrics.total_bytes = 0;
1203 download_metrics.download_time_ms = 1000;
1204
Sorin Jianu52de5fa2017-10-09 23:19:331205 // The result must not include a file path in the case of errors.
sorin6bb8de42015-06-03 00:23:271206 result.error = -118;
sorin6bb8de42015-06-03 00:23:271207 } else if (url.path() ==
1208 "/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx") {
1209 download_metrics.url = url;
1210 download_metrics.downloader = DownloadMetrics::kNone;
1211 download_metrics.error = 0;
1212 download_metrics.downloaded_bytes = 53638;
1213 download_metrics.total_bytes = 53638;
1214 download_metrics.download_time_ms = 2000;
1215
1216 EXPECT_TRUE(MakeTestFile(
1217 TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"), &path));
1218
1219 result.error = 0;
1220 result.response = path;
sorin6bb8de42015-06-03 00:23:271221 } else {
1222 NOTREACHED();
1223 }
1224
1225 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianua8926bf2018-03-09 21:02:531226 FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadProgress,
Antonio Gomes31237fb2018-08-27 19:11:031227 base::Unretained(this)));
sorin6bb8de42015-06-03 00:23:271228
1229 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianua8926bf2018-03-09 21:02:531230 FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadComplete,
Sorin Jianuebd652462017-07-23 02:00:581231 base::Unretained(this), true, result,
1232 download_metrics));
sorin6bb8de42015-06-03 00:23:271233 }
1234 };
1235
Sorin Jianua8926bf2018-03-09 21:02:531236 class MockPingManager : public MockPingManagerImpl {
sorin6bb8de42015-06-03 00:23:271237 public:
Sorin Jianua8926bf2018-03-09 21:02:531238 explicit MockPingManager(scoped_refptr<Configurator> config)
1239 : MockPingManagerImpl(config) {}
Sorin Jianu560d5022018-02-12 23:11:541240
1241 protected:
Sorin Jianua8926bf2018-03-09 21:02:531242 ~MockPingManager() override {
1243 const auto ping_data = MockPingManagerImpl::ping_data();
sorin30474f02017-04-27 00:45:481244 EXPECT_EQ(2u, ping_data.size());
1245 EXPECT_EQ("jebgalgnebhfojomionfpkfelancnnkf", ping_data[0].id);
1246 EXPECT_EQ(base::Version("0.9"), ping_data[0].previous_version);
1247 EXPECT_EQ(base::Version("1.0"), ping_data[0].next_version);
Minh X. Nguyena4640cb2018-05-23 21:29:101248 EXPECT_EQ(1, static_cast<int>(ping_data[0].error_category));
sorin30474f02017-04-27 00:45:481249 EXPECT_EQ(-118, ping_data[0].error_code);
1250 EXPECT_EQ("ihfokbkgjpifnbbojhneepfflplebdkc", ping_data[1].id);
1251 EXPECT_EQ(base::Version("0.8"), ping_data[1].previous_version);
1252 EXPECT_EQ(base::Version("1.0"), ping_data[1].next_version);
Minh X. Nguyena4640cb2018-05-23 21:29:101253 EXPECT_EQ(0, static_cast<int>(ping_data[1].error_category));
sorin30474f02017-04-27 00:45:481254 EXPECT_EQ(0, ping_data[1].error_code);
sorin6bb8de42015-06-03 00:23:271255 }
1256 };
1257
sorin30474f02017-04-27 00:45:481258 scoped_refptr<UpdateClient> update_client =
Taiju Tsuiki36c517d2017-05-18 06:45:431259 base::MakeRefCounted<UpdateClientImpl>(
Sorin Jianua8926bf2018-03-09 21:02:531260 config(), base::MakeRefCounted<MockPingManager>(config()),
1261 &MockUpdateChecker::Create, &MockCrxDownloader::Create);
sorin6bb8de42015-06-03 00:23:271262
1263 MockObserver observer;
1264 {
1265 InSequence seq;
1266 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
1267 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
1268 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
1269 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
1270 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
sorin30474f02017-04-27 00:45:481271 "jebgalgnebhfojomionfpkfelancnnkf"))
1272 .Times(AtLeast(1));
Sorin Jianucbb10e12018-01-23 18:01:441273 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
1274 "jebgalgnebhfojomionfpkfelancnnkf"))
Sorin Jianuafcb70dd2018-05-16 20:14:151275 .Times(1)
1276 .WillOnce(Invoke([&update_client](Events event, const std::string& id) {
1277 CrxUpdateItem item;
Sorin Jianu73900242018-08-17 01:11:531278 EXPECT_TRUE(update_client->GetCrxUpdateState(id, &item));
Sorin Jianuafcb70dd2018-05-16 20:14:151279 EXPECT_EQ(ComponentState::kUpdateError, item.state);
Minh X. Nguyena4640cb2018-05-23 21:29:101280 EXPECT_EQ(1, static_cast<int>(item.error_category));
Sorin Jianuafcb70dd2018-05-16 20:14:151281 EXPECT_EQ(-118, item.error_code);
1282 EXPECT_EQ(0, item.extra_code1);
1283 }));
sorin6bb8de42015-06-03 00:23:271284 }
1285 {
1286 InSequence seq;
1287 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
1288 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1289 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
1290 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1291 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_WAIT,
1292 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1293 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
sorin30474f02017-04-27 00:45:481294 "ihfokbkgjpifnbbojhneepfflplebdkc"))
1295 .Times(AtLeast(1));
sorin6bb8de42015-06-03 00:23:271296 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
1297 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1298 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED,
1299 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1300 }
1301
1302 update_client->AddObserver(&observer);
1303
sorin30474f02017-04-27 00:45:481304 const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf",
1305 "ihfokbkgjpifnbbojhneepfflplebdkc"};
sorin6bb8de42015-06-03 00:23:271306
1307 update_client->Update(
Sorin Jianua8926bf2018-03-09 21:02:531308 ids, base::BindOnce(&DataCallbackMock::Callback), false,
1309 base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
sorin6bb8de42015-06-03 00:23:271310
1311 RunThreads();
1312
1313 update_client->RemoveObserver(&observer);
sorin6bb8de42015-06-03 00:23:271314}
1315
sorin9797aba2015-04-17 17:15:031316// Tests the differential update scenario for one CRX.
1317TEST_F(UpdateClientTest, OneCrxDiffUpdate) {
Sorin Jianua8926bf2018-03-09 21:02:531318 class DataCallbackMock {
sorin9797aba2015-04-17 17:15:031319 public:
Sorin Jianu73900242018-08-17 01:11:531320 static std::vector<base::Optional<CrxComponent>> Callback(
Sorin Jianu7c22795b2018-04-26 22:16:521321 const std::vector<std::string>& ids) {
sorin9797aba2015-04-17 17:15:031322 static int num_calls = 0;
1323
1324 // Must use the same stateful installer object.
sorin30474f02017-04-27 00:45:481325 static scoped_refptr<CrxInstaller> installer =
Taiju Tsuiki36c517d2017-05-18 06:45:431326 base::MakeRefCounted<VersionedTestInstaller>();
sorin9797aba2015-04-17 17:15:031327
1328 ++num_calls;
1329
Sorin Jianu73900242018-08-17 01:11:531330 CrxComponent crx;
1331 crx.name = "test_ihfo";
1332 crx.pk_hash.assign(ihfo_hash, ihfo_hash + base::size(ihfo_hash));
1333 crx.installer = installer;
Joshua Pawlickif4b33f382018-08-17 17:36:511334 crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
sorin9797aba2015-04-17 17:15:031335 if (num_calls == 1) {
Sorin Jianu73900242018-08-17 01:11:531336 crx.version = base::Version("0.8");
sorin9797aba2015-04-17 17:15:031337 } else if (num_calls == 2) {
Sorin Jianu73900242018-08-17 01:11:531338 crx.version = base::Version("1.0");
sorin9797aba2015-04-17 17:15:031339 } else {
1340 NOTREACHED();
1341 }
1342
Sorin Jianu73900242018-08-17 01:11:531343 return {crx};
sorin9797aba2015-04-17 17:15:031344 }
1345 };
1346
Sorin Jianua8926bf2018-03-09 21:02:531347 class CompletionCallbackMock {
sorin9797aba2015-04-17 17:15:031348 public:
Sorin Jianua8ef73d2017-11-02 16:55:171349 static void Callback(base::OnceClosure quit_closure, Error error) {
sorin7b8650522016-11-02 18:23:411350 EXPECT_EQ(Error::NONE, error);
Sorin Jianua8ef73d2017-11-02 16:55:171351 std::move(quit_closure).Run();
sorin9797aba2015-04-17 17:15:031352 }
1353 };
1354
Sorin Jianua8926bf2018-03-09 21:02:531355 class MockUpdateChecker : public UpdateChecker {
sorin9797aba2015-04-17 17:15:031356 public:
dchengd0fc6aa92016-04-22 18:03:121357 static std::unique_ptr<UpdateChecker> Create(
Sorin Jianu49126332018-02-13 17:07:421358 scoped_refptr<Configurator> config,
wafflese7dff732016-04-15 23:51:491359 PersistedData* metadata) {
Sorin Jianua8926bf2018-03-09 21:02:531360 return std::make_unique<MockUpdateChecker>();
sorin9797aba2015-04-17 17:15:031361 }
1362
Sorin Jianuc303bf42018-09-07 16:19:331363 void CheckForUpdates(
1364 const std::string& session_id,
1365 const std::vector<std::string>& ids_to_check,
1366 const IdToComponentPtrMap& components,
1367 const base::flat_map<std::string, std::string>& additional_attributes,
1368 bool enabled_component_updates,
1369 UpdateCheckCallback update_check_callback) override {
Sorin Jianud69d4372018-02-07 19:44:221370 EXPECT_FALSE(session_id.empty());
1371
sorin9797aba2015-04-17 17:15:031372 static int num_call = 0;
1373 ++num_call;
1374
sorin7cff6e52017-05-17 16:37:231375 ProtocolParser::Results results;
sorin9797aba2015-04-17 17:15:031376
1377 if (num_call == 1) {
1378 /*
Sorin Jianua8926bf2018-03-09 21:02:531379 Mock the following response:
sorin9797aba2015-04-17 17:15:031380 <?xml version='1.0' encoding='UTF-8'?>
sorin39852802017-05-01 22:46:281381 <response protocol='3.1'>
sorin9797aba2015-04-17 17:15:031382 <app appid='ihfokbkgjpifnbbojhneepfflplebdkc'>
1383 <updatecheck status='ok'>
1384 <urls>
1385 <url codebase='http://localhost/download/'/>
1386 </urls>
1387 <manifest version='1.0' prodversionmin='11.0.1.0'>
1388 <packages>
sorin74e70672016-02-03 03:13:101389 <package name='ihfokbkgjpifnbbojhneepfflplebdkc_1.crx'
1390 hash_sha256='813c59747e139a608b3b5fc49633affc6db57437
1391 3f309f156ea6d27229c0b3f9'/>
sorin9797aba2015-04-17 17:15:031392 </packages>
1393 </manifest>
1394 </updatecheck>
1395 </app>
1396 </response>
1397 */
sorin30474f02017-04-27 00:45:481398 const std::string id = "ihfokbkgjpifnbbojhneepfflplebdkc";
1399 EXPECT_EQ(id, ids_to_check[0]);
1400 EXPECT_EQ(1u, components.count(id));
1401
sorin7cff6e52017-05-17 16:37:231402 ProtocolParser::Result::Manifest::Package package;
sorin9797aba2015-04-17 17:15:031403 package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_1.crx";
sorin74e70672016-02-03 03:13:101404 package.hash_sha256 =
1405 "813c59747e139a608b3b5fc49633affc6db574373f309f156ea6d27229c0b3f9";
sorin30474f02017-04-27 00:45:481406
sorin7cff6e52017-05-17 16:37:231407 ProtocolParser::Result result;
sorin30474f02017-04-27 00:45:481408 result.extension_id = id;
sorin9ef301c2017-02-16 20:29:171409 result.status = "ok";
sorin9797aba2015-04-17 17:15:031410 result.crx_urls.push_back(GURL("http://localhost/download/"));
1411 result.manifest.version = "1.0";
1412 result.manifest.browser_min_version = "11.0.1.0";
1413 result.manifest.packages.push_back(package);
Sorin Jianu888ec292018-06-01 15:35:421414 results.list.push_back(result);
sorin9797aba2015-04-17 17:15:031415 } else if (num_call == 2) {
1416 /*
Sorin Jianua8926bf2018-03-09 21:02:531417 Mock the following response:
sorin9797aba2015-04-17 17:15:031418 <?xml version='1.0' encoding='UTF-8'?>
sorin39852802017-05-01 22:46:281419 <response protocol='3.1'>
sorin9797aba2015-04-17 17:15:031420 <app appid='ihfokbkgjpifnbbojhneepfflplebdkc'>
1421 <updatecheck status='ok'>
1422 <urls>
1423 <url codebase='http://localhost/download/'/>
1424 <url codebasediff='http://localhost/download/'/>
1425 </urls>
1426 <manifest version='2.0' prodversionmin='11.0.1.0'>
1427 <packages>
1428 <package name='ihfokbkgjpifnbbojhneepfflplebdkc_2.crx'
1429 namediff='ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx'
sorin74e70672016-02-03 03:13:101430 hash_sha256='1af337fbd19c72db0f870753bcd7711c3ae9dcaa
1431 0ecde26c262bad942b112990'
1432 fp='22'
1433 hashdiff_sha256='73c6e2d4f783fc4ca5481e89e0b8bfce7aec
sorin46bdd0b32016-08-30 22:42:261434 8ead3686290c94792658ec06f2f2'/>
sorin9797aba2015-04-17 17:15:031435 </packages>
1436 </manifest>
1437 </updatecheck>
1438 </app>
1439 </response>
1440 */
sorin30474f02017-04-27 00:45:481441 const std::string id = "ihfokbkgjpifnbbojhneepfflplebdkc";
1442 EXPECT_EQ(id, ids_to_check[0]);
1443 EXPECT_EQ(1u, components.count(id));
1444
sorin7cff6e52017-05-17 16:37:231445 ProtocolParser::Result::Manifest::Package package;
sorin9797aba2015-04-17 17:15:031446 package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_2.crx";
1447 package.namediff = "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx";
sorin74e70672016-02-03 03:13:101448 package.hash_sha256 =
1449 "1af337fbd19c72db0f870753bcd7711c3ae9dcaa0ecde26c262bad942b112990";
1450 package.hashdiff_sha256 =
1451 "73c6e2d4f783fc4ca5481e89e0b8bfce7aec8ead3686290c94792658ec06f2f2";
sorin9797aba2015-04-17 17:15:031452 package.fingerprint = "22";
sorin30474f02017-04-27 00:45:481453
sorin7cff6e52017-05-17 16:37:231454 ProtocolParser::Result result;
sorin30474f02017-04-27 00:45:481455 result.extension_id = id;
sorin9ef301c2017-02-16 20:29:171456 result.status = "ok";
sorin9797aba2015-04-17 17:15:031457 result.crx_urls.push_back(GURL("http://localhost/download/"));
1458 result.crx_diffurls.push_back(GURL("http://localhost/download/"));
1459 result.manifest.version = "2.0";
1460 result.manifest.browser_min_version = "11.0.1.0";
1461 result.manifest.packages.push_back(package);
Sorin Jianu888ec292018-06-01 15:35:421462 results.list.push_back(result);
sorin9797aba2015-04-17 17:15:031463 } else {
1464 NOTREACHED();
1465 }
1466
1467 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianuaa4165532018-06-08 19:46:461468 FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
1469 ErrorCategory::kNone, 0, 0));
sorin9797aba2015-04-17 17:15:031470 }
1471 };
1472
Sorin Jianua8926bf2018-03-09 21:02:531473 class MockCrxDownloader : public CrxDownloader {
sorin9797aba2015-04-17 17:15:031474 public:
dchengd0fc6aa92016-04-22 18:03:121475 static std::unique_ptr<CrxDownloader> Create(
sorin9797aba2015-04-17 17:15:031476 bool is_background_download,
Antonio Gomes0807dd62018-08-10 14:28:471477 scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
Sorin Jianua8926bf2018-03-09 21:02:531478 return std::make_unique<MockCrxDownloader>();
sorin9797aba2015-04-17 17:15:031479 }
1480
Sorin Jianua8926bf2018-03-09 21:02:531481 MockCrxDownloader() : CrxDownloader(nullptr) {}
sorin9797aba2015-04-17 17:15:031482
sorin30474f02017-04-27 00:45:481483 private:
sorin9797aba2015-04-17 17:15:031484 void DoStartDownload(const GURL& url) override {
1485 DownloadMetrics download_metrics;
1486 FilePath path;
1487 Result result;
1488 if (url.path() == "/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx") {
1489 download_metrics.url = url;
1490 download_metrics.downloader = DownloadMetrics::kNone;
1491 download_metrics.error = 0;
1492 download_metrics.downloaded_bytes = 53638;
1493 download_metrics.total_bytes = 53638;
1494 download_metrics.download_time_ms = 2000;
1495
1496 EXPECT_TRUE(MakeTestFile(
1497 TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"), &path));
1498
1499 result.error = 0;
1500 result.response = path;
sorin9797aba2015-04-17 17:15:031501 } else if (url.path() ==
1502 "/download/ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx") {
1503 download_metrics.url = url;
1504 download_metrics.downloader = DownloadMetrics::kNone;
1505 download_metrics.error = 0;
1506 download_metrics.downloaded_bytes = 2105;
1507 download_metrics.total_bytes = 2105;
1508 download_metrics.download_time_ms = 1000;
1509
1510 EXPECT_TRUE(MakeTestFile(
1511 TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"), &path));
1512
1513 result.error = 0;
1514 result.response = path;
sorin9797aba2015-04-17 17:15:031515 } else {
1516 NOTREACHED();
1517 }
1518
1519 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianua8926bf2018-03-09 21:02:531520 FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadProgress,
Antonio Gomes31237fb2018-08-27 19:11:031521 base::Unretained(this)));
sorin9797aba2015-04-17 17:15:031522
1523 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianua8926bf2018-03-09 21:02:531524 FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadComplete,
Sorin Jianuebd652462017-07-23 02:00:581525 base::Unretained(this), true, result,
1526 download_metrics));
sorin9797aba2015-04-17 17:15:031527 }
1528 };
1529
Sorin Jianua8926bf2018-03-09 21:02:531530 class MockPingManager : public MockPingManagerImpl {
sorin9797aba2015-04-17 17:15:031531 public:
Sorin Jianua8926bf2018-03-09 21:02:531532 explicit MockPingManager(scoped_refptr<Configurator> config)
1533 : MockPingManagerImpl(config) {}
Sorin Jianu560d5022018-02-12 23:11:541534
1535 protected:
Sorin Jianua8926bf2018-03-09 21:02:531536 ~MockPingManager() override {
1537 const auto ping_data = MockPingManagerImpl::ping_data();
sorin30474f02017-04-27 00:45:481538 EXPECT_EQ(2u, ping_data.size());
1539 EXPECT_EQ("ihfokbkgjpifnbbojhneepfflplebdkc", ping_data[0].id);
1540 EXPECT_EQ(base::Version("0.8"), ping_data[0].previous_version);
1541 EXPECT_EQ(base::Version("1.0"), ping_data[0].next_version);
Minh X. Nguyena4640cb2018-05-23 21:29:101542 EXPECT_EQ(0, static_cast<int>(ping_data[0].error_category));
sorin30474f02017-04-27 00:45:481543 EXPECT_EQ(0, ping_data[0].error_code);
1544 EXPECT_EQ("ihfokbkgjpifnbbojhneepfflplebdkc", ping_data[1].id);
1545 EXPECT_EQ(base::Version("1.0"), ping_data[1].previous_version);
1546 EXPECT_EQ(base::Version("2.0"), ping_data[1].next_version);
1547 EXPECT_FALSE(ping_data[1].diff_update_failed);
Minh X. Nguyena4640cb2018-05-23 21:29:101548 EXPECT_EQ(0, static_cast<int>(ping_data[1].diff_error_category));
sorin30474f02017-04-27 00:45:481549 EXPECT_EQ(0, ping_data[1].diff_error_code);
Minh X. Nguyena4640cb2018-05-23 21:29:101550 EXPECT_EQ(0, static_cast<int>(ping_data[1].error_category));
sorin30474f02017-04-27 00:45:481551 EXPECT_EQ(0, ping_data[1].error_code);
sorin9797aba2015-04-17 17:15:031552 }
1553 };
1554
sorin30474f02017-04-27 00:45:481555 scoped_refptr<UpdateClient> update_client =
Taiju Tsuiki36c517d2017-05-18 06:45:431556 base::MakeRefCounted<UpdateClientImpl>(
Sorin Jianua8926bf2018-03-09 21:02:531557 config(), base::MakeRefCounted<MockPingManager>(config()),
1558 &MockUpdateChecker::Create, &MockCrxDownloader::Create);
sorin9797aba2015-04-17 17:15:031559
1560 MockObserver observer;
1561 {
1562 InSequence seq;
1563 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
1564 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1565 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
1566 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1567 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
sorin30474f02017-04-27 00:45:481568 "ihfokbkgjpifnbbojhneepfflplebdkc"))
1569 .Times(AtLeast(1));
sorin9797aba2015-04-17 17:15:031570 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
1571 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1572 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED,
1573 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1574 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
1575 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1576 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
1577 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1578 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
sorin30474f02017-04-27 00:45:481579 "ihfokbkgjpifnbbojhneepfflplebdkc"))
1580 .Times(AtLeast(1));
sorin9797aba2015-04-17 17:15:031581 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
1582 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1583 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED,
1584 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1585 }
1586
1587 update_client->AddObserver(&observer);
1588
sorin30474f02017-04-27 00:45:481589 const std::vector<std::string> ids = {"ihfokbkgjpifnbbojhneepfflplebdkc"};
sorin9797aba2015-04-17 17:15:031590 {
1591 base::RunLoop runloop;
Sorin Jianua8926bf2018-03-09 21:02:531592 update_client->Update(ids, base::BindOnce(&DataCallbackMock::Callback),
Sorin Jianub41a592a2018-03-02 16:30:271593 false,
Sorin Jianua8926bf2018-03-09 21:02:531594 base::BindOnce(&CompletionCallbackMock::Callback,
Sorin Jianua8ef73d2017-11-02 16:55:171595 runloop.QuitClosure()));
sorin9797aba2015-04-17 17:15:031596 runloop.Run();
1597 }
1598
1599 {
1600 base::RunLoop runloop;
Sorin Jianua8926bf2018-03-09 21:02:531601 update_client->Update(ids, base::BindOnce(&DataCallbackMock::Callback),
Sorin Jianub41a592a2018-03-02 16:30:271602 false,
Sorin Jianua8926bf2018-03-09 21:02:531603 base::BindOnce(&CompletionCallbackMock::Callback,
Sorin Jianua8ef73d2017-11-02 16:55:171604 runloop.QuitClosure()));
sorin9797aba2015-04-17 17:15:031605 runloop.Run();
1606 }
1607
1608 update_client->RemoveObserver(&observer);
1609}
1610
1611// Tests the update scenario for one CRX where the CRX installer returns
Sorin Jianuf40ab4b32017-10-06 22:53:411612// an error. Tests that the |unpack_path| argument refers to a valid path
1613// then |Install| is called, then tests that the |unpack| path is deleted
1614// by the |update_client| code before the test ends.
sorin9797aba2015-04-17 17:15:031615TEST_F(UpdateClientTest, OneCrxInstallError) {
1616 class MockInstaller : public CrxInstaller {
1617 public:
1618 MOCK_METHOD1(OnUpdateError, void(int error));
Sorin Jianua8ef73d2017-11-02 16:55:171619 MOCK_METHOD2(DoInstall,
Sorin Jianu7aa6d1f2017-10-13 20:29:291620 void(const base::FilePath& unpack_path,
Sorin Jianuf40ab4b32017-10-06 22:53:411621 const Callback& callback));
sorin9797aba2015-04-17 17:15:031622 MOCK_METHOD2(GetInstalledFile,
1623 bool(const std::string& file, base::FilePath* installed_file));
1624 MOCK_METHOD0(Uninstall, bool());
1625
Sorin Jianua8ef73d2017-11-02 16:55:171626 void Install(const base::FilePath& unpack_path,
1627 const std::string& public_key,
Daniel Cheng67848522018-04-27 22:04:411628 Callback callback) override {
Sorin Jianua8ef73d2017-11-02 16:55:171629 DoInstall(unpack_path, std::move(callback));
1630
Sorin Jianu23f70f752017-05-30 16:21:581631 unpack_path_ = unpack_path;
1632 EXPECT_TRUE(base::DirectoryExists(unpack_path_));
Sorin Jianuf40ab4b32017-10-06 22:53:411633 base::PostTaskWithTraits(
1634 FROM_HERE, {base::MayBlock()},
Sorin Jianua8ef73d2017-11-02 16:55:171635 base::BindOnce(std::move(callback),
Sorin Jianuf40ab4b32017-10-06 22:53:411636 CrxInstaller::Result(InstallError::GENERIC_ERROR)));
sorin9797aba2015-04-17 17:15:031637 }
1638
1639 protected:
Sorin Jianu23f70f752017-05-30 16:21:581640 ~MockInstaller() override {
1641 // The unpack path is deleted unconditionally by the component state code,
1642 // which is driving this installer. Therefore, the unpack path must not
1643 // exist when this object is destroyed.
1644 if (!unpack_path_.empty())
1645 EXPECT_FALSE(base::DirectoryExists(unpack_path_));
1646 }
1647
1648 private:
1649 // Contains the |unpack_path| argument of the Install call.
1650 base::FilePath unpack_path_;
sorin9797aba2015-04-17 17:15:031651 };
1652
Sorin Jianua8926bf2018-03-09 21:02:531653 class DataCallbackMock {
sorin9797aba2015-04-17 17:15:031654 public:
Sorin Jianu73900242018-08-17 01:11:531655 static std::vector<base::Optional<CrxComponent>> Callback(
Sorin Jianu7c22795b2018-04-26 22:16:521656 const std::vector<std::string>& ids) {
sorin30474f02017-04-27 00:45:481657 scoped_refptr<MockInstaller> installer =
Taiju Tsuiki36c517d2017-05-18 06:45:431658 base::MakeRefCounted<MockInstaller>();
sorin9797aba2015-04-17 17:15:031659
1660 EXPECT_CALL(*installer, OnUpdateError(_)).Times(0);
Sorin Jianua8ef73d2017-11-02 16:55:171661 EXPECT_CALL(*installer, DoInstall(_, _)).Times(1);
sorin9797aba2015-04-17 17:15:031662 EXPECT_CALL(*installer, GetInstalledFile(_, _)).Times(0);
1663 EXPECT_CALL(*installer, Uninstall()).Times(0);
1664
Sorin Jianu73900242018-08-17 01:11:531665 CrxComponent crx;
1666 crx.name = "test_jebg";
1667 crx.pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
1668 crx.version = base::Version("0.9");
1669 crx.installer = installer;
Joshua Pawlickif4b33f382018-08-17 17:36:511670 crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
Sorin Jianu7c22795b2018-04-26 22:16:521671
Sorin Jianu73900242018-08-17 01:11:531672 return {crx};
sorin9797aba2015-04-17 17:15:031673 }
1674 };
1675
Sorin Jianua8926bf2018-03-09 21:02:531676 class CompletionCallbackMock {
sorin9797aba2015-04-17 17:15:031677 public:
Sorin Jianua8ef73d2017-11-02 16:55:171678 static void Callback(base::OnceClosure quit_closure, Error error) {
sorin7b8650522016-11-02 18:23:411679 EXPECT_EQ(Error::NONE, error);
Sorin Jianua8ef73d2017-11-02 16:55:171680 std::move(quit_closure).Run();
sorin9797aba2015-04-17 17:15:031681 }
1682 };
1683
Sorin Jianua8926bf2018-03-09 21:02:531684 class MockUpdateChecker : public UpdateChecker {
sorin9797aba2015-04-17 17:15:031685 public:
dchengd0fc6aa92016-04-22 18:03:121686 static std::unique_ptr<UpdateChecker> Create(
Sorin Jianu49126332018-02-13 17:07:421687 scoped_refptr<Configurator> config,
wafflese7dff732016-04-15 23:51:491688 PersistedData* metadata) {
Sorin Jianua8926bf2018-03-09 21:02:531689 return std::make_unique<MockUpdateChecker>();
sorin9797aba2015-04-17 17:15:031690 }
1691
Sorin Jianuc303bf42018-09-07 16:19:331692 void CheckForUpdates(
1693 const std::string& session_id,
1694 const std::vector<std::string>& ids_to_check,
1695 const IdToComponentPtrMap& components,
1696 const base::flat_map<std::string, std::string>& additional_attributes,
1697 bool enabled_component_updates,
1698 UpdateCheckCallback update_check_callback) override {
sorin9797aba2015-04-17 17:15:031699 /*
Sorin Jianua8926bf2018-03-09 21:02:531700 Mock the following response:
sorin9797aba2015-04-17 17:15:031701
1702 <?xml version='1.0' encoding='UTF-8'?>
sorin39852802017-05-01 22:46:281703 <response protocol='3.1'>
sorin9797aba2015-04-17 17:15:031704 <app appid='jebgalgnebhfojomionfpkfelancnnkf'>
1705 <updatecheck status='ok'>
1706 <urls>
1707 <url codebase='http://localhost/download/'/>
1708 </urls>
1709 <manifest version='1.0' prodversionmin='11.0.1.0'>
1710 <packages>
sorin74e70672016-02-03 03:13:101711 <package name='jebgalgnebhfojomionfpkfelancnnkf.crx'
1712 hash_sha256='6fc4b93fd11134de1300c2c0bb88c12b644a4ec0fd
1713 7c9b12cb7cc067667bde87'/>
sorin9797aba2015-04-17 17:15:031714 </packages>
1715 </manifest>
1716 </updatecheck>
1717 </app>
1718 </response>
1719 */
Sorin Jianud69d4372018-02-07 19:44:221720 EXPECT_FALSE(session_id.empty());
1721
sorin30474f02017-04-27 00:45:481722 const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
1723 EXPECT_EQ(id, ids_to_check[0]);
1724 EXPECT_EQ(1u, components.count(id));
1725
sorin7cff6e52017-05-17 16:37:231726 ProtocolParser::Result::Manifest::Package package;
sorin9797aba2015-04-17 17:15:031727 package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
sorin74e70672016-02-03 03:13:101728 package.hash_sha256 =
1729 "6fc4b93fd11134de1300c2c0bb88c12b644a4ec0fd7c9b12cb7cc067667bde87";
sorin30474f02017-04-27 00:45:481730
sorin7cff6e52017-05-17 16:37:231731 ProtocolParser::Result result;
sorin30474f02017-04-27 00:45:481732 result.extension_id = id;
sorin9ef301c2017-02-16 20:29:171733 result.status = "ok";
sorin9797aba2015-04-17 17:15:031734 result.crx_urls.push_back(GURL("http://localhost/download/"));
1735 result.manifest.version = "1.0";
1736 result.manifest.browser_min_version = "11.0.1.0";
1737 result.manifest.packages.push_back(package);
1738
Sorin Jianu888ec292018-06-01 15:35:421739 ProtocolParser::Results results;
1740 results.list.push_back(result);
sorin9797aba2015-04-17 17:15:031741 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianuaa4165532018-06-08 19:46:461742 FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
1743 ErrorCategory::kNone, 0, 0));
sorin9797aba2015-04-17 17:15:031744 }
1745 };
1746
Sorin Jianua8926bf2018-03-09 21:02:531747 class MockCrxDownloader : public CrxDownloader {
sorin9797aba2015-04-17 17:15:031748 public:
dchengd0fc6aa92016-04-22 18:03:121749 static std::unique_ptr<CrxDownloader> Create(
sorin9797aba2015-04-17 17:15:031750 bool is_background_download,
Antonio Gomes0807dd62018-08-10 14:28:471751 scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
Sorin Jianua8926bf2018-03-09 21:02:531752 return std::make_unique<MockCrxDownloader>();
sorin9797aba2015-04-17 17:15:031753 }
1754
Sorin Jianua8926bf2018-03-09 21:02:531755 MockCrxDownloader() : CrxDownloader(nullptr) {}
sorin9797aba2015-04-17 17:15:031756
sorin30474f02017-04-27 00:45:481757 private:
sorin9797aba2015-04-17 17:15:031758 void DoStartDownload(const GURL& url) override {
1759 DownloadMetrics download_metrics;
1760 download_metrics.url = url;
1761 download_metrics.downloader = DownloadMetrics::kNone;
1762 download_metrics.error = 0;
1763 download_metrics.downloaded_bytes = 1843;
1764 download_metrics.total_bytes = 1843;
1765 download_metrics.download_time_ms = 1000;
1766
1767 FilePath path;
1768 EXPECT_TRUE(MakeTestFile(
1769 TestFilePath("jebgalgnebhfojomionfpkfelancnnkf.crx"), &path));
1770
1771 Result result;
1772 result.error = 0;
1773 result.response = path;
sorin9797aba2015-04-17 17:15:031774
1775 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianua8926bf2018-03-09 21:02:531776 FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadProgress,
Antonio Gomes31237fb2018-08-27 19:11:031777 base::Unretained(this)));
sorin9797aba2015-04-17 17:15:031778
1779 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianua8926bf2018-03-09 21:02:531780 FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadComplete,
Sorin Jianuebd652462017-07-23 02:00:581781 base::Unretained(this), true, result,
1782 download_metrics));
sorin9797aba2015-04-17 17:15:031783 }
1784 };
1785
Sorin Jianua8926bf2018-03-09 21:02:531786 class MockPingManager : public MockPingManagerImpl {
sorin9797aba2015-04-17 17:15:031787 public:
Sorin Jianua8926bf2018-03-09 21:02:531788 explicit MockPingManager(scoped_refptr<Configurator> config)
1789 : MockPingManagerImpl(config) {}
Sorin Jianu560d5022018-02-12 23:11:541790
1791 protected:
Sorin Jianua8926bf2018-03-09 21:02:531792 ~MockPingManager() override {
1793 const auto ping_data = MockPingManagerImpl::ping_data();
sorin30474f02017-04-27 00:45:481794 EXPECT_EQ(1u, ping_data.size());
1795 EXPECT_EQ("jebgalgnebhfojomionfpkfelancnnkf", ping_data[0].id);
1796 EXPECT_EQ(base::Version("0.9"), ping_data[0].previous_version);
1797 EXPECT_EQ(base::Version("1.0"), ping_data[0].next_version);
Minh X. Nguyena4640cb2018-05-23 21:29:101798 EXPECT_EQ(3, static_cast<int>(ping_data[0].error_category)); // kInstall.
1799 EXPECT_EQ(9, ping_data[0].error_code); // kInstallerError.
sorin9797aba2015-04-17 17:15:031800 }
1801 };
1802
sorin30474f02017-04-27 00:45:481803 scoped_refptr<UpdateClient> update_client =
Taiju Tsuiki36c517d2017-05-18 06:45:431804 base::MakeRefCounted<UpdateClientImpl>(
Sorin Jianua8926bf2018-03-09 21:02:531805 config(), base::MakeRefCounted<MockPingManager>(config()),
1806 &MockUpdateChecker::Create, &MockCrxDownloader::Create);
sorin9797aba2015-04-17 17:15:031807
1808 MockObserver observer;
1809 {
1810 InSequence seq;
1811 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
1812 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
1813 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
1814 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
1815 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
sorin30474f02017-04-27 00:45:481816 "jebgalgnebhfojomionfpkfelancnnkf"))
1817 .Times(AtLeast(1));
sorin9797aba2015-04-17 17:15:031818 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
1819 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
Sorin Jianucbb10e12018-01-23 18:01:441820 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
1821 "jebgalgnebhfojomionfpkfelancnnkf"))
1822 .Times(1);
sorin9797aba2015-04-17 17:15:031823 }
1824
1825 update_client->AddObserver(&observer);
1826
sorin30474f02017-04-27 00:45:481827 std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf"};
sorin9797aba2015-04-17 17:15:031828 update_client->Update(
Sorin Jianua8926bf2018-03-09 21:02:531829 ids, base::BindOnce(&DataCallbackMock::Callback), false,
1830 base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
sorin9797aba2015-04-17 17:15:031831
1832 RunThreads();
1833
1834 update_client->RemoveObserver(&observer);
1835}
1836
1837// Tests the fallback from differential to full update scenario for one CRX.
1838TEST_F(UpdateClientTest, OneCrxDiffUpdateFailsFullUpdateSucceeds) {
Sorin Jianua8926bf2018-03-09 21:02:531839 class DataCallbackMock {
sorin9797aba2015-04-17 17:15:031840 public:
Sorin Jianu73900242018-08-17 01:11:531841 static std::vector<base::Optional<CrxComponent>> Callback(
Sorin Jianu7c22795b2018-04-26 22:16:521842 const std::vector<std::string>& ids) {
sorin9797aba2015-04-17 17:15:031843 static int num_calls = 0;
1844
1845 // Must use the same stateful installer object.
sorin30474f02017-04-27 00:45:481846 static scoped_refptr<CrxInstaller> installer =
Taiju Tsuiki36c517d2017-05-18 06:45:431847 base::MakeRefCounted<VersionedTestInstaller>();
sorin9797aba2015-04-17 17:15:031848
1849 ++num_calls;
1850
Sorin Jianu73900242018-08-17 01:11:531851 CrxComponent crx;
1852 crx.name = "test_ihfo";
1853 crx.pk_hash.assign(ihfo_hash, ihfo_hash + base::size(ihfo_hash));
1854 crx.installer = installer;
Joshua Pawlickif4b33f382018-08-17 17:36:511855 crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
sorin9797aba2015-04-17 17:15:031856 if (num_calls == 1) {
Sorin Jianu73900242018-08-17 01:11:531857 crx.version = base::Version("0.8");
sorin9797aba2015-04-17 17:15:031858 } else if (num_calls == 2) {
Sorin Jianu73900242018-08-17 01:11:531859 crx.version = base::Version("1.0");
sorin9797aba2015-04-17 17:15:031860 } else {
1861 NOTREACHED();
1862 }
1863
Sorin Jianu73900242018-08-17 01:11:531864 return {crx};
sorin9797aba2015-04-17 17:15:031865 }
1866 };
1867
Sorin Jianua8926bf2018-03-09 21:02:531868 class CompletionCallbackMock {
sorin9797aba2015-04-17 17:15:031869 public:
Sorin Jianua8ef73d2017-11-02 16:55:171870 static void Callback(base::OnceClosure quit_closure, Error error) {
sorin7b8650522016-11-02 18:23:411871 EXPECT_EQ(Error::NONE, error);
Sorin Jianua8ef73d2017-11-02 16:55:171872 std::move(quit_closure).Run();
sorin9797aba2015-04-17 17:15:031873 }
1874 };
1875
Sorin Jianua8926bf2018-03-09 21:02:531876 class MockUpdateChecker : public UpdateChecker {
sorin9797aba2015-04-17 17:15:031877 public:
dchengd0fc6aa92016-04-22 18:03:121878 static std::unique_ptr<UpdateChecker> Create(
Sorin Jianu49126332018-02-13 17:07:421879 scoped_refptr<Configurator> config,
wafflese7dff732016-04-15 23:51:491880 PersistedData* metadata) {
Sorin Jianua8926bf2018-03-09 21:02:531881 return std::make_unique<MockUpdateChecker>();
sorin9797aba2015-04-17 17:15:031882 }
1883
Sorin Jianuc303bf42018-09-07 16:19:331884 void CheckForUpdates(
1885 const std::string& session_id,
1886 const std::vector<std::string>& ids_to_check,
1887 const IdToComponentPtrMap& components,
1888 const base::flat_map<std::string, std::string>& additional_attributes,
1889 bool enabled_component_updates,
1890 UpdateCheckCallback update_check_callback) override {
Sorin Jianud69d4372018-02-07 19:44:221891 EXPECT_FALSE(session_id.empty());
1892
sorin9797aba2015-04-17 17:15:031893 static int num_call = 0;
1894 ++num_call;
1895
sorin7cff6e52017-05-17 16:37:231896 ProtocolParser::Results results;
sorin9797aba2015-04-17 17:15:031897
1898 if (num_call == 1) {
1899 /*
Sorin Jianua8926bf2018-03-09 21:02:531900 Mock the following response:
sorin9797aba2015-04-17 17:15:031901 <?xml version='1.0' encoding='UTF-8'?>
sorin39852802017-05-01 22:46:281902 <response protocol='3.1'>
sorin9797aba2015-04-17 17:15:031903 <app appid='ihfokbkgjpifnbbojhneepfflplebdkc'>
1904 <updatecheck status='ok'>
1905 <urls>
1906 <url codebase='http://localhost/download/'/>
1907 </urls>
1908 <manifest version='1.0' prodversionmin='11.0.1.0'>
1909 <packages>
sorin74e70672016-02-03 03:13:101910 <package name='ihfokbkgjpifnbbojhneepfflplebdkc_1.crx'
1911 hash_sha256='813c59747e139a608b3b5fc49633affc6db57437
sorin30474f02017-04-27 00:45:481912 3f309f156ea6d27229c0b3f9'
1913 fp='1'/>
sorin9797aba2015-04-17 17:15:031914 </packages>
1915 </manifest>
1916 </updatecheck>
1917 </app>
1918 </response>
1919 */
sorin30474f02017-04-27 00:45:481920 const std::string id = "ihfokbkgjpifnbbojhneepfflplebdkc";
1921 EXPECT_EQ(id, ids_to_check[0]);
1922 EXPECT_EQ(1u, components.count(id));
1923
sorin7cff6e52017-05-17 16:37:231924 ProtocolParser::Result::Manifest::Package package;
sorin9797aba2015-04-17 17:15:031925 package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_1.crx";
sorin74e70672016-02-03 03:13:101926 package.hash_sha256 =
1927 "813c59747e139a608b3b5fc49633affc6db574373f309f156ea6d27229c0b3f9";
sorin9797aba2015-04-17 17:15:031928 package.fingerprint = "1";
sorin30474f02017-04-27 00:45:481929
sorin7cff6e52017-05-17 16:37:231930 ProtocolParser::Result result;
sorin30474f02017-04-27 00:45:481931 result.extension_id = id;
sorin9ef301c2017-02-16 20:29:171932 result.status = "ok";
sorin9797aba2015-04-17 17:15:031933 result.crx_urls.push_back(GURL("http://localhost/download/"));
1934 result.manifest.version = "1.0";
1935 result.manifest.browser_min_version = "11.0.1.0";
1936 result.manifest.packages.push_back(package);
Sorin Jianu888ec292018-06-01 15:35:421937 results.list.push_back(result);
sorin9797aba2015-04-17 17:15:031938 } else if (num_call == 2) {
1939 /*
Sorin Jianua8926bf2018-03-09 21:02:531940 Mock the following response:
sorin9797aba2015-04-17 17:15:031941 <?xml version='1.0' encoding='UTF-8'?>
sorin39852802017-05-01 22:46:281942 <response protocol='3.1'>
sorin9797aba2015-04-17 17:15:031943 <app appid='ihfokbkgjpifnbbojhneepfflplebdkc'>
1944 <updatecheck status='ok'>
1945 <urls>
1946 <url codebase='http://localhost/download/'/>
1947 <url codebasediff='http://localhost/download/'/>
1948 </urls>
1949 <manifest version='2.0' prodversionmin='11.0.1.0'>
1950 <packages>
1951 <package name='ihfokbkgjpifnbbojhneepfflplebdkc_2.crx'
1952 namediff='ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx'
sorin74e70672016-02-03 03:13:101953 hash_sha256='1af337fbd19c72db0f870753bcd7711c3ae9dcaa
1954 0ecde26c262bad942b112990'
1955 fp='22'
1956 hashdiff_sha256='73c6e2d4f783fc4ca5481e89e0b8bfce7aec
sorin46bdd0b32016-08-30 22:42:261957 8ead3686290c94792658ec06f2f2'/>
sorin9797aba2015-04-17 17:15:031958 </packages>
1959 </manifest>
1960 </updatecheck>
1961 </app>
1962 </response>
1963 */
sorin30474f02017-04-27 00:45:481964 const std::string id = "ihfokbkgjpifnbbojhneepfflplebdkc";
1965 EXPECT_EQ(id, ids_to_check[0]);
1966 EXPECT_EQ(1u, components.count(id));
1967
sorin7cff6e52017-05-17 16:37:231968 ProtocolParser::Result::Manifest::Package package;
sorin9797aba2015-04-17 17:15:031969 package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_2.crx";
1970 package.namediff = "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx";
sorin74e70672016-02-03 03:13:101971 package.hash_sha256 =
1972 "1af337fbd19c72db0f870753bcd7711c3ae9dcaa0ecde26c262bad942b112990";
1973 package.hashdiff_sha256 =
1974 "73c6e2d4f783fc4ca5481e89e0b8bfce7aec8ead3686290c94792658ec06f2f2";
sorin9797aba2015-04-17 17:15:031975 package.fingerprint = "22";
sorin30474f02017-04-27 00:45:481976
sorin7cff6e52017-05-17 16:37:231977 ProtocolParser::Result result;
sorin30474f02017-04-27 00:45:481978 result.extension_id = id;
sorin9ef301c2017-02-16 20:29:171979 result.status = "ok";
sorin9797aba2015-04-17 17:15:031980 result.crx_urls.push_back(GURL("http://localhost/download/"));
1981 result.crx_diffurls.push_back(GURL("http://localhost/download/"));
1982 result.manifest.version = "2.0";
1983 result.manifest.browser_min_version = "11.0.1.0";
1984 result.manifest.packages.push_back(package);
Sorin Jianu888ec292018-06-01 15:35:421985 results.list.push_back(result);
sorin9797aba2015-04-17 17:15:031986 } else {
1987 NOTREACHED();
1988 }
1989
1990 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianuaa4165532018-06-08 19:46:461991 FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
1992 ErrorCategory::kNone, 0, 0));
sorin9797aba2015-04-17 17:15:031993 }
1994 };
1995
Sorin Jianua8926bf2018-03-09 21:02:531996 class MockCrxDownloader : public CrxDownloader {
sorin9797aba2015-04-17 17:15:031997 public:
dchengd0fc6aa92016-04-22 18:03:121998 static std::unique_ptr<CrxDownloader> Create(
sorin9797aba2015-04-17 17:15:031999 bool is_background_download,
Antonio Gomes0807dd62018-08-10 14:28:472000 scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
Sorin Jianua8926bf2018-03-09 21:02:532001 return std::make_unique<MockCrxDownloader>();
sorin9797aba2015-04-17 17:15:032002 }
2003
Sorin Jianua8926bf2018-03-09 21:02:532004 MockCrxDownloader() : CrxDownloader(nullptr) {}
sorin9797aba2015-04-17 17:15:032005
sorin30474f02017-04-27 00:45:482006 private:
sorin9797aba2015-04-17 17:15:032007 void DoStartDownload(const GURL& url) override {
2008 DownloadMetrics download_metrics;
2009 FilePath path;
2010 Result result;
2011 if (url.path() == "/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx") {
2012 download_metrics.url = url;
2013 download_metrics.downloader = DownloadMetrics::kNone;
2014 download_metrics.error = 0;
2015 download_metrics.downloaded_bytes = 53638;
2016 download_metrics.total_bytes = 53638;
2017 download_metrics.download_time_ms = 2000;
2018
2019 EXPECT_TRUE(MakeTestFile(
2020 TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"), &path));
2021
2022 result.error = 0;
2023 result.response = path;
sorin9797aba2015-04-17 17:15:032024 } else if (url.path() ==
2025 "/download/ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx") {
2026 // A download error is injected on this execution path.
2027 download_metrics.url = url;
2028 download_metrics.downloader = DownloadMetrics::kNone;
2029 download_metrics.error = -1;
2030 download_metrics.downloaded_bytes = 0;
2031 download_metrics.total_bytes = 2105;
2032 download_metrics.download_time_ms = 1000;
2033
Sorin Jianu52de5fa2017-10-09 23:19:332034 // The response must not include a file path in the case of errors.
sorin9797aba2015-04-17 17:15:032035 result.error = -1;
sorin9797aba2015-04-17 17:15:032036 } else if (url.path() ==
2037 "/download/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx") {
2038 download_metrics.url = url;
2039 download_metrics.downloader = DownloadMetrics::kNone;
2040 download_metrics.error = 0;
2041 download_metrics.downloaded_bytes = 53855;
2042 download_metrics.total_bytes = 53855;
2043 download_metrics.download_time_ms = 1000;
2044
2045 EXPECT_TRUE(MakeTestFile(
2046 TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"), &path));
2047
2048 result.error = 0;
2049 result.response = path;
sorin9797aba2015-04-17 17:15:032050 }
2051
2052 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianua8926bf2018-03-09 21:02:532053 FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadProgress,
Antonio Gomes31237fb2018-08-27 19:11:032054 base::Unretained(this)));
sorin9797aba2015-04-17 17:15:032055
2056 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianua8926bf2018-03-09 21:02:532057 FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadComplete,
Sorin Jianuebd652462017-07-23 02:00:582058 base::Unretained(this), true, result,
2059 download_metrics));
sorin9797aba2015-04-17 17:15:032060 }
2061 };
2062
Sorin Jianua8926bf2018-03-09 21:02:532063 class MockPingManager : public MockPingManagerImpl {
sorin9797aba2015-04-17 17:15:032064 public:
Sorin Jianua8926bf2018-03-09 21:02:532065 explicit MockPingManager(scoped_refptr<Configurator> config)
2066 : MockPingManagerImpl(config) {}
Sorin Jianu560d5022018-02-12 23:11:542067
2068 protected:
Sorin Jianua8926bf2018-03-09 21:02:532069 ~MockPingManager() override {
2070 const auto ping_data = MockPingManagerImpl::ping_data();
sorin30474f02017-04-27 00:45:482071 EXPECT_EQ(2u, ping_data.size());
2072 EXPECT_EQ("ihfokbkgjpifnbbojhneepfflplebdkc", ping_data[0].id);
2073 EXPECT_EQ(base::Version("0.8"), ping_data[0].previous_version);
2074 EXPECT_EQ(base::Version("1.0"), ping_data[0].next_version);
Minh X. Nguyena4640cb2018-05-23 21:29:102075 EXPECT_EQ(0, static_cast<int>(ping_data[0].error_category));
sorin30474f02017-04-27 00:45:482076 EXPECT_EQ(0, ping_data[0].error_code);
2077 EXPECT_EQ("ihfokbkgjpifnbbojhneepfflplebdkc", ping_data[1].id);
2078 EXPECT_EQ(base::Version("1.0"), ping_data[1].previous_version);
2079 EXPECT_EQ(base::Version("2.0"), ping_data[1].next_version);
Minh X. Nguyena4640cb2018-05-23 21:29:102080 EXPECT_EQ(0, static_cast<int>(ping_data[1].error_category));
sorin30474f02017-04-27 00:45:482081 EXPECT_EQ(0, ping_data[1].error_code);
2082 EXPECT_TRUE(ping_data[1].diff_update_failed);
Minh X. Nguyena4640cb2018-05-23 21:29:102083 EXPECT_EQ(1, static_cast<int>(ping_data[1].diff_error_category));
sorin30474f02017-04-27 00:45:482084 EXPECT_EQ(-1, ping_data[1].diff_error_code);
sorin9797aba2015-04-17 17:15:032085 }
2086 };
2087
sorin30474f02017-04-27 00:45:482088 scoped_refptr<UpdateClient> update_client =
Taiju Tsuiki36c517d2017-05-18 06:45:432089 base::MakeRefCounted<UpdateClientImpl>(
Sorin Jianua8926bf2018-03-09 21:02:532090 config(), base::MakeRefCounted<MockPingManager>(config()),
2091 &MockUpdateChecker::Create, &MockCrxDownloader::Create);
sorin9797aba2015-04-17 17:15:032092
2093 MockObserver observer;
2094 {
2095 InSequence seq;
2096 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
2097 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
2098 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
2099 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
2100 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
sorin30474f02017-04-27 00:45:482101 "ihfokbkgjpifnbbojhneepfflplebdkc"))
2102 .Times(AtLeast(1));
sorin9797aba2015-04-17 17:15:032103 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
2104 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
2105 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED,
2106 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
2107
2108 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
2109 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
2110 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
2111 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
2112 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
sorin30474f02017-04-27 00:45:482113 "ihfokbkgjpifnbbojhneepfflplebdkc"))
2114 .Times(AtLeast(1));
sorin9797aba2015-04-17 17:15:032115 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
2116 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
2117 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED,
2118 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
2119 }
2120
2121 update_client->AddObserver(&observer);
2122
sorin30474f02017-04-27 00:45:482123 const std::vector<std::string> ids = {"ihfokbkgjpifnbbojhneepfflplebdkc"};
sorin9797aba2015-04-17 17:15:032124
2125 {
2126 base::RunLoop runloop;
Sorin Jianua8926bf2018-03-09 21:02:532127 update_client->Update(ids, base::BindOnce(&DataCallbackMock::Callback),
Sorin Jianub41a592a2018-03-02 16:30:272128 false,
Sorin Jianua8926bf2018-03-09 21:02:532129 base::BindOnce(&CompletionCallbackMock::Callback,
Sorin Jianua8ef73d2017-11-02 16:55:172130 runloop.QuitClosure()));
sorin9797aba2015-04-17 17:15:032131 runloop.Run();
2132 }
2133
2134 {
2135 base::RunLoop runloop;
Sorin Jianua8926bf2018-03-09 21:02:532136 update_client->Update(ids, base::BindOnce(&DataCallbackMock::Callback),
Sorin Jianub41a592a2018-03-02 16:30:272137 false,
Sorin Jianua8926bf2018-03-09 21:02:532138 base::BindOnce(&CompletionCallbackMock::Callback,
Sorin Jianua8ef73d2017-11-02 16:55:172139 runloop.QuitClosure()));
sorin9797aba2015-04-17 17:15:032140 runloop.Run();
2141 }
2142
2143 update_client->RemoveObserver(&observer);
sorin7c717622015-05-26 19:59:092144}
2145
2146// Tests the queuing of update checks. In this scenario, two update checks are
2147// done for one CRX. The second update check call is queued up and will run
2148// after the first check has completed. The CRX has no updates.
2149TEST_F(UpdateClientTest, OneCrxNoUpdateQueuedCall) {
Sorin Jianua8926bf2018-03-09 21:02:532150 class DataCallbackMock {
sorin7c717622015-05-26 19:59:092151 public:
Sorin Jianu73900242018-08-17 01:11:532152 static std::vector<base::Optional<CrxComponent>> Callback(
Sorin Jianu7c22795b2018-04-26 22:16:522153 const std::vector<std::string>& ids) {
Sorin Jianu73900242018-08-17 01:11:532154 CrxComponent crx;
2155 crx.name = "test_jebg";
2156 crx.pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
2157 crx.version = base::Version("0.9");
2158 crx.installer = base::MakeRefCounted<TestInstaller>();
Joshua Pawlickif4b33f382018-08-17 17:36:512159 crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
Sorin Jianu73900242018-08-17 01:11:532160 return {crx};
sorin7c717622015-05-26 19:59:092161 }
2162 };
2163
Sorin Jianua8926bf2018-03-09 21:02:532164 class CompletionCallbackMock {
sorin7c717622015-05-26 19:59:092165 public:
Sorin Jianua8ef73d2017-11-02 16:55:172166 static void Callback(base::OnceClosure quit_closure, Error error) {
sorin7c717622015-05-26 19:59:092167 static int num_call = 0;
2168 ++num_call;
2169
sorin7b8650522016-11-02 18:23:412170 EXPECT_EQ(Error::NONE, error);
sorin7c717622015-05-26 19:59:092171
2172 if (num_call == 2)
Sorin Jianua8ef73d2017-11-02 16:55:172173 std::move(quit_closure).Run();
sorin7c717622015-05-26 19:59:092174 }
2175 };
2176
Sorin Jianua8926bf2018-03-09 21:02:532177 class MockUpdateChecker : public UpdateChecker {
sorin7c717622015-05-26 19:59:092178 public:
dchengd0fc6aa92016-04-22 18:03:122179 static std::unique_ptr<UpdateChecker> Create(
Sorin Jianu49126332018-02-13 17:07:422180 scoped_refptr<Configurator> config,
wafflese7dff732016-04-15 23:51:492181 PersistedData* metadata) {
Sorin Jianua8926bf2018-03-09 21:02:532182 return std::make_unique<MockUpdateChecker>();
sorin7c717622015-05-26 19:59:092183 }
2184
Sorin Jianuc303bf42018-09-07 16:19:332185 void CheckForUpdates(
2186 const std::string& session_id,
2187 const std::vector<std::string>& ids_to_check,
2188 const IdToComponentPtrMap& components,
2189 const base::flat_map<std::string, std::string>& additional_attributes,
2190 bool enabled_component_updates,
2191 UpdateCheckCallback update_check_callback) override {
Sorin Jianud69d4372018-02-07 19:44:222192 EXPECT_FALSE(session_id.empty());
sorin30474f02017-04-27 00:45:482193 EXPECT_TRUE(enabled_component_updates);
2194 EXPECT_EQ(1u, ids_to_check.size());
2195 const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
2196 EXPECT_EQ(id, ids_to_check.front());
2197 EXPECT_EQ(1u, components.count(id));
2198
2199 auto& component = components.at(id);
2200
Sorin Jianub41a592a2018-03-02 16:30:272201 EXPECT_FALSE(component->is_foreground());
sorin30474f02017-04-27 00:45:482202
sorin7cff6e52017-05-17 16:37:232203 ProtocolParser::Result result;
sorin30474f02017-04-27 00:45:482204 result.extension_id = id;
2205 result.status = "noupdate";
Sorin Jianu888ec292018-06-01 15:35:422206 ProtocolParser::Results results;
2207 results.list.push_back(result);
sorin30474f02017-04-27 00:45:482208
sorin7c717622015-05-26 19:59:092209 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianuaa4165532018-06-08 19:46:462210 FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
2211 ErrorCategory::kNone, 0, 0));
sorin7c717622015-05-26 19:59:092212 }
2213 };
2214
Sorin Jianua8926bf2018-03-09 21:02:532215 class MockCrxDownloader : public CrxDownloader {
sorin7c717622015-05-26 19:59:092216 public:
dchengd0fc6aa92016-04-22 18:03:122217 static std::unique_ptr<CrxDownloader> Create(
sorin7c717622015-05-26 19:59:092218 bool is_background_download,
Antonio Gomes0807dd62018-08-10 14:28:472219 scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
Sorin Jianua8926bf2018-03-09 21:02:532220 return std::make_unique<MockCrxDownloader>();
sorin7c717622015-05-26 19:59:092221 }
2222
Sorin Jianua8926bf2018-03-09 21:02:532223 MockCrxDownloader() : CrxDownloader(nullptr) {}
sorin7c717622015-05-26 19:59:092224
sorin30474f02017-04-27 00:45:482225 private:
sorin7c717622015-05-26 19:59:092226 void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); }
2227 };
2228
Sorin Jianua8926bf2018-03-09 21:02:532229 class MockPingManager : public MockPingManagerImpl {
sorin7c717622015-05-26 19:59:092230 public:
Sorin Jianua8926bf2018-03-09 21:02:532231 explicit MockPingManager(scoped_refptr<Configurator> config)
2232 : MockPingManagerImpl(config) {}
Sorin Jianu560d5022018-02-12 23:11:542233
2234 protected:
Sorin Jianua8926bf2018-03-09 21:02:532235 ~MockPingManager() override { EXPECT_TRUE(ping_data().empty()); }
sorin7c717622015-05-26 19:59:092236 };
2237
sorin30474f02017-04-27 00:45:482238 scoped_refptr<UpdateClient> update_client =
Taiju Tsuiki36c517d2017-05-18 06:45:432239 base::MakeRefCounted<UpdateClientImpl>(
Sorin Jianua8926bf2018-03-09 21:02:532240 config(), base::MakeRefCounted<MockPingManager>(config()),
2241 &MockUpdateChecker::Create, &MockCrxDownloader::Create);
sorin7c717622015-05-26 19:59:092242
2243 MockObserver observer;
2244 InSequence seq;
2245 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
2246 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
2247 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED,
2248 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
2249 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
2250 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
2251 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED,
2252 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
2253
2254 update_client->AddObserver(&observer);
2255
sorin30474f02017-04-27 00:45:482256 const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf"};
sorin7c717622015-05-26 19:59:092257 update_client->Update(
Sorin Jianua8926bf2018-03-09 21:02:532258 ids, base::BindOnce(&DataCallbackMock::Callback), false,
2259 base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
sorin7c717622015-05-26 19:59:092260 update_client->Update(
Sorin Jianua8926bf2018-03-09 21:02:532261 ids, base::BindOnce(&DataCallbackMock::Callback), false,
2262 base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
sorin7c717622015-05-26 19:59:092263
2264 RunThreads();
2265
2266 update_client->RemoveObserver(&observer);
sorin7c717622015-05-26 19:59:092267}
2268
2269// Tests the install of one CRX.
2270TEST_F(UpdateClientTest, OneCrxInstall) {
Sorin Jianua8926bf2018-03-09 21:02:532271 class DataCallbackMock {
sorin7c717622015-05-26 19:59:092272 public:
Sorin Jianu73900242018-08-17 01:11:532273 static std::vector<base::Optional<CrxComponent>> Callback(
Sorin Jianu7c22795b2018-04-26 22:16:522274 const std::vector<std::string>& ids) {
Sorin Jianu73900242018-08-17 01:11:532275 CrxComponent crx;
2276 crx.name = "test_jebg";
2277 crx.pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
2278 crx.version = base::Version("0.0");
2279 crx.installer = base::MakeRefCounted<TestInstaller>();
Joshua Pawlickif4b33f382018-08-17 17:36:512280 crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
Sorin Jianu73900242018-08-17 01:11:532281 return {crx};
sorin7c717622015-05-26 19:59:092282 }
2283 };
2284
Sorin Jianua8926bf2018-03-09 21:02:532285 class CompletionCallbackMock {
sorin7c717622015-05-26 19:59:092286 public:
Sorin Jianua8ef73d2017-11-02 16:55:172287 static void Callback(base::OnceClosure quit_closure, Error error) {
sorin7b8650522016-11-02 18:23:412288 EXPECT_EQ(Error::NONE, error);
Sorin Jianua8ef73d2017-11-02 16:55:172289 std::move(quit_closure).Run();
sorin7c717622015-05-26 19:59:092290 }
2291 };
2292
Sorin Jianua8926bf2018-03-09 21:02:532293 class MockUpdateChecker : public UpdateChecker {
sorin7c717622015-05-26 19:59:092294 public:
dchengd0fc6aa92016-04-22 18:03:122295 static std::unique_ptr<UpdateChecker> Create(
Sorin Jianu49126332018-02-13 17:07:422296 scoped_refptr<Configurator> config,
wafflese7dff732016-04-15 23:51:492297 PersistedData* metadata) {
Sorin Jianua8926bf2018-03-09 21:02:532298 return std::make_unique<MockUpdateChecker>();
sorin7c717622015-05-26 19:59:092299 }
2300
Sorin Jianuc303bf42018-09-07 16:19:332301 void CheckForUpdates(
2302 const std::string& session_id,
2303 const std::vector<std::string>& ids_to_check,
2304 const IdToComponentPtrMap& components,
2305 const base::flat_map<std::string, std::string>& additional_attributes,
2306 bool enabled_component_updates,
2307 UpdateCheckCallback update_check_callback) override {
sorin7c717622015-05-26 19:59:092308 /*
Sorin Jianua8926bf2018-03-09 21:02:532309 Mock the following response:
sorin7c717622015-05-26 19:59:092310
2311 <?xml version='1.0' encoding='UTF-8'?>
sorin39852802017-05-01 22:46:282312 <response protocol='3.1'>
sorin7c717622015-05-26 19:59:092313 <app appid='jebgalgnebhfojomionfpkfelancnnkf'>
2314 <updatecheck status='ok'>
2315 <urls>
2316 <url codebase='http://localhost/download/'/>
2317 </urls>
2318 <manifest version='1.0' prodversionmin='11.0.1.0'>
2319 <packages>
sorin74e70672016-02-03 03:13:102320 <package name='jebgalgnebhfojomionfpkfelancnnkf.crx'
2321 hash_sha256='6fc4b93fd11134de1300c2c0bb88c12b644a4ec0fd
2322 7c9b12cb7cc067667bde87'/>
sorin7c717622015-05-26 19:59:092323 </packages>
2324 </manifest>
2325 </updatecheck>
2326 </app>
2327 </response>
2328 */
Sorin Jianud69d4372018-02-07 19:44:222329 EXPECT_FALSE(session_id.empty());
sorin30474f02017-04-27 00:45:482330 EXPECT_TRUE(enabled_component_updates);
2331 EXPECT_EQ(1u, ids_to_check.size());
2332
2333 const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
2334 EXPECT_EQ(id, ids_to_check[0]);
2335 EXPECT_EQ(1u, components.count(id));
2336
sorin7cff6e52017-05-17 16:37:232337 ProtocolParser::Result::Manifest::Package package;
sorin7c717622015-05-26 19:59:092338 package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
sorin74e70672016-02-03 03:13:102339 package.hash_sha256 =
2340 "6fc4b93fd11134de1300c2c0bb88c12b644a4ec0fd7c9b12cb7cc067667bde87";
sorin30474f02017-04-27 00:45:482341
sorin7cff6e52017-05-17 16:37:232342 ProtocolParser::Result result;
sorin30474f02017-04-27 00:45:482343 result.extension_id = id;
sorin9ef301c2017-02-16 20:29:172344 result.status = "ok";
sorin7c717622015-05-26 19:59:092345 result.crx_urls.push_back(GURL("http://localhost/download/"));
2346 result.manifest.version = "1.0";
2347 result.manifest.browser_min_version = "11.0.1.0";
2348 result.manifest.packages.push_back(package);
2349
Sorin Jianu888ec292018-06-01 15:35:422350 ProtocolParser::Results results;
2351 results.list.push_back(result);
sorin30474f02017-04-27 00:45:482352
2353 // Verify that calling Install sets ondemand.
Sorin Jianu888ec292018-06-01 15:35:422354 EXPECT_TRUE(components.at(id)->is_foreground());
sorin7c717622015-05-26 19:59:092355
2356 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianuaa4165532018-06-08 19:46:462357 FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
2358 ErrorCategory::kNone, 0, 0));
sorin7c717622015-05-26 19:59:092359 }
2360 };
2361
Sorin Jianua8926bf2018-03-09 21:02:532362 class MockCrxDownloader : public CrxDownloader {
sorin7c717622015-05-26 19:59:092363 public:
dchengd0fc6aa92016-04-22 18:03:122364 static std::unique_ptr<CrxDownloader> Create(
sorin7c717622015-05-26 19:59:092365 bool is_background_download,
Antonio Gomes0807dd62018-08-10 14:28:472366 scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
Sorin Jianua8926bf2018-03-09 21:02:532367 return std::make_unique<MockCrxDownloader>();
sorin7c717622015-05-26 19:59:092368 }
2369
Sorin Jianua8926bf2018-03-09 21:02:532370 MockCrxDownloader() : CrxDownloader(nullptr) {}
sorin7c717622015-05-26 19:59:092371
sorin30474f02017-04-27 00:45:482372 private:
sorin7c717622015-05-26 19:59:092373 void DoStartDownload(const GURL& url) override {
2374 DownloadMetrics download_metrics;
2375 FilePath path;
2376 Result result;
2377 if (url.path() == "/download/jebgalgnebhfojomionfpkfelancnnkf.crx") {
2378 download_metrics.url = url;
2379 download_metrics.downloader = DownloadMetrics::kNone;
2380 download_metrics.error = 0;
2381 download_metrics.downloaded_bytes = 1843;
2382 download_metrics.total_bytes = 1843;
2383 download_metrics.download_time_ms = 1000;
2384
2385 EXPECT_TRUE(MakeTestFile(
2386 TestFilePath("jebgalgnebhfojomionfpkfelancnnkf.crx"), &path));
2387
2388 result.error = 0;
2389 result.response = path;
sorin7c717622015-05-26 19:59:092390 } else {
2391 NOTREACHED();
2392 }
2393
2394 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianua8926bf2018-03-09 21:02:532395 FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadProgress,
Antonio Gomes31237fb2018-08-27 19:11:032396 base::Unretained(this)));
sorin7c717622015-05-26 19:59:092397
2398 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianua8926bf2018-03-09 21:02:532399 FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadComplete,
Sorin Jianuebd652462017-07-23 02:00:582400 base::Unretained(this), true, result,
2401 download_metrics));
sorin7c717622015-05-26 19:59:092402 }
2403 };
2404
Sorin Jianua8926bf2018-03-09 21:02:532405 class MockPingManager : public MockPingManagerImpl {
sorin7c717622015-05-26 19:59:092406 public:
Sorin Jianua8926bf2018-03-09 21:02:532407 explicit MockPingManager(scoped_refptr<Configurator> config)
2408 : MockPingManagerImpl(config) {}
Sorin Jianu560d5022018-02-12 23:11:542409
2410 protected:
Sorin Jianua8926bf2018-03-09 21:02:532411 ~MockPingManager() override {
2412 const auto ping_data = MockPingManagerImpl::ping_data();
sorin30474f02017-04-27 00:45:482413 EXPECT_EQ(1u, ping_data.size());
2414 EXPECT_EQ("jebgalgnebhfojomionfpkfelancnnkf", ping_data[0].id);
2415 EXPECT_EQ(base::Version("0.0"), ping_data[0].previous_version);
2416 EXPECT_EQ(base::Version("1.0"), ping_data[0].next_version);
Minh X. Nguyena4640cb2018-05-23 21:29:102417 EXPECT_EQ(0, static_cast<int>(ping_data[0].error_category));
sorin30474f02017-04-27 00:45:482418 EXPECT_EQ(0, ping_data[0].error_code);
sorin7c717622015-05-26 19:59:092419 }
2420 };
2421
sorin30474f02017-04-27 00:45:482422 scoped_refptr<UpdateClient> update_client =
Taiju Tsuiki36c517d2017-05-18 06:45:432423 base::MakeRefCounted<UpdateClientImpl>(
Sorin Jianua8926bf2018-03-09 21:02:532424 config(), base::MakeRefCounted<MockPingManager>(config()),
2425 &MockUpdateChecker::Create, &MockCrxDownloader::Create);
sorin7c717622015-05-26 19:59:092426
2427 MockObserver observer;
sorin7c717622015-05-26 19:59:092428 InSequence seq;
2429 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
2430 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
2431 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
2432 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
2433 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
sorin30474f02017-04-27 00:45:482434 "jebgalgnebhfojomionfpkfelancnnkf"))
2435 .Times(AtLeast(1));
sorin7c717622015-05-26 19:59:092436 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
2437 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
2438 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED,
2439 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
2440
2441 update_client->AddObserver(&observer);
2442
2443 update_client->Install(
2444 std::string("jebgalgnebhfojomionfpkfelancnnkf"),
Sorin Jianua8926bf2018-03-09 21:02:532445 base::BindOnce(&DataCallbackMock::Callback),
2446 base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
sorin7c717622015-05-26 19:59:092447
2448 RunThreads();
2449
2450 update_client->RemoveObserver(&observer);
sorin9797aba2015-04-17 17:15:032451}
2452
Sorin Jianucb4431a2018-04-30 20:59:242453// Tests the install of one CRX when no component data is provided. This
2454// results in an install error.
2455TEST_F(UpdateClientTest, OneCrxInstallNoCrxComponentData) {
2456 class DataCallbackMock {
2457 public:
Sorin Jianu73900242018-08-17 01:11:532458 static std::vector<base::Optional<CrxComponent>> Callback(
Sorin Jianucb4431a2018-04-30 20:59:242459 const std::vector<std::string>& ids) {
Sorin Jianu73900242018-08-17 01:11:532460 return {base::nullopt};
Sorin Jianucb4431a2018-04-30 20:59:242461 }
2462 };
2463
2464 class CompletionCallbackMock {
2465 public:
2466 static void Callback(base::OnceClosure quit_closure, Error error) {
2467 EXPECT_EQ(Error::NONE, error);
2468 std::move(quit_closure).Run();
2469 }
2470 };
2471
2472 class MockUpdateChecker : public UpdateChecker {
2473 public:
2474 static std::unique_ptr<UpdateChecker> Create(
2475 scoped_refptr<Configurator> config,
2476 PersistedData* metadata) {
2477 return std::make_unique<MockUpdateChecker>();
2478 }
2479
Sorin Jianuc303bf42018-09-07 16:19:332480 void CheckForUpdates(
2481 const std::string& session_id,
2482 const std::vector<std::string>& ids_to_check,
2483 const IdToComponentPtrMap& components,
2484 const base::flat_map<std::string, std::string>& additional_attributes,
2485 bool enabled_component_updates,
2486 UpdateCheckCallback update_check_callback) override {
Sorin Jianucb4431a2018-04-30 20:59:242487 NOTREACHED();
2488 }
2489 };
2490
2491 class MockCrxDownloader : public CrxDownloader {
2492 public:
2493 static std::unique_ptr<CrxDownloader> Create(
2494 bool is_background_download,
Antonio Gomes0807dd62018-08-10 14:28:472495 scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
Sorin Jianucb4431a2018-04-30 20:59:242496 return std::make_unique<MockCrxDownloader>();
2497 }
2498
2499 MockCrxDownloader() : CrxDownloader(nullptr) {}
2500
2501 private:
2502 void DoStartDownload(const GURL& url) override { NOTREACHED(); }
2503 };
2504
2505 class MockPingManager : public MockPingManagerImpl {
2506 public:
2507 explicit MockPingManager(scoped_refptr<Configurator> config)
2508 : MockPingManagerImpl(config) {}
2509
2510 protected:
2511 ~MockPingManager() override {
2512 EXPECT_EQ(0u, MockPingManagerImpl::ping_data().size());
2513 }
2514 };
2515
2516 scoped_refptr<UpdateClient> update_client =
2517 base::MakeRefCounted<UpdateClientImpl>(
2518 config(), base::MakeRefCounted<MockPingManager>(config()),
2519 &MockUpdateChecker::Create, &MockCrxDownloader::Create);
2520
2521 MockObserver observer;
2522 InSequence seq;
2523 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
2524 "jebgalgnebhfojomionfpkfelancnnkf"))
Sorin Jianu73900242018-08-17 01:11:532525 .Times(1)
2526 .WillOnce(Invoke([&update_client](Events event, const std::string& id) {
2527 // Tests that the state of the component when the CrxComponent data
2528 // is not provided. In this case, the optional |item.component| instance
2529 // is not present.
2530 CrxUpdateItem item;
2531 EXPECT_TRUE(update_client->GetCrxUpdateState(id, &item));
2532 EXPECT_EQ(ComponentState::kUpdateError, item.state);
2533 EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", item.id.c_str());
2534 EXPECT_FALSE(item.component);
2535 EXPECT_EQ(ErrorCategory::kService, item.error_category);
2536 EXPECT_EQ(static_cast<int>(Error::CRX_NOT_FOUND), item.error_code);
2537 EXPECT_EQ(0, item.extra_code1);
2538 }));
Sorin Jianucb4431a2018-04-30 20:59:242539
2540 update_client->AddObserver(&observer);
2541
2542 update_client->Install(
2543 std::string("jebgalgnebhfojomionfpkfelancnnkf"),
2544 base::BindOnce(&DataCallbackMock::Callback),
2545 base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
2546
2547 RunThreads();
2548
2549 update_client->RemoveObserver(&observer);
2550}
2551
sorin08d153c2015-10-30 00:04:202552// Tests that overlapping installs of the same CRX result in an error.
2553TEST_F(UpdateClientTest, ConcurrentInstallSameCRX) {
Sorin Jianua8926bf2018-03-09 21:02:532554 class DataCallbackMock {
sorin08d153c2015-10-30 00:04:202555 public:
Sorin Jianu73900242018-08-17 01:11:532556 static std::vector<base::Optional<CrxComponent>> Callback(
Sorin Jianu7c22795b2018-04-26 22:16:522557 const std::vector<std::string>& ids) {
Sorin Jianu73900242018-08-17 01:11:532558 CrxComponent crx;
2559 crx.name = "test_jebg";
2560 crx.pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
2561 crx.version = base::Version("0.0");
2562 crx.installer = base::MakeRefCounted<TestInstaller>();
Joshua Pawlickif4b33f382018-08-17 17:36:512563 crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
Sorin Jianu73900242018-08-17 01:11:532564 return {crx};
sorin08d153c2015-10-30 00:04:202565 }
2566 };
2567
Sorin Jianua8926bf2018-03-09 21:02:532568 class CompletionCallbackMock {
sorin08d153c2015-10-30 00:04:202569 public:
Sorin Jianua8ef73d2017-11-02 16:55:172570 static void Callback(base::OnceClosure quit_closure, Error error) {
sorin08d153c2015-10-30 00:04:202571 static int num_call = 0;
2572 ++num_call;
2573
2574 EXPECT_LE(num_call, 2);
2575
2576 if (num_call == 1) {
sorin7b8650522016-11-02 18:23:412577 EXPECT_EQ(Error::UPDATE_IN_PROGRESS, error);
sorin08d153c2015-10-30 00:04:202578 return;
2579 }
2580 if (num_call == 2) {
sorin7b8650522016-11-02 18:23:412581 EXPECT_EQ(Error::NONE, error);
Sorin Jianua8ef73d2017-11-02 16:55:172582 std::move(quit_closure).Run();
sorin08d153c2015-10-30 00:04:202583 }
2584 }
2585 };
2586
Sorin Jianua8926bf2018-03-09 21:02:532587 class MockUpdateChecker : public UpdateChecker {
sorin08d153c2015-10-30 00:04:202588 public:
dchengd0fc6aa92016-04-22 18:03:122589 static std::unique_ptr<UpdateChecker> Create(
Sorin Jianu49126332018-02-13 17:07:422590 scoped_refptr<Configurator> config,
wafflese7dff732016-04-15 23:51:492591 PersistedData* metadata) {
Sorin Jianua8926bf2018-03-09 21:02:532592 return std::make_unique<MockUpdateChecker>();
sorin08d153c2015-10-30 00:04:202593 }
2594
Sorin Jianuc303bf42018-09-07 16:19:332595 void CheckForUpdates(
2596 const std::string& session_id,
2597 const std::vector<std::string>& ids_to_check,
2598 const IdToComponentPtrMap& components,
2599 const base::flat_map<std::string, std::string>& additional_attributes,
2600 bool enabled_component_updates,
2601 UpdateCheckCallback update_check_callback) override {
Sorin Jianud69d4372018-02-07 19:44:222602 EXPECT_FALSE(session_id.empty());
sorin30474f02017-04-27 00:45:482603 EXPECT_TRUE(enabled_component_updates);
2604 EXPECT_EQ(1u, ids_to_check.size());
2605 const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
2606 EXPECT_EQ(id, ids_to_check.front());
2607 EXPECT_EQ(1u, components.count(id));
2608
sorin7cff6e52017-05-17 16:37:232609 ProtocolParser::Result result;
sorin30474f02017-04-27 00:45:482610 result.extension_id = id;
2611 result.status = "noupdate";
2612
Sorin Jianu888ec292018-06-01 15:35:422613 ProtocolParser::Results results;
2614 results.list.push_back(result);
sorin30474f02017-04-27 00:45:482615
Sorin Jianub41a592a2018-03-02 16:30:272616 // Verify that calling Install sets |is_foreground| for the component.
Sorin Jianu888ec292018-06-01 15:35:422617 EXPECT_TRUE(components.at(id)->is_foreground());
sorin30474f02017-04-27 00:45:482618
sorin08d153c2015-10-30 00:04:202619 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianuaa4165532018-06-08 19:46:462620 FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
2621 ErrorCategory::kNone, 0, 0));
sorin08d153c2015-10-30 00:04:202622 }
2623 };
2624
Sorin Jianua8926bf2018-03-09 21:02:532625 class MockCrxDownloader : public CrxDownloader {
sorin08d153c2015-10-30 00:04:202626 public:
dchengd0fc6aa92016-04-22 18:03:122627 static std::unique_ptr<CrxDownloader> Create(
sorin08d153c2015-10-30 00:04:202628 bool is_background_download,
Antonio Gomes0807dd62018-08-10 14:28:472629 scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
Sorin Jianua8926bf2018-03-09 21:02:532630 return std::make_unique<MockCrxDownloader>();
sorin08d153c2015-10-30 00:04:202631 }
2632
Sorin Jianua8926bf2018-03-09 21:02:532633 MockCrxDownloader() : CrxDownloader(nullptr) {}
sorin08d153c2015-10-30 00:04:202634
sorin30474f02017-04-27 00:45:482635 private:
sorin08d153c2015-10-30 00:04:202636 void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); }
2637 };
2638
Sorin Jianua8926bf2018-03-09 21:02:532639 class MockPingManager : public MockPingManagerImpl {
sorin08d153c2015-10-30 00:04:202640 public:
Sorin Jianua8926bf2018-03-09 21:02:532641 explicit MockPingManager(scoped_refptr<Configurator> config)
2642 : MockPingManagerImpl(config) {}
Sorin Jianu560d5022018-02-12 23:11:542643
2644 protected:
Sorin Jianua8926bf2018-03-09 21:02:532645 ~MockPingManager() override { EXPECT_TRUE(ping_data().empty()); }
sorin08d153c2015-10-30 00:04:202646 };
2647
sorin30474f02017-04-27 00:45:482648 scoped_refptr<UpdateClient> update_client =
Taiju Tsuiki36c517d2017-05-18 06:45:432649 base::MakeRefCounted<UpdateClientImpl>(
Sorin Jianua8926bf2018-03-09 21:02:532650 config(), base::MakeRefCounted<MockPingManager>(config()),
2651 &MockUpdateChecker::Create, &MockCrxDownloader::Create);
sorin08d153c2015-10-30 00:04:202652
2653 MockObserver observer;
sorin08d153c2015-10-30 00:04:202654 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
2655 "jebgalgnebhfojomionfpkfelancnnkf"))
2656 .Times(1);
2657 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED,
2658 "jebgalgnebhfojomionfpkfelancnnkf"))
2659 .Times(1);
2660
2661 update_client->AddObserver(&observer);
2662
2663 update_client->Install(
2664 std::string("jebgalgnebhfojomionfpkfelancnnkf"),
Sorin Jianua8926bf2018-03-09 21:02:532665 base::BindOnce(&DataCallbackMock::Callback),
2666 base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
sorin08d153c2015-10-30 00:04:202667
2668 update_client->Install(
2669 std::string("jebgalgnebhfojomionfpkfelancnnkf"),
Sorin Jianua8926bf2018-03-09 21:02:532670 base::BindOnce(&DataCallbackMock::Callback),
2671 base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
sorin08d153c2015-10-30 00:04:202672
2673 RunThreads();
2674
2675 update_client->RemoveObserver(&observer);
sorin08d153c2015-10-30 00:04:202676}
2677
sorin30474f02017-04-27 00:45:482678// Tests that UpdateClient::Update returns Error::INVALID_ARGUMENT when
2679// the |ids| parameter is empty.
asargente90363b2015-09-09 22:40:072680TEST_F(UpdateClientTest, EmptyIdList) {
Sorin Jianua8926bf2018-03-09 21:02:532681 class DataCallbackMock {
asargente90363b2015-09-09 22:40:072682 public:
Sorin Jianu73900242018-08-17 01:11:532683 static std::vector<base::Optional<CrxComponent>> Callback(
Sorin Jianu7c22795b2018-04-26 22:16:522684 const std::vector<std::string>& ids) {
2685 return {};
2686 }
asargente90363b2015-09-09 22:40:072687 };
2688
Sorin Jianua8926bf2018-03-09 21:02:532689 class CompletionCallbackMock {
asargente90363b2015-09-09 22:40:072690 public:
Sorin Jianua8ef73d2017-11-02 16:55:172691 static void Callback(base::OnceClosure quit_closure, Error error) {
sorin30474f02017-04-27 00:45:482692 DCHECK_EQ(Error::INVALID_ARGUMENT, error);
Sorin Jianua8ef73d2017-11-02 16:55:172693 std::move(quit_closure).Run();
asargente90363b2015-09-09 22:40:072694 }
2695 };
sorin30474f02017-04-27 00:45:482696
Sorin Jianua8926bf2018-03-09 21:02:532697 class MockUpdateChecker : public UpdateChecker {
asargente90363b2015-09-09 22:40:072698 public:
dchengd0fc6aa92016-04-22 18:03:122699 static std::unique_ptr<UpdateChecker> Create(
Sorin Jianu49126332018-02-13 17:07:422700 scoped_refptr<Configurator> config,
wafflese7dff732016-04-15 23:51:492701 PersistedData* metadata) {
Sorin Jianua8926bf2018-03-09 21:02:532702 return std::make_unique<MockUpdateChecker>();
asargente90363b2015-09-09 22:40:072703 }
2704
Sorin Jianuc303bf42018-09-07 16:19:332705 void CheckForUpdates(
2706 const std::string& session_id,
2707 const std::vector<std::string>& ids_to_check,
2708 const IdToComponentPtrMap& components,
2709 const base::flat_map<std::string, std::string>& additional_attributes,
2710 bool enabled_component_updates,
2711 UpdateCheckCallback update_check_callback) override {
Sorin Jianud69d4372018-02-07 19:44:222712 NOTREACHED();
2713 }
asargente90363b2015-09-09 22:40:072714 };
2715
Sorin Jianua8926bf2018-03-09 21:02:532716 class MockCrxDownloader : public CrxDownloader {
asargente90363b2015-09-09 22:40:072717 public:
dchengd0fc6aa92016-04-22 18:03:122718 static std::unique_ptr<CrxDownloader> Create(
asargente90363b2015-09-09 22:40:072719 bool is_background_download,
Antonio Gomes0807dd62018-08-10 14:28:472720 scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
Sorin Jianua8926bf2018-03-09 21:02:532721 return std::make_unique<MockCrxDownloader>();
asargente90363b2015-09-09 22:40:072722 }
2723
Sorin Jianua8926bf2018-03-09 21:02:532724 MockCrxDownloader() : CrxDownloader(nullptr) {}
asargente90363b2015-09-09 22:40:072725
sorin30474f02017-04-27 00:45:482726 private:
asargente90363b2015-09-09 22:40:072727 void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); }
2728 };
2729
Sorin Jianua8926bf2018-03-09 21:02:532730 class MockPingManager : public MockPingManagerImpl {
Sorin Jianu560d5022018-02-12 23:11:542731 public:
Sorin Jianua8926bf2018-03-09 21:02:532732 explicit MockPingManager(scoped_refptr<Configurator> config)
2733 : MockPingManagerImpl(config) {}
Sorin Jianu560d5022018-02-12 23:11:542734
2735 protected:
Sorin Jianua8926bf2018-03-09 21:02:532736 ~MockPingManager() override { EXPECT_TRUE(ping_data().empty()); }
Sorin Jianu560d5022018-02-12 23:11:542737 };
2738
sorin30474f02017-04-27 00:45:482739 scoped_refptr<UpdateClient> update_client =
Taiju Tsuiki36c517d2017-05-18 06:45:432740 base::MakeRefCounted<UpdateClientImpl>(
Sorin Jianua8926bf2018-03-09 21:02:532741 config(), base::MakeRefCounted<MockPingManager>(config()),
2742 &MockUpdateChecker::Create, &MockCrxDownloader::Create);
asargente90363b2015-09-09 22:40:072743
sorin30474f02017-04-27 00:45:482744 const std::vector<std::string> empty_id_list;
asargente90363b2015-09-09 22:40:072745 update_client->Update(
Sorin Jianua8926bf2018-03-09 21:02:532746 empty_id_list, base::BindOnce(&DataCallbackMock::Callback), false,
2747 base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
sorin30474f02017-04-27 00:45:482748 RunThreads();
asargente90363b2015-09-09 22:40:072749}
2750
sorin805aa03112016-01-14 23:01:312751TEST_F(UpdateClientTest, SendUninstallPing) {
Sorin Jianua8926bf2018-03-09 21:02:532752 class CompletionCallbackMock {
sorin8037ac8c2017-04-19 16:28:002753 public:
Sorin Jianua8ef73d2017-11-02 16:55:172754 static void Callback(base::OnceClosure quit_closure, Error error) {
2755 std::move(quit_closure).Run();
sorin8037ac8c2017-04-19 16:28:002756 }
2757 };
2758
Sorin Jianua8926bf2018-03-09 21:02:532759 class MockUpdateChecker : public UpdateChecker {
sorin805aa03112016-01-14 23:01:312760 public:
dchengd0fc6aa92016-04-22 18:03:122761 static std::unique_ptr<UpdateChecker> Create(
Sorin Jianu49126332018-02-13 17:07:422762 scoped_refptr<Configurator> config,
wafflese7dff732016-04-15 23:51:492763 PersistedData* metadata) {
sorin805aa03112016-01-14 23:01:312764 return nullptr;
2765 }
2766
Sorin Jianuc303bf42018-09-07 16:19:332767 void CheckForUpdates(
2768 const std::string& session_id,
2769 const std::vector<std::string>& ids_to_check,
2770 const IdToComponentPtrMap& components,
2771 const base::flat_map<std::string, std::string>& additional_attributes,
2772 bool enabled_component_updates,
2773 UpdateCheckCallback update_check_callback) override {
Sorin Jianud69d4372018-02-07 19:44:222774 NOTREACHED();
2775 }
sorin805aa03112016-01-14 23:01:312776 };
2777
Sorin Jianua8926bf2018-03-09 21:02:532778 class MockCrxDownloader : public CrxDownloader {
sorin805aa03112016-01-14 23:01:312779 public:
dchengd0fc6aa92016-04-22 18:03:122780 static std::unique_ptr<CrxDownloader> Create(
sorin805aa03112016-01-14 23:01:312781 bool is_background_download,
Antonio Gomes0807dd62018-08-10 14:28:472782 scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
sorin805aa03112016-01-14 23:01:312783 return nullptr;
2784 }
2785
2786 private:
Sorin Jianua8926bf2018-03-09 21:02:532787 MockCrxDownloader() : CrxDownloader(nullptr) {}
2788 ~MockCrxDownloader() override {}
sorin805aa03112016-01-14 23:01:312789
2790 void DoStartDownload(const GURL& url) override {}
2791 };
2792
Sorin Jianua8926bf2018-03-09 21:02:532793 class MockPingManager : public MockPingManagerImpl {
sorin805aa03112016-01-14 23:01:312794 public:
Sorin Jianua8926bf2018-03-09 21:02:532795 explicit MockPingManager(scoped_refptr<Configurator> config)
2796 : MockPingManagerImpl(config) {}
Sorin Jianu560d5022018-02-12 23:11:542797
2798 protected:
Sorin Jianua8926bf2018-03-09 21:02:532799 ~MockPingManager() override {
2800 const auto ping_data = MockPingManagerImpl::ping_data();
sorin30474f02017-04-27 00:45:482801 EXPECT_EQ(1u, ping_data.size());
2802 EXPECT_EQ("jebgalgnebhfojomionfpkfelancnnkf", ping_data[0].id);
Minh X. Nguyen01d3586d2018-01-03 21:53:392803 EXPECT_EQ(base::Version("1.2.3.4"), ping_data[0].previous_version);
2804 EXPECT_EQ(base::Version("0"), ping_data[0].next_version);
sorin30474f02017-04-27 00:45:482805 EXPECT_EQ(10, ping_data[0].extra_code1);
sorin805aa03112016-01-14 23:01:312806 }
2807 };
2808
sorin30474f02017-04-27 00:45:482809 scoped_refptr<UpdateClient> update_client =
Taiju Tsuiki36c517d2017-05-18 06:45:432810 base::MakeRefCounted<UpdateClientImpl>(
Sorin Jianua8926bf2018-03-09 21:02:532811 config(), base::MakeRefCounted<MockPingManager>(config()),
2812 &MockUpdateChecker::Create, &MockCrxDownloader::Create);
sorin805aa03112016-01-14 23:01:312813
sorin8037ac8c2017-04-19 16:28:002814 update_client->SendUninstallPing(
Minh X. Nguyen01d3586d2018-01-03 21:53:392815 "jebgalgnebhfojomionfpkfelancnnkf", base::Version("1.2.3.4"), 10,
Sorin Jianua8926bf2018-03-09 21:02:532816 base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
sorin8037ac8c2017-04-19 16:28:002817
2818 RunThreads();
sorin805aa03112016-01-14 23:01:312819}
2820
sorinfccbf2d2016-04-04 20:34:342821TEST_F(UpdateClientTest, RetryAfter) {
Sorin Jianua8926bf2018-03-09 21:02:532822 class DataCallbackMock {
sorinfccbf2d2016-04-04 20:34:342823 public:
Sorin Jianu73900242018-08-17 01:11:532824 static std::vector<base::Optional<CrxComponent>> Callback(
Sorin Jianu7c22795b2018-04-26 22:16:522825 const std::vector<std::string>& ids) {
Sorin Jianu73900242018-08-17 01:11:532826 CrxComponent crx;
2827 crx.name = "test_jebg";
2828 crx.pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
2829 crx.version = base::Version("0.9");
2830 crx.installer = base::MakeRefCounted<TestInstaller>();
Joshua Pawlickif4b33f382018-08-17 17:36:512831 crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
Sorin Jianu73900242018-08-17 01:11:532832 return {crx};
sorinfccbf2d2016-04-04 20:34:342833 }
2834 };
2835
Sorin Jianua8926bf2018-03-09 21:02:532836 class CompletionCallbackMock {
sorinfccbf2d2016-04-04 20:34:342837 public:
Sorin Jianua8ef73d2017-11-02 16:55:172838 static void Callback(base::OnceClosure quit_closure, Error error) {
sorinfccbf2d2016-04-04 20:34:342839 static int num_call = 0;
2840 ++num_call;
2841
2842 EXPECT_LE(num_call, 4);
2843
2844 if (num_call == 1) {
sorin7b8650522016-11-02 18:23:412845 EXPECT_EQ(Error::NONE, error);
sorinfccbf2d2016-04-04 20:34:342846 } else if (num_call == 2) {
2847 // This request is throttled since the update engine received a
2848 // positive |retry_after_sec| value in the update check response.
sorin7b8650522016-11-02 18:23:412849 EXPECT_EQ(Error::RETRY_LATER, error);
sorinfccbf2d2016-04-04 20:34:342850 } else if (num_call == 3) {
2851 // This request is a foreground Install, which is never throttled.
2852 // The update engine received a |retry_after_sec| value of 0, which
2853 // resets the throttling.
sorin7b8650522016-11-02 18:23:412854 EXPECT_EQ(Error::NONE, error);
sorinfccbf2d2016-04-04 20:34:342855 } else if (num_call == 4) {
2856 // This request succeeds since there is no throttling in effect.
sorin7b8650522016-11-02 18:23:412857 EXPECT_EQ(Error::NONE, error);
sorinfccbf2d2016-04-04 20:34:342858 }
2859
Sorin Jianua8ef73d2017-11-02 16:55:172860 std::move(quit_closure).Run();
sorinfccbf2d2016-04-04 20:34:342861 }
2862 };
2863
Sorin Jianua8926bf2018-03-09 21:02:532864 class MockUpdateChecker : public UpdateChecker {
sorinfccbf2d2016-04-04 20:34:342865 public:
dchengd0fc6aa92016-04-22 18:03:122866 static std::unique_ptr<UpdateChecker> Create(
Sorin Jianu49126332018-02-13 17:07:422867 scoped_refptr<Configurator> config,
wafflese7dff732016-04-15 23:51:492868 PersistedData* metadata) {
Sorin Jianua8926bf2018-03-09 21:02:532869 return std::make_unique<MockUpdateChecker>();
sorinfccbf2d2016-04-04 20:34:342870 }
2871
Sorin Jianuc303bf42018-09-07 16:19:332872 void CheckForUpdates(
2873 const std::string& session_id,
2874 const std::vector<std::string>& ids_to_check,
2875 const IdToComponentPtrMap& components,
2876 const base::flat_map<std::string, std::string>& additional_attributes,
2877 bool enabled_component_updates,
2878 UpdateCheckCallback update_check_callback) override {
Sorin Jianud69d4372018-02-07 19:44:222879 EXPECT_FALSE(session_id.empty());
2880
sorinfccbf2d2016-04-04 20:34:342881 static int num_call = 0;
2882 ++num_call;
2883
2884 EXPECT_LE(num_call, 3);
2885
2886 int retry_after_sec(0);
2887 if (num_call == 1) {
2888 // Throttle the next call.
2889 retry_after_sec = 60 * 60; // 1 hour.
2890 }
2891
sorin30474f02017-04-27 00:45:482892 EXPECT_EQ(1u, ids_to_check.size());
2893 const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
2894 EXPECT_EQ(id, ids_to_check.front());
2895 EXPECT_EQ(1u, components.count(id));
2896
sorin7cff6e52017-05-17 16:37:232897 ProtocolParser::Result result;
sorin30474f02017-04-27 00:45:482898 result.extension_id = id;
2899 result.status = "noupdate";
Sorin Jianu888ec292018-06-01 15:35:422900
2901 ProtocolParser::Results results;
2902 results.list.push_back(result);
sorin30474f02017-04-27 00:45:482903
sorinfccbf2d2016-04-04 20:34:342904 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianuaa4165532018-06-08 19:46:462905 FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
2906 ErrorCategory::kNone, 0, retry_after_sec));
sorinfccbf2d2016-04-04 20:34:342907 }
2908 };
2909
Sorin Jianua8926bf2018-03-09 21:02:532910 class MockCrxDownloader : public CrxDownloader {
sorinfccbf2d2016-04-04 20:34:342911 public:
dchengd0fc6aa92016-04-22 18:03:122912 static std::unique_ptr<CrxDownloader> Create(
sorinfccbf2d2016-04-04 20:34:342913 bool is_background_download,
Antonio Gomes0807dd62018-08-10 14:28:472914 scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
Sorin Jianua8926bf2018-03-09 21:02:532915 return std::make_unique<MockCrxDownloader>();
sorinfccbf2d2016-04-04 20:34:342916 }
2917
Sorin Jianua8926bf2018-03-09 21:02:532918 MockCrxDownloader() : CrxDownloader(nullptr) {}
sorinfccbf2d2016-04-04 20:34:342919
sorin30474f02017-04-27 00:45:482920 private:
sorinfccbf2d2016-04-04 20:34:342921 void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); }
2922 };
2923
Sorin Jianua8926bf2018-03-09 21:02:532924 class MockPingManager : public MockPingManagerImpl {
sorinfccbf2d2016-04-04 20:34:342925 public:
Sorin Jianua8926bf2018-03-09 21:02:532926 explicit MockPingManager(scoped_refptr<Configurator> config)
2927 : MockPingManagerImpl(config) {}
Sorin Jianu560d5022018-02-12 23:11:542928
2929 protected:
Sorin Jianua8926bf2018-03-09 21:02:532930 ~MockPingManager() override { EXPECT_TRUE(ping_data().empty()); }
sorinfccbf2d2016-04-04 20:34:342931 };
2932
sorin30474f02017-04-27 00:45:482933 scoped_refptr<UpdateClient> update_client =
Taiju Tsuiki36c517d2017-05-18 06:45:432934 base::MakeRefCounted<UpdateClientImpl>(
Sorin Jianua8926bf2018-03-09 21:02:532935 config(), base::MakeRefCounted<MockPingManager>(config()),
2936 &MockUpdateChecker::Create, &MockCrxDownloader::Create);
sorinfccbf2d2016-04-04 20:34:342937
2938 MockObserver observer;
2939
2940 InSequence seq;
2941 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
2942 "jebgalgnebhfojomionfpkfelancnnkf"))
2943 .Times(1);
2944 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED,
2945 "jebgalgnebhfojomionfpkfelancnnkf"))
2946 .Times(1);
2947 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
2948 "jebgalgnebhfojomionfpkfelancnnkf"))
2949 .Times(1);
2950 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED,
2951 "jebgalgnebhfojomionfpkfelancnnkf"))
2952 .Times(1);
2953 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
2954 "jebgalgnebhfojomionfpkfelancnnkf"))
2955 .Times(1);
2956 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED,
2957 "jebgalgnebhfojomionfpkfelancnnkf"))
2958 .Times(1);
2959
2960 update_client->AddObserver(&observer);
2961
sorin30474f02017-04-27 00:45:482962 const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf"};
sorinfccbf2d2016-04-04 20:34:342963 {
2964 // The engine handles this Update call but responds with a valid
2965 // |retry_after_sec|, which causes subsequent calls to fail.
2966 base::RunLoop runloop;
Sorin Jianua8926bf2018-03-09 21:02:532967 update_client->Update(ids, base::BindOnce(&DataCallbackMock::Callback),
Sorin Jianub41a592a2018-03-02 16:30:272968 false,
Sorin Jianua8926bf2018-03-09 21:02:532969 base::BindOnce(&CompletionCallbackMock::Callback,
Sorin Jianua8ef73d2017-11-02 16:55:172970 runloop.QuitClosure()));
sorinfccbf2d2016-04-04 20:34:342971 runloop.Run();
2972 }
2973
2974 {
2975 // This call will result in a completion callback invoked with
2976 // Error::ERROR_UPDATE_RETRY_LATER.
2977 base::RunLoop runloop;
Sorin Jianua8926bf2018-03-09 21:02:532978 update_client->Update(ids, base::BindOnce(&DataCallbackMock::Callback),
Sorin Jianub41a592a2018-03-02 16:30:272979 false,
Sorin Jianua8926bf2018-03-09 21:02:532980 base::BindOnce(&CompletionCallbackMock::Callback,
Sorin Jianua8ef73d2017-11-02 16:55:172981 runloop.QuitClosure()));
sorinfccbf2d2016-04-04 20:34:342982 runloop.Run();
2983 }
2984
2985 {
2986 // The Install call is handled, and the throttling is reset due to
2987 // the value of |retry_after_sec| in the completion callback.
2988 base::RunLoop runloop;
Sorin Jianua8ef73d2017-11-02 16:55:172989 update_client->Install(std::string("jebgalgnebhfojomionfpkfelancnnkf"),
Sorin Jianua8926bf2018-03-09 21:02:532990 base::BindOnce(&DataCallbackMock::Callback),
2991 base::BindOnce(&CompletionCallbackMock::Callback,
Sorin Jianua8ef73d2017-11-02 16:55:172992 runloop.QuitClosure()));
sorinfccbf2d2016-04-04 20:34:342993 runloop.Run();
2994 }
2995
2996 {
2997 // This call succeeds.
2998 base::RunLoop runloop;
Sorin Jianua8926bf2018-03-09 21:02:532999 update_client->Update(ids, base::BindOnce(&DataCallbackMock::Callback),
Sorin Jianub41a592a2018-03-02 16:30:273000 false,
Sorin Jianua8926bf2018-03-09 21:02:533001 base::BindOnce(&CompletionCallbackMock::Callback,
Sorin Jianua8ef73d2017-11-02 16:55:173002 runloop.QuitClosure()));
sorinfccbf2d2016-04-04 20:34:343003 runloop.Run();
3004 }
3005
3006 update_client->RemoveObserver(&observer);
3007}
3008
sorine84ff702016-08-04 01:22:023009// Tests the update check for two CRXs scenario. The first component supports
3010// the group policy to enable updates, and has its updates disabled. The second
3011// component has an update. The server does not honor the "updatedisabled"
sorin30474f02017-04-27 00:45:483012// attribute and returns updates for both components. However, the update for
Sorin Jianu888ec292018-06-01 15:35:423013// the first component is not applied and the client responds with a
sorin30474f02017-04-27 00:45:483014// (SERVICE_ERROR, UPDATE_DISABLED)
sorine84ff702016-08-04 01:22:023015TEST_F(UpdateClientTest, TwoCrxUpdateOneUpdateDisabled) {
Sorin Jianua8926bf2018-03-09 21:02:533016 class DataCallbackMock {
sorine84ff702016-08-04 01:22:023017 public:
Sorin Jianu73900242018-08-17 01:11:533018 static std::vector<base::Optional<CrxComponent>> Callback(
Sorin Jianu7c22795b2018-04-26 22:16:523019 const std::vector<std::string>& ids) {
Sorin Jianu73900242018-08-17 01:11:533020 CrxComponent crx1;
3021 crx1.name = "test_jebg";
3022 crx1.pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
3023 crx1.version = base::Version("0.9");
3024 crx1.installer = base::MakeRefCounted<TestInstaller>();
Joshua Pawlickif4b33f382018-08-17 17:36:513025 crx1.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
Sorin Jianu73900242018-08-17 01:11:533026 crx1.supports_group_policy_enable_component_updates = true;
sorine84ff702016-08-04 01:22:023027
Sorin Jianu73900242018-08-17 01:11:533028 CrxComponent crx2;
3029 crx2.name = "test_ihfo";
3030 crx2.pk_hash.assign(ihfo_hash, ihfo_hash + base::size(ihfo_hash));
3031 crx2.version = base::Version("0.8");
3032 crx2.installer = base::MakeRefCounted<TestInstaller>();
Joshua Pawlickif4b33f382018-08-17 17:36:513033 crx2.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
sorine84ff702016-08-04 01:22:023034
Sorin Jianu73900242018-08-17 01:11:533035 return {crx1, crx2};
sorine84ff702016-08-04 01:22:023036 }
3037 };
3038
Sorin Jianua8926bf2018-03-09 21:02:533039 class CompletionCallbackMock {
sorine84ff702016-08-04 01:22:023040 public:
Sorin Jianua8ef73d2017-11-02 16:55:173041 static void Callback(base::OnceClosure quit_closure, Error error) {
sorin7b8650522016-11-02 18:23:413042 EXPECT_EQ(Error::NONE, error);
Sorin Jianua8ef73d2017-11-02 16:55:173043 std::move(quit_closure).Run();
sorine84ff702016-08-04 01:22:023044 }
3045 };
3046
Sorin Jianua8926bf2018-03-09 21:02:533047 class MockUpdateChecker : public UpdateChecker {
sorine84ff702016-08-04 01:22:023048 public:
3049 static std::unique_ptr<UpdateChecker> Create(
Sorin Jianu49126332018-02-13 17:07:423050 scoped_refptr<Configurator> config,
sorine84ff702016-08-04 01:22:023051 PersistedData* metadata) {
Sorin Jianua8926bf2018-03-09 21:02:533052 return std::make_unique<MockUpdateChecker>();
sorine84ff702016-08-04 01:22:023053 }
3054
Sorin Jianuc303bf42018-09-07 16:19:333055 void CheckForUpdates(
3056 const std::string& session_id,
3057 const std::vector<std::string>& ids_to_check,
3058 const IdToComponentPtrMap& components,
3059 const base::flat_map<std::string, std::string>& additional_attributes,
3060 bool enabled_component_updates,
3061 UpdateCheckCallback update_check_callback) override {
sorine84ff702016-08-04 01:22:023062 /*
Sorin Jianua8926bf2018-03-09 21:02:533063 Mock the following response:
sorine84ff702016-08-04 01:22:023064
3065 <?xml version='1.0' encoding='UTF-8'?>
sorin39852802017-05-01 22:46:283066 <response protocol='3.1'>
sorine84ff702016-08-04 01:22:023067 <app appid='jebgalgnebhfojomionfpkfelancnnkf'>
3068 <updatecheck status='ok'>
3069 <urls>
3070 <url codebase='http://localhost/download/'/>
3071 </urls>
3072 <manifest version='1.0' prodversionmin='11.0.1.0'>
3073 <packages>
3074 <package name='jebgalgnebhfojomionfpkfelancnnkf.crx'
3075 hash_sha256='6fc4b93fd11134de1300c2c0bb88c12b644a4ec0fd
3076 7c9b12cb7cc067667bde87'/>
3077 </packages>
3078 </manifest>
3079 </updatecheck>
3080 </app>
3081 <app appid='ihfokbkgjpifnbbojhneepfflplebdkc'>
3082 <updatecheck status='ok'>
3083 <urls>
3084 <url codebase='http://localhost/download/'/>
3085 </urls>
3086 <manifest version='1.0' prodversionmin='11.0.1.0'>
3087 <packages>
3088 <package name='ihfokbkgjpifnbbojhneepfflplebdkc_1.crx'
3089 hash_sha256='813c59747e139a608b3b5fc49633affc6db574373f
3090 309f156ea6d27229c0b3f9'/>
3091 </packages>
3092 </manifest>
3093 </updatecheck>
3094 </app>
3095 </response>
3096 */
sorin590921d2016-08-11 23:48:363097
3098 // UpdateClient reads the state of |enabled_component_updates| from the
3099 // configurator instance, persists its value in the corresponding
3100 // update context, and propagates it down to each of the update actions,
3101 // and further down to the UpdateChecker instance.
Sorin Jianud69d4372018-02-07 19:44:223102 EXPECT_FALSE(session_id.empty());
sorin590921d2016-08-11 23:48:363103 EXPECT_FALSE(enabled_component_updates);
sorin30474f02017-04-27 00:45:483104 EXPECT_EQ(2u, ids_to_check.size());
sorine84ff702016-08-04 01:22:023105
Sorin Jianu888ec292018-06-01 15:35:423106 ProtocolParser::Results results;
sorin30474f02017-04-27 00:45:483107 {
3108 const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
3109 EXPECT_EQ(id, ids_to_check[0]);
3110 EXPECT_EQ(1u, components.count(id));
sorine84ff702016-08-04 01:22:023111
sorin7cff6e52017-05-17 16:37:233112 ProtocolParser::Result::Manifest::Package package;
sorin30474f02017-04-27 00:45:483113 package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
3114 package.hash_sha256 =
3115 "6fc4b93fd11134de1300c2c0bb88c12b644a4ec0fd7c9b12cb7cc067667bde87";
sorine84ff702016-08-04 01:22:023116
sorin7cff6e52017-05-17 16:37:233117 ProtocolParser::Result result;
sorin30474f02017-04-27 00:45:483118 result.extension_id = id;
3119 result.status = "ok";
3120 result.crx_urls.push_back(GURL("http://localhost/download/"));
3121 result.manifest.version = "1.0";
3122 result.manifest.browser_min_version = "11.0.1.0";
3123 result.manifest.packages.push_back(package);
Sorin Jianu888ec292018-06-01 15:35:423124 results.list.push_back(result);
sorin30474f02017-04-27 00:45:483125 }
3126
3127 {
3128 const std::string id = "ihfokbkgjpifnbbojhneepfflplebdkc";
3129 EXPECT_EQ(id, ids_to_check[1]);
3130 EXPECT_EQ(1u, components.count(id));
3131
sorin7cff6e52017-05-17 16:37:233132 ProtocolParser::Result::Manifest::Package package;
sorin30474f02017-04-27 00:45:483133 package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_1.crx";
3134 package.hash_sha256 =
3135 "813c59747e139a608b3b5fc49633affc6db574373f309f156ea6d27229c0b3f9";
3136
sorin7cff6e52017-05-17 16:37:233137 ProtocolParser::Result result;
sorin30474f02017-04-27 00:45:483138 result.extension_id = id;
3139 result.status = "ok";
3140 result.crx_urls.push_back(GURL("http://localhost/download/"));
3141 result.manifest.version = "1.0";
3142 result.manifest.browser_min_version = "11.0.1.0";
3143 result.manifest.packages.push_back(package);
Sorin Jianu888ec292018-06-01 15:35:423144 results.list.push_back(result);
sorin30474f02017-04-27 00:45:483145 }
sorine84ff702016-08-04 01:22:023146
3147 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianuaa4165532018-06-08 19:46:463148 FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
3149 ErrorCategory::kNone, 0, 0));
sorine84ff702016-08-04 01:22:023150 }
3151 };
3152
Sorin Jianua8926bf2018-03-09 21:02:533153 class MockCrxDownloader : public CrxDownloader {
sorine84ff702016-08-04 01:22:023154 public:
3155 static std::unique_ptr<CrxDownloader> Create(
3156 bool is_background_download,
Antonio Gomes0807dd62018-08-10 14:28:473157 scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
Sorin Jianua8926bf2018-03-09 21:02:533158 return std::make_unique<MockCrxDownloader>();
sorine84ff702016-08-04 01:22:023159 }
3160
Sorin Jianua8926bf2018-03-09 21:02:533161 MockCrxDownloader() : CrxDownloader(nullptr) {}
sorine84ff702016-08-04 01:22:023162
sorin30474f02017-04-27 00:45:483163 private:
sorine84ff702016-08-04 01:22:023164 void DoStartDownload(const GURL& url) override {
3165 DownloadMetrics download_metrics;
3166 FilePath path;
3167 Result result;
3168 if (url.path() == "/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx") {
3169 download_metrics.url = url;
3170 download_metrics.downloader = DownloadMetrics::kNone;
3171 download_metrics.error = 0;
3172 download_metrics.downloaded_bytes = 53638;
3173 download_metrics.total_bytes = 53638;
3174 download_metrics.download_time_ms = 2000;
3175
3176 EXPECT_TRUE(MakeTestFile(
3177 TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"), &path));
3178
3179 result.error = 0;
3180 result.response = path;
sorine84ff702016-08-04 01:22:023181 } else {
3182 NOTREACHED();
3183 }
3184
3185 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianua8926bf2018-03-09 21:02:533186 FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadProgress,
Antonio Gomes31237fb2018-08-27 19:11:033187 base::Unretained(this)));
sorine84ff702016-08-04 01:22:023188
3189 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianua8926bf2018-03-09 21:02:533190 FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadComplete,
Sorin Jianuebd652462017-07-23 02:00:583191 base::Unretained(this), true, result,
3192 download_metrics));
sorine84ff702016-08-04 01:22:023193 }
3194 };
3195
Sorin Jianua8926bf2018-03-09 21:02:533196 class MockPingManager : public MockPingManagerImpl {
sorine84ff702016-08-04 01:22:023197 public:
Sorin Jianua8926bf2018-03-09 21:02:533198 explicit MockPingManager(scoped_refptr<Configurator> config)
3199 : MockPingManagerImpl(config) {}
Sorin Jianu560d5022018-02-12 23:11:543200
3201 protected:
Sorin Jianua8926bf2018-03-09 21:02:533202 ~MockPingManager() override {
3203 const auto ping_data = MockPingManagerImpl::ping_data();
sorin30474f02017-04-27 00:45:483204 EXPECT_EQ(2u, ping_data.size());
3205 EXPECT_EQ("jebgalgnebhfojomionfpkfelancnnkf", ping_data[0].id);
3206 EXPECT_EQ(base::Version("0.9"), ping_data[0].previous_version);
3207 EXPECT_EQ(base::Version("1.0"), ping_data[0].next_version);
Minh X. Nguyena4640cb2018-05-23 21:29:103208 EXPECT_EQ(4, static_cast<int>(ping_data[0].error_category));
sorin30474f02017-04-27 00:45:483209 EXPECT_EQ(2, ping_data[0].error_code);
3210 EXPECT_EQ("ihfokbkgjpifnbbojhneepfflplebdkc", ping_data[1].id);
3211 EXPECT_EQ(base::Version("0.8"), ping_data[1].previous_version);
3212 EXPECT_EQ(base::Version("1.0"), ping_data[1].next_version);
Minh X. Nguyena4640cb2018-05-23 21:29:103213 EXPECT_EQ(0, static_cast<int>(ping_data[1].error_category));
sorin30474f02017-04-27 00:45:483214 EXPECT_EQ(0, ping_data[1].error_code);
sorine84ff702016-08-04 01:22:023215 }
3216 };
3217
3218 // Disables updates for the components declaring support for the group policy.
3219 config()->SetEnabledComponentUpdates(false);
sorin30474f02017-04-27 00:45:483220 scoped_refptr<UpdateClient> update_client =
Taiju Tsuiki36c517d2017-05-18 06:45:433221 base::MakeRefCounted<UpdateClientImpl>(
Sorin Jianua8926bf2018-03-09 21:02:533222 config(), base::MakeRefCounted<MockPingManager>(config()),
3223 &MockUpdateChecker::Create, &MockCrxDownloader::Create);
sorine84ff702016-08-04 01:22:023224
3225 MockObserver observer;
3226 {
3227 InSequence seq;
3228 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
3229 "jebgalgnebhfojomionfpkfelancnnkf"))
3230 .Times(1);
3231 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
3232 "jebgalgnebhfojomionfpkfelancnnkf"))
3233 .Times(1);
Sorin Jianucbb10e12018-01-23 18:01:443234 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
sorine84ff702016-08-04 01:22:023235 "jebgalgnebhfojomionfpkfelancnnkf"))
3236 .Times(1);
3237 }
3238 {
3239 InSequence seq;
3240 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
3241 "ihfokbkgjpifnbbojhneepfflplebdkc"))
3242 .Times(1);
3243 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
3244 "ihfokbkgjpifnbbojhneepfflplebdkc"))
3245 .Times(1);
sorine84ff702016-08-04 01:22:023246 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
3247 "ihfokbkgjpifnbbojhneepfflplebdkc"))
sorin30474f02017-04-27 00:45:483248 .Times(AtLeast(1));
sorine84ff702016-08-04 01:22:023249 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
3250 "ihfokbkgjpifnbbojhneepfflplebdkc"))
3251 .Times(1);
3252 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED,
3253 "ihfokbkgjpifnbbojhneepfflplebdkc"))
3254 .Times(1);
3255 }
3256
3257 update_client->AddObserver(&observer);
3258
sorin30474f02017-04-27 00:45:483259 const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf",
3260 "ihfokbkgjpifnbbojhneepfflplebdkc"};
sorine84ff702016-08-04 01:22:023261 update_client->Update(
Sorin Jianua8926bf2018-03-09 21:02:533262 ids, base::BindOnce(&DataCallbackMock::Callback), false,
3263 base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
sorine84ff702016-08-04 01:22:023264
3265 RunThreads();
3266
3267 update_client->RemoveObserver(&observer);
3268}
3269
sorin03ec5b72017-05-01 23:14:243270// Tests the scenario where the update check fails.
3271TEST_F(UpdateClientTest, OneCrxUpdateCheckFails) {
Sorin Jianua8926bf2018-03-09 21:02:533272 class DataCallbackMock {
sorin03ec5b72017-05-01 23:14:243273 public:
Sorin Jianu73900242018-08-17 01:11:533274 static std::vector<base::Optional<CrxComponent>> Callback(
Sorin Jianu7c22795b2018-04-26 22:16:523275 const std::vector<std::string>& ids) {
Sorin Jianu73900242018-08-17 01:11:533276 CrxComponent crx;
3277 crx.name = "test_jebg";
3278 crx.pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
3279 crx.version = base::Version("0.9");
3280 crx.installer = base::MakeRefCounted<TestInstaller>();
Joshua Pawlickif4b33f382018-08-17 17:36:513281 crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
Sorin Jianu73900242018-08-17 01:11:533282 return {crx};
sorin03ec5b72017-05-01 23:14:243283 }
3284 };
3285
Sorin Jianua8926bf2018-03-09 21:02:533286 class CompletionCallbackMock {
sorin03ec5b72017-05-01 23:14:243287 public:
Sorin Jianua8ef73d2017-11-02 16:55:173288 static void Callback(base::OnceClosure quit_closure, Error error) {
sorin03ec5b72017-05-01 23:14:243289 EXPECT_EQ(Error::UPDATE_CHECK_ERROR, error);
Sorin Jianua8ef73d2017-11-02 16:55:173290 std::move(quit_closure).Run();
sorin03ec5b72017-05-01 23:14:243291 }
3292 };
3293
Sorin Jianua8926bf2018-03-09 21:02:533294 class MockUpdateChecker : public UpdateChecker {
sorin03ec5b72017-05-01 23:14:243295 public:
3296 static std::unique_ptr<UpdateChecker> Create(
Sorin Jianu49126332018-02-13 17:07:423297 scoped_refptr<Configurator> config,
sorin03ec5b72017-05-01 23:14:243298 PersistedData* metadata) {
Sorin Jianua8926bf2018-03-09 21:02:533299 return std::make_unique<MockUpdateChecker>();
sorin03ec5b72017-05-01 23:14:243300 }
3301
Sorin Jianuc303bf42018-09-07 16:19:333302 void CheckForUpdates(
3303 const std::string& session_id,
3304 const std::vector<std::string>& ids_to_check,
3305 const IdToComponentPtrMap& components,
3306 const base::flat_map<std::string, std::string>& additional_attributes,
3307 bool enabled_component_updates,
3308 UpdateCheckCallback update_check_callback) override {
Sorin Jianud69d4372018-02-07 19:44:223309 EXPECT_FALSE(session_id.empty());
sorin03ec5b72017-05-01 23:14:243310 EXPECT_TRUE(enabled_component_updates);
3311 EXPECT_EQ(1u, ids_to_check.size());
3312 const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
3313 EXPECT_EQ(id, ids_to_check.front());
3314 EXPECT_EQ(1u, components.count(id));
sorin03ec5b72017-05-01 23:14:243315 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianu888ec292018-06-01 15:35:423316 FROM_HERE,
3317 base::BindOnce(std::move(update_check_callback), base::nullopt,
3318 ErrorCategory::kUpdateCheck, -1, 0));
sorin03ec5b72017-05-01 23:14:243319 }
3320 };
3321
Sorin Jianua8926bf2018-03-09 21:02:533322 class MockCrxDownloader : public CrxDownloader {
sorin03ec5b72017-05-01 23:14:243323 public:
3324 static std::unique_ptr<CrxDownloader> Create(
3325 bool is_background_download,
Antonio Gomes0807dd62018-08-10 14:28:473326 scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
Sorin Jianua8926bf2018-03-09 21:02:533327 return std::make_unique<MockCrxDownloader>();
sorin03ec5b72017-05-01 23:14:243328 }
3329
Sorin Jianua8926bf2018-03-09 21:02:533330 MockCrxDownloader() : CrxDownloader(nullptr) {}
sorin03ec5b72017-05-01 23:14:243331
3332 private:
3333 void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); }
3334 };
3335
Sorin Jianua8926bf2018-03-09 21:02:533336 class MockPingManager : public MockPingManagerImpl {
sorin03ec5b72017-05-01 23:14:243337 public:
Sorin Jianua8926bf2018-03-09 21:02:533338 explicit MockPingManager(scoped_refptr<Configurator> config)
3339 : MockPingManagerImpl(config) {}
Sorin Jianu560d5022018-02-12 23:11:543340
3341 protected:
Sorin Jianua8926bf2018-03-09 21:02:533342 ~MockPingManager() override { EXPECT_TRUE(ping_data().empty()); }
sorin03ec5b72017-05-01 23:14:243343 };
3344
3345 scoped_refptr<UpdateClient> update_client =
Taiju Tsuiki36c517d2017-05-18 06:45:433346 base::MakeRefCounted<UpdateClientImpl>(
Sorin Jianua8926bf2018-03-09 21:02:533347 config(), base::MakeRefCounted<MockPingManager>(config()),
3348 &MockUpdateChecker::Create, &MockCrxDownloader::Create);
sorin03ec5b72017-05-01 23:14:243349
3350 MockObserver observer;
3351 InSequence seq;
3352 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
3353 "jebgalgnebhfojomionfpkfelancnnkf"))
3354 .Times(1);
Sorin Jianucbb10e12018-01-23 18:01:443355 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
sorin03ec5b72017-05-01 23:14:243356 "jebgalgnebhfojomionfpkfelancnnkf"))
3357 .Times(1)
3358 .WillOnce(Invoke([&update_client](Events event, const std::string& id) {
3359 CrxUpdateItem item;
Sorin Jianu73900242018-08-17 01:11:533360 EXPECT_TRUE(update_client->GetCrxUpdateState(id, &item));
sorin03ec5b72017-05-01 23:14:243361 EXPECT_EQ(ComponentState::kUpdateError, item.state);
Minh X. Nguyena4640cb2018-05-23 21:29:103362 EXPECT_EQ(5, static_cast<int>(item.error_category));
Sorin Jianuafcb70dd2018-05-16 20:14:153363 EXPECT_EQ(-1, item.error_code);
3364 EXPECT_EQ(0, item.extra_code1);
sorin03ec5b72017-05-01 23:14:243365 }));
3366
3367 update_client->AddObserver(&observer);
3368
3369 const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf"};
3370 update_client->Update(
Sorin Jianua8926bf2018-03-09 21:02:533371 ids, base::BindOnce(&DataCallbackMock::Callback), false,
3372 base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
sorin03ec5b72017-05-01 23:14:243373
3374 RunThreads();
3375
3376 update_client->RemoveObserver(&observer);
3377}
3378
Sorin Jianuaa4165532018-06-08 19:46:463379// Tests the scenario where the server responds with different values for
3380// application status.
3381TEST_F(UpdateClientTest, OneCrxErrorUnknownApp) {
3382 class DataCallbackMock {
3383 public:
Sorin Jianu73900242018-08-17 01:11:533384 static std::vector<base::Optional<CrxComponent>> Callback(
Sorin Jianuaa4165532018-06-08 19:46:463385 const std::vector<std::string>& ids) {
Sorin Jianu73900242018-08-17 01:11:533386 std::vector<base::Optional<CrxComponent>> component;
3387 {
3388 CrxComponent crx;
3389 crx.name = "test_jebg";
3390 crx.pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
3391 crx.version = base::Version("0.9");
3392 crx.installer = base::MakeRefCounted<TestInstaller>();
Joshua Pawlickif4b33f382018-08-17 17:36:513393 crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
Sorin Jianu73900242018-08-17 01:11:533394 component.push_back(crx);
3395 }
3396 {
3397 CrxComponent crx;
3398 crx.name = "test_abag";
3399 crx.pk_hash.assign(abag_hash, abag_hash + base::size(abag_hash));
3400 crx.version = base::Version("0.1");
3401 crx.installer = base::MakeRefCounted<TestInstaller>();
Joshua Pawlickif4b33f382018-08-17 17:36:513402 crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
Sorin Jianu73900242018-08-17 01:11:533403 component.push_back(crx);
3404 }
3405 {
3406 CrxComponent crx;
3407 crx.name = "test_ihfo";
3408 crx.pk_hash.assign(ihfo_hash, ihfo_hash + base::size(ihfo_hash));
3409 crx.version = base::Version("0.2");
3410 crx.installer = base::MakeRefCounted<TestInstaller>();
Joshua Pawlickif4b33f382018-08-17 17:36:513411 crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
Sorin Jianu73900242018-08-17 01:11:533412 component.push_back(crx);
3413 }
3414 {
3415 CrxComponent crx;
3416 crx.name = "test_gjpm";
3417 crx.pk_hash.assign(gjpm_hash, gjpm_hash + base::size(gjpm_hash));
3418 crx.version = base::Version("0.3");
3419 crx.installer = base::MakeRefCounted<TestInstaller>();
Joshua Pawlickif4b33f382018-08-17 17:36:513420 crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
Sorin Jianu73900242018-08-17 01:11:533421 component.push_back(crx);
3422 }
Sorin Jianuaa4165532018-06-08 19:46:463423 return component;
3424 }
3425 };
3426
3427 class CompletionCallbackMock {
3428 public:
3429 static void Callback(base::OnceClosure quit_closure, Error error) {
3430 EXPECT_EQ(Error::NONE, error);
3431 std::move(quit_closure).Run();
3432 }
3433 };
3434
3435 class MockUpdateChecker : public UpdateChecker {
3436 public:
3437 static std::unique_ptr<UpdateChecker> Create(
3438 scoped_refptr<Configurator> config,
3439 PersistedData* metadata) {
3440 return std::make_unique<MockUpdateChecker>();
3441 }
3442
Sorin Jianuc303bf42018-09-07 16:19:333443 void CheckForUpdates(
3444 const std::string& session_id,
3445 const std::vector<std::string>& ids_to_check,
3446 const IdToComponentPtrMap& components,
3447 const base::flat_map<std::string, std::string>& additional_attributes,
3448 bool enabled_component_updates,
3449 UpdateCheckCallback update_check_callback) override {
Sorin Jianuaa4165532018-06-08 19:46:463450 EXPECT_FALSE(session_id.empty());
3451 EXPECT_TRUE(enabled_component_updates);
3452 EXPECT_EQ(4u, ids_to_check.size());
3453
3454 const std::string update_response =
3455 R"(<?xml version="1.0" encoding="UTF-8"?>)"
3456 R"(<response protocol="3.1">)"
3457 R"(<app appid="jebgalgnebhfojomionfpkfelancnnkf")"
3458 R"( status="error-unknownApplication"/>)"
3459 R"(<app appid="abagagagagagagagagagagagagagagag")"
3460 R"( status="restricted"/>)"
3461 R"(<app appid="ihfokbkgjpifnbbojhneepfflplebdkc")"
3462 R"( status="error-invalidAppId"/>)"
3463 R"(<app appid="gjpmebpgbhcamgdgjcmnjfhggjpgcimm")"
3464 R"( status="error-foobarApp"/>)"
3465 R"(</response>)";
3466
Sorin Jianu039032b2018-10-12 21:48:133467 const auto parser = ProtocolParser::Create();
3468 EXPECT_TRUE(parser->Parse(update_response));
Sorin Jianuaa4165532018-06-08 19:46:463469
3470 base::ThreadTaskRunnerHandle::Get()->PostTask(
3471 FROM_HERE,
Sorin Jianu039032b2018-10-12 21:48:133472 base::BindOnce(std::move(update_check_callback), parser->results(),
Sorin Jianuaa4165532018-06-08 19:46:463473 ErrorCategory::kNone, 0, 0));
3474 }
3475 };
3476
3477 class MockCrxDownloader : public CrxDownloader {
3478 public:
3479 static std::unique_ptr<CrxDownloader> Create(
3480 bool is_background_download,
Antonio Gomes0807dd62018-08-10 14:28:473481 scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
Sorin Jianuaa4165532018-06-08 19:46:463482 return std::make_unique<MockCrxDownloader>();
3483 }
3484
3485 MockCrxDownloader() : CrxDownloader(nullptr) {}
3486
3487 private:
3488 void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); }
3489 };
3490
3491 class MockPingManager : public MockPingManagerImpl {
3492 public:
3493 explicit MockPingManager(scoped_refptr<Configurator> config)
3494 : MockPingManagerImpl(config) {}
3495
3496 protected:
3497 ~MockPingManager() override { EXPECT_TRUE(ping_data().empty()); }
3498 };
3499
3500 scoped_refptr<UpdateClient> update_client =
3501 base::MakeRefCounted<UpdateClientImpl>(
3502 config(), base::MakeRefCounted<MockPingManager>(config()),
3503 &MockUpdateChecker::Create, &MockCrxDownloader::Create);
3504
3505 MockObserver observer;
3506 {
3507 InSequence seq;
3508 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
3509 "jebgalgnebhfojomionfpkfelancnnkf"))
3510 .Times(1);
3511 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
3512 "jebgalgnebhfojomionfpkfelancnnkf"))
3513 .Times(1)
3514 .WillOnce(Invoke([&update_client](Events event, const std::string& id) {
3515 CrxUpdateItem item;
Sorin Jianu73900242018-08-17 01:11:533516 EXPECT_TRUE(update_client->GetCrxUpdateState(id, &item));
Sorin Jianuaa4165532018-06-08 19:46:463517 EXPECT_EQ(ComponentState::kUpdateError, item.state);
3518 EXPECT_EQ(5, static_cast<int>(item.error_category));
3519 EXPECT_EQ(-10006, item.error_code); // UNKNOWN_APPPLICATION.
3520 EXPECT_EQ(0, item.extra_code1);
3521 }));
3522 }
3523 {
3524 InSequence seq;
3525 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
3526 "abagagagagagagagagagagagagagagag"))
3527 .Times(1);
3528 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
3529 "abagagagagagagagagagagagagagagag"))
3530 .Times(1)
3531 .WillOnce(Invoke([&update_client](Events event, const std::string& id) {
3532 CrxUpdateItem item;
Sorin Jianu73900242018-08-17 01:11:533533 EXPECT_TRUE(update_client->GetCrxUpdateState(id, &item));
Sorin Jianuaa4165532018-06-08 19:46:463534 EXPECT_EQ(ComponentState::kUpdateError, item.state);
3535 EXPECT_EQ(5, static_cast<int>(item.error_category));
3536 EXPECT_EQ(-10007, item.error_code); // RESTRICTED_APPLICATION.
3537 EXPECT_EQ(0, item.extra_code1);
3538 }));
3539 }
3540 {
3541 InSequence seq;
3542 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
3543 "ihfokbkgjpifnbbojhneepfflplebdkc"))
3544 .Times(1);
3545 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
3546 "ihfokbkgjpifnbbojhneepfflplebdkc"))
3547 .Times(1)
3548 .WillOnce(Invoke([&update_client](Events event, const std::string& id) {
3549 CrxUpdateItem item;
Sorin Jianu73900242018-08-17 01:11:533550 EXPECT_TRUE(update_client->GetCrxUpdateState(id, &item));
Sorin Jianuaa4165532018-06-08 19:46:463551 EXPECT_EQ(ComponentState::kUpdateError, item.state);
3552 EXPECT_EQ(5, static_cast<int>(item.error_category));
3553 EXPECT_EQ(-10008, item.error_code); // INVALID_APPID.
3554 EXPECT_EQ(0, item.extra_code1);
3555 }));
3556 }
3557 {
3558 InSequence seq;
3559 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
3560 "gjpmebpgbhcamgdgjcmnjfhggjpgcimm"))
3561 .Times(1);
3562 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
3563 "gjpmebpgbhcamgdgjcmnjfhggjpgcimm"))
3564 .Times(1)
3565 .WillOnce(Invoke([&update_client](Events event, const std::string& id) {
3566 CrxUpdateItem item;
Sorin Jianu73900242018-08-17 01:11:533567 EXPECT_TRUE(update_client->GetCrxUpdateState(id, &item));
Sorin Jianuaa4165532018-06-08 19:46:463568 EXPECT_EQ(ComponentState::kUpdateError, item.state);
3569 EXPECT_EQ(5, static_cast<int>(item.error_category));
3570 EXPECT_EQ(-10004, item.error_code); // UPDATE_RESPONSE_NOT_FOUND.
3571 EXPECT_EQ(0, item.extra_code1);
3572 }));
3573 }
3574
3575 update_client->AddObserver(&observer);
3576
3577 const std::vector<std::string> ids = {
3578 "jebgalgnebhfojomionfpkfelancnnkf", "abagagagagagagagagagagagagagagag",
3579 "ihfokbkgjpifnbbojhneepfflplebdkc", "gjpmebpgbhcamgdgjcmnjfhggjpgcimm"};
3580 update_client->Update(
3581 ids, base::BindOnce(&DataCallbackMock::Callback), true,
3582 base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
3583
3584 RunThreads();
3585
3586 update_client->RemoveObserver(&observer);
3587}
3588
Sorin Jianu7b00a132017-06-19 21:56:543589#if defined(OS_WIN) // ActionRun is only implemented on Windows.
3590
Sorin Jianu4ab7c292017-06-15 18:40:213591// Tests that a run action in invoked in the CRX install scenario.
3592TEST_F(UpdateClientTest, ActionRun_Install) {
Sorin Jianua8926bf2018-03-09 21:02:533593 class MockUpdateChecker : public UpdateChecker {
Sorin Jianu4ab7c292017-06-15 18:40:213594 public:
3595 static std::unique_ptr<UpdateChecker> Create(
Sorin Jianu49126332018-02-13 17:07:423596 scoped_refptr<Configurator> config,
Sorin Jianu4ab7c292017-06-15 18:40:213597 PersistedData* metadata) {
Sorin Jianua8926bf2018-03-09 21:02:533598 return std::make_unique<MockUpdateChecker>();
Sorin Jianu4ab7c292017-06-15 18:40:213599 }
3600
Sorin Jianuc303bf42018-09-07 16:19:333601 void CheckForUpdates(
3602 const std::string& session_id,
3603 const std::vector<std::string>& ids_to_check,
3604 const IdToComponentPtrMap& components,
3605 const base::flat_map<std::string, std::string>& additional_attributes,
3606 bool enabled_component_updates,
3607 UpdateCheckCallback update_check_callback) override {
Sorin Jianu4ab7c292017-06-15 18:40:213608 /*
Sorin Jianua8926bf2018-03-09 21:02:533609 Mock the following response:
Sorin Jianu4ab7c292017-06-15 18:40:213610
3611 <?xml version='1.0' encoding='UTF-8'?>
3612 <response protocol='3.1'>
Sorin Jianue5bfb5b2017-06-20 21:30:563613 <app appid='gjpmebpgbhcamgdgjcmnjfhggjpgcimm'>
Sorin Jianu4ab7c292017-06-15 18:40:213614 <updatecheck status='ok'>
3615 <urls>
3616 <url codebase='http://localhost/download/'/>
3617 </urls>
3618 <manifest version='1.0' prodversionmin='11.0.1.0'>
3619 <packages>
3620 <package name='runaction_test_win.crx3'
Sorin Jianue5bfb5b2017-06-20 21:30:563621 hash_sha256='89290a0d2ff21ca5b45e109c6cc859ab5fe294e19c102d54acd321429c372cea'/>
Sorin Jianu4ab7c292017-06-15 18:40:213622 </packages>
3623 </manifest>
3624 <actions>"
Sorin Jianue5bfb5b2017-06-20 21:30:563625 <action run='ChromeRecovery.crx3'/>"
Sorin Jianu4ab7c292017-06-15 18:40:213626 </actions>"
3627 </updatecheck>
3628 </app>
3629 </response>
3630 */
Sorin Jianud69d4372018-02-07 19:44:223631 EXPECT_FALSE(session_id.empty());
Sorin Jianu4ab7c292017-06-15 18:40:213632 EXPECT_TRUE(enabled_component_updates);
3633 EXPECT_EQ(1u, ids_to_check.size());
3634
Sorin Jianue5bfb5b2017-06-20 21:30:563635 const std::string id = "gjpmebpgbhcamgdgjcmnjfhggjpgcimm";
Sorin Jianu4ab7c292017-06-15 18:40:213636 EXPECT_EQ(id, ids_to_check[0]);
3637 EXPECT_EQ(1u, components.count(id));
3638
3639 ProtocolParser::Result::Manifest::Package package;
3640 package.name = "runaction_test_win.crx3";
3641 package.hash_sha256 =
Sorin Jianue5bfb5b2017-06-20 21:30:563642 "89290a0d2ff21ca5b45e109c6cc859ab5fe294e19c102d54acd321429c372cea";
Sorin Jianu4ab7c292017-06-15 18:40:213643
3644 ProtocolParser::Result result;
3645 result.extension_id = id;
3646 result.status = "ok";
3647 result.crx_urls.push_back(GURL("http://localhost/download/"));
3648 result.manifest.version = "1.0";
3649 result.manifest.browser_min_version = "11.0.1.0";
3650 result.manifest.packages.push_back(package);
Sorin Jianue5bfb5b2017-06-20 21:30:563651 result.action_run = "ChromeRecovery.crx3";
Sorin Jianu4ab7c292017-06-15 18:40:213652
Sorin Jianu888ec292018-06-01 15:35:423653 ProtocolParser::Results results;
3654 results.list.push_back(result);
Sorin Jianu4ab7c292017-06-15 18:40:213655
3656 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianuaa4165532018-06-08 19:46:463657 FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
3658 ErrorCategory::kNone, 0, 0));
Sorin Jianu4ab7c292017-06-15 18:40:213659 }
3660 };
3661
Sorin Jianua8926bf2018-03-09 21:02:533662 class MockCrxDownloader : public CrxDownloader {
Sorin Jianu4ab7c292017-06-15 18:40:213663 public:
3664 static std::unique_ptr<CrxDownloader> Create(
3665 bool is_background_download,
Antonio Gomes0807dd62018-08-10 14:28:473666 scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
Sorin Jianua8926bf2018-03-09 21:02:533667 return std::make_unique<MockCrxDownloader>();
Sorin Jianu4ab7c292017-06-15 18:40:213668 }
3669
Sorin Jianua8926bf2018-03-09 21:02:533670 MockCrxDownloader() : CrxDownloader(nullptr) {}
Sorin Jianu4ab7c292017-06-15 18:40:213671
3672 private:
3673 void DoStartDownload(const GURL& url) override {
3674 DownloadMetrics download_metrics;
3675 FilePath path;
3676 Result result;
3677 if (url.path() == "/download/runaction_test_win.crx3") {
3678 download_metrics.url = url;
3679 download_metrics.downloader = DownloadMetrics::kNone;
3680 download_metrics.error = 0;
3681 download_metrics.downloaded_bytes = 1843;
3682 download_metrics.total_bytes = 1843;
3683 download_metrics.download_time_ms = 1000;
3684
3685 EXPECT_TRUE(
3686 MakeTestFile(TestFilePath("runaction_test_win.crx3"), &path));
3687
3688 result.error = 0;
3689 result.response = path;
Sorin Jianu4ab7c292017-06-15 18:40:213690 } else {
3691 NOTREACHED();
3692 }
3693
3694 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianua8926bf2018-03-09 21:02:533695 FROM_HERE, base::BindOnce(&MockCrxDownloader::OnDownloadComplete,
Sorin Jianuebd652462017-07-23 02:00:583696 base::Unretained(this), true, result,
3697 download_metrics));
Sorin Jianu4ab7c292017-06-15 18:40:213698 }
3699 };
3700
Sorin Jianua8926bf2018-03-09 21:02:533701 class MockPingManager : public MockPingManagerImpl {
Sorin Jianu4ab7c292017-06-15 18:40:213702 public:
Sorin Jianua8926bf2018-03-09 21:02:533703 explicit MockPingManager(scoped_refptr<Configurator> config)
3704 : MockPingManagerImpl(config) {}
Sorin Jianu560d5022018-02-12 23:11:543705
3706 protected:
Sorin Jianua8926bf2018-03-09 21:02:533707 ~MockPingManager() override {
Sorin Jianu039032b2018-10-12 21:48:133708 EXPECT_EQ(3u, events().size());
3709
3710 /*
3711 "<event eventtype="14" eventresult="1" downloader="unknown" "
3712 "url="http://localhost/download/runaction_test_win.crx3"
3713 "downloaded="1843" "
3714 "total="1843" download_time_ms="1000" previousversion="0.0" "
3715 "nextversion="1.0"/>"
3716 */
3717 const auto& event0 = events()[0];
3718 EXPECT_EQ(14, event0.FindKey("eventtype")->GetInt());
3719 EXPECT_EQ(1, event0.FindKey("eventresult")->GetInt());
3720 EXPECT_EQ("unknown", event0.FindKey("downloader")->GetString());
3721 EXPECT_EQ("http://localhost/download/runaction_test_win.crx3",
3722 event0.FindKey("url")->GetString());
3723 EXPECT_EQ("1843", event0.FindKey("downloaded")->GetString());
3724 EXPECT_EQ("1843", event0.FindKey("total")->GetString());
3725 EXPECT_EQ("1000", event0.FindKey("download_time_ms")->GetString());
3726 EXPECT_EQ("0.0", event0.FindKey("previousversion")->GetString());
3727 EXPECT_EQ("1.0", event0.FindKey("nextversion")->GetString());
3728
3729 // "<event eventtype="42" eventresult="1" errorcode="1877345072"/>"
3730 const auto& event1 = events()[1];
3731 EXPECT_EQ(42, event1.FindKey("eventtype")->GetInt());
3732 EXPECT_EQ(1, event1.FindKey("eventresult")->GetInt());
3733 EXPECT_EQ(1877345072, event1.FindKey("errorcode")->GetInt());
3734
3735 // "<event eventtype=\"3\" eventresult=\"1\" previousversion=\"0.0\" "
3736 // "nextversion=\"1.0\"/>",
3737 const auto& event2 = events()[2];
3738 EXPECT_EQ(3, event2.FindKey("eventtype")->GetInt());
3739 EXPECT_EQ(1, event1.FindKey("eventresult")->GetInt());
3740 EXPECT_EQ("0.0", event0.FindKey("previousversion")->GetString());
3741 EXPECT_EQ("1.0", event0.FindKey("nextversion")->GetString());
Sorin Jianu4ab7c292017-06-15 18:40:213742 }
3743 };
3744
3745 scoped_refptr<UpdateClient> update_client =
3746 base::MakeRefCounted<UpdateClientImpl>(
Sorin Jianua8926bf2018-03-09 21:02:533747 config(), base::MakeRefCounted<MockPingManager>(config()),
3748 &MockUpdateChecker::Create, &MockCrxDownloader::Create);
Sorin Jianu4ab7c292017-06-15 18:40:213749
Sorin Jianu7b00a132017-06-19 21:56:543750 // The action is a program which returns 1877345072 as a hardcoded value.
Sorin Jianu4ab7c292017-06-15 18:40:213751 update_client->Install(
Sorin Jianue5bfb5b2017-06-20 21:30:563752 std::string("gjpmebpgbhcamgdgjcmnjfhggjpgcimm"),
Sorin Jianu7c22795b2018-04-26 22:16:523753 base::BindOnce([](const std::vector<std::string>& ids) {
Sorin Jianu73900242018-08-17 01:11:533754 CrxComponent crx;
3755 crx.name = "test_niea";
3756 crx.pk_hash.assign(gjpm_hash, gjpm_hash + base::size(gjpm_hash));
3757 crx.version = base::Version("0.0");
3758 crx.installer = base::MakeRefCounted<VersionedTestInstaller>();
Joshua Pawlickif4b33f382018-08-17 17:36:513759 crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
Sorin Jianu73900242018-08-17 01:11:533760 return std::vector<base::Optional<CrxComponent>>{crx};
Sorin Jianu4ab7c292017-06-15 18:40:213761 }),
Sorin Jianua8ef73d2017-11-02 16:55:173762 base::BindOnce(
3763 [](base::OnceClosure quit_closure, Error error) {
Sorin Jianu4ab7c292017-06-15 18:40:213764 EXPECT_EQ(Error::NONE, error);
Sorin Jianua8ef73d2017-11-02 16:55:173765 std::move(quit_closure).Run();
Sorin Jianu4ab7c292017-06-15 18:40:213766 },
3767 quit_closure()));
3768
3769 RunThreads();
3770}
3771
3772// Tests that a run action is invoked in an update scenario when there was
3773// no update.
3774TEST_F(UpdateClientTest, ActionRun_NoUpdate) {
Sorin Jianua8926bf2018-03-09 21:02:533775 class MockUpdateChecker : public UpdateChecker {
Sorin Jianu4ab7c292017-06-15 18:40:213776 public:
3777 static std::unique_ptr<UpdateChecker> Create(
Sorin Jianu49126332018-02-13 17:07:423778 scoped_refptr<Configurator> config,
Sorin Jianu4ab7c292017-06-15 18:40:213779 PersistedData* metadata) {
Sorin Jianua8926bf2018-03-09 21:02:533780 return std::make_unique<MockUpdateChecker>();
Sorin Jianu4ab7c292017-06-15 18:40:213781 }
3782
Sorin Jianuc303bf42018-09-07 16:19:333783 void CheckForUpdates(
3784 const std::string& session_id,
3785 const std::vector<std::string>& ids_to_check,
3786 const IdToComponentPtrMap& components,
3787 const base::flat_map<std::string, std::string>& additional_attributes,
3788 bool enabled_component_updates,
3789 UpdateCheckCallback update_check_callback) override {
Sorin Jianu4ab7c292017-06-15 18:40:213790 /*
Sorin Jianua8926bf2018-03-09 21:02:533791 Mock the following response:
Sorin Jianu4ab7c292017-06-15 18:40:213792
3793 <?xml version='1.0' encoding='UTF-8'?>
3794 <response protocol='3.1'>
Sorin Jianue5bfb5b2017-06-20 21:30:563795 <app appid='gjpmebpgbhcamgdgjcmnjfhggjpgcimm'>
Sorin Jianu4ab7c292017-06-15 18:40:213796 <updatecheck status='noupdate'>
3797 <actions>"
Sorin Jianue5bfb5b2017-06-20 21:30:563798 <action run=ChromeRecovery.crx3'/>"
Sorin Jianu4ab7c292017-06-15 18:40:213799 </actions>"
3800 </updatecheck>
3801 </app>
3802 </response>
3803 */
Sorin Jianud69d4372018-02-07 19:44:223804 EXPECT_FALSE(session_id.empty());
Sorin Jianu4ab7c292017-06-15 18:40:213805 EXPECT_EQ(1u, ids_to_check.size());
Sorin Jianue5bfb5b2017-06-20 21:30:563806 const std::string id = "gjpmebpgbhcamgdgjcmnjfhggjpgcimm";
Sorin Jianu4ab7c292017-06-15 18:40:213807 EXPECT_EQ(id, ids_to_check[0]);
3808 EXPECT_EQ(1u, components.count(id));
3809
Sorin Jianu4ab7c292017-06-15 18:40:213810 ProtocolParser::Result result;
3811 result.extension_id = id;
3812 result.status = "noupdate";
Sorin Jianue5bfb5b2017-06-20 21:30:563813 result.action_run = "ChromeRecovery.crx3";
Sorin Jianu4ab7c292017-06-15 18:40:213814
Sorin Jianu888ec292018-06-01 15:35:423815 ProtocolParser::Results results;
3816 results.list.push_back(result);
Sorin Jianu4ab7c292017-06-15 18:40:213817
3818 base::ThreadTaskRunnerHandle::Get()->PostTask(
Sorin Jianuaa4165532018-06-08 19:46:463819 FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
3820 ErrorCategory::kNone, 0, 0));
Sorin Jianu4ab7c292017-06-15 18:40:213821 }
3822 };
3823
Sorin Jianua8926bf2018-03-09 21:02:533824 class MockCrxDownloader : public CrxDownloader {
Sorin Jianu4ab7c292017-06-15 18:40:213825 public:
3826 static std::unique_ptr<CrxDownloader> Create(
3827 bool is_background_download,
Antonio Gomes0807dd62018-08-10 14:28:473828 scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
Sorin Jianua8926bf2018-03-09 21:02:533829 return std::make_unique<MockCrxDownloader>();
Sorin Jianu4ab7c292017-06-15 18:40:213830 }
3831
Sorin Jianua8926bf2018-03-09 21:02:533832 MockCrxDownloader() : CrxDownloader(nullptr) {}
Sorin Jianu4ab7c292017-06-15 18:40:213833
3834 private:
3835 void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); }
3836 };
3837
Sorin Jianua8926bf2018-03-09 21:02:533838 class MockPingManager : public MockPingManagerImpl {
Sorin Jianu4ab7c292017-06-15 18:40:213839 public:
Sorin Jianua8926bf2018-03-09 21:02:533840 explicit MockPingManager(scoped_refptr<Configurator> config)
3841 : MockPingManagerImpl(config) {}
Sorin Jianu560d5022018-02-12 23:11:543842
3843 protected:
Sorin Jianua8926bf2018-03-09 21:02:533844 ~MockPingManager() override {
Sorin Jianu039032b2018-10-12 21:48:133845 EXPECT_EQ(1u, events().size());
3846
3847 // "<event eventtype="42" eventresult="1" errorcode="1877345072"/>"
3848 const auto& event = events()[0];
3849 EXPECT_EQ(42, event.FindKey("eventtype")->GetInt());
3850 EXPECT_EQ(1, event.FindKey("eventresult")->GetInt());
3851 EXPECT_EQ(1877345072, event.FindKey("errorcode")->GetInt());
Sorin Jianu4ab7c292017-06-15 18:40:213852 }
3853 };
3854
3855 // Unpack the CRX to mock an existing install to be updated. The payload to
3856 // run is going to be picked up from this directory.
3857 base::FilePath unpack_path;
3858 {
3859 base::RunLoop runloop;
Sorin Jianua8ef73d2017-11-02 16:55:173860 base::OnceClosure quit_closure = runloop.QuitClosure();
Sorin Jianu4ab7c292017-06-15 18:40:213861
Joshua Pawlicki6d764422018-02-21 15:23:103862 auto config = base::MakeRefCounted<TestConfigurator>();
Sorin Jianu7c22795b2018-04-26 22:16:523863 auto component_unpacker = base::MakeRefCounted<ComponentUnpacker>(
Sorin Jianue5bfb5b2017-06-20 21:30:563864 std::vector<uint8_t>(std::begin(gjpm_hash), std::end(gjpm_hash)),
Joshua Pawlicki6d764422018-02-21 15:23:103865 TestFilePath("runaction_test_win.crx3"), nullptr,
Joshua Pawlickif4b33f382018-08-17 17:36:513866 config->CreateServiceManagerConnector(),
3867 crx_file::VerifierFormat::CRX2_OR_CRX3);
Sorin Jianu4ab7c292017-06-15 18:40:213868
Sorin Jianua8ef73d2017-11-02 16:55:173869 component_unpacker->Unpack(base::BindOnce(
3870 [](base::FilePath* unpack_path, base::OnceClosure quit_closure,
Sorin Jianu4ab7c292017-06-15 18:40:213871 const ComponentUnpacker::Result& result) {
3872 EXPECT_EQ(UnpackerError::kNone, result.error);
3873 EXPECT_EQ(0, result.extended_error);
3874 *unpack_path = result.unpack_path;
Sorin Jianua8ef73d2017-11-02 16:55:173875 std::move(quit_closure).Run();
Sorin Jianu4ab7c292017-06-15 18:40:213876 },
3877 &unpack_path, runloop.QuitClosure()));
3878
3879 runloop.Run();
3880 }
3881
3882 EXPECT_FALSE(unpack_path.empty());
3883 EXPECT_TRUE(base::DirectoryExists(unpack_path));
3884 int64_t file_size = 0;
Sorin Jianue5bfb5b2017-06-20 21:30:563885 EXPECT_TRUE(base::GetFileSize(unpack_path.AppendASCII("ChromeRecovery.crx3"),
3886 &file_size));
3887 EXPECT_EQ(44582, file_size);
Sorin Jianu4ab7c292017-06-15 18:40:213888
3889 base::ScopedTempDir unpack_path_owner;
3890 EXPECT_TRUE(unpack_path_owner.Set(unpack_path));
3891
3892 scoped_refptr<UpdateClient> update_client =
3893 base::MakeRefCounted<UpdateClientImpl>(
Sorin Jianua8926bf2018-03-09 21:02:533894 config(), base::MakeRefCounted<MockPingManager>(config()),
3895 &MockUpdateChecker::Create, &MockCrxDownloader::Create);
Sorin Jianu4ab7c292017-06-15 18:40:213896
Sorin Jianu7b00a132017-06-19 21:56:543897 // The action is a program which returns 1877345072 as a hardcoded value.
Sorin Jianue5bfb5b2017-06-20 21:30:563898 const std::vector<std::string> ids = {"gjpmebpgbhcamgdgjcmnjfhggjpgcimm"};
Sorin Jianu4ab7c292017-06-15 18:40:213899 update_client->Update(
3900 ids,
Sorin Jianua8ef73d2017-11-02 16:55:173901 base::BindOnce(
Sorin Jianu4ab7c292017-06-15 18:40:213902 [](const base::FilePath& unpack_path,
Sorin Jianu7c22795b2018-04-26 22:16:523903 const std::vector<std::string>& ids) {
Sorin Jianu73900242018-08-17 01:11:533904 CrxComponent crx;
3905 crx.name = "test_niea";
3906 crx.pk_hash.assign(gjpm_hash, gjpm_hash + base::size(gjpm_hash));
3907 crx.version = base::Version("1.0");
3908 crx.installer =
Sorin Jianu4ab7c292017-06-15 18:40:213909 base::MakeRefCounted<ReadOnlyTestInstaller>(unpack_path);
Joshua Pawlickif4b33f382018-08-17 17:36:513910 crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
Sorin Jianu73900242018-08-17 01:11:533911 return std::vector<base::Optional<CrxComponent>>{crx};
Sorin Jianu4ab7c292017-06-15 18:40:213912 },
3913 unpack_path),
Sorin Jianub41a592a2018-03-02 16:30:273914 false,
Sorin Jianua8ef73d2017-11-02 16:55:173915 base::BindOnce(
3916 [](base::OnceClosure quit_closure, Error error) {
Sorin Jianu4ab7c292017-06-15 18:40:213917 EXPECT_EQ(Error::NONE, error);
Sorin Jianua8ef73d2017-11-02 16:55:173918 std::move(quit_closure).Run();
Sorin Jianu4ab7c292017-06-15 18:40:213919 },
3920 quit_closure()));
3921
3922 RunThreads();
3923}
3924
Sorin Jianu7b00a132017-06-19 21:56:543925#endif // OS_WIN
3926
sorin9797aba2015-04-17 17:15:033927} // namespace update_client