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