component_updater_service_unittest.cc revision a36e5920737c6adbddd3e43b760e5de8431db6e0
1// Copyright (c) 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/files/file_path.h"
8#include "base/memory/scoped_vector.h"
9#include "base/path_service.h"
10#include "base/strings/string_number_conversions.h"
11#include "base/strings/stringprintf.h"
12#include "base/values.h"
13#include "chrome/browser/chrome_notification_types.h"
14#include "chrome/browser/component_updater/component_updater_service.h"
15#include "chrome/browser/component_updater/test/test_installer.h"
16#include "chrome/common/chrome_paths.h"
17#include "content/public/browser/notification_service.h"
18#include "content/test/net/url_request_prepackaged_interceptor.h"
19#include "libxml/globals.h"
20#include "net/base/upload_bytes_element_reader.h"
21#include "net/url_request/url_fetcher.h"
22#include "url/gurl.h"
23
24using content::BrowserThread;
25using content::TestNotificationTracker;
26
27using ::testing::_;
28using ::testing::InSequence;
29using ::testing::Mock;
30
31MockComponentObserver::MockComponentObserver() {
32}
33
34MockComponentObserver::~MockComponentObserver() {
35}
36
37TestConfigurator::TestConfigurator()
38    : times_(1),
39      recheck_time_(0),
40      ondemand_time_(0),
41      cus_(NULL),
42      context_(new net::TestURLRequestContextGetter(
43          BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO))) {
44}
45
46TestConfigurator::~TestConfigurator() {
47}
48
49int TestConfigurator::InitialDelay() { return 0; }
50
51int TestConfigurator::NextCheckDelay() {
52  // This is called when a new full cycle of checking for updates is going
53  // to happen. In test we normally only test one cycle so it is a good
54  // time to break from the test messageloop Run() method so the test can
55  // finish.
56  if (--times_ <= 0) {
57    base::MessageLoop::current()->Quit();
58    return 0;
59  }
60
61  // Look for checks to issue in the middle of the loop.
62  for (std::list<CheckAtLoopCount>::iterator
63           i = components_to_check_.begin();
64       i != components_to_check_.end(); ) {
65    if (i->second == times_) {
66      cus_->CheckForUpdateSoon(*i->first);
67      i = components_to_check_.erase(i);
68    } else {
69      ++i;
70    }
71  }
72  return 1;
73}
74
75int TestConfigurator::StepDelay() {
76  return 0;
77}
78
79int TestConfigurator::MinimumReCheckWait() {
80  return recheck_time_;
81}
82
83int TestConfigurator::OnDemandDelay() {
84  return ondemand_time_;
85}
86
87GURL TestConfigurator::UpdateUrl() {
88  return GURL("http://localhost/upd");
89}
90
91GURL TestConfigurator::PingUrl() {
92  return GURL("http://localhost2/ping");
93}
94
95const char* TestConfigurator::ExtraRequestParams() { return "extra=foo"; }
96
97size_t TestConfigurator::UrlSizeLimit() { return 256; }
98
99net::URLRequestContextGetter* TestConfigurator::RequestContext() {
100  return context_.get();
101}
102
103// Don't use the utility process to decode files.
104bool TestConfigurator::InProcess() { return true; }
105
106ComponentPatcher* TestConfigurator::CreateComponentPatcher() {
107  return new MockComponentPatcher();
108}
109
110bool TestConfigurator::DeltasEnabled() const {
111  return true;
112}
113
114// Set how many update checks are called, the default value is just once.
115void TestConfigurator::SetLoopCount(int times) { times_ = times; }
116
117void TestConfigurator::SetRecheckTime(int seconds) {
118  recheck_time_ = seconds;
119}
120
121void TestConfigurator::SetOnDemandTime(int seconds) {
122  ondemand_time_ = seconds;
123}
124
125void TestConfigurator::AddComponentToCheck(CrxComponent* com,
126                                           int at_loop_iter) {
127  components_to_check_.push_back(std::make_pair(com, at_loop_iter));
128}
129
130void TestConfigurator::SetComponentUpdateService(ComponentUpdateService* cus) {
131  cus_ = cus;
132}
133
134ComponentUpdaterTest::ComponentUpdaterTest()
135    : test_config_(NULL),
136      ui_thread_(BrowserThread::UI, &message_loop_),
137      file_thread_(BrowserThread::FILE),
138      io_thread_(BrowserThread::IO) {
139  // The component updater instance under test.
140  test_config_ = new TestConfigurator;
141  component_updater_.reset(ComponentUpdateServiceFactory(test_config_));
142  test_config_->SetComponentUpdateService(component_updater_.get());
143
144  // The test directory is chrome/test/data/components.
145  PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_);
146  test_data_dir_ = test_data_dir_.AppendASCII("components");
147
148  // Subscribe to all component updater notifications.
149  const int notifications[] = {
150    chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED,
151    chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING,
152    chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND,
153    chrome::NOTIFICATION_COMPONENT_UPDATE_READY
154  };
155
156  for (int ix = 0; ix != arraysize(notifications); ++ix) {
157    notification_tracker_.ListenFor(
158        notifications[ix], content::NotificationService::AllSources());
159  }
160  net::URLFetcher::SetEnableInterceptionForTests(true);
161
162  io_thread_.StartIOThread();
163  file_thread_.Start();
164}
165
166ComponentUpdaterTest::~ComponentUpdaterTest() {
167  net::URLFetcher::SetEnableInterceptionForTests(false);
168}
169
170void ComponentUpdaterTest::TearDown() {
171  xmlCleanupGlobals();
172}
173
174ComponentUpdateService* ComponentUpdaterTest::component_updater() {
175  return component_updater_.get();
176}
177
178  // Makes the full path to a component updater test file.
179const base::FilePath ComponentUpdaterTest::test_file(const char* file) {
180  return test_data_dir_.AppendASCII(file);
181}
182
183TestNotificationTracker& ComponentUpdaterTest::notification_tracker() {
184  return notification_tracker_;
185}
186
187TestConfigurator* ComponentUpdaterTest::test_configurator() {
188  return test_config_;
189}
190
191ComponentUpdateService::Status ComponentUpdaterTest::RegisterComponent(
192    CrxComponent* com,
193    TestComponents component,
194    const Version& version,
195    TestInstaller* installer) {
196  if (component == kTestComponent_abag) {
197    com->name = "test_abag";
198    com->pk_hash.assign(abag_hash, abag_hash + arraysize(abag_hash));
199  } else if (component == kTestComponent_jebg) {
200    com->name = "test_jebg";
201    com->pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash));
202  } else {
203    com->name = "test_ihfo";
204    com->pk_hash.assign(ihfo_hash, ihfo_hash + arraysize(ihfo_hash));
205  }
206  com->version = version;
207  com->installer = installer;
208  return component_updater_->RegisterComponent(*com);
209}
210
211PingChecker::PingChecker(const std::map<std::string, std::string>& attributes)
212    : num_hits_(0), num_misses_(0), attributes_(attributes) {
213}
214
215PingChecker::~PingChecker() {}
216
217void PingChecker::Trial(net::URLRequest* request) {
218  if (Test(request))
219    ++num_hits_;
220  else
221    ++num_misses_;
222}
223
224bool PingChecker::Test(net::URLRequest* request) {
225  if (request->has_upload()) {
226    const net::UploadDataStream* stream = request->get_upload();
227    const net::UploadBytesElementReader* reader =
228        stream->element_readers()[0]->AsBytesReader();
229    int size = reader->length();
230    scoped_refptr <net::IOBuffer> buffer = new net::IOBuffer(size);
231    std::string data(reader->bytes());
232    // For now, we assume that there is only one ping per POST.
233    std::string::size_type start = data.find("<o:event");
234    if (start != std::string::npos) {
235      std::string::size_type end = data.find(">", start);
236      if (end != std::string::npos) {
237        std::string ping = data.substr(start, end - start);
238        std::map<std::string, std::string>::const_iterator iter;
239        for (iter = attributes_.begin(); iter != attributes_.end(); ++iter) {
240          // does the ping contain the specified attribute/value?
241          if (ping.find(std::string(" ") + (iter->first) +
242              std::string("=") + (iter->second)) == string::npos) {
243            return false;
244          }
245        }
246        return true;
247      }
248    }
249  }
250  return false;
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  EXPECT_EQ(0ul, notification_tracker().size());
258}
259
260// Verify that the component updater can be caught in a quick
261// start-shutdown situation. Failure of this test will be a crash. Also
262// if there is no work to do, there are no notifications generated.
263TEST_F(ComponentUpdaterTest, StartStop) {
264  component_updater()->Start();
265  message_loop_.RunUntilIdle();
266  component_updater()->Stop();
267
268  EXPECT_EQ(0ul, notification_tracker().size());
269}
270
271// Verify that when the server has no updates, we go back to sleep and
272// the COMPONENT_UPDATER_STARTED and COMPONENT_UPDATER_SLEEPING notifications
273// are generated.
274TEST_F(ComponentUpdaterTest, CheckCrxSleep) {
275  content::URLLocalHostRequestPrepackagedInterceptor interceptor;
276
277  MockComponentObserver observer;
278
279  TestInstaller installer;
280  CrxComponent com;
281  com.observer = &observer;
282  EXPECT_EQ(ComponentUpdateService::kOk,
283            RegisterComponent(&com,
284                              kTestComponent_abag,
285                              Version("1.1"),
286                              &installer));
287
288  const GURL expected_update_url(
289      "http://localhost/upd?extra=foo"
290      "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D1.1%26fp%3D%26uc");
291
292  interceptor.SetResponse(expected_update_url,
293                          test_file("updatecheck_reply_1.xml"));
294
295  // We loop twice, but there are no updates so we expect two sleep messages.
296  test_configurator()->SetLoopCount(2);
297
298  EXPECT_CALL(observer,
299              OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
300              .Times(1);
301  component_updater()->Start();
302
303  ASSERT_EQ(1ul, notification_tracker().size());
304  TestNotificationTracker::Event ev1 = notification_tracker().at(0);
305  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev1.type);
306
307  EXPECT_CALL(observer,
308              OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
309              .Times(2);
310  message_loop_.Run();
311
312  ASSERT_EQ(3ul, notification_tracker().size());
313  TestNotificationTracker::Event ev2 = notification_tracker().at(1);
314  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev2.type);
315  TestNotificationTracker::Event ev3 = notification_tracker().at(2);
316  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev2.type);
317  EXPECT_EQ(2, interceptor.GetHitCount());
318
319  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
320  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count());
321
322  component_updater()->Stop();
323
324  // Loop twice again but this case we simulate a server error by returning
325  // an empty file.
326
327  interceptor.SetResponse(expected_update_url,
328                          test_file("updatecheck_reply_empty"));
329
330  notification_tracker().Reset();
331  test_configurator()->SetLoopCount(2);
332
333  EXPECT_CALL(observer,
334              OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
335              .Times(1);
336  component_updater()->Start();
337
338  EXPECT_CALL(observer,
339              OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
340              .Times(2);
341  message_loop_.Run();
342
343  ASSERT_EQ(3ul, notification_tracker().size());
344  ev1 = notification_tracker().at(0);
345  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev1.type);
346  ev2 = notification_tracker().at(1);
347  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev2.type);
348  ev3 = notification_tracker().at(2);
349  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev2.type);
350  EXPECT_EQ(4, interceptor.GetHitCount());
351
352  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
353  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count());
354
355  component_updater()->Stop();
356}
357
358// Verify that we can check for updates and install one component. Besides
359// the notifications above NOTIFICATION_COMPONENT_UPDATE_FOUND and
360// NOTIFICATION_COMPONENT_UPDATE_READY should have been fired. We do two loops
361// so the second time around there should be nothing left to do.
362// We also check that only 3 non-ping network requests are issued:
363// 1- manifest check
364// 2- download crx
365// 3- second manifest check.
366TEST_F(ComponentUpdaterTest, InstallCrx) {
367  std::map<std::string, std::string> map;
368  map.insert(std::pair<std::string, std::string>("eventtype", "\"3\""));
369  map.insert(std::pair<std::string, std::string>("eventresult", "\"1\""));
370  map.insert(std::pair<std::string, std::string>("previousversion",
371                                                 "\"0.9\""));
372  map.insert(std::pair<std::string, std::string>("nextversion", "\"1.0\""));
373  PingChecker ping_checker(map);
374  URLRequestPostInterceptor post_interceptor(&ping_checker);
375  content::URLLocalHostRequestPrepackagedInterceptor interceptor;
376
377  MockComponentObserver observer1;
378  {
379    InSequence seq;
380    EXPECT_CALL(observer1,
381                OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
382                .Times(1);
383    EXPECT_CALL(observer1,
384                OnEvent(ComponentObserver::COMPONENT_UPDATE_FOUND, 0))
385                .Times(1);
386    EXPECT_CALL(observer1,
387                OnEvent(ComponentObserver::COMPONENT_UPDATE_READY, 0))
388                .Times(1);
389    EXPECT_CALL(observer1,
390                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
391                .Times(2);
392  }
393
394  MockComponentObserver observer2;
395  {
396    InSequence seq;
397    EXPECT_CALL(observer2,
398                OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
399                .Times(1);
400    EXPECT_CALL(observer2,
401                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
402                .Times(2);
403  }
404
405  TestInstaller installer1;
406  CrxComponent com1;
407  com1.observer = &observer1;
408  RegisterComponent(&com1, kTestComponent_jebg, Version("0.9"), &installer1);
409  TestInstaller installer2;
410  CrxComponent com2;
411  com2.observer = &observer2;
412  RegisterComponent(&com2, kTestComponent_abag, Version("2.2"), &installer2);
413
414  const GURL expected_update_url_1(
415      "http://localhost/upd?extra=foo"
416      "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26fp%3D%26uc"
417      "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc");
418
419  const GURL expected_update_url_2(
420      "http://localhost/upd?extra=foo"
421      "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc"
422      "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D1.0%26fp%3D%26uc");
423
424  interceptor.SetResponse(expected_update_url_1,
425                          test_file("updatecheck_reply_1.xml"));
426  interceptor.SetResponse(expected_update_url_2,
427                          test_file("updatecheck_reply_1.xml"));
428  interceptor.SetResponse(GURL(expected_crx_url),
429                          test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
430
431  test_configurator()->SetLoopCount(2);
432
433  component_updater()->Start();
434  message_loop_.Run();
435
436  EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error());
437  EXPECT_EQ(1, static_cast<TestInstaller*>(com1.installer)->install_count());
438  EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error());
439  EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->install_count());
440
441  EXPECT_EQ(3, interceptor.GetHitCount());
442  EXPECT_EQ(1, ping_checker.NumHits());
443  EXPECT_EQ(0, ping_checker.NumMisses());
444
445  ASSERT_EQ(5ul, notification_tracker().size());
446
447  TestNotificationTracker::Event ev0 = notification_tracker().at(0);
448  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev0.type);
449
450  TestNotificationTracker::Event ev1 = notification_tracker().at(1);
451  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND, ev1.type);
452
453  TestNotificationTracker::Event ev2 = notification_tracker().at(2);
454  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_READY, ev2.type);
455
456  TestNotificationTracker::Event ev3 = notification_tracker().at(3);
457  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev3.type);
458
459  TestNotificationTracker::Event ev4 = notification_tracker().at(4);
460  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev4.type);
461
462  component_updater()->Stop();
463}
464
465// This test checks that the "prodversionmin" value is handled correctly. In
466// particular there should not be an install because the minimum product
467// version is much higher than of chrome.
468TEST_F(ComponentUpdaterTest, ProdVersionCheck) {
469  std::map<std::string, std::string> map;
470  PingChecker ping_checker(map);
471  URLRequestPostInterceptor post_interceptor(&ping_checker);
472  content::URLLocalHostRequestPrepackagedInterceptor interceptor;
473
474  TestInstaller installer;
475  CrxComponent com;
476  RegisterComponent(&com, kTestComponent_jebg, Version("0.9"), &installer);
477
478  const GURL expected_update_url(
479      "http://localhost/upd?extra=foo&x=id%3D"
480      "jebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26fp%3D%26uc");
481
482  interceptor.SetResponse(expected_update_url,
483                          test_file("updatecheck_reply_2.xml"));
484  interceptor.SetResponse(GURL(expected_crx_url),
485                          test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
486
487  test_configurator()->SetLoopCount(1);
488  component_updater()->Start();
489  message_loop_.Run();
490
491  EXPECT_EQ(0, ping_checker.NumHits());
492  EXPECT_EQ(0, ping_checker.NumMisses());
493  EXPECT_EQ(1, interceptor.GetHitCount());
494  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
495  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count());
496
497  component_updater()->Stop();
498}
499
500// Test that a ping for an update check can cause installs.
501// Here is the timeline:
502//  - First loop: we return a reply that indicates no update, so
503//    nothing happens.
504//  - We ping.
505//  - This triggers a second loop, which has a reply that triggers an install.
506TEST_F(ComponentUpdaterTest, CheckForUpdateSoon) {
507  std::map<std::string, std::string> map;
508  map.insert(std::pair<std::string, std::string>("eventtype", "\"3\""));
509  map.insert(std::pair<std::string, std::string>("eventresult", "\"1\""));
510  map.insert(std::pair<std::string, std::string>("previousversion",
511                                                 "\"0.9\""));
512  map.insert(std::pair<std::string, std::string>("nextversion", "\"1.0\""));
513  PingChecker ping_checker(map);
514  URLRequestPostInterceptor post_interceptor(&ping_checker);
515  content::URLLocalHostRequestPrepackagedInterceptor interceptor;
516
517  MockComponentObserver observer1;
518  {
519    InSequence seq;
520    EXPECT_CALL(observer1,
521                OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
522                .Times(1);
523    EXPECT_CALL(observer1,
524                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
525                .Times(1);
526    EXPECT_CALL(observer1,
527                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
528                .Times(1);
529  }
530
531  MockComponentObserver observer2;
532  {
533    InSequence seq;
534    EXPECT_CALL(observer2,
535                OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
536                .Times(1);
537    EXPECT_CALL(observer2,
538                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
539                .Times(1);
540    EXPECT_CALL(observer2,
541                OnEvent(ComponentObserver::COMPONENT_UPDATE_FOUND, 0))
542                .Times(1);
543    EXPECT_CALL(observer2,
544                OnEvent(ComponentObserver::COMPONENT_UPDATE_READY, 0))
545                .Times(1);
546    EXPECT_CALL(observer2,
547                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
548                .Times(1);
549  }
550
551  TestInstaller installer1;
552  CrxComponent com1;
553  com1.observer = &observer1;
554  RegisterComponent(&com1, kTestComponent_abag, Version("2.2"), &installer1);
555  TestInstaller installer2;
556  CrxComponent com2;
557  com2.observer = &observer2;
558  RegisterComponent(&com2, kTestComponent_jebg, Version("0.9"), &installer2);
559
560  const GURL expected_update_url_1(
561      "http://localhost/upd?extra=foo"
562      "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc"
563      "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26fp%3D%26uc");
564
565  const GURL expected_update_url_2(
566      "http://localhost/upd?extra=foo"
567      "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26fp%3D%26uc"
568      "%26installsource%3Dondemand"
569      "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc");
570
571  interceptor.SetResponse(expected_update_url_1,
572                          test_file("updatecheck_reply_empty"));
573  interceptor.SetResponse(expected_update_url_2,
574                          test_file("updatecheck_reply_1.xml"));
575  interceptor.SetResponse(GURL(expected_crx_url),
576                          test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
577  // Test success.
578  test_configurator()->SetLoopCount(2);
579  test_configurator()->AddComponentToCheck(&com2, 1);
580  component_updater()->Start();
581  message_loop_.Run();
582
583  EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error());
584  EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->install_count());
585  EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error());
586  EXPECT_EQ(1, static_cast<TestInstaller*>(com2.installer)->install_count());
587
588  EXPECT_EQ(3, interceptor.GetHitCount());
589
590  ASSERT_EQ(5ul, notification_tracker().size());
591
592  TestNotificationTracker::Event ev0= notification_tracker().at(0);
593  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev0.type);
594
595  TestNotificationTracker::Event ev1 = notification_tracker().at(1);
596  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev1.type);
597
598  TestNotificationTracker::Event ev2 = notification_tracker().at(2);
599  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND, ev2.type);
600
601  TestNotificationTracker::Event ev3 = notification_tracker().at(3);
602  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_READY, ev3.type);
603
604  TestNotificationTracker::Event ev4 = notification_tracker().at(4);
605  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev4.type);
606
607  // Also check what happens if previous check too soon.
608  test_configurator()->SetOnDemandTime(60 * 60);
609  EXPECT_EQ(ComponentUpdateService::kError,
610            component_updater()->CheckForUpdateSoon(com2));
611  // Okay, now reset to 0 for the other tests.
612  test_configurator()->SetOnDemandTime(0);
613  component_updater()->Stop();
614
615  // Test a few error cases. NOTE: We don't have callbacks for
616  // when the updates failed yet.
617  EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer1));
618  {
619    InSequence seq;
620    EXPECT_CALL(observer1,
621                OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
622                .Times(1);
623    EXPECT_CALL(observer1,
624                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
625                .Times(1);
626  }
627  EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer2));
628  {
629    InSequence seq;
630    EXPECT_CALL(observer2,
631                OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
632                .Times(1);
633    EXPECT_CALL(observer2,
634                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
635                .Times(1);
636  }
637
638  const GURL expected_update_url_3(
639      "http://localhost/upd?extra=foo"
640      "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D1.0%26fp%3D%26uc"
641      "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc");
642
643  // No update: error from no server response
644  interceptor.SetResponse(expected_update_url_3,
645                          test_file("updatecheck_reply_empty"));
646  notification_tracker().Reset();
647  test_configurator()->SetLoopCount(1);
648  component_updater()->Start();
649  EXPECT_EQ(ComponentUpdateService::kOk,
650            component_updater()->CheckForUpdateSoon(com2));
651
652  message_loop_.Run();
653
654  ASSERT_EQ(2ul, notification_tracker().size());
655  ev0 = notification_tracker().at(0);
656  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev0.type);
657  ev1 = notification_tracker().at(1);
658  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev1.type);
659  component_updater()->Stop();
660
661  // No update: already updated to 1.0 so nothing new
662  EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer1));
663  {
664    InSequence seq;
665    EXPECT_CALL(observer1,
666                OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
667                .Times(1);
668    EXPECT_CALL(observer1,
669                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
670                .Times(1);
671  }
672  EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer2));
673  {
674    InSequence seq;
675    EXPECT_CALL(observer2,
676                OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
677                .Times(1);
678    EXPECT_CALL(observer2,
679                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
680                .Times(1);
681  }
682
683  interceptor.SetResponse(expected_update_url_3,
684                          test_file("updatecheck_reply_1.xml"));
685  notification_tracker().Reset();
686  test_configurator()->SetLoopCount(1);
687  component_updater()->Start();
688  EXPECT_EQ(ComponentUpdateService::kOk,
689            component_updater()->CheckForUpdateSoon(com2));
690
691  message_loop_.Run();
692
693  EXPECT_EQ(1, ping_checker.NumHits());
694  EXPECT_EQ(0, ping_checker.NumMisses());
695  ASSERT_EQ(2ul, notification_tracker().size());
696  ev0 = notification_tracker().at(0);
697  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev0.type);
698  ev1 = notification_tracker().at(1);
699  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev1.type);
700  component_updater()->Stop();
701}
702
703// Verify that a previously registered component can get re-registered
704// with a different version.
705TEST_F(ComponentUpdaterTest, CheckReRegistration) {
706  std::map<std::string, std::string> map;
707  map.insert(std::pair<std::string, std::string>("eventtype", "\"3\""));
708  map.insert(std::pair<std::string, std::string>("eventresult", "\"1\""));
709  map.insert(std::pair<std::string, std::string>("previousversion",
710                                                 "\"0.9\""));
711  map.insert(std::pair<std::string, std::string>("nextversion", "\"1.0\""));
712  PingChecker ping_checker(map);
713  URLRequestPostInterceptor post_interceptor(&ping_checker);
714  content::URLLocalHostRequestPrepackagedInterceptor interceptor;
715
716  MockComponentObserver observer1;
717  {
718    InSequence seq;
719    EXPECT_CALL(observer1,
720                OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
721                .Times(1);
722    EXPECT_CALL(observer1,
723                OnEvent(ComponentObserver::COMPONENT_UPDATE_FOUND, 0))
724                .Times(1);
725    EXPECT_CALL(observer1,
726                OnEvent(ComponentObserver::COMPONENT_UPDATE_READY, 0))
727                .Times(1);
728    EXPECT_CALL(observer1,
729                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
730                .Times(1);
731    EXPECT_CALL(observer1,
732                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
733                .Times(1);
734  }
735
736  MockComponentObserver observer2;
737  {
738    InSequence seq;
739    EXPECT_CALL(observer2,
740                OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
741                .Times(1);
742    EXPECT_CALL(observer2,
743                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
744                .Times(1);
745    EXPECT_CALL(observer2,
746                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
747                .Times(1);
748  }
749
750  TestInstaller installer1;
751  CrxComponent com1;
752  com1.observer = &observer1;
753  RegisterComponent(&com1, kTestComponent_jebg, Version("0.9"), &installer1);
754  TestInstaller installer2;
755  CrxComponent com2;
756  com2.observer = &observer2;
757  RegisterComponent(&com2, kTestComponent_abag, Version("2.2"), &installer2);
758
759  // Start with 0.9, and update to 1.0
760  const GURL expected_update_url_1(
761      "http://localhost/upd?extra=foo"
762      "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26fp%3D%26uc"
763      "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc");
764
765  const GURL expected_update_url_2(
766      "http://localhost/upd?extra=foo"
767      "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc"
768      "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D1.0%26fp%3D%26uc");
769
770  interceptor.SetResponse(expected_update_url_1,
771                          test_file("updatecheck_reply_1.xml"));
772  interceptor.SetResponse(expected_update_url_2,
773                          test_file("updatecheck_reply_1.xml"));
774  interceptor.SetResponse(GURL(expected_crx_url),
775                          test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
776
777  // Loop twice to issue two checks: (1) with original 0.9 version
778  // and (2) with the updated 1.0 version.
779  test_configurator()->SetLoopCount(2);
780
781  component_updater()->Start();
782  message_loop_.Run();
783
784  EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error());
785  EXPECT_EQ(1, static_cast<TestInstaller*>(com1.installer)->install_count());
786  EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error());
787  EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->install_count());
788
789  EXPECT_EQ(1, ping_checker.NumHits());
790  EXPECT_EQ(0, ping_checker.NumMisses());
791  EXPECT_EQ(3, interceptor.GetHitCount());
792
793  ASSERT_EQ(5ul, notification_tracker().size());
794
795  TestNotificationTracker::Event ev0 = notification_tracker().at(0);
796  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev0.type);
797
798  TestNotificationTracker::Event ev1 = notification_tracker().at(1);
799  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND, ev1.type);
800
801  TestNotificationTracker::Event ev2 = notification_tracker().at(2);
802  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_READY, ev2.type);
803
804  TestNotificationTracker::Event ev3 = notification_tracker().at(3);
805  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev3.type);
806
807  TestNotificationTracker::Event ev4 = notification_tracker().at(4);
808  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev4.type);
809
810  component_updater()->Stop();
811
812  // Now re-register, pretending to be an even newer version (2.2)
813  EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer1));
814  {
815    InSequence seq;
816    EXPECT_CALL(observer1,
817                OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
818                .Times(1);
819    EXPECT_CALL(observer1,
820                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
821                .Times(1);
822  }
823
824  EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer2));
825  {
826    InSequence seq;
827    EXPECT_CALL(observer2,
828                OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
829                .Times(1);
830    EXPECT_CALL(observer2,
831                OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
832                .Times(1);
833  }
834
835  TestInstaller installer3;
836  EXPECT_EQ(ComponentUpdateService::kReplaced,
837            RegisterComponent(&com1,
838                              kTestComponent_jebg,
839                              Version("2.2"),
840                              &installer3));
841
842  // Check that we send out 2.2 as our version.
843  // Interceptor's hit count should go up by 1.
844  const GURL expected_update_url_3(
845      "http://localhost/upd?extra=foo"
846      "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D2.2%26fp%3D%26uc"
847      "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc");
848
849  interceptor.SetResponse(expected_update_url_3,
850                          test_file("updatecheck_reply_1.xml"));
851
852  notification_tracker().Reset();
853
854  // Loop once just to notice the check happening with the re-register version.
855  test_configurator()->SetLoopCount(1);
856  component_updater()->Start();
857  message_loop_.Run();
858
859  ASSERT_EQ(2ul, notification_tracker().size());
860
861  ev0 = notification_tracker().at(0);
862  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev0.type);
863
864  ev1 = notification_tracker().at(1);
865  EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev1.type);
866
867  EXPECT_EQ(4, interceptor.GetHitCount());
868
869  // We created a new installer, so the counts go back to 0.
870  EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error());
871  EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->install_count());
872  EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error());
873  EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->install_count());
874
875  component_updater()->Stop();
876}
877
878// Verify that we can download and install a component and a differential
879// update to that component. We do three loops; the final loop should do
880// nothing.
881// We also check that exactly 5 non-ping network requests are issued:
882// 1- update check (response: v1 available)
883// 2- download crx (v1)
884// 3- update check (response: v2 available)
885// 4- download differential crx (v1 to v2)
886// 5- update check (response: no further update available)
887// There should be two pings, one for each update. The second will bear a
888// diffresult=1, while the first will not.
889TEST_F(ComponentUpdaterTest, DifferentialUpdate) {
890  std::map<std::string, std::string> map;
891  map.insert(std::pair<std::string, std::string>("eventtype", "\"3\""));
892  map.insert(std::pair<std::string, std::string>("eventresult", "\"1\""));
893  map.insert(std::pair<std::string, std::string>("diffresult", "\"1\""));
894  PingChecker ping_checker(map);
895  URLRequestPostInterceptor post_interceptor(&ping_checker);
896  content::URLLocalHostRequestPrepackagedInterceptor interceptor;
897
898  VersionedTestInstaller installer;
899  CrxComponent com;
900  RegisterComponent(&com, kTestComponent_ihfo, Version("0.0"), &installer);
901
902  const GURL expected_update_url_0(
903      "http://localhost/upd?extra=foo"
904      "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D0.0%26fp%3D%26uc");
905  const GURL expected_update_url_1(
906      "http://localhost/upd?extra=foo"
907      "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D1.0%26fp%3D1%26uc");
908  const GURL expected_update_url_2(
909      "http://localhost/upd?extra=foo"
910      "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D2.0%26fp%3Df22%26uc");
911  const GURL expected_crx_url_1(
912      "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx");
913  const GURL expected_crx_url_1_diff_2(
914      "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx");
915
916  interceptor.SetResponse(expected_update_url_0,
917                          test_file("updatecheck_diff_reply_1.xml"));
918  interceptor.SetResponse(expected_update_url_1,
919                          test_file("updatecheck_diff_reply_2.xml"));
920  interceptor.SetResponse(expected_update_url_2,
921                          test_file("updatecheck_diff_reply_3.xml"));
922  interceptor.SetResponse(expected_crx_url_1,
923                          test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"));
924  interceptor.SetResponse(
925      expected_crx_url_1_diff_2,
926      test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"));
927
928  test_configurator()->SetLoopCount(3);
929
930  component_updater()->Start();
931  message_loop_.Run();
932
933  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
934  EXPECT_EQ(2, static_cast<TestInstaller*>(com.installer)->install_count());
935
936  // One ping has the diffresult=1, the other does not.
937  EXPECT_EQ(1, ping_checker.NumHits());
938  EXPECT_EQ(1, ping_checker.NumMisses());
939
940  EXPECT_EQ(5, interceptor.GetHitCount());
941
942  component_updater()->Stop();
943}
944
945// Verify that component installation falls back to downloading and installing
946// a full update if the differential update fails (in this case, because the
947// installer does not know about the existing files). We do two loops; the final
948// loop should do nothing.
949// We also check that exactly 4 non-ping network requests are issued:
950// 1- update check (loop 1)
951// 2- download differential crx
952// 3- download full crx
953// 4- update check (loop 2 - no update available)
954// There should be one ping for the first attempted update.
955
956TEST_F(ComponentUpdaterTest, DifferentialUpdateFails) {
957
958  std::map<std::string, std::string> map;
959  map.insert(std::pair<std::string, std::string>("eventtype", "\"3\""));
960  map.insert(std::pair<std::string, std::string>("eventresult", "\"1\""));
961  map.insert(std::pair<std::string, std::string>("diffresult", "\"0\""));
962  map.insert(std::pair<std::string, std::string>("differrorcode", "\"16\""));
963  PingChecker ping_checker(map);
964  URLRequestPostInterceptor post_interceptor(&ping_checker);
965  content::URLLocalHostRequestPrepackagedInterceptor interceptor;
966
967  TestInstaller installer;
968  CrxComponent com;
969  RegisterComponent(&com, kTestComponent_ihfo, Version("1.0"), &installer);
970
971  const GURL expected_update_url_1(
972      "http://localhost/upd?extra=foo"
973      "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D1.0%26fp%3D%26uc");
974  const GURL expected_update_url_2(
975      "http://localhost/upd?extra=foo"
976      "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D2.0%26fp%3Df22%26uc");
977  const GURL expected_crx_url_1(
978      "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx");
979  const GURL expected_crx_url_1_diff_2(
980      "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx");
981  const GURL expected_crx_url_2(
982      "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx");
983
984  interceptor.SetResponse(expected_update_url_1,
985                          test_file("updatecheck_diff_reply_2.xml"));
986  interceptor.SetResponse(expected_update_url_2,
987                          test_file("updatecheck_diff_reply_3.xml"));
988  interceptor.SetResponse(expected_crx_url_1,
989                          test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"));
990  interceptor.SetResponse(
991      expected_crx_url_1_diff_2,
992      test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"));
993  interceptor.SetResponse(expected_crx_url_2,
994                          test_file("ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"));
995
996  test_configurator()->SetLoopCount(2);
997
998  component_updater()->Start();
999  message_loop_.Run();
1000
1001  // A failed differential update does not count as a failed install.
1002  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
1003  EXPECT_EQ(1, static_cast<TestInstaller*>(com.installer)->install_count());
1004
1005  EXPECT_EQ(1, ping_checker.NumHits());
1006  EXPECT_EQ(0, ping_checker.NumMisses());
1007  EXPECT_EQ(4, interceptor.GetHitCount());
1008
1009  component_updater()->Stop();
1010}
1011
1012// Verify that a failed installation causes an install failure ping.
1013TEST_F(ComponentUpdaterTest, CheckFailedInstallPing) {
1014  std::map<std::string, std::string> map;
1015  map.insert(std::pair<std::string, std::string>("eventtype", "\"3\""));
1016  map.insert(std::pair<std::string, std::string>("eventresult", "\"0\""));
1017  map.insert(std::pair<std::string, std::string>("errorcode", "\"9\""));
1018  map.insert(std::pair<std::string, std::string>("previousversion",
1019                                                 "\"0.9\""));
1020  map.insert(std::pair<std::string, std::string>("nextversion", "\"1.0\""));
1021  PingChecker ping_checker(map);
1022  URLRequestPostInterceptor post_interceptor(&ping_checker);
1023  content::URLLocalHostRequestPrepackagedInterceptor interceptor;
1024
1025  // This test installer reports installation failure.
1026  class : public TestInstaller {
1027    virtual bool Install(const base::DictionaryValue& manifest,
1028                         const base::FilePath& unpack_path) OVERRIDE {
1029      ++install_count_;
1030      base::DeleteFile(unpack_path, true);
1031      return false;
1032    }
1033  } installer;
1034
1035  CrxComponent com;
1036  RegisterComponent(&com, kTestComponent_jebg, Version("0.9"), &installer);
1037
1038  // Start with 0.9, and attempt update to 1.0
1039  const GURL expected_update_url_1(
1040      "http://localhost/upd?extra=foo"
1041      "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26fp%3D%26uc");
1042
1043  interceptor.SetResponse(expected_update_url_1,
1044                          test_file("updatecheck_reply_1.xml"));
1045  interceptor.SetResponse(GURL(expected_crx_url),
1046                          test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
1047
1048  // Loop twice to issue two checks: (1) with original 0.9 version
1049  // and (2), which should retry with 0.9.
1050  test_configurator()->SetLoopCount(2);
1051  component_updater()->Start();
1052  message_loop_.Run();
1053
1054  // Loop once more, but expect no ping because a noupdate response is issued.
1055  // This is necessary to clear out the fire-and-forget ping from the previous
1056  // iteration.
1057  interceptor.SetResponse(expected_update_url_1,
1058                          test_file("updatecheck_reply_noupdate.xml"));
1059  test_configurator()->SetLoopCount(1);
1060  component_updater()->Start();
1061  message_loop_.Run();
1062
1063  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
1064  EXPECT_EQ(2, static_cast<TestInstaller*>(com.installer)->install_count());
1065
1066  EXPECT_EQ(2, ping_checker.NumHits());
1067  EXPECT_EQ(0, ping_checker.NumMisses());
1068  EXPECT_EQ(5, interceptor.GetHitCount());
1069
1070  component_updater()->Stop();
1071}
1072
1073// Verify that we successfully propagate a patcher error.
1074// ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad.crx contains an incorrect
1075// patching instruction that should fail.
1076TEST_F(ComponentUpdaterTest, DifferentialUpdateFailErrorcode) {
1077  std::map<std::string, std::string> map;
1078  map.insert(std::pair<std::string, std::string>("eventtype", "\"3\""));
1079  map.insert(std::pair<std::string, std::string>("eventresult", "\"1\""));
1080  map.insert(std::pair<std::string, std::string>("diffresult", "\"0\""));
1081  map.insert(std::pair<std::string, std::string>("differrorcode", "\"14\""));
1082  map.insert(std::pair<std::string, std::string>("diffextracode1", "\"305\""));
1083  PingChecker ping_checker(map);
1084  URLRequestPostInterceptor post_interceptor(&ping_checker);
1085  content::URLLocalHostRequestPrepackagedInterceptor interceptor;
1086
1087  VersionedTestInstaller installer;
1088  CrxComponent com;
1089  RegisterComponent(&com, kTestComponent_ihfo, Version("0.0"), &installer);
1090
1091  const GURL expected_update_url_0(
1092      "http://localhost/upd?extra=foo"
1093      "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D0.0%26fp%3D%26uc");
1094  const GURL expected_update_url_1(
1095      "http://localhost/upd?extra=foo"
1096      "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D1.0%26fp%3D1%26uc");
1097  const GURL expected_update_url_2(
1098      "http://localhost/upd?extra=foo"
1099      "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D2.0%26fp%3Df22%26uc");
1100  const GURL expected_crx_url_1(
1101      "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx");
1102  const GURL expected_crx_url_1_diff_2(
1103      "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx");
1104  const GURL expected_crx_url_2(
1105      "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx");
1106
1107  interceptor.SetResponse(expected_update_url_0,
1108                          test_file("updatecheck_diff_reply_1.xml"));
1109  interceptor.SetResponse(expected_update_url_1,
1110                          test_file("updatecheck_diff_reply_2.xml"));
1111  interceptor.SetResponse(expected_update_url_2,
1112                          test_file("updatecheck_diff_reply_3.xml"));
1113  interceptor.SetResponse(expected_crx_url_1,
1114                          test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"));
1115  interceptor.SetResponse(
1116      expected_crx_url_1_diff_2,
1117      test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad.crx"));
1118  interceptor.SetResponse(expected_crx_url_2,
1119                          test_file("ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"));
1120
1121  test_configurator()->SetLoopCount(3);
1122
1123  component_updater()->Start();
1124  message_loop_.Run();
1125
1126  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
1127  EXPECT_EQ(2, static_cast<TestInstaller*>(com.installer)->install_count());
1128
1129  EXPECT_EQ(1, ping_checker.NumHits());
1130  EXPECT_EQ(1, ping_checker.NumMisses());
1131  EXPECT_EQ(6, interceptor.GetHitCount());
1132
1133  component_updater()->Stop();
1134}
1135