component_updater_service_unittest.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1// Copyright 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/component_updater/test/component_updater_service_unittest.h"
6#include "base/file_util.h"
7#include "base/path_service.h"
8#include "base/run_loop.h"
9#include "base/strings/string_number_conversions.h"
10#include "base/strings/string_util.h"
11#include "base/strings/stringprintf.h"
12#include "base/values.h"
13#include "chrome/browser/component_updater/component_updater_utils.h"
14#include "chrome/browser/component_updater/test/test_installer.h"
15#include "chrome/common/chrome_paths.h"
16#include "content/public/browser/browser_thread.h"
17#include "content/public/browser/resource_controller.h"
18#include "content/public/browser/resource_request_info.h"
19#include "content/public/browser/resource_throttle.h"
20#include "libxml/globals.h"
21#include "net/base/upload_bytes_element_reader.h"
22#include "net/url_request/url_fetcher.h"
23#include "net/url_request/url_request_test_util.h"
24#include "url/gurl.h"
25
26using content::BrowserThread;
27
28using ::testing::_;
29using ::testing::InSequence;
30using ::testing::Mock;
31
32namespace component_updater {
33
34#define POST_INTERCEPT_SCHEME    "http"
35#define POST_INTERCEPT_HOSTNAME  "localhost2"
36#define POST_INTERCEPT_PATH      "/update2"
37
38MockComponentObserver::MockComponentObserver() {
39}
40
41MockComponentObserver::~MockComponentObserver() {
42}
43
44bool PartialMatch::Match(const std::string& actual) const {
45  return actual.find(expected_) != std::string::npos;
46}
47
48TestConfigurator::TestConfigurator()
49    : initial_time_(0),
50      times_(1),
51      recheck_time_(0),
52      ondemand_time_(0),
53      cus_(NULL),
54      context_(new net::TestURLRequestContextGetter(
55          BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO))) {
56}
57
58TestConfigurator::~TestConfigurator() {
59}
60
61int TestConfigurator::InitialDelay() { return initial_time_; }
62
63int TestConfigurator::NextCheckDelay() {
64  // This is called when a new full cycle of checking for updates is going
65  // to happen. In test we normally only test one cycle so it is a good
66  // time to break from the test messageloop Run() method so the test can
67  // finish.
68  if (--times_ <= 0) {
69    quit_closure_.Run();
70    return 0;
71  }
72  return 1;
73}
74
75int TestConfigurator::StepDelay() {
76  return 0;
77}
78
79int TestConfigurator::StepDelayMedium() {
80  return NextCheckDelay();
81}
82
83int TestConfigurator::MinimumReCheckWait() {
84  return recheck_time_;
85}
86
87int TestConfigurator::OnDemandDelay() {
88  return ondemand_time_;
89}
90
91GURL TestConfigurator::UpdateUrl() {
92  return GURL(POST_INTERCEPT_SCHEME "://"
93              POST_INTERCEPT_HOSTNAME POST_INTERCEPT_PATH);
94}
95
96GURL TestConfigurator::PingUrl() {
97  return UpdateUrl();
98}
99
100std::string TestConfigurator::ExtraRequestParams() { return "extra=\"foo\""; }
101
102size_t TestConfigurator::UrlSizeLimit() { return 256; }
103
104net::URLRequestContextGetter* TestConfigurator::RequestContext() {
105  return context_.get();
106}
107
108// Don't use the utility process to run code out-of-process.
109bool TestConfigurator::InProcess() { return true; }
110
111ComponentPatcher* TestConfigurator::CreateComponentPatcher() {
112  return new MockComponentPatcher();
113}
114
115bool TestConfigurator::DeltasEnabled() const {
116  return true;
117}
118
119bool TestConfigurator::UseBackgroundDownloader() const {
120  return false;
121}
122
123// Set how many update checks are called, the default value is just once.
124void TestConfigurator::SetLoopCount(int times) { times_ = times; }
125
126void TestConfigurator::SetRecheckTime(int seconds) {
127  recheck_time_ = seconds;
128}
129
130void TestConfigurator::SetOnDemandTime(int seconds) {
131  ondemand_time_ = seconds;
132}
133
134void TestConfigurator::SetComponentUpdateService(ComponentUpdateService* cus) {
135  cus_ = cus;
136}
137
138void TestConfigurator::SetQuitClosure(const base::Closure& quit_closure) {
139  quit_closure_ = quit_closure;
140}
141
142void TestConfigurator::SetInitialDelay(int seconds) {
143  initial_time_ = seconds;
144}
145
146InterceptorFactory::InterceptorFactory()
147    : URLRequestPostInterceptorFactory(POST_INTERCEPT_SCHEME,
148                                       POST_INTERCEPT_HOSTNAME) {}
149
150InterceptorFactory::~InterceptorFactory() {}
151
152URLRequestPostInterceptor* InterceptorFactory::CreateInterceptor() {
153  return URLRequestPostInterceptorFactory::CreateInterceptor(
154    base::FilePath::FromUTF8Unsafe(POST_INTERCEPT_PATH));
155}
156
157ComponentUpdaterTest::ComponentUpdaterTest()
158    : test_config_(NULL),
159      thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
160  // The component updater instance under test.
161  test_config_ = new TestConfigurator;
162  component_updater_.reset(ComponentUpdateServiceFactory(test_config_));
163  test_config_->SetComponentUpdateService(component_updater_.get());
164
165  // The test directory is chrome/test/data/components.
166  PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_);
167  test_data_dir_ = test_data_dir_.AppendASCII("components");
168
169  net::URLFetcher::SetEnableInterceptionForTests(true);
170}
171
172ComponentUpdaterTest::~ComponentUpdaterTest() {
173  net::URLFetcher::SetEnableInterceptionForTests(false);
174}
175
176void ComponentUpdaterTest::SetUp() {
177  get_interceptor_.reset(new GetInterceptor);
178  interceptor_factory_.reset(new InterceptorFactory);
179  post_interceptor_ = interceptor_factory_->CreateInterceptor();
180  EXPECT_TRUE(post_interceptor_);
181}
182
183void ComponentUpdaterTest::TearDown() {
184  interceptor_factory_.reset();
185  get_interceptor_.reset();
186  xmlCleanupGlobals();
187}
188
189ComponentUpdateService* ComponentUpdaterTest::component_updater() {
190  return component_updater_.get();
191}
192
193  // Makes the full path to a component updater test file.
194const base::FilePath ComponentUpdaterTest::test_file(const char* file) {
195  return test_data_dir_.AppendASCII(file);
196}
197
198TestConfigurator* ComponentUpdaterTest::test_configurator() {
199  return test_config_;
200}
201
202ComponentUpdateService::Status ComponentUpdaterTest::RegisterComponent(
203    CrxComponent* com,
204    TestComponents component,
205    const Version& version,
206    TestInstaller* installer) {
207  if (component == kTestComponent_abag) {
208    com->name = "test_abag";
209    com->pk_hash.assign(abag_hash, abag_hash + arraysize(abag_hash));
210  } else if (component == kTestComponent_jebg) {
211    com->name = "test_jebg";
212    com->pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash));
213  } else {
214    com->name = "test_ihfo";
215    com->pk_hash.assign(ihfo_hash, ihfo_hash + arraysize(ihfo_hash));
216  }
217  com->version = version;
218  com->installer = installer;
219  return component_updater_->RegisterComponent(*com);
220}
221
222void ComponentUpdaterTest::RunThreads() {
223  base::RunLoop runloop;
224  test_configurator()->SetQuitClosure(runloop.QuitClosure());
225  runloop.Run();
226
227  // Since some tests need to drain currently enqueued tasks such as network
228  // intercepts on the IO thread, run the threads until they are
229  // idle. The component updater service won't loop again until the loop count
230  // is set and the service is started.
231  RunThreadsUntilIdle();
232}
233
234void ComponentUpdaterTest::RunThreadsUntilIdle() {
235  base::RunLoop().RunUntilIdle();
236}
237
238ComponentUpdateService::Status OnDemandTester::OnDemand(
239    ComponentUpdateService* cus, const std::string& component_id) {
240  return cus->OnDemandUpdate(component_id);
241}
242
243// Verify that our test fixture work and the component updater can
244// be created and destroyed with no side effects.
245TEST_F(ComponentUpdaterTest, VerifyFixture) {
246  EXPECT_TRUE(component_updater() != NULL);
247}
248
249// Verify that the component updater can be caught in a quick
250// start-shutdown situation. Failure of this test will be a crash.
251TEST_F(ComponentUpdaterTest, StartStop) {
252  component_updater()->Start();
253  RunThreadsUntilIdle();
254  component_updater()->Stop();
255}
256
257// Verify that when the server has no updates, we go back to sleep and
258// the COMPONENT_UPDATER_STARTED and COMPONENT_UPDATER_SLEEPING notifications
259// are generated. No pings are sent.
260TEST_F(ComponentUpdaterTest, CheckCrxSleep) {
261  MockComponentObserver observer;
262
263  EXPECT_CALL(observer,
264              OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
265              .Times(1);
266  EXPECT_CALL(observer,
267              OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
268              .Times(2);
269  EXPECT_CALL(observer,
270              OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
271              .Times(2);
272
273  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
274      "updatecheck"), test_file("updatecheck_reply_1.xml")));
275  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
276      "updatecheck"), test_file("updatecheck_reply_1.xml")));
277
278  TestInstaller installer;
279  CrxComponent com;
280  com.observer = &observer;
281  EXPECT_EQ(ComponentUpdateService::kOk,
282            RegisterComponent(&com,
283                              kTestComponent_abag,
284                              Version("1.1"),
285                              &installer));
286
287  // We loop twice, but there are no updates so we expect two sleep messages.
288  test_configurator()->SetLoopCount(2);
289  component_updater()->Start();
290  RunThreads();
291
292  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
293  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count());
294
295  // Expect to see the two update check requests and no other requests,
296  // including pings.
297  EXPECT_EQ(2, post_interceptor_->GetHitCount())
298      << post_interceptor_->GetRequestsAsString();
299  EXPECT_EQ(2, post_interceptor_->GetCount())
300      << post_interceptor_->GetRequestsAsString();
301  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find(
302      "<app appid=\"abagagagagagagagagagagagagagagag\" version=\"1.1\">"
303      "<updatecheck /></app>"))
304      << post_interceptor_->GetRequestsAsString();
305  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find(
306      "<app appid=\"abagagagagagagagagagagagagagagag\" version=\"1.1\">"
307      "<updatecheck /></app>"))
308      << post_interceptor_->GetRequestsAsString();
309
310  component_updater()->Stop();
311
312  // Loop twice again but this case we simulate a server error by returning
313  // an empty file. Expect the behavior of the service to be the same as before.
314  EXPECT_CALL(observer,
315              OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
316              .Times(1);
317  EXPECT_CALL(observer,
318              OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
319              .Times(2);
320  EXPECT_CALL(observer,
321              OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
322              .Times(2);
323
324  post_interceptor_->Reset();
325  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
326      "updatecheck"), test_file("updatecheck_reply_empty")));
327  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
328      "updatecheck"), test_file("updatecheck_reply_empty")));
329
330  test_configurator()->SetLoopCount(2);
331  component_updater()->Start();
332  RunThreads();
333
334  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
335  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count());
336
337  EXPECT_EQ(2, post_interceptor_->GetHitCount())
338      << post_interceptor_->GetRequestsAsString();
339  EXPECT_EQ(2, post_interceptor_->GetCount())
340      << post_interceptor_->GetRequestsAsString();
341  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find(
342      "<app appid=\"abagagagagagagagagagagagagagagag\" version=\"1.1\">"
343      "<updatecheck /></app>"))
344      << post_interceptor_->GetRequestsAsString();
345  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find(
346      "<app appid=\"abagagagagagagagagagagagagagagag\" version=\"1.1\">"
347      "<updatecheck /></app>"))
348      << post_interceptor_->GetRequestsAsString();
349
350  component_updater()->Stop();
351}
352
353// Verify that we can check for updates and install one component. Besides
354// the notifications above COMPONENT_UPDATE_FOUND and COMPONENT_UPDATE_READY
355// should have been fired. We do two loops so the second time around there
356// should be nothing left to do.
357// We also check that the following network requests are issued:
358// 1- update check
359// 2- download crx
360// 3- ping
361// 4- second update check.
362TEST_F(ComponentUpdaterTest, InstallCrx) {
363  MockComponentObserver observer1;
364  {
365    InSequence seq;
366    EXPECT_CALL(observer1,
367                OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
368                .Times(1);
369    EXPECT_CALL(observer1,
370                OnEvent(ComponentObserver::COMPONENT_UPDATE_FOUND, 0))
371                .Times(1);
372    EXPECT_CALL(observer1,
373                OnEvent(ComponentObserver::COMPONENT_UPDATE_READY, 0))
374                .Times(1);
375    EXPECT_CALL(observer1,
376                OnEvent(ComponentObserver::COMPONENT_UPDATED, 0))
377                .Times(1);
378    EXPECT_CALL(observer1,
379                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
380                .Times(1);
381    EXPECT_CALL(observer1,
382                OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
383                .Times(1);
384    EXPECT_CALL(observer1,
385                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
386                .Times(1);
387  }
388
389  MockComponentObserver observer2;
390  {
391    InSequence seq;
392    EXPECT_CALL(observer2,
393                OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
394                .Times(1);
395    EXPECT_CALL(observer2,
396                OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
397                .Times(1);
398    EXPECT_CALL(observer2,
399                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
400                .Times(1);
401    EXPECT_CALL(observer2,
402                OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
403                .Times(1);
404    EXPECT_CALL(observer2,
405                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
406                .Times(1);
407  }
408
409  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
410      "updatecheck"), test_file("updatecheck_reply_1.xml")));
411  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event")));
412  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
413      "updatecheck"), test_file("updatecheck_reply_1.xml")));
414
415  get_interceptor_->SetResponse(
416      GURL(expected_crx_url),
417      test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
418
419  TestInstaller installer1;
420  CrxComponent com1;
421  com1.observer = &observer1;
422  RegisterComponent(&com1, kTestComponent_jebg, Version("0.9"), &installer1);
423  TestInstaller installer2;
424  CrxComponent com2;
425  com2.observer = &observer2;
426  RegisterComponent(&com2, kTestComponent_abag, Version("2.2"), &installer2);
427
428  test_configurator()->SetLoopCount(2);
429  component_updater()->Start();
430  RunThreads();
431
432  EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error());
433  EXPECT_EQ(1, static_cast<TestInstaller*>(com1.installer)->install_count());
434  EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error());
435  EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->install_count());
436
437  // Expect three request in total: two update checks and one ping.
438  EXPECT_EQ(3, post_interceptor_->GetHitCount())
439      << post_interceptor_->GetRequestsAsString();
440  EXPECT_EQ(3, post_interceptor_->GetCount())
441      << post_interceptor_->GetRequestsAsString();
442
443  // Expect one component download.
444  EXPECT_EQ(1, get_interceptor_->GetHitCount());
445
446  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find(
447      "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">"
448      "<updatecheck /></app>"))
449      << post_interceptor_->GetRequestsAsString();
450  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find(
451      "<app appid=\"abagagagagagagagagagagagagagagag\" version=\"2.2\">"
452      "<updatecheck /></app>"))
453      << post_interceptor_->GetRequestsAsString();
454
455  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find(
456      "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" "
457      "version=\"0.9\" nextversion=\"1.0\">"
458      "<event eventtype=\"3\" eventresult=\"1\"/>"))
459      << post_interceptor_->GetRequestsAsString();
460
461  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[2].find(
462      "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"1.0\">"
463      "<updatecheck /></app>"));
464  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[2].find(
465      "<app appid=\"abagagagagagagagagagagagagagagag\" version=\"2.2\">"
466      "<updatecheck /></app>"))
467      << post_interceptor_->GetRequestsAsString();
468
469  // Test the protocol version is correct and the extra request attributes
470  // are included in the request.
471  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find(
472      "request protocol=\"3.0\" extra=\"foo\""))
473      << post_interceptor_->GetRequestsAsString();
474
475  // Tokenize the request string to look for specific attributes, which
476  // are important for backward compatibility with the version v2 of the update
477  // protocol. In this case, inspect the <request>, which is the first element
478  // after the xml declaration of the update request body.
479  // Expect to find the |os|, |arch|, |prodchannel|, and |prodversion|
480  // attributes:
481  // <?xml version="1.0" encoding="UTF-8"?>
482  // <request... os=... arch=... prodchannel=... prodversion=...>
483  // ...
484  // </request>
485  const std::string update_request(post_interceptor_->GetRequests()[0]);
486  std::vector<base::StringPiece> elements;
487  Tokenize(update_request, "<>", &elements);
488  EXPECT_NE(string::npos, elements[1].find(" os="));
489  EXPECT_NE(string::npos, elements[1].find(" arch="));
490  EXPECT_NE(string::npos, elements[1].find(" prodchannel="));
491  EXPECT_NE(string::npos, elements[1].find(" prodversion="));
492
493  // Look for additional attributes of the request, such as |version|,
494  // |requestid|, |lang|, and |nacl_arch|.
495  EXPECT_NE(string::npos, elements[1].find(" version="));
496  EXPECT_NE(string::npos, elements[1].find(" requestid="));
497  EXPECT_NE(string::npos, elements[1].find(" lang="));
498  EXPECT_NE(string::npos, elements[1].find(" nacl_arch="));
499
500  component_updater()->Stop();
501}
502
503// This test checks that the "prodversionmin" value is handled correctly. In
504// particular there should not be an install because the minimum product
505// version is much higher than of chrome.
506TEST_F(ComponentUpdaterTest, ProdVersionCheck) {
507  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
508      "updatecheck"), test_file("updatecheck_reply_2.xml")));
509
510  get_interceptor_->SetResponse(
511      GURL(expected_crx_url),
512      test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
513
514  TestInstaller installer;
515  CrxComponent com;
516  RegisterComponent(&com, kTestComponent_jebg, Version("0.9"), &installer);
517
518  test_configurator()->SetLoopCount(1);
519  component_updater()->Start();
520  RunThreads();
521
522  // Expect one update check and no ping.
523  EXPECT_EQ(1, post_interceptor_->GetHitCount())
524      << post_interceptor_->GetRequestsAsString();
525  EXPECT_EQ(1, post_interceptor_->GetCount())
526      << post_interceptor_->GetRequestsAsString();
527
528  // Expect no download to occur.
529  EXPECT_EQ(0, get_interceptor_->GetHitCount());
530
531  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
532  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count());
533
534  component_updater()->Stop();
535}
536
537// Test that a update check due to an on demand call can cause installs.
538// Here is the timeline:
539//  - First loop: we return a reply that indicates no update, so
540//    nothing happens.
541//  - We make an on demand call.
542//  - This triggers a second loop, which has a reply that triggers an install.
543TEST_F(ComponentUpdaterTest, OnDemandUpdate) {
544  MockComponentObserver observer1;
545  {
546    InSequence seq;
547    EXPECT_CALL(observer1,
548                OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
549                .Times(1);
550    EXPECT_CALL(observer1,
551                OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
552                .Times(1);
553    EXPECT_CALL(observer1,
554                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
555                .Times(1);
556    EXPECT_CALL(observer1,
557                OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
558                .Times(1);
559    EXPECT_CALL(observer1,
560                OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
561                .Times(1);
562    EXPECT_CALL(observer1,
563                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
564                .Times(1);
565  }
566
567  MockComponentObserver observer2;
568  {
569    InSequence seq;
570    EXPECT_CALL(observer2,
571                OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
572                .Times(1);
573    EXPECT_CALL(observer2,
574                OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
575                .Times(1);
576    EXPECT_CALL(observer2,
577                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
578                .Times(1);
579    EXPECT_CALL(observer2,
580                OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
581                .Times(1);
582    EXPECT_CALL(observer2,
583                OnEvent(ComponentObserver::COMPONENT_UPDATE_FOUND, 0))
584                .Times(1);
585    EXPECT_CALL(observer2,
586                OnEvent(ComponentObserver::COMPONENT_UPDATE_READY, 0))
587                .Times(1);
588    EXPECT_CALL(observer2,
589                OnEvent(ComponentObserver::COMPONENT_UPDATED, 0))
590                .Times(1);
591    EXPECT_CALL(observer2,
592                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
593                .Times(1);
594  }
595
596  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
597      "updatecheck"), test_file("updatecheck_reply_empty")));
598
599  get_interceptor_->SetResponse(
600      GURL(expected_crx_url),
601      test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
602
603  TestInstaller installer1;
604  CrxComponent com1;
605  com1.observer = &observer1;
606  RegisterComponent(&com1, kTestComponent_abag, Version("2.2"), &installer1);
607  TestInstaller installer2;
608  CrxComponent com2;
609  com2.observer = &observer2;
610  RegisterComponent(&com2, kTestComponent_jebg, Version("0.9"), &installer2);
611
612  // No update normally.
613  test_configurator()->SetLoopCount(1);
614  component_updater()->Start();
615  RunThreads();
616  component_updater()->Stop();
617
618  EXPECT_EQ(1, post_interceptor_->GetHitCount())
619      << post_interceptor_->GetRequestsAsString();
620  EXPECT_EQ(1, post_interceptor_->GetCount())
621      << post_interceptor_->GetRequestsAsString();
622
623  EXPECT_EQ(0, get_interceptor_->GetHitCount());
624
625  // Update after an on-demand check is issued.
626  post_interceptor_->Reset();
627  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
628      "updatecheck"), test_file("updatecheck_reply_1.xml")));
629  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event")));
630
631  EXPECT_EQ(ComponentUpdateService::kOk,
632            OnDemandTester::OnDemand(component_updater(),
633                                     GetCrxComponentID(com2)));
634  test_configurator()->SetLoopCount(1);
635  component_updater()->Start();
636  RunThreads();
637
638  EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error());
639  EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->install_count());
640  EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error());
641  EXPECT_EQ(1, static_cast<TestInstaller*>(com2.installer)->install_count());
642
643  EXPECT_EQ(2, post_interceptor_->GetHitCount())
644      << post_interceptor_->GetRequestsAsString();
645  EXPECT_EQ(2, post_interceptor_->GetCount())
646      << post_interceptor_->GetRequestsAsString();
647
648  EXPECT_EQ(1, get_interceptor_->GetHitCount());
649
650  // Expect the update check to contain an "ondemand" request for the
651  // second component (com2) and a normal request for the other component.
652  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find(
653      "<app appid=\"abagagagagagagagagagagagagagagag\" "
654      "version=\"2.2\"><updatecheck /></app>"))
655      << post_interceptor_->GetRequestsAsString();
656  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find(
657      "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" "
658      "version=\"0.9\" installsource=\"ondemand\"><updatecheck /></app>"))
659      << post_interceptor_->GetRequestsAsString();
660  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find(
661      "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" "
662      "version=\"0.9\" nextversion=\"1.0\">"
663      "<event eventtype=\"3\" eventresult=\"1\"/>"))
664      << post_interceptor_->GetRequestsAsString();
665
666  // Also check what happens if previous check too soon.
667  test_configurator()->SetOnDemandTime(60 * 60);
668  EXPECT_EQ(ComponentUpdateService::kError,
669            OnDemandTester::OnDemand(component_updater(),
670                                     GetCrxComponentID(com2)));
671  // Okay, now reset to 0 for the other tests.
672  test_configurator()->SetOnDemandTime(0);
673  component_updater()->Stop();
674
675  // Test a few error cases. NOTE: We don't have callbacks for
676  // when the updates failed yet.
677  EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer1));
678  {
679    InSequence seq;
680    EXPECT_CALL(observer1,
681                OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
682                .Times(1);
683    EXPECT_CALL(observer1,
684                OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
685                .Times(1);
686    EXPECT_CALL(observer1,
687                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
688                .Times(1);
689  }
690  EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer2));
691  {
692    InSequence seq;
693    EXPECT_CALL(observer2,
694                OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
695                .Times(1);
696    EXPECT_CALL(observer2,
697                OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
698                .Times(1);
699    EXPECT_CALL(observer2,
700                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
701                .Times(1);
702  }
703
704  // No update: error from no server response
705  post_interceptor_->Reset();
706  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
707      "updatecheck"), test_file("updatecheck_reply_empty")));
708
709  test_configurator()->SetLoopCount(1);
710  component_updater()->Start();
711  EXPECT_EQ(ComponentUpdateService::kOk,
712            OnDemandTester::OnDemand(component_updater(),
713                                     GetCrxComponentID(com2)));
714  RunThreads();
715  component_updater()->Stop();
716
717  EXPECT_EQ(1, post_interceptor_->GetHitCount())
718      << post_interceptor_->GetRequestsAsString();
719  EXPECT_EQ(1, post_interceptor_->GetCount())
720      << post_interceptor_->GetRequestsAsString();
721
722  // No update: already updated to 1.0 so nothing new
723  EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer1));
724  {
725    InSequence seq;
726    EXPECT_CALL(observer1,
727                OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
728                .Times(1);
729    EXPECT_CALL(observer1,
730                OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
731                .Times(1);
732    EXPECT_CALL(observer1,
733                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
734                .Times(1);
735  }
736  EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer2));
737  {
738    InSequence seq;
739    EXPECT_CALL(observer2,
740                OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
741                .Times(1);
742    EXPECT_CALL(observer2,
743                OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
744                .Times(1);
745    EXPECT_CALL(observer2,
746                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
747                .Times(1);
748  }
749
750  post_interceptor_->Reset();
751  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
752      "updatecheck"), test_file("updatecheck_reply_1.xml")));
753
754  test_configurator()->SetLoopCount(1);
755  component_updater()->Start();
756  EXPECT_EQ(ComponentUpdateService::kOk,
757            OnDemandTester::OnDemand(component_updater(),
758                                     GetCrxComponentID(com2)));
759  RunThreads();
760
761  EXPECT_EQ(1, post_interceptor_->GetHitCount())
762      << post_interceptor_->GetRequestsAsString();
763  EXPECT_EQ(1, post_interceptor_->GetCount())
764      << post_interceptor_->GetRequestsAsString();
765
766  component_updater()->Stop();
767}
768
769// Verify that a previously registered component can get re-registered
770// with a different version.
771TEST_F(ComponentUpdaterTest, CheckReRegistration) {
772  MockComponentObserver observer1;
773  {
774    InSequence seq;
775    EXPECT_CALL(observer1,
776                OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
777                .Times(1);
778    EXPECT_CALL(observer1,
779                OnEvent(ComponentObserver::COMPONENT_UPDATE_FOUND, 0))
780                .Times(1);
781    EXPECT_CALL(observer1,
782                OnEvent(ComponentObserver::COMPONENT_UPDATE_READY, 0))
783                .Times(1);
784    EXPECT_CALL(observer1,
785                OnEvent(ComponentObserver::COMPONENT_UPDATED, 0))
786                .Times(1);
787    EXPECT_CALL(observer1,
788                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
789                .Times(1);
790    EXPECT_CALL(observer1,
791                OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
792                .Times(1);
793    EXPECT_CALL(observer1,
794                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
795                .Times(1);
796  }
797
798  MockComponentObserver observer2;
799  {
800    InSequence seq;
801    EXPECT_CALL(observer2,
802                OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
803                .Times(1);
804    EXPECT_CALL(observer2,
805                OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
806                .Times(1);
807    EXPECT_CALL(observer2,
808                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
809                .Times(1);
810    EXPECT_CALL(observer2,
811                OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
812                .Times(1);
813    EXPECT_CALL(observer2,
814                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
815                .Times(1);
816  }
817
818  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
819      "updatecheck"), test_file("updatecheck_reply_1.xml")));
820  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event")));
821  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
822      "updatecheck"), test_file("updatecheck_reply_1.xml")));
823
824  get_interceptor_->SetResponse(
825      GURL(expected_crx_url),
826      test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
827
828  TestInstaller installer1;
829  CrxComponent com1;
830  com1.observer = &observer1;
831  RegisterComponent(&com1, kTestComponent_jebg, Version("0.9"), &installer1);
832  TestInstaller installer2;
833  CrxComponent com2;
834  com2.observer = &observer2;
835  RegisterComponent(&com2, kTestComponent_abag, Version("2.2"), &installer2);
836
837  // Loop twice to issue two checks: (1) with original 0.9 version, update to
838  // 1.0, and do the second check (2) with the updated 1.0 version.
839  test_configurator()->SetLoopCount(2);
840  component_updater()->Start();
841  RunThreads();
842
843  EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error());
844  EXPECT_EQ(1, static_cast<TestInstaller*>(com1.installer)->install_count());
845  EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error());
846  EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->install_count());
847
848  EXPECT_EQ(3, post_interceptor_->GetHitCount())
849        << post_interceptor_->GetRequestsAsString();
850  EXPECT_EQ(1, get_interceptor_->GetHitCount());
851
852  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find(
853      "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">"
854      "<updatecheck /></app>"))
855      << post_interceptor_->GetRequestsAsString();
856  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find(
857      "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" "
858      "version=\"0.9\" nextversion=\"1.0\">"
859      "<event eventtype=\"3\" eventresult=\"1\"/>"))
860      << post_interceptor_->GetRequestsAsString();
861  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[2].find(
862      "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"1.0\">"
863      "<updatecheck /></app>"))
864      << post_interceptor_->GetRequestsAsString();
865
866  component_updater()->Stop();
867
868  // Now re-register, pretending to be an even newer version (2.2)
869  EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer1));
870  {
871    InSequence seq;
872    EXPECT_CALL(observer1,
873                OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
874                .Times(1);
875    EXPECT_CALL(observer1,
876                OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
877                .Times(1);
878    EXPECT_CALL(observer1,
879                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
880                .Times(1);
881  }
882
883  EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer2));
884  {
885    InSequence seq;
886    EXPECT_CALL(observer2,
887                OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
888                .Times(1);
889    EXPECT_CALL(observer2,
890                OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
891                .Times(1);
892    EXPECT_CALL(observer2,
893                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
894                .Times(1);
895  }
896
897  post_interceptor_->Reset();
898  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
899      "updatecheck"), test_file("updatecheck_reply_1.xml")));
900
901  TestInstaller installer3;
902  EXPECT_EQ(ComponentUpdateService::kReplaced,
903            RegisterComponent(&com1,
904                              kTestComponent_jebg,
905                              Version("2.2"),
906                              &installer3));
907
908  // Loop once just to notice the check happening with the re-register version.
909  test_configurator()->SetLoopCount(1);
910  component_updater()->Start();
911  RunThreads();
912
913  // We created a new installer, so the counts go back to 0.
914  EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error());
915  EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->install_count());
916  EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error());
917  EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->install_count());
918
919  // One update check and no additional pings are expected.
920  EXPECT_EQ(1, post_interceptor_->GetHitCount())
921        << post_interceptor_->GetRequestsAsString();
922  EXPECT_EQ(1, post_interceptor_->GetCount())
923        << post_interceptor_->GetRequestsAsString();
924
925  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find(
926      "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"2.2\">"
927      "<updatecheck /></app>"));
928
929  component_updater()->Stop();
930}
931
932// Verify that we can download and install a component and a differential
933// update to that component. We do three loops; the final loop should do
934// nothing.
935// We also check that exactly 5 non-ping network requests are issued:
936// 1- update check (response: v1 available)
937// 2- download crx (v1)
938// 3- update check (response: v2 available)
939// 4- download differential crx (v1 to v2)
940// 5- update check (response: no further update available)
941// There should be two pings, one for each update. The second will bear a
942// diffresult=1, while the first will not.
943TEST_F(ComponentUpdaterTest, DifferentialUpdate) {
944  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
945      "updatecheck"), test_file("updatecheck_diff_reply_1.xml")));
946  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event")));
947  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
948      "updatecheck"), test_file("updatecheck_diff_reply_2.xml")));
949  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event")));
950  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
951      "updatecheck"), test_file("updatecheck_diff_reply_3.xml")));
952
953  get_interceptor_->SetResponse(
954      GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"),
955      test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"));
956  get_interceptor_->SetResponse(
957      GURL("http://localhost/download/"
958           "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"),
959      test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"));
960
961  VersionedTestInstaller installer;
962  CrxComponent com;
963  RegisterComponent(&com, kTestComponent_ihfo, Version("0.0"), &installer);
964
965  test_configurator()->SetLoopCount(3);
966  component_updater()->Start();
967  RunThreads();
968
969  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
970  EXPECT_EQ(2, static_cast<TestInstaller*>(com.installer)->install_count());
971
972  EXPECT_EQ(5, post_interceptor_->GetHitCount())
973      << post_interceptor_->GetRequestsAsString();
974  EXPECT_EQ(5, post_interceptor_->GetCount())
975      << post_interceptor_->GetRequestsAsString();
976  EXPECT_EQ(2, get_interceptor_->GetHitCount());
977
978  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find(
979      "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"0.0\">"
980      "<updatecheck /></app>"))
981      << post_interceptor_->GetRequestsAsString();
982  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find(
983      "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" "
984      "version=\"0.0\" nextversion=\"1.0\">"
985      "<event eventtype=\"3\" eventresult=\"1\" nextfp=\"1\"/>"))
986      << post_interceptor_->GetRequestsAsString();
987  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[2].find(
988      "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"1.0\">"
989      "<updatecheck /><packages><package fp=\"1\"/></packages></app>"))
990      << post_interceptor_->GetRequestsAsString();
991  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[3].find(
992      "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" "
993      "version=\"1.0\" nextversion=\"2.0\">"
994      "<event eventtype=\"3\" eventresult=\"1\" diffresult=\"1\" "
995      "previousfp=\"1\" nextfp=\"22\"/>"))
996      << post_interceptor_->GetRequestsAsString();
997  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[4].find(
998      "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"2.0\">"
999      "<updatecheck /><packages><package fp=\"22\"/></packages></app>"))
1000      << post_interceptor_->GetRequestsAsString();
1001  component_updater()->Stop();
1002}
1003
1004// Verify that component installation falls back to downloading and installing
1005// a full update if the differential update fails (in this case, because the
1006// installer does not know about the existing files). We do two loops; the final
1007// loop should do nothing.
1008// We also check that exactly 4 non-ping network requests are issued:
1009// 1- update check (loop 1)
1010// 2- download differential crx
1011// 3- download full crx
1012// 4- update check (loop 2 - no update available)
1013// There should be one ping for the first attempted update.
1014TEST_F(ComponentUpdaterTest, DifferentialUpdateFails) {
1015  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
1016      "updatecheck"), test_file("updatecheck_diff_reply_2.xml")));
1017  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event")));
1018  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
1019      "updatecheck"), test_file("updatecheck_diff_reply_3.xml")));
1020
1021  get_interceptor_->SetResponse(
1022      GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"),
1023      test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"));
1024  get_interceptor_->SetResponse(
1025      GURL("http://localhost/download/"
1026           "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"),
1027      test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"));
1028  get_interceptor_->SetResponse(
1029      GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"),
1030      test_file("ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"));
1031
1032  TestInstaller installer;
1033  CrxComponent com;
1034  RegisterComponent(&com, kTestComponent_ihfo, Version("1.0"), &installer);
1035
1036  test_configurator()->SetLoopCount(2);
1037  component_updater()->Start();
1038  RunThreads();
1039
1040  // A failed differential update does not count as a failed install.
1041  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
1042  EXPECT_EQ(1, static_cast<TestInstaller*>(com.installer)->install_count());
1043
1044  EXPECT_EQ(3, post_interceptor_->GetHitCount())
1045      << post_interceptor_->GetRequestsAsString();
1046  EXPECT_EQ(3, post_interceptor_->GetCount())
1047      << post_interceptor_->GetRequestsAsString();
1048  EXPECT_EQ(2, get_interceptor_->GetHitCount());
1049
1050  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find(
1051      "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"1.0\">"
1052      "<updatecheck /></app>"))
1053      << post_interceptor_->GetRequestsAsString();
1054  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find(
1055      "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" "
1056      "version=\"1.0\" nextversion=\"2.0\">"
1057      "<event eventtype=\"3\" eventresult=\"1\" diffresult=\"0\" "
1058      "differrorcat=\"2\" differrorcode=\"16\" nextfp=\"22\"/>"))
1059      << post_interceptor_->GetRequestsAsString();
1060  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[2].find(
1061      "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"2.0\">"
1062      "<updatecheck /><packages><package fp=\"22\"/></packages></app>"))
1063      << post_interceptor_->GetRequestsAsString();
1064
1065  component_updater()->Stop();
1066}
1067
1068// Test is flakey on Android bots. See crbug.com/331420.
1069#if defined(OS_ANDROID)
1070#define MAYBE_CheckFailedInstallPing DISABLED_CheckFailedInstallPing
1071#else
1072#define MAYBE_CheckFailedInstallPing CheckFailedInstallPing
1073#endif
1074// Verify that a failed installation causes an install failure ping.
1075  TEST_F(ComponentUpdaterTest, MAYBE_CheckFailedInstallPing) {
1076  // This test installer reports installation failure.
1077  class : public TestInstaller {
1078    virtual bool Install(const base::DictionaryValue& manifest,
1079                         const base::FilePath& unpack_path) OVERRIDE {
1080      ++install_count_;
1081      base::DeleteFile(unpack_path, true);
1082      return false;
1083    }
1084  } installer;
1085
1086  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
1087      "updatecheck"), test_file("updatecheck_reply_1.xml")));
1088  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event")));
1089  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
1090      "updatecheck"), test_file("updatecheck_reply_1.xml")));
1091  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event")));
1092  get_interceptor_->SetResponse(
1093      GURL(expected_crx_url),
1094      test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
1095
1096  // Start with 0.9, and attempt update to 1.0.
1097  // Loop twice to issue two checks: (1) with original 0.9 version
1098  // and (2), which should retry with 0.9.
1099  CrxComponent com;
1100  RegisterComponent(&com, kTestComponent_jebg, Version("0.9"), &installer);
1101
1102  test_configurator()->SetLoopCount(2);
1103  component_updater()->Start();
1104  RunThreads();
1105
1106  EXPECT_EQ(4, post_interceptor_->GetHitCount())
1107      << post_interceptor_->GetRequestsAsString();
1108  EXPECT_EQ(2, get_interceptor_->GetHitCount());
1109
1110  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find(
1111      "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">"
1112      "<updatecheck /></app>"))
1113      << post_interceptor_->GetRequestsAsString();
1114  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find(
1115      "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" "
1116      "version=\"0.9\" nextversion=\"1.0\">"
1117      "<event eventtype=\"3\" eventresult=\"0\" "
1118      "errorcat=\"3\" errorcode=\"9\"/>"))
1119      << post_interceptor_->GetRequestsAsString();
1120  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[2].find(
1121      "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">"
1122      "<updatecheck /></app>"))
1123      << post_interceptor_->GetRequestsAsString();
1124  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[3].find(
1125      "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" "
1126      "version=\"0.9\" nextversion=\"1.0\">"
1127      "<event eventtype=\"3\" eventresult=\"0\" "
1128      "errorcat=\"3\" errorcode=\"9\"/>"))
1129      << post_interceptor_->GetRequestsAsString();
1130
1131  // Loop once more, but expect no ping because a noupdate response is issued.
1132  // This is necessary to clear out the fire-and-forget ping from the previous
1133  // iteration.
1134  post_interceptor_->Reset();
1135  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
1136      "updatecheck"), test_file("updatecheck_reply_noupdate.xml")));
1137
1138  test_configurator()->SetLoopCount(1);
1139  component_updater()->Start();
1140  RunThreads();
1141
1142  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
1143  EXPECT_EQ(2, static_cast<TestInstaller*>(com.installer)->install_count());
1144
1145  EXPECT_EQ(1, post_interceptor_->GetHitCount())
1146      << post_interceptor_->GetRequestsAsString();
1147  EXPECT_EQ(1, post_interceptor_->GetCount())
1148      << post_interceptor_->GetRequestsAsString();
1149
1150  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find(
1151      "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">"
1152      "<updatecheck /></app>"))
1153      << post_interceptor_->GetRequestsAsString();
1154
1155  component_updater()->Stop();
1156}
1157
1158// Verify that we successfully propagate a patcher error.
1159// ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad.crx contains an incorrect
1160// patching instruction that should fail.
1161TEST_F(ComponentUpdaterTest, DifferentialUpdateFailErrorcode) {
1162  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
1163      "updatecheck"), test_file("updatecheck_diff_reply_1.xml")));
1164  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event")));
1165  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
1166      "updatecheck"), test_file("updatecheck_diff_reply_2.xml")));
1167  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event")));
1168  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
1169      "updatecheck"), test_file("updatecheck_diff_reply_3.xml")));
1170
1171  get_interceptor_->SetResponse(
1172      GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"),
1173      test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"));
1174  // This intercept returns a different file than what is specified in the
1175  // update check response and requested in the download. The file that is
1176  // actually dowloaded contains a patching error, an therefore, an error
1177  // is injected at the time of patching.
1178  get_interceptor_->SetResponse(
1179      GURL("http://localhost/download/"
1180           "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"),
1181      test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad.crx"));
1182  get_interceptor_->SetResponse(
1183      GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"),
1184      test_file("ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"));
1185
1186  VersionedTestInstaller installer;
1187  CrxComponent com;
1188  RegisterComponent(&com, kTestComponent_ihfo, Version("0.0"), &installer);
1189
1190  test_configurator()->SetLoopCount(3);
1191  component_updater()->Start();
1192  RunThreads();
1193  component_updater()->Stop();
1194
1195  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
1196  EXPECT_EQ(2, static_cast<TestInstaller*>(com.installer)->install_count());
1197
1198  EXPECT_EQ(5, post_interceptor_->GetHitCount())
1199      << post_interceptor_->GetRequestsAsString();
1200  EXPECT_EQ(5, post_interceptor_->GetCount())
1201      << post_interceptor_->GetRequestsAsString();
1202  EXPECT_EQ(3, get_interceptor_->GetHitCount());
1203
1204  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find(
1205      "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"0.0\">"
1206      "<updatecheck /></app>"))
1207      << post_interceptor_->GetRequestsAsString();
1208  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find(
1209      "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" "
1210      "version=\"0.0\" nextversion=\"1.0\">"
1211      "<event eventtype=\"3\" eventresult=\"1\" nextfp=\"1\"/>"))
1212      << post_interceptor_->GetRequestsAsString();
1213  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[2].find(
1214      "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"1.0\">"
1215      "<updatecheck /><packages><package fp=\"1\"/></packages></app>"))
1216      << post_interceptor_->GetRequestsAsString();
1217  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[3].find(
1218      "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" "
1219      "version=\"1.0\" nextversion=\"2.0\">"
1220      "<event eventtype=\"3\" eventresult=\"1\" "
1221      "diffresult=\"0\" differrorcat=\"2\" "
1222      "differrorcode=\"14\" diffextracode1=\"305\" "
1223      "previousfp=\"1\" nextfp=\"22\"/>"))
1224      << post_interceptor_->GetRequestsAsString();
1225  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[4].find(
1226      "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"2.0\">"
1227      "<updatecheck /><packages><package fp=\"22\"/></packages></app>"))
1228      << post_interceptor_->GetRequestsAsString();
1229}
1230
1231class TestResourceController : public content::ResourceController {
1232 public:
1233  virtual void SetThrottle(content::ResourceThrottle* throttle) {}
1234};
1235
1236content::ResourceThrottle* RequestTestResourceThrottle(
1237    ComponentUpdateService* cus,
1238    TestResourceController* controller,
1239    const char* crx_id) {
1240
1241  net::TestURLRequestContext context;
1242  net::TestURLRequest url_request(
1243      GURL("http://foo.example.com/thing.bin"),
1244      net::DEFAULT_PRIORITY,
1245      NULL,
1246      &context);
1247
1248  content::ResourceThrottle* rt =
1249      cus->GetOnDemandResourceThrottle(&url_request, crx_id);
1250  rt->set_controller_for_testing(controller);
1251  controller->SetThrottle(rt);
1252  return rt;
1253}
1254
1255void RequestAndDeleteResourceThrottle(
1256    ComponentUpdateService* cus, const char* crx_id) {
1257  // By requesting a throttle and deleting it immediately we ensure that we
1258  // hit the case where the component updater tries to use the weak
1259  // pointer to a dead Resource throttle.
1260  class  NoCallResourceController : public TestResourceController {
1261   public:
1262    virtual ~NoCallResourceController() {}
1263    virtual void Cancel() OVERRIDE { CHECK(false); }
1264    virtual void CancelAndIgnore() OVERRIDE { CHECK(false); }
1265    virtual void CancelWithError(int error_code) OVERRIDE { CHECK(false); }
1266    virtual void Resume() OVERRIDE { CHECK(false); }
1267  } controller;
1268
1269  delete RequestTestResourceThrottle(cus, &controller, crx_id);
1270}
1271
1272TEST_F(ComponentUpdaterTest, ResourceThrottleDeletedNoUpdate) {
1273  MockComponentObserver observer;
1274  EXPECT_CALL(observer,
1275              OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
1276              .Times(1);
1277  EXPECT_CALL(observer,
1278              OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
1279              .Times(1);
1280  EXPECT_CALL(observer,
1281              OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
1282              .Times(1);
1283
1284  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
1285      "updatecheck"), test_file("updatecheck_reply_1.xml")));
1286
1287  TestInstaller installer;
1288  CrxComponent com;
1289  com.observer = &observer;
1290  EXPECT_EQ(ComponentUpdateService::kOk,
1291            RegisterComponent(&com,
1292                              kTestComponent_abag,
1293                              Version("1.1"),
1294                              &installer));
1295  // The following two calls ensure that we don't do an update check via the
1296  // timer, so the only update check should be the on-demand one.
1297  test_configurator()->SetInitialDelay(1000000);
1298  test_configurator()->SetRecheckTime(1000000);
1299  test_configurator()->SetLoopCount(1);
1300  component_updater()->Start();
1301
1302  RunThreadsUntilIdle();
1303
1304  EXPECT_EQ(0, post_interceptor_->GetHitCount());
1305
1306  BrowserThread::PostTask(
1307      BrowserThread::IO,
1308      FROM_HERE,
1309      base::Bind(&RequestAndDeleteResourceThrottle,
1310                 component_updater(),
1311                 "abagagagagagagagagagagagagagagag"));
1312
1313  RunThreads();
1314
1315  EXPECT_EQ(1, post_interceptor_->GetHitCount());
1316  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
1317  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count());
1318
1319  component_updater()->Stop();
1320}
1321
1322class  CancelResourceController: public TestResourceController {
1323  public:
1324  CancelResourceController() : throttle_(NULL), resume_called_(0) {}
1325  virtual ~CancelResourceController() {
1326    // Check that the throttle has been resumed by the time we
1327    // exit the test.
1328    CHECK(resume_called_ == 1);
1329    delete throttle_;
1330  }
1331  virtual void Cancel() OVERRIDE { CHECK(false); }
1332  virtual void CancelAndIgnore() OVERRIDE { CHECK(false); }
1333  virtual void CancelWithError(int error_code) OVERRIDE { CHECK(false); }
1334  virtual void Resume() OVERRIDE {
1335    BrowserThread::PostTask(
1336        BrowserThread::IO,
1337        FROM_HERE,
1338        base::Bind(&CancelResourceController::ResumeCalled,
1339                    base::Unretained(this)));
1340  }
1341  virtual void SetThrottle(content::ResourceThrottle* throttle) OVERRIDE {
1342    throttle_ = throttle;
1343    bool defer = false;
1344    // Initially the throttle is blocked. The CUS needs to run a
1345    // task on the UI thread to  decide if it should unblock.
1346    throttle_->WillStartRequest(&defer);
1347    CHECK(defer);
1348  }
1349
1350  private:
1351  void ResumeCalled() { ++resume_called_; }
1352
1353  content::ResourceThrottle* throttle_;
1354  int resume_called_;
1355};
1356
1357TEST_F(ComponentUpdaterTest, ResourceThrottleLiveNoUpdate) {
1358  MockComponentObserver observer;
1359  EXPECT_CALL(observer,
1360              OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
1361              .Times(1);
1362  EXPECT_CALL(observer,
1363              OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
1364              .Times(1);
1365  EXPECT_CALL(observer,
1366              OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
1367              .Times(1);
1368
1369  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
1370      "updatecheck"), test_file("updatecheck_reply_1.xml")));
1371
1372  TestInstaller installer;
1373  CrxComponent com;
1374  com.observer = &observer;
1375  EXPECT_EQ(ComponentUpdateService::kOk,
1376            RegisterComponent(&com,
1377                              kTestComponent_abag,
1378                              Version("1.1"),
1379                              &installer));
1380  // The following two calls ensure that we don't do an update check via the
1381  // timer, so the only update check should be the on-demand one.
1382  test_configurator()->SetInitialDelay(1000000);
1383  test_configurator()->SetRecheckTime(1000000);
1384  test_configurator()->SetLoopCount(1);
1385  component_updater()->Start();
1386
1387  RunThreadsUntilIdle();
1388
1389  EXPECT_EQ(0, post_interceptor_->GetHitCount());
1390
1391  CancelResourceController controller;
1392
1393  BrowserThread::PostTask(
1394      BrowserThread::IO,
1395      FROM_HERE,
1396      base::Bind(base::IgnoreResult(&RequestTestResourceThrottle),
1397                 component_updater(),
1398                 &controller,
1399                 "abagagagagagagagagagagagagagagag"));
1400
1401  RunThreads();
1402
1403  EXPECT_EQ(1, post_interceptor_->GetHitCount());
1404  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
1405  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count());
1406
1407  component_updater()->Stop();
1408}
1409
1410
1411}  // namespace component_updater
1412
1413