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