component_updater_service_unittest.cc revision 010d83a9304c5a91596085d917d248abff47903a
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->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.
691  test_configurator()->SetOnDemandTime(60 * 60);
692  EXPECT_EQ(
693      ComponentUpdateService::kError,
694      OnDemandTester::OnDemand(component_updater(), GetCrxComponentID(com2)));
695  // Okay, now reset to 0 for the other tests.
696  test_configurator()->SetOnDemandTime(0);
697  component_updater()->Stop();
698
699  // Test a few error cases. NOTE: We don't have callbacks for
700  // when the updates failed yet.
701  EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer));
702  {
703    InSequence seq;
704    EXPECT_CALL(observer,
705                OnEvent(ServiceObserver::COMPONENT_UPDATER_STARTED, ""))
706        .Times(1);
707    EXPECT_CALL(observer,
708                OnEvent(ServiceObserver::COMPONENT_NOT_UPDATED,
709                        "abagagagagagagagagagagagagagagag"))
710        .Times(1);
711    EXPECT_CALL(observer,
712                OnEvent(ServiceObserver::COMPONENT_NOT_UPDATED,
713                        "jebgalgnebhfojomionfpkfelancnnkf"))
714        .Times(1);
715    EXPECT_CALL(observer,
716                OnEvent(ServiceObserver::COMPONENT_UPDATER_SLEEPING, ""))
717        .Times(1);
718  }
719
720  // No update: error from no server response
721  post_interceptor_->Reset();
722  EXPECT_TRUE(post_interceptor_->ExpectRequest(
723      new PartialMatch("updatecheck"), test_file("updatecheck_reply_empty")));
724
725  test_configurator()->SetLoopCount(1);
726  component_updater()->Start();
727  EXPECT_EQ(
728      ComponentUpdateService::kOk,
729      OnDemandTester::OnDemand(component_updater(), GetCrxComponentID(com2)));
730  RunThreads();
731  component_updater()->Stop();
732
733  EXPECT_EQ(1, post_interceptor_->GetHitCount())
734      << post_interceptor_->GetRequestsAsString();
735  EXPECT_EQ(1, post_interceptor_->GetCount())
736      << post_interceptor_->GetRequestsAsString();
737
738  // No update: already updated to 1.0 so nothing new
739  EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer));
740  {
741    InSequence seq;
742    EXPECT_CALL(observer,
743                OnEvent(ServiceObserver::COMPONENT_UPDATER_STARTED, ""))
744        .Times(1);
745    EXPECT_CALL(observer,
746                OnEvent(ServiceObserver::COMPONENT_NOT_UPDATED,
747                        "jebgalgnebhfojomionfpkfelancnnkf"))
748        .Times(1);
749    EXPECT_CALL(observer,
750                OnEvent(ServiceObserver::COMPONENT_NOT_UPDATED,
751                        "abagagagagagagagagagagagagagagag"))
752        .Times(1);
753    EXPECT_CALL(observer,
754                OnEvent(ServiceObserver::COMPONENT_UPDATER_SLEEPING, ""))
755        .Times(1);
756  }
757
758  post_interceptor_->Reset();
759  EXPECT_TRUE(post_interceptor_->ExpectRequest(
760      new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
761
762  test_configurator()->SetLoopCount(1);
763  component_updater()->Start();
764  EXPECT_EQ(
765      ComponentUpdateService::kOk,
766      OnDemandTester::OnDemand(component_updater(), GetCrxComponentID(com2)));
767  RunThreads();
768
769  EXPECT_EQ(1, post_interceptor_->GetHitCount())
770      << post_interceptor_->GetRequestsAsString();
771  EXPECT_EQ(1, post_interceptor_->GetCount())
772      << post_interceptor_->GetRequestsAsString();
773
774  component_updater()->Stop();
775}
776
777// Verify that a previously registered component can get re-registered
778// with a different version.
779TEST_F(ComponentUpdaterTest, CheckReRegistration) {
780  MockServiceObserver observer;
781  {
782    InSequence seq;
783    EXPECT_CALL(observer,
784                OnEvent(ServiceObserver::COMPONENT_UPDATER_STARTED, ""))
785        .Times(1);
786    EXPECT_CALL(observer,
787                OnEvent(ServiceObserver::COMPONENT_UPDATE_FOUND,
788                        "jebgalgnebhfojomionfpkfelancnnkf"))
789        .Times(1);
790    EXPECT_CALL(observer,
791                OnEvent(ServiceObserver::COMPONENT_NOT_UPDATED,
792                        "abagagagagagagagagagagagagagagag"))
793        .Times(1);
794    EXPECT_CALL(observer,
795                OnEvent(ServiceObserver::COMPONENT_UPDATE_DOWNLOADING,
796                        "jebgalgnebhfojomionfpkfelancnnkf"))
797                .Times(AnyNumber());
798    EXPECT_CALL(observer,
799                OnEvent(ServiceObserver::COMPONENT_UPDATE_READY,
800                        "jebgalgnebhfojomionfpkfelancnnkf"))
801        .Times(1);
802    EXPECT_CALL(observer,
803                OnEvent(ServiceObserver::COMPONENT_UPDATED,
804                        "jebgalgnebhfojomionfpkfelancnnkf"))
805        .Times(1);
806    EXPECT_CALL(observer,
807                OnEvent(ServiceObserver::COMPONENT_UPDATER_SLEEPING, ""))
808        .Times(1);
809    EXPECT_CALL(observer,
810                OnEvent(ServiceObserver::COMPONENT_NOT_UPDATED,
811                        "jebgalgnebhfojomionfpkfelancnnkf"))
812        .Times(1);
813    EXPECT_CALL(observer,
814                OnEvent(ServiceObserver::COMPONENT_NOT_UPDATED,
815                        "abagagagagagagagagagagagagagagag"))
816        .Times(1);
817    EXPECT_CALL(observer,
818                OnEvent(ServiceObserver::COMPONENT_UPDATER_SLEEPING, ""))
819        .Times(1);
820  }
821
822  EXPECT_TRUE(post_interceptor_->ExpectRequest(
823      new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
824  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event")));
825  EXPECT_TRUE(post_interceptor_->ExpectRequest(
826      new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
827
828  get_interceptor_->SetResponse(
829      GURL(expected_crx_url),
830      test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
831
832  component_updater()->AddObserver(&observer);
833
834  TestInstaller installer1;
835  CrxComponent com1;
836  RegisterComponent(&com1, kTestComponent_jebg, Version("0.9"), &installer1);
837  TestInstaller installer2;
838  CrxComponent com2;
839  RegisterComponent(&com2, kTestComponent_abag, Version("2.2"), &installer2);
840
841  // Loop twice to issue two checks: (1) with original 0.9 version, update to
842  // 1.0, and do the second check (2) with the updated 1.0 version.
843  test_configurator()->SetLoopCount(2);
844  component_updater()->Start();
845  RunThreads();
846
847  EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error());
848  EXPECT_EQ(1, static_cast<TestInstaller*>(com1.installer)->install_count());
849  EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error());
850  EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->install_count());
851
852  EXPECT_EQ(3, post_interceptor_->GetHitCount())
853      << post_interceptor_->GetRequestsAsString();
854  EXPECT_EQ(1, get_interceptor_->GetHitCount());
855
856  EXPECT_NE(
857      string::npos,
858      post_interceptor_->GetRequests()[0].find(
859          "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">"
860          "<updatecheck /></app>"))
861      << post_interceptor_->GetRequestsAsString();
862  EXPECT_NE(
863      string::npos,
864      post_interceptor_->GetRequests()[1].find(
865          "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" "
866          "version=\"0.9\" nextversion=\"1.0\">"
867          "<event eventtype=\"3\" eventresult=\"1\"/>"))
868      << post_interceptor_->GetRequestsAsString();
869  EXPECT_NE(
870      string::npos,
871      post_interceptor_->GetRequests()[2].find(
872          "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"1.0\">"
873          "<updatecheck /></app>"))
874      << post_interceptor_->GetRequestsAsString();
875
876  component_updater()->Stop();
877
878  // Now re-register, pretending to be an even newer version (2.2)
879  EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer));
880  {
881    InSequence seq;
882    EXPECT_CALL(observer,
883                OnEvent(ServiceObserver::COMPONENT_UPDATER_STARTED, ""))
884        .Times(1);
885    EXPECT_CALL(observer,
886                OnEvent(ServiceObserver::COMPONENT_NOT_UPDATED,
887                        "jebgalgnebhfojomionfpkfelancnnkf"))
888        .Times(1);
889    EXPECT_CALL(observer,
890                OnEvent(ServiceObserver::COMPONENT_NOT_UPDATED,
891                        "abagagagagagagagagagagagagagagag"))
892        .Times(1);
893    EXPECT_CALL(observer,
894                OnEvent(ServiceObserver::COMPONENT_UPDATER_SLEEPING, ""))
895        .Times(1);
896  }
897
898  post_interceptor_->Reset();
899  EXPECT_TRUE(post_interceptor_->ExpectRequest(
900      new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
901
902  TestInstaller installer3;
903  EXPECT_EQ(ComponentUpdateService::kReplaced,
904            RegisterComponent(
905                &com1, kTestComponent_jebg, Version("2.2"), &installer3));
906
907  // Loop once just to notice the check happening with the re-register version.
908  test_configurator()->SetLoopCount(1);
909  component_updater()->Start();
910  RunThreads();
911
912  // We created a new installer, so the counts go back to 0.
913  EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error());
914  EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->install_count());
915  EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error());
916  EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->install_count());
917
918  // One update check and no additional pings are expected.
919  EXPECT_EQ(1, post_interceptor_->GetHitCount())
920      << post_interceptor_->GetRequestsAsString();
921  EXPECT_EQ(1, post_interceptor_->GetCount())
922      << post_interceptor_->GetRequestsAsString();
923
924  EXPECT_NE(
925      string::npos,
926      post_interceptor_->GetRequests()[0].find(
927          "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"2.2\">"
928          "<updatecheck /></app>"));
929
930  component_updater()->Stop();
931}
932
933// Verify that we can download and install a component and a differential
934// update to that component. We do three loops; the final loop should do
935// nothing.
936// We also check that exactly 5 non-ping network requests are issued:
937// 1- update check (response: v1 available)
938// 2- download crx (v1)
939// 3- update check (response: v2 available)
940// 4- download differential crx (v1 to v2)
941// 5- update check (response: no further update available)
942// There should be two pings, one for each update. The second will bear a
943// diffresult=1, while the first will not.
944TEST_F(ComponentUpdaterTest, DifferentialUpdate) {
945  EXPECT_TRUE(post_interceptor_->ExpectRequest(
946      new PartialMatch("updatecheck"),
947      test_file("updatecheck_diff_reply_1.xml")));
948  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event")));
949  EXPECT_TRUE(post_interceptor_->ExpectRequest(
950      new PartialMatch("updatecheck"),
951      test_file("updatecheck_diff_reply_2.xml")));
952  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event")));
953  EXPECT_TRUE(post_interceptor_->ExpectRequest(
954      new PartialMatch("updatecheck"),
955      test_file("updatecheck_diff_reply_3.xml")));
956
957  get_interceptor_->SetResponse(
958      GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"),
959      test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"));
960  get_interceptor_->SetResponse(
961      GURL("http://localhost/download/"
962           "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"),
963      test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"));
964
965  VersionedTestInstaller installer;
966  CrxComponent com;
967  RegisterComponent(&com, kTestComponent_ihfo, Version("0.0"), &installer);
968
969  test_configurator()->SetLoopCount(3);
970  component_updater()->Start();
971  RunThreads();
972
973  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
974  EXPECT_EQ(2, static_cast<TestInstaller*>(com.installer)->install_count());
975
976  EXPECT_EQ(5, post_interceptor_->GetHitCount())
977      << post_interceptor_->GetRequestsAsString();
978  EXPECT_EQ(5, post_interceptor_->GetCount())
979      << post_interceptor_->GetRequestsAsString();
980  EXPECT_EQ(2, get_interceptor_->GetHitCount());
981
982  EXPECT_NE(
983      string::npos,
984      post_interceptor_->GetRequests()[0].find(
985          "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"0.0\">"
986          "<updatecheck /></app>"))
987      << post_interceptor_->GetRequestsAsString();
988  EXPECT_NE(
989      string::npos,
990      post_interceptor_->GetRequests()[1].find(
991          "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" "
992          "version=\"0.0\" nextversion=\"1.0\">"
993          "<event eventtype=\"3\" eventresult=\"1\" nextfp=\"1\"/>"))
994      << post_interceptor_->GetRequestsAsString();
995  EXPECT_NE(
996      string::npos,
997      post_interceptor_->GetRequests()[2].find(
998          "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"1.0\">"
999          "<updatecheck /><packages><package fp=\"1\"/></packages></app>"))
1000      << post_interceptor_->GetRequestsAsString();
1001  EXPECT_NE(
1002      string::npos,
1003      post_interceptor_->GetRequests()[3].find(
1004          "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" "
1005          "version=\"1.0\" nextversion=\"2.0\">"
1006          "<event eventtype=\"3\" eventresult=\"1\" diffresult=\"1\" "
1007          "previousfp=\"1\" nextfp=\"22\"/>"))
1008      << post_interceptor_->GetRequestsAsString();
1009  EXPECT_NE(
1010      string::npos,
1011      post_interceptor_->GetRequests()[4].find(
1012          "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"2.0\">"
1013          "<updatecheck /><packages><package fp=\"22\"/></packages></app>"))
1014      << post_interceptor_->GetRequestsAsString();
1015  component_updater()->Stop();
1016}
1017
1018// Verify that component installation falls back to downloading and installing
1019// a full update if the differential update fails (in this case, because the
1020// installer does not know about the existing files). We do two loops; the final
1021// loop should do nothing.
1022// We also check that exactly 4 non-ping network requests are issued:
1023// 1- update check (loop 1)
1024// 2- download differential crx
1025// 3- download full crx
1026// 4- update check (loop 2 - no update available)
1027// There should be one ping for the first attempted update.
1028// This test is flaky on Android. crbug.com/329883
1029#if defined(OS_ANDROID)
1030#define MAYBE_DifferentialUpdateFails DISABLED_DifferentialUpdateFails
1031#else
1032#define MAYBE_DifferentialUpdateFails DifferentialUpdateFails
1033#endif
1034TEST_F(ComponentUpdaterTest, MAYBE_DifferentialUpdateFails) {
1035  EXPECT_TRUE(post_interceptor_->ExpectRequest(
1036      new PartialMatch("updatecheck"),
1037      test_file("updatecheck_diff_reply_2.xml")));
1038  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event")));
1039  EXPECT_TRUE(post_interceptor_->ExpectRequest(
1040      new PartialMatch("updatecheck"),
1041      test_file("updatecheck_diff_reply_3.xml")));
1042
1043  get_interceptor_->SetResponse(
1044      GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"),
1045      test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"));
1046  get_interceptor_->SetResponse(
1047      GURL("http://localhost/download/"
1048          "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"),
1049      test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"));
1050  get_interceptor_->SetResponse(
1051      GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"),
1052      test_file("ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"));
1053
1054  TestInstaller installer;
1055  CrxComponent com;
1056  RegisterComponent(&com, kTestComponent_ihfo, Version("1.0"), &installer);
1057
1058  test_configurator()->SetLoopCount(2);
1059  component_updater()->Start();
1060  RunThreads();
1061
1062  // A failed differential update does not count as a failed install.
1063  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
1064  EXPECT_EQ(1, static_cast<TestInstaller*>(com.installer)->install_count());
1065
1066  EXPECT_EQ(3, post_interceptor_->GetHitCount())
1067      << post_interceptor_->GetRequestsAsString();
1068  EXPECT_EQ(3, post_interceptor_->GetCount())
1069      << post_interceptor_->GetRequestsAsString();
1070  EXPECT_EQ(2, get_interceptor_->GetHitCount());
1071
1072  EXPECT_NE(
1073      string::npos,
1074      post_interceptor_->GetRequests()[0].find(
1075          "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"1.0\">"
1076          "<updatecheck /></app>"))
1077      << post_interceptor_->GetRequestsAsString();
1078  EXPECT_NE(
1079      string::npos,
1080      post_interceptor_->GetRequests()[1].find(
1081          "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" "
1082          "version=\"1.0\" nextversion=\"2.0\">"
1083          "<event eventtype=\"3\" eventresult=\"1\" diffresult=\"0\" "
1084          "differrorcat=\"2\" differrorcode=\"16\" nextfp=\"22\"/>"))
1085      << post_interceptor_->GetRequestsAsString();
1086  EXPECT_NE(
1087      string::npos,
1088      post_interceptor_->GetRequests()[2].find(
1089          "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"2.0\">"
1090          "<updatecheck /><packages><package fp=\"22\"/></packages></app>"))
1091      << post_interceptor_->GetRequestsAsString();
1092
1093  component_updater()->Stop();
1094}
1095
1096// Test is flakey on Android bots. See crbug.com/331420.
1097#if defined(OS_ANDROID)
1098#define MAYBE_CheckFailedInstallPing DISABLED_CheckFailedInstallPing
1099#else
1100#define MAYBE_CheckFailedInstallPing CheckFailedInstallPing
1101#endif
1102// Verify that a failed installation causes an install failure ping.
1103TEST_F(ComponentUpdaterTest, MAYBE_CheckFailedInstallPing) {
1104  // This test installer reports installation failure.
1105  class : public TestInstaller {
1106    virtual bool Install(const base::DictionaryValue& manifest,
1107                         const base::FilePath& unpack_path) OVERRIDE {
1108      ++install_count_;
1109      base::DeleteFile(unpack_path, true);
1110      return false;
1111    }
1112  } installer;
1113
1114  EXPECT_TRUE(post_interceptor_->ExpectRequest(
1115      new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
1116  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event")));
1117  EXPECT_TRUE(post_interceptor_->ExpectRequest(
1118      new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
1119  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event")));
1120  get_interceptor_->SetResponse(
1121      GURL(expected_crx_url),
1122      test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
1123
1124  // Start with 0.9, and attempt update to 1.0.
1125  // Loop twice to issue two checks: (1) with original 0.9 version
1126  // and (2), which should retry with 0.9.
1127  CrxComponent com;
1128  RegisterComponent(&com, kTestComponent_jebg, Version("0.9"), &installer);
1129
1130  test_configurator()->SetLoopCount(2);
1131  component_updater()->Start();
1132  RunThreads();
1133
1134  EXPECT_EQ(4, post_interceptor_->GetHitCount())
1135      << post_interceptor_->GetRequestsAsString();
1136  EXPECT_EQ(2, get_interceptor_->GetHitCount());
1137
1138  EXPECT_NE(
1139      string::npos,
1140      post_interceptor_->GetRequests()[0].find(
1141          "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">"
1142          "<updatecheck /></app>"))
1143      << post_interceptor_->GetRequestsAsString();
1144  EXPECT_NE(
1145      string::npos,
1146      post_interceptor_->GetRequests()[1].find(
1147          "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" "
1148          "version=\"0.9\" nextversion=\"1.0\">"
1149          "<event eventtype=\"3\" eventresult=\"0\" "
1150          "errorcat=\"3\" errorcode=\"9\"/>"))
1151      << post_interceptor_->GetRequestsAsString();
1152  EXPECT_NE(
1153      string::npos,
1154      post_interceptor_->GetRequests()[2].find(
1155          "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">"
1156          "<updatecheck /></app>"))
1157      << post_interceptor_->GetRequestsAsString();
1158  EXPECT_NE(
1159      string::npos,
1160      post_interceptor_->GetRequests()[3].find(
1161          "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" "
1162          "version=\"0.9\" nextversion=\"1.0\">"
1163          "<event eventtype=\"3\" eventresult=\"0\" "
1164          "errorcat=\"3\" errorcode=\"9\"/>"))
1165      << post_interceptor_->GetRequestsAsString();
1166
1167  // Loop once more, but expect no ping because a noupdate response is issued.
1168  // This is necessary to clear out the fire-and-forget ping from the previous
1169  // iteration.
1170  post_interceptor_->Reset();
1171  EXPECT_TRUE(post_interceptor_->ExpectRequest(
1172      new PartialMatch("updatecheck"),
1173      test_file("updatecheck_reply_noupdate.xml")));
1174
1175  test_configurator()->SetLoopCount(1);
1176  component_updater()->Start();
1177  RunThreads();
1178
1179  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
1180  EXPECT_EQ(2, static_cast<TestInstaller*>(com.installer)->install_count());
1181
1182  EXPECT_EQ(1, post_interceptor_->GetHitCount())
1183      << post_interceptor_->GetRequestsAsString();
1184  EXPECT_EQ(1, post_interceptor_->GetCount())
1185      << post_interceptor_->GetRequestsAsString();
1186
1187  EXPECT_NE(
1188      string::npos,
1189      post_interceptor_->GetRequests()[0].find(
1190          "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">"
1191          "<updatecheck /></app>"))
1192      << post_interceptor_->GetRequestsAsString();
1193
1194  component_updater()->Stop();
1195}
1196
1197// Verify that we successfully propagate a patcher error.
1198// ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad.crx contains an incorrect
1199// patching instruction that should fail.
1200TEST_F(ComponentUpdaterTest, DifferentialUpdateFailErrorcode) {
1201  EXPECT_TRUE(post_interceptor_->ExpectRequest(
1202      new PartialMatch("updatecheck"),
1203      test_file("updatecheck_diff_reply_1.xml")));
1204  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event")));
1205  EXPECT_TRUE(post_interceptor_->ExpectRequest(
1206      new PartialMatch("updatecheck"),
1207      test_file("updatecheck_diff_reply_2.xml")));
1208  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event")));
1209  EXPECT_TRUE(post_interceptor_->ExpectRequest(
1210      new PartialMatch("updatecheck"),
1211      test_file("updatecheck_diff_reply_3.xml")));
1212
1213  get_interceptor_->SetResponse(
1214      GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"),
1215      test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"));
1216  // This intercept returns a different file than what is specified in the
1217  // update check response and requested in the download. The file that is
1218  // actually dowloaded contains a patching error, an therefore, an error
1219  // is injected at the time of patching.
1220  get_interceptor_->SetResponse(
1221      GURL("http://localhost/download/"
1222           "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"),
1223      test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad.crx"));
1224  get_interceptor_->SetResponse(
1225      GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"),
1226      test_file("ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"));
1227
1228  VersionedTestInstaller installer;
1229  CrxComponent com;
1230  RegisterComponent(&com, kTestComponent_ihfo, Version("0.0"), &installer);
1231
1232  test_configurator()->SetLoopCount(3);
1233  component_updater()->Start();
1234  RunThreads();
1235  component_updater()->Stop();
1236
1237  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
1238  EXPECT_EQ(2, static_cast<TestInstaller*>(com.installer)->install_count());
1239
1240  EXPECT_EQ(5, post_interceptor_->GetHitCount())
1241      << post_interceptor_->GetRequestsAsString();
1242  EXPECT_EQ(5, post_interceptor_->GetCount())
1243      << post_interceptor_->GetRequestsAsString();
1244  EXPECT_EQ(3, get_interceptor_->GetHitCount());
1245
1246  EXPECT_NE(
1247      string::npos,
1248      post_interceptor_->GetRequests()[0].find(
1249          "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"0.0\">"
1250          "<updatecheck /></app>"))
1251      << post_interceptor_->GetRequestsAsString();
1252  EXPECT_NE(
1253      string::npos,
1254      post_interceptor_->GetRequests()[1].find(
1255          "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" "
1256          "version=\"0.0\" nextversion=\"1.0\">"
1257          "<event eventtype=\"3\" eventresult=\"1\" nextfp=\"1\"/>"))
1258      << post_interceptor_->GetRequestsAsString();
1259  EXPECT_NE(
1260      string::npos,
1261      post_interceptor_->GetRequests()[2].find(
1262          "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"1.0\">"
1263          "<updatecheck /><packages><package fp=\"1\"/></packages></app>"))
1264      << post_interceptor_->GetRequestsAsString();
1265  EXPECT_NE(
1266      string::npos,
1267      post_interceptor_->GetRequests()[3].find(
1268          "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" "
1269          "version=\"1.0\" nextversion=\"2.0\">"
1270          "<event eventtype=\"3\" eventresult=\"1\" "
1271          "diffresult=\"0\" differrorcat=\"2\" "
1272          "differrorcode=\"14\" diffextracode1=\"305\" "
1273          "previousfp=\"1\" nextfp=\"22\"/>"))
1274      << post_interceptor_->GetRequestsAsString();
1275  EXPECT_NE(
1276      string::npos,
1277      post_interceptor_->GetRequests()[4].find(
1278          "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"2.0\">"
1279          "<updatecheck /><packages><package fp=\"22\"/></packages></app>"))
1280      << post_interceptor_->GetRequestsAsString();
1281}
1282
1283class TestResourceController : public content::ResourceController {
1284 public:
1285  virtual void SetThrottle(content::ResourceThrottle* throttle) {}
1286};
1287
1288content::ResourceThrottle* RequestTestResourceThrottle(
1289    ComponentUpdateService* cus,
1290    TestResourceController* controller,
1291    const char* crx_id) {
1292  net::TestURLRequestContext context;
1293  net::TestURLRequest url_request(GURL("http://foo.example.com/thing.bin"),
1294                                  net::DEFAULT_PRIORITY,
1295                                  NULL,
1296                                  &context);
1297
1298  content::ResourceThrottle* rt =
1299      cus->GetOnDemandResourceThrottle(&url_request, crx_id);
1300  rt->set_controller_for_testing(controller);
1301  controller->SetThrottle(rt);
1302  return rt;
1303}
1304
1305void RequestAndDeleteResourceThrottle(ComponentUpdateService* cus,
1306                                      const char* crx_id) {
1307  // By requesting a throttle and deleting it immediately we ensure that we
1308  // hit the case where the component updater tries to use the weak
1309  // pointer to a dead Resource throttle.
1310  class NoCallResourceController : public TestResourceController {
1311   public:
1312    virtual ~NoCallResourceController() {}
1313    virtual void Cancel() OVERRIDE { CHECK(false); }
1314    virtual void CancelAndIgnore() OVERRIDE { CHECK(false); }
1315    virtual void CancelWithError(int error_code) OVERRIDE { CHECK(false); }
1316    virtual void Resume() OVERRIDE { CHECK(false); }
1317  } controller;
1318
1319  delete RequestTestResourceThrottle(cus, &controller, crx_id);
1320}
1321
1322TEST_F(ComponentUpdaterTest, ResourceThrottleDeletedNoUpdate) {
1323  MockServiceObserver observer;
1324  {
1325    InSequence seq;
1326    EXPECT_CALL(observer,
1327                OnEvent(ServiceObserver::COMPONENT_UPDATER_STARTED, ""))
1328        .Times(1);
1329    EXPECT_CALL(observer,
1330                OnEvent(ServiceObserver::COMPONENT_NOT_UPDATED,
1331                        "abagagagagagagagagagagagagagagag"))
1332        .Times(1);
1333    EXPECT_CALL(observer,
1334                OnEvent(ServiceObserver::COMPONENT_UPDATER_SLEEPING, ""))
1335        .Times(1);
1336  }
1337
1338  EXPECT_TRUE(post_interceptor_->ExpectRequest(
1339      new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
1340
1341  TestInstaller installer;
1342  CrxComponent com;
1343  component_updater()->AddObserver(&observer);
1344  EXPECT_EQ(
1345      ComponentUpdateService::kOk,
1346      RegisterComponent(&com, kTestComponent_abag, Version("1.1"), &installer));
1347  // The following two calls ensure that we don't do an update check via the
1348  // timer, so the only update check should be the on-demand one.
1349  test_configurator()->SetInitialDelay(1000000);
1350  test_configurator()->SetRecheckTime(1000000);
1351  test_configurator()->SetLoopCount(1);
1352  component_updater()->Start();
1353
1354  RunThreadsUntilIdle();
1355
1356  EXPECT_EQ(0, post_interceptor_->GetHitCount());
1357
1358  BrowserThread::PostTask(BrowserThread::IO,
1359                          FROM_HERE,
1360                          base::Bind(&RequestAndDeleteResourceThrottle,
1361                                     component_updater(),
1362                                     "abagagagagagagagagagagagagagagag"));
1363
1364  RunThreads();
1365
1366  EXPECT_EQ(1, post_interceptor_->GetHitCount());
1367  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
1368  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count());
1369
1370  component_updater()->Stop();
1371}
1372
1373class CancelResourceController : public TestResourceController {
1374 public:
1375  CancelResourceController() : throttle_(NULL), resume_called_(0) {}
1376  virtual ~CancelResourceController() {
1377    // Check that the throttle has been resumed by the time we
1378    // exit the test.
1379    CHECK_EQ(1, resume_called_);
1380    delete throttle_;
1381  }
1382  virtual void Cancel() OVERRIDE { CHECK(false); }
1383  virtual void CancelAndIgnore() OVERRIDE { CHECK(false); }
1384  virtual void CancelWithError(int error_code) OVERRIDE { CHECK(false); }
1385  virtual void Resume() OVERRIDE {
1386    BrowserThread::PostTask(BrowserThread::IO,
1387                            FROM_HERE,
1388                            base::Bind(&CancelResourceController::ResumeCalled,
1389                                       base::Unretained(this)));
1390  }
1391  virtual void SetThrottle(content::ResourceThrottle* throttle) OVERRIDE {
1392    throttle_ = throttle;
1393    bool defer = false;
1394    // Initially the throttle is blocked. The CUS needs to run a
1395    // task on the UI thread to  decide if it should unblock.
1396    throttle_->WillStartRequest(&defer);
1397    CHECK(defer);
1398  }
1399
1400 private:
1401  void ResumeCalled() { ++resume_called_; }
1402
1403  content::ResourceThrottle* throttle_;
1404  int resume_called_;
1405};
1406
1407TEST_F(ComponentUpdaterTest, ResourceThrottleLiveNoUpdate) {
1408  MockServiceObserver observer;
1409  {
1410    InSequence seq;
1411    EXPECT_CALL(observer,
1412                OnEvent(ServiceObserver::COMPONENT_UPDATER_STARTED, ""))
1413        .Times(1);
1414    EXPECT_CALL(observer,
1415                OnEvent(ServiceObserver::COMPONENT_NOT_UPDATED,
1416                        "abagagagagagagagagagagagagagagag"))
1417        .Times(1);
1418    EXPECT_CALL(observer,
1419                OnEvent(ServiceObserver::COMPONENT_UPDATER_SLEEPING, ""))
1420        .Times(1);
1421  }
1422
1423  EXPECT_TRUE(post_interceptor_->ExpectRequest(
1424      new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
1425
1426  TestInstaller installer;
1427  CrxComponent com;
1428  component_updater()->AddObserver(&observer);
1429  EXPECT_EQ(
1430      ComponentUpdateService::kOk,
1431      RegisterComponent(&com, kTestComponent_abag, Version("1.1"), &installer));
1432  // The following two calls ensure that we don't do an update check via the
1433  // timer, so the only update check should be the on-demand one.
1434  test_configurator()->SetInitialDelay(1000000);
1435  test_configurator()->SetRecheckTime(1000000);
1436  test_configurator()->SetLoopCount(1);
1437  component_updater()->Start();
1438
1439  RunThreadsUntilIdle();
1440
1441  EXPECT_EQ(0, post_interceptor_->GetHitCount());
1442
1443  CancelResourceController controller;
1444
1445  BrowserThread::PostTask(
1446      BrowserThread::IO,
1447      FROM_HERE,
1448      base::Bind(base::IgnoreResult(&RequestTestResourceThrottle),
1449                 component_updater(),
1450                 &controller,
1451                 "abagagagagagagagagagagagagagagag"));
1452
1453  RunThreads();
1454
1455  EXPECT_EQ(1, post_interceptor_->GetHitCount());
1456  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
1457  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count());
1458
1459  component_updater()->Stop();
1460}
1461
1462// Tests adding and removing observers.
1463TEST_F(ComponentUpdaterTest, Observer) {
1464  MockServiceObserver observer1, observer2;
1465
1466  // Expect that two observers see the events.
1467  {
1468    InSequence seq;
1469    EXPECT_CALL(observer1,
1470                OnEvent(ServiceObserver::COMPONENT_UPDATER_STARTED, ""))
1471        .Times(1);
1472    EXPECT_CALL(observer2,
1473                OnEvent(ServiceObserver::COMPONENT_UPDATER_STARTED, ""))
1474        .Times(1);
1475    EXPECT_CALL(observer1,
1476                OnEvent(ServiceObserver::COMPONENT_NOT_UPDATED,
1477                        "abagagagagagagagagagagagagagagag"))
1478        .Times(1);
1479    EXPECT_CALL(observer2,
1480                OnEvent(ServiceObserver::COMPONENT_NOT_UPDATED,
1481                        "abagagagagagagagagagagagagagagag"))
1482        .Times(1);
1483    EXPECT_CALL(observer1,
1484                OnEvent(ServiceObserver::COMPONENT_UPDATER_SLEEPING, ""))
1485        .Times(1);
1486    EXPECT_CALL(observer2,
1487                OnEvent(ServiceObserver::COMPONENT_UPDATER_SLEEPING, ""))
1488        .Times(1);
1489  }
1490
1491  EXPECT_TRUE(post_interceptor_->ExpectRequest(
1492      new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
1493
1494  component_updater()->AddObserver(&observer1);
1495  component_updater()->AddObserver(&observer2);
1496
1497  TestInstaller installer;
1498  CrxComponent com;
1499  EXPECT_EQ(
1500      ComponentUpdateService::kOk,
1501      RegisterComponent(&com, kTestComponent_abag, Version("1.1"), &installer));
1502  test_configurator()->SetLoopCount(1);
1503  component_updater()->Start();
1504  RunThreads();
1505
1506  // After removing the first observer, it's only the second observer that
1507  // gets the events.
1508  EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer1));
1509  EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer2));
1510  {
1511    InSequence seq;
1512    EXPECT_CALL(observer2,
1513                OnEvent(ServiceObserver::COMPONENT_UPDATER_STARTED, ""))
1514        .Times(1);
1515    EXPECT_CALL(observer2,
1516                OnEvent(ServiceObserver::COMPONENT_NOT_UPDATED,
1517                        "abagagagagagagagagagagagagagagag"))
1518        .Times(1);
1519    EXPECT_CALL(observer2,
1520                OnEvent(ServiceObserver::COMPONENT_UPDATER_SLEEPING, ""))
1521        .Times(1);
1522  }
1523
1524  component_updater()->RemoveObserver(&observer1);
1525
1526  test_configurator()->SetLoopCount(1);
1527  component_updater()->Start();
1528  RunThreads();
1529
1530  // Both observers are removed and no one gets the events.
1531  EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer1));
1532  EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer2));
1533  component_updater()->RemoveObserver(&observer2);
1534
1535  test_configurator()->SetLoopCount(1);
1536  component_updater()->Start();
1537  RunThreads();
1538
1539  component_updater()->Stop();
1540}
1541
1542}  // namespace component_updater
1543