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