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