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