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