Only grant permissions to new extensions from sync if they have the expected version
[chromium-blink-merge.git] / components / update_client / update_client_unittest.cc
blob790a8cbe273e89747a36f11734dc277c31e4f083
1 // 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.
5 #include "base/bind.h"
6 #include "base/bind_helpers.h"
7 #include "base/files/file_path.h"
8 #include "base/files/file_util.h"
9 #include "base/location.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/path_service.h"
14 #include "base/run_loop.h"
15 #include "base/test/sequenced_worker_pool_owner.h"
16 #include "base/thread_task_runner_handle.h"
17 #include "base/values.h"
18 #include "base/version.h"
19 #include "components/update_client/crx_update_item.h"
20 #include "components/update_client/ping_manager.h"
21 #include "components/update_client/test_configurator.h"
22 #include "components/update_client/test_installer.h"
23 #include "components/update_client/update_checker.h"
24 #include "components/update_client/update_client_internal.h"
25 #include "testing/gmock/include/gmock/gmock.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27 #include "url/gurl.h"
29 namespace update_client {
31 namespace {
33 using base::FilePath;
35 // Makes a copy of the file specified by |from_path| in a temporary directory
36 // and returns the path of the copy. Returns true if successful. Cleans up if
37 // there was an error creating the copy.
38 bool MakeTestFile(const FilePath& from_path, FilePath* to_path) {
39 FilePath temp_dir;
40 bool result =
41 CreateNewTempDirectory(FILE_PATH_LITERAL("update_client"), &temp_dir);
42 if (!result)
43 return false;
45 FilePath temp_file;
46 result = CreateTemporaryFileInDir(temp_dir, &temp_file);
47 if (!result)
48 return false;
50 result = CopyFile(from_path, temp_file);
51 if (!result) {
52 DeleteFile(temp_file, false);
53 return false;
56 *to_path = temp_file;
57 return true;
60 using Events = UpdateClient::Observer::Events;
62 class MockObserver : public UpdateClient::Observer {
63 public:
64 MOCK_METHOD2(OnEvent, void(Events event, const std::string&));
67 class OnDemandTester {
68 public:
69 OnDemandTester(const scoped_refptr<UpdateClient>& update_client,
70 bool expected_value);
72 void CheckOnDemand(Events event, const std::string&);
74 private:
75 const scoped_refptr<UpdateClient> update_client_;
76 const bool expected_value_;
79 OnDemandTester::OnDemandTester(const scoped_refptr<UpdateClient>& update_client,
80 bool expected_value)
81 : update_client_(update_client), expected_value_(expected_value) {
84 void OnDemandTester::CheckOnDemand(Events event, const std::string& id) {
85 if (event == Events::COMPONENT_CHECKING_FOR_UPDATES) {
86 CrxUpdateItem update_item;
87 EXPECT_TRUE(update_client_->GetCrxUpdateState(id, &update_item));
88 EXPECT_EQ(update_item.on_demand, expected_value_);
92 class FakePingManagerImpl : public PingManager {
93 public:
94 explicit FakePingManagerImpl(const Configurator& config);
95 ~FakePingManagerImpl() override;
97 void OnUpdateComplete(const CrxUpdateItem* item) override;
99 const std::vector<CrxUpdateItem>& items() const;
101 private:
102 std::vector<CrxUpdateItem> items_;
103 DISALLOW_COPY_AND_ASSIGN(FakePingManagerImpl);
106 FakePingManagerImpl::FakePingManagerImpl(const Configurator& config)
107 : PingManager(config) {
110 FakePingManagerImpl::~FakePingManagerImpl() {
113 void FakePingManagerImpl::OnUpdateComplete(const CrxUpdateItem* item) {
114 items_.push_back(*item);
117 const std::vector<CrxUpdateItem>& FakePingManagerImpl::items() const {
118 return items_;
121 } // namespace
123 using ::testing::_;
124 using ::testing::AnyNumber;
125 using ::testing::DoAll;
126 using ::testing::InSequence;
127 using ::testing::Invoke;
128 using ::testing::Mock;
129 using ::testing::Return;
131 using std::string;
133 class UpdateClientTest : public testing::Test {
134 public:
135 UpdateClientTest();
136 ~UpdateClientTest() override;
138 protected:
139 void RunThreads();
140 void StopWorkerPool();
142 // Returns the full path to a test file.
143 static base::FilePath TestFilePath(const char* file);
145 scoped_refptr<update_client::Configurator> config() { return config_; }
147 base::Closure quit_closure() { return quit_closure_; }
149 private:
150 static const int kNumWorkerThreads_ = 2;
152 base::MessageLoopForUI message_loop_;
153 base::RunLoop runloop_;
154 base::Closure quit_closure_;
156 scoped_ptr<base::SequencedWorkerPoolOwner> worker_pool_;
158 scoped_refptr<update_client::Configurator> config_;
160 DISALLOW_COPY_AND_ASSIGN(UpdateClientTest);
163 UpdateClientTest::UpdateClientTest()
164 : worker_pool_(
165 new base::SequencedWorkerPoolOwner(kNumWorkerThreads_, "test")) {
166 quit_closure_ = runloop_.QuitClosure();
168 auto pool = worker_pool_->pool();
169 config_ = new TestConfigurator(
170 pool->GetSequencedTaskRunner(pool->GetSequenceToken()),
171 message_loop_.task_runner());
174 UpdateClientTest::~UpdateClientTest() {
177 void UpdateClientTest::RunThreads() {
178 runloop_.Run();
181 void UpdateClientTest::StopWorkerPool() {
182 worker_pool_->pool()->Shutdown();
185 base::FilePath UpdateClientTest::TestFilePath(const char* file) {
186 base::FilePath path;
187 PathService::Get(base::DIR_SOURCE_ROOT, &path);
188 return path.AppendASCII("components")
189 .AppendASCII("test")
190 .AppendASCII("data")
191 .AppendASCII("update_client")
192 .AppendASCII(file);
195 // Tests the scenario where one update check is done for one CRX. The CRX
196 // has no update.
197 TEST_F(UpdateClientTest, OneCrxNoUpdate) {
198 class DataCallbackFake {
199 public:
200 static void Callback(const std::vector<std::string>& ids,
201 std::vector<CrxComponent>* components) {
202 CrxComponent crx;
203 crx.name = "test_jebg";
204 crx.pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash));
205 crx.version = Version("0.9");
206 crx.installer = new TestInstaller;
207 components->push_back(crx);
211 class CompletionCallbackFake {
212 public:
213 static void Callback(const base::Closure& quit_closure, int error) {
214 EXPECT_EQ(0, error);
215 quit_closure.Run();
219 class FakeUpdateChecker : public UpdateChecker {
220 public:
221 static scoped_ptr<UpdateChecker> Create(const Configurator& config) {
222 return scoped_ptr<UpdateChecker>(new FakeUpdateChecker());
225 bool CheckForUpdates(
226 const std::vector<CrxUpdateItem*>& items_to_check,
227 const std::string& additional_attributes,
228 const UpdateCheckCallback& update_check_callback) override {
229 base::ThreadTaskRunnerHandle::Get()->PostTask(
230 FROM_HERE, base::Bind(update_check_callback, GURL(), 0, "",
231 UpdateResponse::Results()));
232 return true;
236 class FakeCrxDownloader : public CrxDownloader {
237 public:
238 static scoped_ptr<CrxDownloader> Create(
239 bool is_background_download,
240 net::URLRequestContextGetter* context_getter,
241 const scoped_refptr<base::SequencedTaskRunner>& url_fetcher_task_runner,
242 const scoped_refptr<base::SingleThreadTaskRunner>&
243 background_task_runner) {
244 return scoped_ptr<CrxDownloader>(new FakeCrxDownloader());
247 private:
248 FakeCrxDownloader() : CrxDownloader(scoped_ptr<CrxDownloader>().Pass()) {}
249 ~FakeCrxDownloader() override {}
251 void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); }
254 class FakePingManager : public FakePingManagerImpl {
255 public:
256 explicit FakePingManager(const Configurator& config)
257 : FakePingManagerImpl(config) {}
258 ~FakePingManager() override { EXPECT_TRUE(items().empty()); }
261 scoped_ptr<PingManager> ping_manager(new FakePingManager(*config()));
262 scoped_refptr<UpdateClient> update_client(new UpdateClientImpl(
263 config(), ping_manager.Pass(), &FakeUpdateChecker::Create,
264 &FakeCrxDownloader::Create));
266 // Verify that calling Update does not set ondemand.
267 OnDemandTester ondemand_tester(update_client, false);
269 MockObserver observer;
270 ON_CALL(observer, OnEvent(_, _))
271 .WillByDefault(Invoke(&ondemand_tester, &OnDemandTester::CheckOnDemand));
273 InSequence seq;
274 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
275 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
276 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED,
277 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
279 update_client->AddObserver(&observer);
281 std::vector<std::string> ids;
282 ids.push_back(std::string("jebgalgnebhfojomionfpkfelancnnkf"));
284 update_client->Update(
285 ids, base::Bind(&DataCallbackFake::Callback),
286 base::Bind(&CompletionCallbackFake::Callback, quit_closure()));
288 RunThreads();
290 update_client->RemoveObserver(&observer);
292 StopWorkerPool();
295 // Tests the scenario where two CRXs are checked for updates. On CRX has
296 // an update, the other CRX does not.
297 TEST_F(UpdateClientTest, TwoCrxUpdateNoUpdate) {
298 class DataCallbackFake {
299 public:
300 static void Callback(const std::vector<std::string>& ids,
301 std::vector<CrxComponent>* components) {
302 CrxComponent crx1;
303 crx1.name = "test_jebg";
304 crx1.pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash));
305 crx1.version = Version("0.9");
306 crx1.installer = new TestInstaller;
308 CrxComponent crx2;
309 crx2.name = "test_abag";
310 crx2.pk_hash.assign(abag_hash, abag_hash + arraysize(abag_hash));
311 crx2.version = Version("2.2");
312 crx2.installer = new TestInstaller;
314 components->push_back(crx1);
315 components->push_back(crx2);
319 class CompletionCallbackFake {
320 public:
321 static void Callback(const base::Closure& quit_closure, int error) {
322 EXPECT_EQ(0, error);
323 quit_closure.Run();
327 class FakeUpdateChecker : public UpdateChecker {
328 public:
329 static scoped_ptr<UpdateChecker> Create(const Configurator& config) {
330 return scoped_ptr<UpdateChecker>(new FakeUpdateChecker());
333 bool CheckForUpdates(
334 const std::vector<CrxUpdateItem*>& items_to_check,
335 const std::string& additional_attributes,
336 const UpdateCheckCallback& update_check_callback) override {
338 Fake the following response:
340 <?xml version='1.0' encoding='UTF-8'?>
341 <response protocol='3.0'>
342 <app appid='jebgalgnebhfojomionfpkfelancnnkf'>
343 <updatecheck status='ok'>
344 <urls>
345 <url codebase='http://localhost/download/'/>
346 </urls>
347 <manifest version='1.0' prodversionmin='11.0.1.0'>
348 <packages>
349 <package name='jebgalgnebhfojomionfpkfelancnnkf.crx'/>
350 </packages>
351 </manifest>
352 </updatecheck>
353 </app>
354 </response>
356 UpdateResponse::Result::Manifest::Package package;
357 package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
359 UpdateResponse::Result result;
360 result.extension_id = "jebgalgnebhfojomionfpkfelancnnkf";
361 result.crx_urls.push_back(GURL("http://localhost/download/"));
362 result.manifest.version = "1.0";
363 result.manifest.browser_min_version = "11.0.1.0";
364 result.manifest.packages.push_back(package);
366 UpdateResponse::Results results;
367 results.list.push_back(result);
369 base::ThreadTaskRunnerHandle::Get()->PostTask(
370 FROM_HERE, base::Bind(update_check_callback, GURL(), 0, "", results));
371 return true;
375 class FakeCrxDownloader : public CrxDownloader {
376 public:
377 static scoped_ptr<CrxDownloader> Create(
378 bool is_background_download,
379 net::URLRequestContextGetter* context_getter,
380 const scoped_refptr<base::SequencedTaskRunner>& url_fetcher_task_runner,
381 const scoped_refptr<base::SingleThreadTaskRunner>&
382 background_task_runner) {
383 return scoped_ptr<CrxDownloader>(new FakeCrxDownloader());
386 private:
387 FakeCrxDownloader() : CrxDownloader(scoped_ptr<CrxDownloader>().Pass()) {}
388 ~FakeCrxDownloader() override {}
390 void DoStartDownload(const GURL& url) override {
391 DownloadMetrics download_metrics;
392 download_metrics.url = url;
393 download_metrics.downloader = DownloadMetrics::kNone;
394 download_metrics.error = 0;
395 download_metrics.downloaded_bytes = 1843;
396 download_metrics.total_bytes = 1843;
397 download_metrics.download_time_ms = 1000;
399 FilePath path;
400 EXPECT_TRUE(MakeTestFile(
401 TestFilePath("jebgalgnebhfojomionfpkfelancnnkf.crx"), &path));
403 Result result;
404 result.error = 0;
405 result.response = path;
406 result.downloaded_bytes = 1843;
407 result.total_bytes = 1843;
409 base::ThreadTaskRunnerHandle::Get()->PostTask(
410 FROM_HERE, base::Bind(&FakeCrxDownloader::OnDownloadProgress,
411 base::Unretained(this), result));
413 base::ThreadTaskRunnerHandle::Get()->PostTask(
414 FROM_HERE,
415 base::Bind(&FakeCrxDownloader::OnDownloadComplete,
416 base::Unretained(this), true, result, download_metrics));
420 class FakePingManager : public FakePingManagerImpl {
421 public:
422 explicit FakePingManager(const Configurator& config)
423 : FakePingManagerImpl(config) {}
424 ~FakePingManager() override {
425 const auto& ping_items = items();
426 EXPECT_EQ(1U, ping_items.size());
427 EXPECT_EQ("jebgalgnebhfojomionfpkfelancnnkf", ping_items[0].id);
428 EXPECT_TRUE(base::Version("0.9").Equals(ping_items[0].previous_version));
429 EXPECT_TRUE(base::Version("1.0").Equals(ping_items[0].next_version));
430 EXPECT_EQ(0, ping_items[0].error_category);
431 EXPECT_EQ(0, ping_items[0].error_code);
435 scoped_ptr<PingManager> ping_manager(new FakePingManager(*config()));
436 scoped_refptr<UpdateClient> update_client(new UpdateClientImpl(
437 config(), ping_manager.Pass(), &FakeUpdateChecker::Create,
438 &FakeCrxDownloader::Create));
440 MockObserver observer;
442 InSequence seq;
443 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
444 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
445 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
446 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
447 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
448 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
449 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
450 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
451 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED,
452 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
455 InSequence seq;
456 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
457 "abagagagagagagagagagagagagagagag")).Times(1);
458 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED,
459 "abagagagagagagagagagagagagagagag")).Times(1);
462 update_client->AddObserver(&observer);
464 std::vector<std::string> ids;
465 ids.push_back(std::string("jebgalgnebhfojomionfpkfelancnnkf"));
466 ids.push_back(std::string("abagagagagagagagagagagagagagagag"));
468 update_client->Update(
469 ids, base::Bind(&DataCallbackFake::Callback),
470 base::Bind(&CompletionCallbackFake::Callback, quit_closure()));
472 RunThreads();
474 update_client->RemoveObserver(&observer);
476 StopWorkerPool();
479 // Tests the update check for two CRXs scenario. Both CRXs have updates.
480 TEST_F(UpdateClientTest, TwoCrxUpdate) {
481 class DataCallbackFake {
482 public:
483 static void Callback(const std::vector<std::string>& ids,
484 std::vector<CrxComponent>* components) {
485 CrxComponent crx1;
486 crx1.name = "test_jebg";
487 crx1.pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash));
488 crx1.version = Version("0.9");
489 crx1.installer = new TestInstaller;
491 CrxComponent crx2;
492 crx2.name = "test_ihfo";
493 crx2.pk_hash.assign(ihfo_hash, ihfo_hash + arraysize(ihfo_hash));
494 crx2.version = Version("0.8");
495 crx2.installer = new TestInstaller;
497 components->push_back(crx1);
498 components->push_back(crx2);
502 class CompletionCallbackFake {
503 public:
504 static void Callback(const base::Closure& quit_closure, int error) {
505 EXPECT_EQ(0, error);
506 quit_closure.Run();
510 class FakeUpdateChecker : public UpdateChecker {
511 public:
512 static scoped_ptr<UpdateChecker> Create(const Configurator& config) {
513 return scoped_ptr<UpdateChecker>(new FakeUpdateChecker());
516 bool CheckForUpdates(
517 const std::vector<CrxUpdateItem*>& items_to_check,
518 const std::string& additional_attributes,
519 const UpdateCheckCallback& update_check_callback) override {
521 Fake the following response:
523 <?xml version='1.0' encoding='UTF-8'?>
524 <response protocol='3.0'>
525 <app appid='jebgalgnebhfojomionfpkfelancnnkf'>
526 <updatecheck status='ok'>
527 <urls>
528 <url codebase='http://localhost/download/'/>
529 </urls>
530 <manifest version='1.0' prodversionmin='11.0.1.0'>
531 <packages>
532 <package name='jebgalgnebhfojomionfpkfelancnnkf.crx'/>
533 </packages>
534 </manifest>
535 </updatecheck>
536 </app>
537 <app appid='ihfokbkgjpifnbbojhneepfflplebdkc'>
538 <updatecheck status='ok'>
539 <urls>
540 <url codebase='http://localhost/download/'/>
541 </urls>
542 <manifest version='1.0' prodversionmin='11.0.1.0'>
543 <packages>
544 <package name='ihfokbkgjpifnbbojhneepfflplebdkc_1.crx'/>
545 </packages>
546 </manifest>
547 </updatecheck>
548 </app>
549 </response>
551 UpdateResponse::Result::Manifest::Package package1;
552 package1.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
554 UpdateResponse::Result result1;
555 result1.extension_id = "jebgalgnebhfojomionfpkfelancnnkf";
556 result1.crx_urls.push_back(GURL("http://localhost/download/"));
557 result1.manifest.version = "1.0";
558 result1.manifest.browser_min_version = "11.0.1.0";
559 result1.manifest.packages.push_back(package1);
561 UpdateResponse::Result::Manifest::Package package2;
562 package2.name = "ihfokbkgjpifnbbojhneepfflplebdkc_1.crx";
564 UpdateResponse::Result result2;
565 result2.extension_id = "ihfokbkgjpifnbbojhneepfflplebdkc";
566 result2.crx_urls.push_back(GURL("http://localhost/download/"));
567 result2.manifest.version = "1.0";
568 result2.manifest.browser_min_version = "11.0.1.0";
569 result2.manifest.packages.push_back(package2);
571 UpdateResponse::Results results;
572 results.list.push_back(result1);
573 results.list.push_back(result2);
575 base::ThreadTaskRunnerHandle::Get()->PostTask(
576 FROM_HERE, base::Bind(update_check_callback, GURL(), 0, "", results));
577 return true;
581 class FakeCrxDownloader : public CrxDownloader {
582 public:
583 static scoped_ptr<CrxDownloader> Create(
584 bool is_background_download,
585 net::URLRequestContextGetter* context_getter,
586 const scoped_refptr<base::SequencedTaskRunner>& url_fetcher_task_runner,
587 const scoped_refptr<base::SingleThreadTaskRunner>&
588 background_task_runner) {
589 return scoped_ptr<CrxDownloader>(new FakeCrxDownloader());
592 private:
593 FakeCrxDownloader() : CrxDownloader(scoped_ptr<CrxDownloader>().Pass()) {}
594 ~FakeCrxDownloader() override {}
596 void DoStartDownload(const GURL& url) override {
597 DownloadMetrics download_metrics;
598 FilePath path;
599 Result result;
600 if (url.path() == "/download/jebgalgnebhfojomionfpkfelancnnkf.crx") {
601 download_metrics.url = url;
602 download_metrics.downloader = DownloadMetrics::kNone;
603 download_metrics.error = 0;
604 download_metrics.downloaded_bytes = 1843;
605 download_metrics.total_bytes = 1843;
606 download_metrics.download_time_ms = 1000;
608 EXPECT_TRUE(MakeTestFile(
609 TestFilePath("jebgalgnebhfojomionfpkfelancnnkf.crx"), &path));
611 result.error = 0;
612 result.response = path;
613 result.downloaded_bytes = 1843;
614 result.total_bytes = 1843;
615 } else if (url.path() ==
616 "/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx") {
617 download_metrics.url = url;
618 download_metrics.downloader = DownloadMetrics::kNone;
619 download_metrics.error = 0;
620 download_metrics.downloaded_bytes = 53638;
621 download_metrics.total_bytes = 53638;
622 download_metrics.download_time_ms = 2000;
624 EXPECT_TRUE(MakeTestFile(
625 TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"), &path));
627 result.error = 0;
628 result.response = path;
629 result.downloaded_bytes = 53638;
630 result.total_bytes = 53638;
631 } else {
632 NOTREACHED();
635 base::ThreadTaskRunnerHandle::Get()->PostTask(
636 FROM_HERE, base::Bind(&FakeCrxDownloader::OnDownloadProgress,
637 base::Unretained(this), result));
639 base::ThreadTaskRunnerHandle::Get()->PostTask(
640 FROM_HERE,
641 base::Bind(&FakeCrxDownloader::OnDownloadComplete,
642 base::Unretained(this), true, result, download_metrics));
646 class FakePingManager : public FakePingManagerImpl {
647 public:
648 explicit FakePingManager(const Configurator& config)
649 : FakePingManagerImpl(config) {}
650 ~FakePingManager() override {
651 const auto& ping_items = items();
652 EXPECT_EQ(2U, ping_items.size());
653 EXPECT_EQ("jebgalgnebhfojomionfpkfelancnnkf", ping_items[0].id);
654 EXPECT_TRUE(base::Version("0.9").Equals(ping_items[0].previous_version));
655 EXPECT_TRUE(base::Version("1.0").Equals(ping_items[0].next_version));
656 EXPECT_EQ(0, ping_items[0].error_category);
657 EXPECT_EQ(0, ping_items[0].error_code);
658 EXPECT_EQ("ihfokbkgjpifnbbojhneepfflplebdkc", ping_items[1].id);
659 EXPECT_TRUE(base::Version("0.8").Equals(ping_items[1].previous_version));
660 EXPECT_TRUE(base::Version("1.0").Equals(ping_items[1].next_version));
661 EXPECT_EQ(0, ping_items[1].error_category);
662 EXPECT_EQ(0, ping_items[1].error_code);
666 scoped_ptr<FakePingManager> ping_manager(new FakePingManager(*config()));
667 scoped_refptr<UpdateClient> update_client(new UpdateClientImpl(
668 config(), ping_manager.Pass(), &FakeUpdateChecker::Create,
669 &FakeCrxDownloader::Create));
671 MockObserver observer;
673 InSequence seq;
674 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
675 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
676 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
677 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
678 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
679 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
680 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
681 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
682 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED,
683 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
686 InSequence seq;
687 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
688 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
689 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
690 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
691 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_WAIT,
692 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
693 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
694 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
695 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
696 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
697 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED,
698 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
701 update_client->AddObserver(&observer);
703 std::vector<std::string> ids;
704 ids.push_back(std::string("jebgalgnebhfojomionfpkfelancnnkf"));
705 ids.push_back(std::string("ihfokbkgjpifnbbojhneepfflplebdkc"));
707 update_client->Update(
708 ids, base::Bind(&DataCallbackFake::Callback),
709 base::Bind(&CompletionCallbackFake::Callback, quit_closure()));
711 RunThreads();
713 update_client->RemoveObserver(&observer);
715 StopWorkerPool();
718 // Tests the scenario where there is a download timeout for the first
719 // CRX. The update for the first CRX fails. The update client waits before
720 // attempting the update for the second CRX. This update succeeds.
721 TEST_F(UpdateClientTest, TwoCrxUpdateDownloadTimeout) {
722 class DataCallbackFake {
723 public:
724 static void Callback(const std::vector<std::string>& ids,
725 std::vector<CrxComponent>* components) {
726 CrxComponent crx1;
727 crx1.name = "test_jebg";
728 crx1.pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash));
729 crx1.version = Version("0.9");
730 crx1.installer = new TestInstaller;
732 CrxComponent crx2;
733 crx2.name = "test_ihfo";
734 crx2.pk_hash.assign(ihfo_hash, ihfo_hash + arraysize(ihfo_hash));
735 crx2.version = Version("0.8");
736 crx2.installer = new TestInstaller;
738 components->push_back(crx1);
739 components->push_back(crx2);
743 class CompletionCallbackFake {
744 public:
745 static void Callback(const base::Closure& quit_closure, int error) {
746 EXPECT_EQ(0, error);
747 quit_closure.Run();
751 class FakeUpdateChecker : public UpdateChecker {
752 public:
753 static scoped_ptr<UpdateChecker> Create(const Configurator& config) {
754 return scoped_ptr<UpdateChecker>(new FakeUpdateChecker());
757 bool CheckForUpdates(
758 const std::vector<CrxUpdateItem*>& items_to_check,
759 const std::string& additional_attributes,
760 const UpdateCheckCallback& update_check_callback) override {
762 Fake the following response:
764 <?xml version='1.0' encoding='UTF-8'?>
765 <response protocol='3.0'>
766 <app appid='jebgalgnebhfojomionfpkfelancnnkf'>
767 <updatecheck status='ok'>
768 <urls>
769 <url codebase='http://localhost/download/'/>
770 </urls>
771 <manifest version='1.0' prodversionmin='11.0.1.0'>
772 <packages>
773 <package name='jebgalgnebhfojomionfpkfelancnnkf.crx'/>
774 </packages>
775 </manifest>
776 </updatecheck>
777 </app>
778 <app appid='ihfokbkgjpifnbbojhneepfflplebdkc'>
779 <updatecheck status='ok'>
780 <urls>
781 <url codebase='http://localhost/download/'/>
782 </urls>
783 <manifest version='1.0' prodversionmin='11.0.1.0'>
784 <packages>
785 <package name='ihfokbkgjpifnbbojhneepfflplebdkc_1.crx'/>
786 </packages>
787 </manifest>
788 </updatecheck>
789 </app>
790 </response>
792 UpdateResponse::Result::Manifest::Package package1;
793 package1.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
795 UpdateResponse::Result result1;
796 result1.extension_id = "jebgalgnebhfojomionfpkfelancnnkf";
797 result1.crx_urls.push_back(GURL("http://localhost/download/"));
798 result1.manifest.version = "1.0";
799 result1.manifest.browser_min_version = "11.0.1.0";
800 result1.manifest.packages.push_back(package1);
802 UpdateResponse::Result::Manifest::Package package2;
803 package2.name = "ihfokbkgjpifnbbojhneepfflplebdkc_1.crx";
805 UpdateResponse::Result result2;
806 result2.extension_id = "ihfokbkgjpifnbbojhneepfflplebdkc";
807 result2.crx_urls.push_back(GURL("http://localhost/download/"));
808 result2.manifest.version = "1.0";
809 result2.manifest.browser_min_version = "11.0.1.0";
810 result2.manifest.packages.push_back(package2);
812 UpdateResponse::Results results;
813 results.list.push_back(result1);
814 results.list.push_back(result2);
816 base::ThreadTaskRunnerHandle::Get()->PostTask(
817 FROM_HERE, base::Bind(update_check_callback, GURL(), 0, "", results));
818 return true;
822 class FakeCrxDownloader : public CrxDownloader {
823 public:
824 static scoped_ptr<CrxDownloader> Create(
825 bool is_background_download,
826 net::URLRequestContextGetter* context_getter,
827 const scoped_refptr<base::SequencedTaskRunner>& url_fetcher_task_runner,
828 const scoped_refptr<base::SingleThreadTaskRunner>&
829 background_task_runner) {
830 return scoped_ptr<CrxDownloader>(new FakeCrxDownloader());
833 private:
834 FakeCrxDownloader() : CrxDownloader(scoped_ptr<CrxDownloader>().Pass()) {}
835 ~FakeCrxDownloader() override {}
837 void DoStartDownload(const GURL& url) override {
838 DownloadMetrics download_metrics;
839 FilePath path;
840 Result result;
841 if (url.path() == "/download/jebgalgnebhfojomionfpkfelancnnkf.crx") {
842 download_metrics.url = url;
843 download_metrics.downloader = DownloadMetrics::kNone;
844 download_metrics.error = -118;
845 download_metrics.downloaded_bytes = 0;
846 download_metrics.total_bytes = 0;
847 download_metrics.download_time_ms = 1000;
849 EXPECT_TRUE(MakeTestFile(
850 TestFilePath("jebgalgnebhfojomionfpkfelancnnkf.crx"), &path));
852 result.error = -118;
853 result.response = path;
854 result.downloaded_bytes = 0;
855 result.total_bytes = 0;
856 } else if (url.path() ==
857 "/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx") {
858 download_metrics.url = url;
859 download_metrics.downloader = DownloadMetrics::kNone;
860 download_metrics.error = 0;
861 download_metrics.downloaded_bytes = 53638;
862 download_metrics.total_bytes = 53638;
863 download_metrics.download_time_ms = 2000;
865 EXPECT_TRUE(MakeTestFile(
866 TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"), &path));
868 result.error = 0;
869 result.response = path;
870 result.downloaded_bytes = 53638;
871 result.total_bytes = 53638;
872 } else {
873 NOTREACHED();
876 base::ThreadTaskRunnerHandle::Get()->PostTask(
877 FROM_HERE, base::Bind(&FakeCrxDownloader::OnDownloadProgress,
878 base::Unretained(this), result));
880 base::ThreadTaskRunnerHandle::Get()->PostTask(
881 FROM_HERE,
882 base::Bind(&FakeCrxDownloader::OnDownloadComplete,
883 base::Unretained(this), true, result, download_metrics));
887 class FakePingManager : public FakePingManagerImpl {
888 public:
889 explicit FakePingManager(const Configurator& config)
890 : FakePingManagerImpl(config) {}
891 ~FakePingManager() override {
892 const auto& ping_items = items();
893 EXPECT_EQ(2U, ping_items.size());
894 EXPECT_EQ("jebgalgnebhfojomionfpkfelancnnkf", ping_items[0].id);
895 EXPECT_TRUE(base::Version("0.9").Equals(ping_items[0].previous_version));
896 EXPECT_TRUE(base::Version("1.0").Equals(ping_items[0].next_version));
897 EXPECT_EQ(1, ping_items[0].error_category); // Network error.
898 EXPECT_EQ(-118, ping_items[0].error_code);
899 EXPECT_EQ("ihfokbkgjpifnbbojhneepfflplebdkc", ping_items[1].id);
900 EXPECT_TRUE(base::Version("0.8").Equals(ping_items[1].previous_version));
901 EXPECT_TRUE(base::Version("1.0").Equals(ping_items[1].next_version));
902 EXPECT_EQ(0, ping_items[1].error_category);
903 EXPECT_EQ(0, ping_items[1].error_code);
907 scoped_ptr<FakePingManager> ping_manager(new FakePingManager(*config()));
908 scoped_refptr<UpdateClient> update_client(new UpdateClientImpl(
909 config(), ping_manager.Pass(), &FakeUpdateChecker::Create,
910 &FakeCrxDownloader::Create));
912 MockObserver observer;
914 InSequence seq;
915 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
916 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
917 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
918 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
919 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
920 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
921 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED,
922 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
925 InSequence seq;
926 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
927 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
928 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
929 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
930 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_WAIT,
931 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
932 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
933 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
934 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
935 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
936 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED,
937 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
940 update_client->AddObserver(&observer);
942 std::vector<std::string> ids;
943 ids.push_back(std::string("jebgalgnebhfojomionfpkfelancnnkf"));
944 ids.push_back(std::string("ihfokbkgjpifnbbojhneepfflplebdkc"));
946 update_client->Update(
947 ids, base::Bind(&DataCallbackFake::Callback),
948 base::Bind(&CompletionCallbackFake::Callback, quit_closure()));
950 RunThreads();
952 update_client->RemoveObserver(&observer);
954 StopWorkerPool();
957 // Tests the differential update scenario for one CRX.
958 TEST_F(UpdateClientTest, OneCrxDiffUpdate) {
959 class DataCallbackFake {
960 public:
961 static void Callback(const std::vector<std::string>& ids,
962 std::vector<CrxComponent>* components) {
963 static int num_calls = 0;
965 // Must use the same stateful installer object.
966 static scoped_refptr<CrxInstaller> installer(
967 new VersionedTestInstaller());
969 ++num_calls;
971 CrxComponent crx;
972 crx.name = "test_ihfo";
973 crx.pk_hash.assign(ihfo_hash, ihfo_hash + arraysize(ihfo_hash));
974 crx.installer = installer;
975 if (num_calls == 1) {
976 crx.version = Version("0.8");
977 } else if (num_calls == 2) {
978 crx.version = Version("1.0");
979 } else {
980 NOTREACHED();
983 components->push_back(crx);
987 class CompletionCallbackFake {
988 public:
989 static void Callback(const base::Closure& quit_closure, int error) {
990 EXPECT_EQ(0, error);
991 quit_closure.Run();
995 class FakeUpdateChecker : public UpdateChecker {
996 public:
997 static scoped_ptr<UpdateChecker> Create(const Configurator& config) {
998 return scoped_ptr<UpdateChecker>(new FakeUpdateChecker());
1001 bool CheckForUpdates(
1002 const std::vector<CrxUpdateItem*>& items_to_check,
1003 const std::string& additional_attributes,
1004 const UpdateCheckCallback& update_check_callback) override {
1005 static int num_call = 0;
1006 ++num_call;
1008 UpdateResponse::Results results;
1010 if (num_call == 1) {
1012 Fake the following response:
1013 <?xml version='1.0' encoding='UTF-8'?>
1014 <response protocol='3.0'>
1015 <app appid='ihfokbkgjpifnbbojhneepfflplebdkc'>
1016 <updatecheck status='ok'>
1017 <urls>
1018 <url codebase='http://localhost/download/'/>
1019 </urls>
1020 <manifest version='1.0' prodversionmin='11.0.1.0'>
1021 <packages>
1022 <package name='ihfokbkgjpifnbbojhneepfflplebdkc_1.crx'/>
1023 </packages>
1024 </manifest>
1025 </updatecheck>
1026 </app>
1027 </response>
1029 UpdateResponse::Result::Manifest::Package package;
1030 package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_1.crx";
1031 package.fingerprint = "1";
1032 UpdateResponse::Result result;
1033 result.extension_id = "ihfokbkgjpifnbbojhneepfflplebdkc";
1034 result.crx_urls.push_back(GURL("http://localhost/download/"));
1035 result.manifest.version = "1.0";
1036 result.manifest.browser_min_version = "11.0.1.0";
1037 result.manifest.packages.push_back(package);
1038 results.list.push_back(result);
1039 } else if (num_call == 2) {
1041 Fake the following response:
1042 <?xml version='1.0' encoding='UTF-8'?>
1043 <response protocol='3.0'>
1044 <app appid='ihfokbkgjpifnbbojhneepfflplebdkc'>
1045 <updatecheck status='ok'>
1046 <urls>
1047 <url codebase='http://localhost/download/'/>
1048 <url codebasediff='http://localhost/download/'/>
1049 </urls>
1050 <manifest version='2.0' prodversionmin='11.0.1.0'>
1051 <packages>
1052 <package name='ihfokbkgjpifnbbojhneepfflplebdkc_2.crx'
1053 namediff='ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx'
1054 fp='22'/>
1055 </packages>
1056 </manifest>
1057 </updatecheck>
1058 </app>
1059 </response>
1061 UpdateResponse::Result::Manifest::Package package;
1062 package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_2.crx";
1063 package.namediff = "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx";
1064 package.fingerprint = "22";
1065 UpdateResponse::Result result;
1066 result.extension_id = "ihfokbkgjpifnbbojhneepfflplebdkc";
1067 result.crx_urls.push_back(GURL("http://localhost/download/"));
1068 result.crx_diffurls.push_back(GURL("http://localhost/download/"));
1069 result.manifest.version = "2.0";
1070 result.manifest.browser_min_version = "11.0.1.0";
1071 result.manifest.packages.push_back(package);
1072 results.list.push_back(result);
1073 } else {
1074 NOTREACHED();
1077 base::ThreadTaskRunnerHandle::Get()->PostTask(
1078 FROM_HERE, base::Bind(update_check_callback, GURL(), 0, "", results));
1079 return true;
1083 class FakeCrxDownloader : public CrxDownloader {
1084 public:
1085 static scoped_ptr<CrxDownloader> Create(
1086 bool is_background_download,
1087 net::URLRequestContextGetter* context_getter,
1088 const scoped_refptr<base::SequencedTaskRunner>& url_fetcher_task_runner,
1089 const scoped_refptr<base::SingleThreadTaskRunner>&
1090 background_task_runner) {
1091 return scoped_ptr<CrxDownloader>(new FakeCrxDownloader());
1094 private:
1095 FakeCrxDownloader() : CrxDownloader(scoped_ptr<CrxDownloader>().Pass()) {}
1096 ~FakeCrxDownloader() override {}
1098 void DoStartDownload(const GURL& url) override {
1099 DownloadMetrics download_metrics;
1100 FilePath path;
1101 Result result;
1102 if (url.path() == "/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx") {
1103 download_metrics.url = url;
1104 download_metrics.downloader = DownloadMetrics::kNone;
1105 download_metrics.error = 0;
1106 download_metrics.downloaded_bytes = 53638;
1107 download_metrics.total_bytes = 53638;
1108 download_metrics.download_time_ms = 2000;
1110 EXPECT_TRUE(MakeTestFile(
1111 TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"), &path));
1113 result.error = 0;
1114 result.response = path;
1115 result.downloaded_bytes = 53638;
1116 result.total_bytes = 53638;
1117 } else if (url.path() ==
1118 "/download/ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx") {
1119 download_metrics.url = url;
1120 download_metrics.downloader = DownloadMetrics::kNone;
1121 download_metrics.error = 0;
1122 download_metrics.downloaded_bytes = 2105;
1123 download_metrics.total_bytes = 2105;
1124 download_metrics.download_time_ms = 1000;
1126 EXPECT_TRUE(MakeTestFile(
1127 TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"), &path));
1129 result.error = 0;
1130 result.response = path;
1131 result.downloaded_bytes = 2105;
1132 result.total_bytes = 2105;
1133 } else {
1134 NOTREACHED();
1137 base::ThreadTaskRunnerHandle::Get()->PostTask(
1138 FROM_HERE, base::Bind(&FakeCrxDownloader::OnDownloadProgress,
1139 base::Unretained(this), result));
1141 base::ThreadTaskRunnerHandle::Get()->PostTask(
1142 FROM_HERE,
1143 base::Bind(&FakeCrxDownloader::OnDownloadComplete,
1144 base::Unretained(this), true, result, download_metrics));
1148 class FakePingManager : public FakePingManagerImpl {
1149 public:
1150 explicit FakePingManager(const Configurator& config)
1151 : FakePingManagerImpl(config) {}
1152 ~FakePingManager() override {
1153 const auto& ping_items = items();
1154 EXPECT_EQ(2U, ping_items.size());
1155 EXPECT_EQ("ihfokbkgjpifnbbojhneepfflplebdkc", ping_items[0].id);
1156 EXPECT_TRUE(base::Version("0.8").Equals(ping_items[0].previous_version));
1157 EXPECT_TRUE(base::Version("1.0").Equals(ping_items[0].next_version));
1158 EXPECT_EQ(0, ping_items[0].error_category);
1159 EXPECT_EQ(0, ping_items[0].error_code);
1160 EXPECT_EQ("ihfokbkgjpifnbbojhneepfflplebdkc", ping_items[1].id);
1161 EXPECT_TRUE(base::Version("1.0").Equals(ping_items[1].previous_version));
1162 EXPECT_TRUE(base::Version("2.0").Equals(ping_items[1].next_version));
1163 EXPECT_EQ(0, ping_items[1].diff_error_category);
1164 EXPECT_EQ(0, ping_items[1].diff_error_code);
1168 scoped_ptr<FakePingManager> ping_manager(new FakePingManager(*config()));
1169 scoped_refptr<UpdateClient> update_client(new UpdateClientImpl(
1170 config(), ping_manager.Pass(), &FakeUpdateChecker::Create,
1171 &FakeCrxDownloader::Create));
1173 MockObserver observer;
1175 InSequence seq;
1176 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
1177 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1178 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
1179 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1180 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
1181 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1182 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
1183 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1184 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED,
1185 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1186 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
1187 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1188 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
1189 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1190 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
1191 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1192 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
1193 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1194 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED,
1195 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1198 update_client->AddObserver(&observer);
1200 std::vector<std::string> ids;
1201 ids.push_back(std::string("ihfokbkgjpifnbbojhneepfflplebdkc"));
1204 base::RunLoop runloop;
1205 update_client->Update(
1206 ids, base::Bind(&DataCallbackFake::Callback),
1207 base::Bind(&CompletionCallbackFake::Callback, runloop.QuitClosure()));
1208 runloop.Run();
1212 base::RunLoop runloop;
1213 update_client->Update(
1214 ids, base::Bind(&DataCallbackFake::Callback),
1215 base::Bind(&CompletionCallbackFake::Callback, runloop.QuitClosure()));
1216 runloop.Run();
1219 update_client->RemoveObserver(&observer);
1221 StopWorkerPool();
1224 // Tests the update scenario for one CRX where the CRX installer returns
1225 // an error.
1226 TEST_F(UpdateClientTest, OneCrxInstallError) {
1227 class MockInstaller : public CrxInstaller {
1228 public:
1229 MOCK_METHOD1(OnUpdateError, void(int error));
1230 MOCK_METHOD2(Install,
1231 bool(const base::DictionaryValue& manifest,
1232 const base::FilePath& unpack_path));
1233 MOCK_METHOD2(GetInstalledFile,
1234 bool(const std::string& file, base::FilePath* installed_file));
1235 MOCK_METHOD0(Uninstall, bool());
1237 static void OnInstall(const base::DictionaryValue& manifest,
1238 const base::FilePath& unpack_path) {
1239 base::DeleteFile(unpack_path, true);
1242 protected:
1243 ~MockInstaller() override {}
1246 class DataCallbackFake {
1247 public:
1248 static void Callback(const std::vector<std::string>& ids,
1249 std::vector<CrxComponent>* components) {
1250 scoped_refptr<MockInstaller> installer(new MockInstaller());
1252 EXPECT_CALL(*installer, OnUpdateError(_)).Times(0);
1253 EXPECT_CALL(*installer, Install(_, _))
1254 .WillOnce(DoAll(Invoke(MockInstaller::OnInstall), Return(false)));
1255 EXPECT_CALL(*installer, GetInstalledFile(_, _)).Times(0);
1256 EXPECT_CALL(*installer, Uninstall()).Times(0);
1258 CrxComponent crx;
1259 crx.name = "test_jebg";
1260 crx.pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash));
1261 crx.version = Version("0.9");
1262 crx.installer = installer;
1263 components->push_back(crx);
1267 class CompletionCallbackFake {
1268 public:
1269 static void Callback(const base::Closure& quit_closure, int error) {
1270 EXPECT_EQ(0, error);
1271 quit_closure.Run();
1275 class FakeUpdateChecker : public UpdateChecker {
1276 public:
1277 static scoped_ptr<UpdateChecker> Create(const Configurator& config) {
1278 return scoped_ptr<UpdateChecker>(new FakeUpdateChecker());
1281 bool CheckForUpdates(
1282 const std::vector<CrxUpdateItem*>& items_to_check,
1283 const std::string& additional_attributes,
1284 const UpdateCheckCallback& update_check_callback) override {
1286 Fake the following response:
1288 <?xml version='1.0' encoding='UTF-8'?>
1289 <response protocol='3.0'>
1290 <app appid='jebgalgnebhfojomionfpkfelancnnkf'>
1291 <updatecheck status='ok'>
1292 <urls>
1293 <url codebase='http://localhost/download/'/>
1294 </urls>
1295 <manifest version='1.0' prodversionmin='11.0.1.0'>
1296 <packages>
1297 <package name='jebgalgnebhfojomionfpkfelancnnkf.crx'/>
1298 </packages>
1299 </manifest>
1300 </updatecheck>
1301 </app>
1302 </response>
1304 UpdateResponse::Result::Manifest::Package package;
1305 package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
1307 UpdateResponse::Result result;
1308 result.extension_id = "jebgalgnebhfojomionfpkfelancnnkf";
1309 result.crx_urls.push_back(GURL("http://localhost/download/"));
1310 result.manifest.version = "1.0";
1311 result.manifest.browser_min_version = "11.0.1.0";
1312 result.manifest.packages.push_back(package);
1314 UpdateResponse::Results results;
1315 results.list.push_back(result);
1317 base::ThreadTaskRunnerHandle::Get()->PostTask(
1318 FROM_HERE, base::Bind(update_check_callback, GURL(), 0, "", results));
1319 return true;
1323 class FakeCrxDownloader : public CrxDownloader {
1324 public:
1325 static scoped_ptr<CrxDownloader> Create(
1326 bool is_background_download,
1327 net::URLRequestContextGetter* context_getter,
1328 const scoped_refptr<base::SequencedTaskRunner>& url_fetcher_task_runner,
1329 const scoped_refptr<base::SingleThreadTaskRunner>&
1330 background_task_runner) {
1331 return scoped_ptr<CrxDownloader>(new FakeCrxDownloader());
1334 private:
1335 FakeCrxDownloader() : CrxDownloader(scoped_ptr<CrxDownloader>().Pass()) {}
1336 ~FakeCrxDownloader() override {}
1338 void DoStartDownload(const GURL& url) override {
1339 DownloadMetrics download_metrics;
1340 download_metrics.url = url;
1341 download_metrics.downloader = DownloadMetrics::kNone;
1342 download_metrics.error = 0;
1343 download_metrics.downloaded_bytes = 1843;
1344 download_metrics.total_bytes = 1843;
1345 download_metrics.download_time_ms = 1000;
1347 FilePath path;
1348 EXPECT_TRUE(MakeTestFile(
1349 TestFilePath("jebgalgnebhfojomionfpkfelancnnkf.crx"), &path));
1351 Result result;
1352 result.error = 0;
1353 result.response = path;
1354 result.downloaded_bytes = 1843;
1355 result.total_bytes = 1843;
1357 base::ThreadTaskRunnerHandle::Get()->PostTask(
1358 FROM_HERE, base::Bind(&FakeCrxDownloader::OnDownloadProgress,
1359 base::Unretained(this), result));
1361 base::ThreadTaskRunnerHandle::Get()->PostTask(
1362 FROM_HERE,
1363 base::Bind(&FakeCrxDownloader::OnDownloadComplete,
1364 base::Unretained(this), true, result, download_metrics));
1368 class FakePingManager : public FakePingManagerImpl {
1369 public:
1370 explicit FakePingManager(const Configurator& config)
1371 : FakePingManagerImpl(config) {}
1372 ~FakePingManager() override {
1373 const auto& ping_items = items();
1374 EXPECT_EQ(1U, ping_items.size());
1375 EXPECT_EQ("jebgalgnebhfojomionfpkfelancnnkf", ping_items[0].id);
1376 EXPECT_TRUE(base::Version("0.9").Equals(ping_items[0].previous_version));
1377 EXPECT_TRUE(base::Version("1.0").Equals(ping_items[0].next_version));
1378 EXPECT_EQ(3, ping_items[0].error_category); // kInstallError.
1379 EXPECT_EQ(9, ping_items[0].error_code); // kInstallerError.
1383 scoped_ptr<PingManager> ping_manager(new FakePingManager(*config()));
1384 scoped_refptr<UpdateClient> update_client(new UpdateClientImpl(
1385 config(), ping_manager.Pass(), &FakeUpdateChecker::Create,
1386 &FakeCrxDownloader::Create));
1388 MockObserver observer;
1390 InSequence seq;
1391 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
1392 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
1393 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
1394 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
1395 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
1396 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
1397 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
1398 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
1399 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED,
1400 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
1403 update_client->AddObserver(&observer);
1405 std::vector<std::string> ids;
1406 ids.push_back(std::string("jebgalgnebhfojomionfpkfelancnnkf"));
1408 update_client->Update(
1409 ids, base::Bind(&DataCallbackFake::Callback),
1410 base::Bind(&CompletionCallbackFake::Callback, quit_closure()));
1412 RunThreads();
1414 update_client->RemoveObserver(&observer);
1416 StopWorkerPool();
1419 // Tests the fallback from differential to full update scenario for one CRX.
1420 TEST_F(UpdateClientTest, OneCrxDiffUpdateFailsFullUpdateSucceeds) {
1421 class DataCallbackFake {
1422 public:
1423 static void Callback(const std::vector<std::string>& ids,
1424 std::vector<CrxComponent>* components) {
1425 static int num_calls = 0;
1427 // Must use the same stateful installer object.
1428 static scoped_refptr<CrxInstaller> installer(
1429 new VersionedTestInstaller());
1431 ++num_calls;
1433 CrxComponent crx;
1434 crx.name = "test_ihfo";
1435 crx.pk_hash.assign(ihfo_hash, ihfo_hash + arraysize(ihfo_hash));
1436 crx.installer = installer;
1437 if (num_calls == 1) {
1438 crx.version = Version("0.8");
1439 } else if (num_calls == 2) {
1440 crx.version = Version("1.0");
1441 } else {
1442 NOTREACHED();
1445 components->push_back(crx);
1449 class CompletionCallbackFake {
1450 public:
1451 static void Callback(const base::Closure& quit_closure, int error) {
1452 EXPECT_EQ(0, error);
1453 quit_closure.Run();
1457 class FakeUpdateChecker : public UpdateChecker {
1458 public:
1459 static scoped_ptr<UpdateChecker> Create(const Configurator& config) {
1460 return scoped_ptr<UpdateChecker>(new FakeUpdateChecker());
1463 bool CheckForUpdates(
1464 const std::vector<CrxUpdateItem*>& items_to_check,
1465 const std::string& additional_attributes,
1466 const UpdateCheckCallback& update_check_callback) override {
1467 static int num_call = 0;
1468 ++num_call;
1470 UpdateResponse::Results results;
1472 if (num_call == 1) {
1474 Fake the following response:
1475 <?xml version='1.0' encoding='UTF-8'?>
1476 <response protocol='3.0'>
1477 <app appid='ihfokbkgjpifnbbojhneepfflplebdkc'>
1478 <updatecheck status='ok'>
1479 <urls>
1480 <url codebase='http://localhost/download/'/>
1481 </urls>
1482 <manifest version='1.0' prodversionmin='11.0.1.0'>
1483 <packages>
1484 <package name='ihfokbkgjpifnbbojhneepfflplebdkc_1.crx'/>
1485 </packages>
1486 </manifest>
1487 </updatecheck>
1488 </app>
1489 </response>
1491 UpdateResponse::Result::Manifest::Package package;
1492 package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_1.crx";
1493 package.fingerprint = "1";
1494 UpdateResponse::Result result;
1495 result.extension_id = "ihfokbkgjpifnbbojhneepfflplebdkc";
1496 result.crx_urls.push_back(GURL("http://localhost/download/"));
1497 result.manifest.version = "1.0";
1498 result.manifest.browser_min_version = "11.0.1.0";
1499 result.manifest.packages.push_back(package);
1500 results.list.push_back(result);
1501 } else if (num_call == 2) {
1503 Fake the following response:
1504 <?xml version='1.0' encoding='UTF-8'?>
1505 <response protocol='3.0'>
1506 <app appid='ihfokbkgjpifnbbojhneepfflplebdkc'>
1507 <updatecheck status='ok'>
1508 <urls>
1509 <url codebase='http://localhost/download/'/>
1510 <url codebasediff='http://localhost/download/'/>
1511 </urls>
1512 <manifest version='2.0' prodversionmin='11.0.1.0'>
1513 <packages>
1514 <package name='ihfokbkgjpifnbbojhneepfflplebdkc_2.crx'
1515 namediff='ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx'
1516 fp='22'/>
1517 </packages>
1518 </manifest>
1519 </updatecheck>
1520 </app>
1521 </response>
1523 UpdateResponse::Result::Manifest::Package package;
1524 package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_2.crx";
1525 package.namediff = "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx";
1526 package.fingerprint = "22";
1527 UpdateResponse::Result result;
1528 result.extension_id = "ihfokbkgjpifnbbojhneepfflplebdkc";
1529 result.crx_urls.push_back(GURL("http://localhost/download/"));
1530 result.crx_diffurls.push_back(GURL("http://localhost/download/"));
1531 result.manifest.version = "2.0";
1532 result.manifest.browser_min_version = "11.0.1.0";
1533 result.manifest.packages.push_back(package);
1534 results.list.push_back(result);
1535 } else {
1536 NOTREACHED();
1539 base::ThreadTaskRunnerHandle::Get()->PostTask(
1540 FROM_HERE, base::Bind(update_check_callback, GURL(), 0, "", results));
1541 return true;
1545 class FakeCrxDownloader : public CrxDownloader {
1546 public:
1547 static scoped_ptr<CrxDownloader> Create(
1548 bool is_background_download,
1549 net::URLRequestContextGetter* context_getter,
1550 const scoped_refptr<base::SequencedTaskRunner>& url_fetcher_task_runner,
1551 const scoped_refptr<base::SingleThreadTaskRunner>&
1552 background_task_runner) {
1553 return scoped_ptr<CrxDownloader>(new FakeCrxDownloader());
1556 private:
1557 FakeCrxDownloader() : CrxDownloader(scoped_ptr<CrxDownloader>().Pass()) {}
1558 ~FakeCrxDownloader() override {}
1560 void DoStartDownload(const GURL& url) override {
1561 DownloadMetrics download_metrics;
1562 FilePath path;
1563 Result result;
1564 if (url.path() == "/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx") {
1565 download_metrics.url = url;
1566 download_metrics.downloader = DownloadMetrics::kNone;
1567 download_metrics.error = 0;
1568 download_metrics.downloaded_bytes = 53638;
1569 download_metrics.total_bytes = 53638;
1570 download_metrics.download_time_ms = 2000;
1572 EXPECT_TRUE(MakeTestFile(
1573 TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"), &path));
1575 result.error = 0;
1576 result.response = path;
1577 result.downloaded_bytes = 53638;
1578 result.total_bytes = 53638;
1579 } else if (url.path() ==
1580 "/download/ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx") {
1581 // A download error is injected on this execution path.
1582 download_metrics.url = url;
1583 download_metrics.downloader = DownloadMetrics::kNone;
1584 download_metrics.error = -1;
1585 download_metrics.downloaded_bytes = 0;
1586 download_metrics.total_bytes = 2105;
1587 download_metrics.download_time_ms = 1000;
1589 EXPECT_TRUE(MakeTestFile(
1590 TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"), &path));
1592 result.error = -1;
1593 result.response = path;
1594 result.downloaded_bytes = 0;
1595 result.total_bytes = 2105;
1596 } else if (url.path() ==
1597 "/download/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx") {
1598 download_metrics.url = url;
1599 download_metrics.downloader = DownloadMetrics::kNone;
1600 download_metrics.error = 0;
1601 download_metrics.downloaded_bytes = 53855;
1602 download_metrics.total_bytes = 53855;
1603 download_metrics.download_time_ms = 1000;
1605 EXPECT_TRUE(MakeTestFile(
1606 TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"), &path));
1608 result.error = 0;
1609 result.response = path;
1610 result.downloaded_bytes = 53855;
1611 result.total_bytes = 53855;
1614 base::ThreadTaskRunnerHandle::Get()->PostTask(
1615 FROM_HERE, base::Bind(&FakeCrxDownloader::OnDownloadProgress,
1616 base::Unretained(this), result));
1618 base::ThreadTaskRunnerHandle::Get()->PostTask(
1619 FROM_HERE,
1620 base::Bind(&FakeCrxDownloader::OnDownloadComplete,
1621 base::Unretained(this), true, result, download_metrics));
1625 class FakePingManager : public FakePingManagerImpl {
1626 public:
1627 explicit FakePingManager(const Configurator& config)
1628 : FakePingManagerImpl(config) {}
1629 ~FakePingManager() override {
1630 const auto& ping_items = items();
1631 EXPECT_EQ(2U, ping_items.size());
1632 EXPECT_EQ("ihfokbkgjpifnbbojhneepfflplebdkc", ping_items[0].id);
1633 EXPECT_TRUE(base::Version("0.8").Equals(ping_items[0].previous_version));
1634 EXPECT_TRUE(base::Version("1.0").Equals(ping_items[0].next_version));
1635 EXPECT_EQ(0, ping_items[0].error_category);
1636 EXPECT_EQ(0, ping_items[0].error_code);
1637 EXPECT_EQ("ihfokbkgjpifnbbojhneepfflplebdkc", ping_items[1].id);
1638 EXPECT_TRUE(base::Version("1.0").Equals(ping_items[1].previous_version));
1639 EXPECT_TRUE(base::Version("2.0").Equals(ping_items[1].next_version));
1640 EXPECT_TRUE(ping_items[1].diff_update_failed);
1641 EXPECT_EQ(1, ping_items[1].diff_error_category); // kNetworkError.
1642 EXPECT_EQ(-1, ping_items[1].diff_error_code);
1646 scoped_ptr<FakePingManager> ping_manager(new FakePingManager(*config()));
1647 scoped_refptr<UpdateClient> update_client(new UpdateClientImpl(
1648 config(), ping_manager.Pass(), &FakeUpdateChecker::Create,
1649 &FakeCrxDownloader::Create));
1651 MockObserver observer;
1653 InSequence seq;
1654 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
1655 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1656 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
1657 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1658 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
1659 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1660 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
1661 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1662 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED,
1663 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1665 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
1666 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1667 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
1668 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1669 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
1670 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1671 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
1672 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1673 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
1674 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1675 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED,
1676 "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
1679 update_client->AddObserver(&observer);
1681 std::vector<std::string> ids;
1682 ids.push_back(std::string("ihfokbkgjpifnbbojhneepfflplebdkc"));
1685 base::RunLoop runloop;
1686 update_client->Update(
1687 ids, base::Bind(&DataCallbackFake::Callback),
1688 base::Bind(&CompletionCallbackFake::Callback, runloop.QuitClosure()));
1689 runloop.Run();
1693 base::RunLoop runloop;
1694 update_client->Update(
1695 ids, base::Bind(&DataCallbackFake::Callback),
1696 base::Bind(&CompletionCallbackFake::Callback, runloop.QuitClosure()));
1697 runloop.Run();
1700 update_client->RemoveObserver(&observer);
1702 StopWorkerPool();
1705 // Tests the queuing of update checks. In this scenario, two update checks are
1706 // done for one CRX. The second update check call is queued up and will run
1707 // after the first check has completed. The CRX has no updates.
1708 TEST_F(UpdateClientTest, OneCrxNoUpdateQueuedCall) {
1709 class DataCallbackFake {
1710 public:
1711 static void Callback(const std::vector<std::string>& ids,
1712 std::vector<CrxComponent>* components) {
1713 CrxComponent crx;
1714 crx.name = "test_jebg";
1715 crx.pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash));
1716 crx.version = Version("0.9");
1717 crx.installer = new TestInstaller;
1718 components->push_back(crx);
1722 class CompletionCallbackFake {
1723 public:
1724 static void Callback(const base::Closure& quit_closure, int error) {
1725 static int num_call = 0;
1726 ++num_call;
1728 EXPECT_EQ(0, error);
1730 if (num_call == 2)
1731 quit_closure.Run();
1735 class FakeUpdateChecker : public UpdateChecker {
1736 public:
1737 static scoped_ptr<UpdateChecker> Create(const Configurator& config) {
1738 return scoped_ptr<UpdateChecker>(new FakeUpdateChecker());
1741 bool CheckForUpdates(
1742 const std::vector<CrxUpdateItem*>& items_to_check,
1743 const std::string& additional_attributes,
1744 const UpdateCheckCallback& update_check_callback) override {
1745 base::ThreadTaskRunnerHandle::Get()->PostTask(
1746 FROM_HERE, base::Bind(update_check_callback, GURL(), 0, "",
1747 UpdateResponse::Results()));
1748 return true;
1752 class FakeCrxDownloader : public CrxDownloader {
1753 public:
1754 static scoped_ptr<CrxDownloader> Create(
1755 bool is_background_download,
1756 net::URLRequestContextGetter* context_getter,
1757 const scoped_refptr<base::SequencedTaskRunner>& url_fetcher_task_runner,
1758 const scoped_refptr<base::SingleThreadTaskRunner>&
1759 background_task_runner) {
1760 return scoped_ptr<CrxDownloader>(new FakeCrxDownloader());
1763 private:
1764 FakeCrxDownloader() : CrxDownloader(scoped_ptr<CrxDownloader>().Pass()) {}
1765 ~FakeCrxDownloader() override {}
1767 void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); }
1770 class FakePingManager : public FakePingManagerImpl {
1771 public:
1772 explicit FakePingManager(const Configurator& config)
1773 : FakePingManagerImpl(config) {}
1774 ~FakePingManager() override { EXPECT_TRUE(items().empty()); }
1777 scoped_ptr<PingManager> ping_manager(new FakePingManager(*config()));
1778 scoped_refptr<UpdateClient> update_client(new UpdateClientImpl(
1779 config(), ping_manager.Pass(), &FakeUpdateChecker::Create,
1780 &FakeCrxDownloader::Create));
1782 MockObserver observer;
1783 InSequence seq;
1784 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
1785 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
1786 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED,
1787 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
1788 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
1789 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
1790 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED,
1791 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
1793 update_client->AddObserver(&observer);
1795 std::vector<std::string> ids;
1796 ids.push_back(std::string("jebgalgnebhfojomionfpkfelancnnkf"));
1798 update_client->Update(
1799 ids, base::Bind(&DataCallbackFake::Callback),
1800 base::Bind(&CompletionCallbackFake::Callback, quit_closure()));
1801 update_client->Update(
1802 ids, base::Bind(&DataCallbackFake::Callback),
1803 base::Bind(&CompletionCallbackFake::Callback, quit_closure()));
1805 RunThreads();
1807 update_client->RemoveObserver(&observer);
1809 StopWorkerPool();
1812 // Tests the install of one CRX.
1813 TEST_F(UpdateClientTest, OneCrxInstall) {
1814 class DataCallbackFake {
1815 public:
1816 static void Callback(const std::vector<std::string>& ids,
1817 std::vector<CrxComponent>* components) {
1818 CrxComponent crx;
1819 crx.name = "test_jebg";
1820 crx.pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash));
1821 crx.version = Version("0.0");
1822 crx.installer = new TestInstaller;
1824 components->push_back(crx);
1828 class CompletionCallbackFake {
1829 public:
1830 static void Callback(const base::Closure& quit_closure, int error) {
1831 EXPECT_EQ(0, error);
1832 quit_closure.Run();
1836 class FakeUpdateChecker : public UpdateChecker {
1837 public:
1838 static scoped_ptr<UpdateChecker> Create(const Configurator& config) {
1839 return scoped_ptr<UpdateChecker>(new FakeUpdateChecker());
1842 bool CheckForUpdates(
1843 const std::vector<CrxUpdateItem*>& items_to_check,
1844 const std::string& additional_attributes,
1845 const UpdateCheckCallback& update_check_callback) override {
1847 Fake the following response:
1849 <?xml version='1.0' encoding='UTF-8'?>
1850 <response protocol='3.0'>
1851 <app appid='jebgalgnebhfojomionfpkfelancnnkf'>
1852 <updatecheck status='ok'>
1853 <urls>
1854 <url codebase='http://localhost/download/'/>
1855 </urls>
1856 <manifest version='1.0' prodversionmin='11.0.1.0'>
1857 <packages>
1858 <package name='jebgalgnebhfojomionfpkfelancnnkf.crx'/>
1859 </packages>
1860 </manifest>
1861 </updatecheck>
1862 </app>
1863 </response>
1865 UpdateResponse::Result::Manifest::Package package;
1866 package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
1868 UpdateResponse::Result result;
1869 result.extension_id = "jebgalgnebhfojomionfpkfelancnnkf";
1870 result.crx_urls.push_back(GURL("http://localhost/download/"));
1871 result.manifest.version = "1.0";
1872 result.manifest.browser_min_version = "11.0.1.0";
1873 result.manifest.packages.push_back(package);
1875 UpdateResponse::Results results;
1876 results.list.push_back(result);
1878 base::ThreadTaskRunnerHandle::Get()->PostTask(
1879 FROM_HERE, base::Bind(update_check_callback, GURL(), 0, "", results));
1880 return true;
1884 class FakeCrxDownloader : public CrxDownloader {
1885 public:
1886 static scoped_ptr<CrxDownloader> Create(
1887 bool is_background_download,
1888 net::URLRequestContextGetter* context_getter,
1889 const scoped_refptr<base::SequencedTaskRunner>& url_fetcher_task_runner,
1890 const scoped_refptr<base::SingleThreadTaskRunner>&
1891 background_task_runner) {
1892 return scoped_ptr<CrxDownloader>(new FakeCrxDownloader());
1895 private:
1896 FakeCrxDownloader() : CrxDownloader(scoped_ptr<CrxDownloader>().Pass()) {}
1897 ~FakeCrxDownloader() override {}
1899 void DoStartDownload(const GURL& url) override {
1900 DownloadMetrics download_metrics;
1901 FilePath path;
1902 Result result;
1903 if (url.path() == "/download/jebgalgnebhfojomionfpkfelancnnkf.crx") {
1904 download_metrics.url = url;
1905 download_metrics.downloader = DownloadMetrics::kNone;
1906 download_metrics.error = 0;
1907 download_metrics.downloaded_bytes = 1843;
1908 download_metrics.total_bytes = 1843;
1909 download_metrics.download_time_ms = 1000;
1911 EXPECT_TRUE(MakeTestFile(
1912 TestFilePath("jebgalgnebhfojomionfpkfelancnnkf.crx"), &path));
1914 result.error = 0;
1915 result.response = path;
1916 result.downloaded_bytes = 1843;
1917 result.total_bytes = 1843;
1918 } else {
1919 NOTREACHED();
1922 base::ThreadTaskRunnerHandle::Get()->PostTask(
1923 FROM_HERE, base::Bind(&FakeCrxDownloader::OnDownloadProgress,
1924 base::Unretained(this), result));
1926 base::ThreadTaskRunnerHandle::Get()->PostTask(
1927 FROM_HERE,
1928 base::Bind(&FakeCrxDownloader::OnDownloadComplete,
1929 base::Unretained(this), true, result, download_metrics));
1933 class FakePingManager : public FakePingManagerImpl {
1934 public:
1935 explicit FakePingManager(const Configurator& config)
1936 : FakePingManagerImpl(config) {}
1937 ~FakePingManager() override {
1938 const auto& ping_items = items();
1939 EXPECT_EQ(1U, ping_items.size());
1940 EXPECT_EQ("jebgalgnebhfojomionfpkfelancnnkf", ping_items[0].id);
1941 EXPECT_TRUE(base::Version("0.0").Equals(ping_items[0].previous_version));
1942 EXPECT_TRUE(base::Version("1.0").Equals(ping_items[0].next_version));
1943 EXPECT_EQ(0, ping_items[0].error_category);
1944 EXPECT_EQ(0, ping_items[0].error_code);
1948 scoped_ptr<FakePingManager> ping_manager(new FakePingManager(*config()));
1949 scoped_refptr<UpdateClient> update_client(new UpdateClientImpl(
1950 config(), ping_manager.Pass(), &FakeUpdateChecker::Create,
1951 &FakeCrxDownloader::Create));
1953 // Verify that calling Install sets ondemand.
1954 OnDemandTester ondemand_tester(update_client, true);
1956 MockObserver observer;
1957 ON_CALL(observer, OnEvent(_, _))
1958 .WillByDefault(Invoke(&ondemand_tester, &OnDemandTester::CheckOnDemand));
1960 InSequence seq;
1961 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
1962 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
1963 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
1964 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
1965 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
1966 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
1967 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
1968 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
1969 EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED,
1970 "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
1972 update_client->AddObserver(&observer);
1974 update_client->Install(
1975 std::string("jebgalgnebhfojomionfpkfelancnnkf"),
1976 base::Bind(&DataCallbackFake::Callback),
1977 base::Bind(&CompletionCallbackFake::Callback, quit_closure()));
1979 RunThreads();
1981 update_client->RemoveObserver(&observer);
1983 StopWorkerPool();
1986 // Make sure that we don't get any crashes when trying to update an empty list
1987 // of ids.
1988 TEST_F(UpdateClientTest, EmptyIdList) {
1989 class DataCallbackFake {
1990 public:
1991 static void Callback(const std::vector<std::string>& ids,
1992 std::vector<CrxComponent>* components) {}
1995 class CompletionCallbackFake {
1996 public:
1997 static void Callback(const base::Closure& quit_closure, int error) {
1998 quit_closure.Run();
2001 class FakeUpdateChecker : public UpdateChecker {
2002 public:
2003 static scoped_ptr<UpdateChecker> Create(const Configurator& config) {
2004 return scoped_ptr<UpdateChecker>(new FakeUpdateChecker());
2007 bool CheckForUpdates(
2008 const std::vector<CrxUpdateItem*>& items_to_check,
2009 const std::string& additional_attributes,
2010 const UpdateCheckCallback& update_check_callback) override {
2011 return false;
2015 class FakeCrxDownloader : public CrxDownloader {
2016 public:
2017 static scoped_ptr<CrxDownloader> Create(
2018 bool is_background_download,
2019 net::URLRequestContextGetter* context_getter,
2020 const scoped_refptr<base::SequencedTaskRunner>& url_fetcher_task_runner,
2021 const scoped_refptr<base::SingleThreadTaskRunner>&
2022 background_task_runner) {
2023 return scoped_ptr<CrxDownloader>(new FakeCrxDownloader());
2026 private:
2027 FakeCrxDownloader() : CrxDownloader(scoped_ptr<CrxDownloader>().Pass()) {}
2028 ~FakeCrxDownloader() override {}
2030 void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); }
2033 scoped_refptr<UpdateClient> update_client(new UpdateClientImpl(
2034 config(), make_scoped_ptr(new FakePingManagerImpl(*config())),
2035 &FakeUpdateChecker::Create, &FakeCrxDownloader::Create));
2037 std::vector<std::string> empty_id_list;
2038 base::RunLoop runloop;
2039 update_client->Update(
2040 empty_id_list, base::Bind(&DataCallbackFake::Callback),
2041 base::Bind(&CompletionCallbackFake::Callback, runloop.QuitClosure()));
2042 runloop.Run();
2044 StopWorkerPool();
2047 } // namespace update_client