Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / safe_browsing / protocol_manager_unittest.cc
blob22854f6882015164fa52ee82f0cbea85978ef754
1 // Copyright (c) 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 //
6 #include "base/strings/stringprintf.h"
7 #include "base/test/test_simple_task_runner.h"
8 #include "base/thread_task_runner_handle.h"
9 #include "base/time/time.h"
10 #include "chrome/browser/safe_browsing/protocol_manager.h"
11 #include "google_apis/google_api_keys.h"
12 #include "net/base/escape.h"
13 #include "net/base/load_flags.h"
14 #include "net/base/net_errors.h"
15 #include "net/url_request/test_url_fetcher_factory.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gmock_mutant.h"
18 #include "testing/gtest/include/gtest/gtest.h"
20 using base::Time;
21 using base::TimeDelta;
22 using testing::_;
23 using testing::Invoke;
25 static const char kUrlPrefix[] = "https://prefix.com/foo";
26 static const char kBackupConnectUrlPrefix[] = "https://alt1-prefix.com/foo";
27 static const char kBackupHttpUrlPrefix[] = "https://alt2-prefix.com/foo";
28 static const char kBackupNetworkUrlPrefix[] = "https://alt3-prefix.com/foo";
29 static const char kClient[] = "unittest";
30 static const char kAppVer[] = "1.0";
31 static const char kAdditionalQuery[] = "additional_query";
33 class SafeBrowsingProtocolManagerTest : public testing::Test {
34 protected:
35 std::string key_param_;
37 virtual void SetUp() {
38 std::string key = google_apis::GetAPIKey();
39 if (!key.empty()) {
40 key_param_ = base::StringPrintf(
41 "&key=%s",
42 net::EscapeQueryParamValue(key, true).c_str());
46 scoped_ptr<SafeBrowsingProtocolManager> CreateProtocolManager(
47 SafeBrowsingProtocolManagerDelegate* delegate) {
48 SafeBrowsingProtocolConfig config;
49 config.client_name = kClient;
50 config.url_prefix = kUrlPrefix;
51 config.backup_connect_error_url_prefix = kBackupConnectUrlPrefix;
52 config.backup_http_error_url_prefix = kBackupHttpUrlPrefix;
53 config.backup_network_error_url_prefix = kBackupNetworkUrlPrefix;
54 config.version = kAppVer;
56 return scoped_ptr<SafeBrowsingProtocolManager>(
57 SafeBrowsingProtocolManager::Create(delegate, NULL, config));
60 void ValidateUpdateFetcherRequest(
61 const net::TestURLFetcher* url_fetcher,
62 const std::string& expected_prefix) {
63 ASSERT_TRUE(url_fetcher);
64 EXPECT_EQ(net::LOAD_DISABLE_CACHE, url_fetcher->GetLoadFlags());
65 EXPECT_EQ("goog-phish-shavar;\ngoog-malware-shavar;\n",
66 url_fetcher->upload_data());
67 EXPECT_EQ(GURL(expected_prefix + "/downloads?client=unittest&appver=1.0"
68 "&pver=2.2" + key_param_),
69 url_fetcher->GetOriginalURL());
72 void ValidateUpdateFetcherRequest(const net::TestURLFetcher* url_fetcher) {
73 ValidateUpdateFetcherRequest(url_fetcher, kUrlPrefix);
76 void ValidateRedirectFetcherRequest(const net::TestURLFetcher* url_fetcher,
77 const std::string& expected_url) {
78 ASSERT_TRUE(url_fetcher);
79 EXPECT_EQ(net::LOAD_DISABLE_CACHE, url_fetcher->GetLoadFlags());
80 EXPECT_EQ("", url_fetcher->upload_data());
81 EXPECT_EQ(GURL(expected_url), url_fetcher->GetOriginalURL());
85 // Ensure that we respect section 5 of the SafeBrowsing protocol specification.
86 TEST_F(SafeBrowsingProtocolManagerTest, TestBackOffTimes) {
87 scoped_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL));
89 pm->next_update_interval_ = TimeDelta::FromSeconds(1800);
90 ASSERT_TRUE(pm->back_off_fuzz_ >= 0.0 && pm->back_off_fuzz_ <= 1.0);
92 TimeDelta next;
94 // No errors received so far.
95 next = pm->GetNextUpdateInterval(false);
96 EXPECT_EQ(next, TimeDelta::FromSeconds(1800));
98 // 1 error.
99 next = pm->GetNextUpdateInterval(true);
100 EXPECT_EQ(next, TimeDelta::FromSeconds(60));
102 // 2 errors.
103 next = pm->GetNextUpdateInterval(true);
104 EXPECT_TRUE(next >= TimeDelta::FromMinutes(30) &&
105 next <= TimeDelta::FromMinutes(60));
107 // 3 errors.
108 next = pm->GetNextUpdateInterval(true);
109 EXPECT_TRUE(next >= TimeDelta::FromMinutes(60) &&
110 next <= TimeDelta::FromMinutes(120));
112 // 4 errors.
113 next = pm->GetNextUpdateInterval(true);
114 EXPECT_TRUE(next >= TimeDelta::FromMinutes(120) &&
115 next <= TimeDelta::FromMinutes(240));
117 // 5 errors.
118 next = pm->GetNextUpdateInterval(true);
119 EXPECT_TRUE(next >= TimeDelta::FromMinutes(240) &&
120 next <= TimeDelta::FromMinutes(480));
122 // 6 errors, reached max backoff.
123 next = pm->GetNextUpdateInterval(true);
124 EXPECT_EQ(next, TimeDelta::FromMinutes(480));
126 // 7 errors.
127 next = pm->GetNextUpdateInterval(true);
128 EXPECT_EQ(next, TimeDelta::FromMinutes(480));
130 // Received a successful response.
131 next = pm->GetNextUpdateInterval(false);
132 EXPECT_EQ(next, TimeDelta::FromSeconds(1800));
135 TEST_F(SafeBrowsingProtocolManagerTest, TestChunkStrings) {
136 scoped_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL));
138 // Add and Sub chunks.
139 SBListChunkRanges phish("goog-phish-shavar");
140 phish.adds = "1,4,6,8-20,99";
141 phish.subs = "16,32,64-96";
142 EXPECT_EQ(pm->FormatList(phish),
143 "goog-phish-shavar;a:1,4,6,8-20,99:s:16,32,64-96\n");
145 // Add chunks only.
146 phish.subs = "";
147 EXPECT_EQ(pm->FormatList(phish), "goog-phish-shavar;a:1,4,6,8-20,99\n");
149 // Sub chunks only.
150 phish.adds = "";
151 phish.subs = "16,32,64-96";
152 EXPECT_EQ(pm->FormatList(phish), "goog-phish-shavar;s:16,32,64-96\n");
154 // No chunks of either type.
155 phish.adds = "";
156 phish.subs = "";
157 EXPECT_EQ(pm->FormatList(phish), "goog-phish-shavar;\n");
160 TEST_F(SafeBrowsingProtocolManagerTest, TestGetHashBackOffTimes) {
161 scoped_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL));
163 // No errors or back off time yet.
164 EXPECT_EQ(pm->gethash_error_count_, 0);
165 EXPECT_TRUE(pm->next_gethash_time_.is_null());
167 Time now = Time::Now();
169 // 1 error.
170 pm->HandleGetHashError(now);
171 EXPECT_EQ(pm->gethash_error_count_, 1);
172 TimeDelta margin = TimeDelta::FromSeconds(5); // Fudge factor.
173 Time future = now + TimeDelta::FromMinutes(1);
174 EXPECT_TRUE(pm->next_gethash_time_ >= future - margin &&
175 pm->next_gethash_time_ <= future + margin);
177 // 2 errors.
178 pm->HandleGetHashError(now);
179 EXPECT_EQ(pm->gethash_error_count_, 2);
180 EXPECT_TRUE(pm->next_gethash_time_ >= now + TimeDelta::FromMinutes(30));
181 EXPECT_TRUE(pm->next_gethash_time_ <= now + TimeDelta::FromMinutes(60));
183 // 3 errors.
184 pm->HandleGetHashError(now);
185 EXPECT_EQ(pm->gethash_error_count_, 3);
186 EXPECT_TRUE(pm->next_gethash_time_ >= now + TimeDelta::FromMinutes(60));
187 EXPECT_TRUE(pm->next_gethash_time_ <= now + TimeDelta::FromMinutes(120));
189 // 4 errors.
190 pm->HandleGetHashError(now);
191 EXPECT_EQ(pm->gethash_error_count_, 4);
192 EXPECT_TRUE(pm->next_gethash_time_ >= now + TimeDelta::FromMinutes(120));
193 EXPECT_TRUE(pm->next_gethash_time_ <= now + TimeDelta::FromMinutes(240));
195 // 5 errors.
196 pm->HandleGetHashError(now);
197 EXPECT_EQ(pm->gethash_error_count_, 5);
198 EXPECT_TRUE(pm->next_gethash_time_ >= now + TimeDelta::FromMinutes(240));
199 EXPECT_TRUE(pm->next_gethash_time_ <= now + TimeDelta::FromMinutes(480));
201 // 6 errors, reached max backoff.
202 pm->HandleGetHashError(now);
203 EXPECT_EQ(pm->gethash_error_count_, 6);
204 EXPECT_TRUE(pm->next_gethash_time_ == now + TimeDelta::FromMinutes(480));
206 // 7 errors.
207 pm->HandleGetHashError(now);
208 EXPECT_EQ(pm->gethash_error_count_, 7);
209 EXPECT_TRUE(pm->next_gethash_time_== now + TimeDelta::FromMinutes(480));
212 TEST_F(SafeBrowsingProtocolManagerTest, TestGetHashUrl) {
213 scoped_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL));
215 EXPECT_EQ("https://prefix.com/foo/gethash?client=unittest&appver=1.0&"
216 "pver=2.2" + key_param_, pm->GetHashUrl().spec());
218 pm->set_additional_query(kAdditionalQuery);
219 EXPECT_EQ("https://prefix.com/foo/gethash?client=unittest&appver=1.0&"
220 "pver=2.2" + key_param_ + "&additional_query",
221 pm->GetHashUrl().spec());
224 TEST_F(SafeBrowsingProtocolManagerTest, TestUpdateUrl) {
225 scoped_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL));
227 EXPECT_EQ("https://prefix.com/foo/downloads?client=unittest&appver=1.0&"
228 "pver=2.2" + key_param_, pm->UpdateUrl().spec());
230 pm->set_additional_query(kAdditionalQuery);
231 EXPECT_EQ("https://prefix.com/foo/downloads?client=unittest&appver=1.0&"
232 "pver=2.2" + key_param_ + "&additional_query",
233 pm->UpdateUrl().spec());
236 TEST_F(SafeBrowsingProtocolManagerTest, TestNextChunkUrl) {
237 scoped_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL));
239 std::string url_partial = "localhost:1234/foo/bar?foo";
240 std::string url_http_full = "http://localhost:1234/foo/bar?foo";
241 std::string url_https_full = "https://localhost:1234/foo/bar?foo";
242 std::string url_https_no_query = "https://localhost:1234/foo/bar";
244 EXPECT_EQ("https://localhost:1234/foo/bar?foo",
245 pm->NextChunkUrl(url_partial).spec());
246 EXPECT_EQ("http://localhost:1234/foo/bar?foo",
247 pm->NextChunkUrl(url_http_full).spec());
248 EXPECT_EQ("https://localhost:1234/foo/bar?foo",
249 pm->NextChunkUrl(url_https_full).spec());
250 EXPECT_EQ("https://localhost:1234/foo/bar",
251 pm->NextChunkUrl(url_https_no_query).spec());
253 pm->set_additional_query(kAdditionalQuery);
254 EXPECT_EQ("https://localhost:1234/foo/bar?foo&additional_query",
255 pm->NextChunkUrl(url_partial).spec());
256 EXPECT_EQ("http://localhost:1234/foo/bar?foo&additional_query",
257 pm->NextChunkUrl(url_http_full).spec());
258 EXPECT_EQ("https://localhost:1234/foo/bar?foo&additional_query",
259 pm->NextChunkUrl(url_https_full).spec());
260 EXPECT_EQ("https://localhost:1234/foo/bar?additional_query",
261 pm->NextChunkUrl(url_https_no_query).spec());
264 namespace {
266 class MockProtocolDelegate : public SafeBrowsingProtocolManagerDelegate {
267 public:
268 MockProtocolDelegate() {}
269 virtual ~MockProtocolDelegate() {}
271 MOCK_METHOD0(UpdateStarted, void());
272 MOCK_METHOD1(UpdateFinished, void(bool));
273 MOCK_METHOD0(ResetDatabase, void());
274 MOCK_METHOD1(GetChunks, void(GetChunksCallback));
275 MOCK_METHOD3(AddChunks, void(const std::string&, SBChunkList*,
276 AddChunksCallback));
277 MOCK_METHOD1(DeleteChunks, void(std::vector<SBChunkDelete>*));
280 // |InvokeGetChunksCallback| is required because GMock's InvokeArgument action
281 // expects to use operator(), and a Callback only provides Run().
282 // TODO(cbentzel): Use ACTION or ACTION_TEMPLATE instead?
283 void InvokeGetChunksCallback(
284 const std::vector<SBListChunkRanges>& ranges,
285 bool database_error,
286 SafeBrowsingProtocolManagerDelegate::GetChunksCallback callback) {
287 callback.Run(ranges, database_error);
290 // |HandleAddChunks| deletes the chunks and asynchronously invokes
291 // |callback| since SafeBrowsingProtocolManager is not re-entrant at the time
292 // this is called. This guarantee is part of the
293 // SafeBrowsingProtocolManagerDelegate contract.
294 void HandleAddChunks(
295 const std::string& unused_list,
296 SBChunkList* chunks,
297 SafeBrowsingProtocolManagerDelegate::AddChunksCallback callback) {
298 delete chunks;
299 scoped_refptr<base::SingleThreadTaskRunner> task_runner(
300 base::ThreadTaskRunnerHandle::Get());
301 if (!task_runner.get())
302 return;
303 task_runner->PostTask(FROM_HERE, callback);
306 } // namespace
308 // Tests that the Update protocol will be skipped if there are problems
309 // accessing the database.
310 TEST_F(SafeBrowsingProtocolManagerTest, ProblemAccessingDatabase) {
311 scoped_refptr<base::TestSimpleTaskRunner> runner(
312 new base::TestSimpleTaskRunner());
313 base::ThreadTaskRunnerHandle runner_handler(runner);
315 testing::StrictMock<MockProtocolDelegate> test_delegate;
316 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
317 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
318 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
319 std::vector<SBListChunkRanges>(),
320 true)));
321 EXPECT_CALL(test_delegate, UpdateFinished(false)).Times(1);
323 scoped_ptr<SafeBrowsingProtocolManager> pm(
324 CreateProtocolManager(&test_delegate));
326 pm->ForceScheduleNextUpdate(TimeDelta());
327 runner->RunPendingTasks();
329 EXPECT_TRUE(pm->IsUpdateScheduled());
332 // Tests the contents of the POST body when there are contents in the
333 // local database. This is not exhaustive, as the actual list formatting
334 // is covered by SafeBrowsingProtocolManagerTest.TestChunkStrings.
335 TEST_F(SafeBrowsingProtocolManagerTest, ExistingDatabase) {
336 scoped_refptr<base::TestSimpleTaskRunner> runner(
337 new base::TestSimpleTaskRunner());
338 base::ThreadTaskRunnerHandle runner_handler(runner);
339 net::TestURLFetcherFactory url_fetcher_factory;
341 std::vector<SBListChunkRanges> ranges;
342 SBListChunkRanges range_phish(safe_browsing_util::kPhishingList);
343 range_phish.adds = "adds_phish";
344 range_phish.subs = "subs_phish";
345 ranges.push_back(range_phish);
347 SBListChunkRanges range_unknown("unknown_list");
348 range_unknown.adds = "adds_unknown";
349 range_unknown.subs = "subs_unknown";
350 ranges.push_back(range_unknown);
352 testing::StrictMock<MockProtocolDelegate> test_delegate;
353 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
354 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
355 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
356 ranges,
357 false)));
358 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
360 scoped_ptr<SafeBrowsingProtocolManager> pm(
361 CreateProtocolManager(&test_delegate));
363 // Kick off initialization. This returns chunks from the DB synchronously.
364 pm->ForceScheduleNextUpdate(TimeDelta());
365 runner->RunPendingTasks();
367 // We should have an URLFetcher at this point in time.
368 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
369 ASSERT_TRUE(url_fetcher);
370 EXPECT_EQ(net::LOAD_DISABLE_CACHE, url_fetcher->GetLoadFlags());
371 EXPECT_EQ("goog-phish-shavar;a:adds_phish:s:subs_phish\n"
372 "unknown_list;a:adds_unknown:s:subs_unknown\n"
373 "goog-malware-shavar;\n",
374 url_fetcher->upload_data());
375 EXPECT_EQ(GURL("https://prefix.com/foo/downloads?client=unittest&appver=1.0"
376 "&pver=2.2" + key_param_),
377 url_fetcher->GetOriginalURL());
379 url_fetcher->set_status(net::URLRequestStatus());
380 url_fetcher->set_response_code(200);
381 url_fetcher->SetResponseString(std::string());
382 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
384 EXPECT_TRUE(pm->IsUpdateScheduled());
387 TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseBadBodyBackupSuccess) {
388 scoped_refptr<base::TestSimpleTaskRunner> runner(
389 new base::TestSimpleTaskRunner());
390 base::ThreadTaskRunnerHandle runner_handler(runner);
391 net::TestURLFetcherFactory url_fetcher_factory;
393 testing::StrictMock<MockProtocolDelegate> test_delegate;
394 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
395 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
396 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
397 std::vector<SBListChunkRanges>(),
398 false)));
399 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
401 scoped_ptr<SafeBrowsingProtocolManager> pm(
402 CreateProtocolManager(&test_delegate));
404 // Kick off initialization. This returns chunks from the DB synchronously.
405 pm->ForceScheduleNextUpdate(TimeDelta());
406 runner->RunPendingTasks();
408 // We should have an URLFetcher at this point in time.
409 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
410 ValidateUpdateFetcherRequest(url_fetcher);
412 // The update response is successful, but an invalid body.
413 url_fetcher->set_status(net::URLRequestStatus());
414 url_fetcher->set_response_code(200);
415 url_fetcher->SetResponseString("THIS_IS_A_BAD_RESPONSE");
416 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
418 // There should now be a backup request.
419 net::TestURLFetcher* backup_url_fetcher =
420 url_fetcher_factory.GetFetcherByID(1);
421 ValidateUpdateFetcherRequest(backup_url_fetcher,
422 kBackupHttpUrlPrefix);
424 // Respond to the backup successfully.
425 backup_url_fetcher->set_status(net::URLRequestStatus());
426 backup_url_fetcher->set_response_code(200);
427 backup_url_fetcher->SetResponseString(std::string());
428 backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
430 EXPECT_TRUE(pm->IsUpdateScheduled());
433 // Tests what happens when there is an HTTP error response to the update
434 // request, as well as an error response to the backup update request.
435 TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseHttpErrorBackupError) {
436 scoped_refptr<base::TestSimpleTaskRunner> runner(
437 new base::TestSimpleTaskRunner());
438 base::ThreadTaskRunnerHandle runner_handler(runner);
439 net::TestURLFetcherFactory url_fetcher_factory;
441 testing::StrictMock<MockProtocolDelegate> test_delegate;
442 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
443 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
444 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
445 std::vector<SBListChunkRanges>(),
446 false)));
447 EXPECT_CALL(test_delegate, UpdateFinished(false)).Times(1);
449 scoped_ptr<SafeBrowsingProtocolManager> pm(
450 CreateProtocolManager(&test_delegate));
452 // Kick off initialization. This returns chunks from the DB synchronously.
453 pm->ForceScheduleNextUpdate(TimeDelta());
454 runner->RunPendingTasks();
456 // We should have an URLFetcher at this point in time.
457 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
458 ValidateUpdateFetcherRequest(url_fetcher);
460 // Go ahead and respond to it.
461 url_fetcher->set_status(net::URLRequestStatus());
462 url_fetcher->set_response_code(404);
463 url_fetcher->SetResponseString(std::string());
464 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
466 // There should now be a backup request.
467 net::TestURLFetcher* backup_url_fetcher =
468 url_fetcher_factory.GetFetcherByID(1);
469 ValidateUpdateFetcherRequest(backup_url_fetcher, kBackupHttpUrlPrefix);
471 // Respond to the backup unsuccessfully.
472 backup_url_fetcher->set_status(net::URLRequestStatus());
473 backup_url_fetcher->set_response_code(404);
474 backup_url_fetcher->SetResponseString(std::string());
475 backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
477 EXPECT_TRUE(pm->IsUpdateScheduled());
480 // Tests what happens when there is an HTTP error response to the update
481 // request, followed by a successful response to the backup update request.
482 TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseHttpErrorBackupSuccess) {
483 scoped_refptr<base::TestSimpleTaskRunner> runner(
484 new base::TestSimpleTaskRunner());
485 base::ThreadTaskRunnerHandle runner_handler(runner);
486 net::TestURLFetcherFactory url_fetcher_factory;
488 testing::StrictMock<MockProtocolDelegate> test_delegate;
489 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
490 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
491 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
492 std::vector<SBListChunkRanges>(),
493 false)));
494 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
496 scoped_ptr<SafeBrowsingProtocolManager> pm(
497 CreateProtocolManager(&test_delegate));
499 // Kick off initialization. This returns chunks from the DB synchronously.
500 pm->ForceScheduleNextUpdate(TimeDelta());
501 runner->RunPendingTasks();
503 // We should have an URLFetcher at this point in time.
504 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
505 ValidateUpdateFetcherRequest(url_fetcher);
507 // Go ahead and respond to it.
508 url_fetcher->set_status(net::URLRequestStatus());
509 url_fetcher->set_response_code(404);
510 url_fetcher->SetResponseString(std::string());
511 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
513 // There should now be a backup request.
514 net::TestURLFetcher* backup_url_fetcher =
515 url_fetcher_factory.GetFetcherByID(1);
516 ValidateUpdateFetcherRequest(backup_url_fetcher,
517 kBackupHttpUrlPrefix);
519 // Respond to the backup successfully.
520 backup_url_fetcher->set_status(net::URLRequestStatus());
521 backup_url_fetcher->set_response_code(200);
522 backup_url_fetcher->SetResponseString(std::string());
523 backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
525 EXPECT_TRUE(pm->IsUpdateScheduled());
528 // Tests what happens when there is an HTTP error response to the update
529 // request, and a timeout on the backup update request.
530 TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseHttpErrorBackupTimeout) {
531 scoped_refptr<base::TestSimpleTaskRunner> runner(
532 new base::TestSimpleTaskRunner());
533 base::ThreadTaskRunnerHandle runner_handler(runner);
534 net::TestURLFetcherFactory url_fetcher_factory;
536 testing::StrictMock<MockProtocolDelegate> test_delegate;
537 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
538 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
539 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
540 std::vector<SBListChunkRanges>(),
541 false)));
542 EXPECT_CALL(test_delegate, UpdateFinished(false)).Times(1);
544 scoped_ptr<SafeBrowsingProtocolManager> pm(
545 CreateProtocolManager(&test_delegate));
547 // Kick off initialization. This returns chunks from the DB synchronously.
548 pm->ForceScheduleNextUpdate(TimeDelta());
549 runner->RunPendingTasks();
551 // We should have an URLFetcher at this point in time.
552 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
553 ValidateUpdateFetcherRequest(url_fetcher);
555 // Go ahead and respond to it.
556 url_fetcher->set_status(net::URLRequestStatus());
557 url_fetcher->set_response_code(404);
558 url_fetcher->SetResponseString(std::string());
559 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
561 // There should now be a backup request.
562 net::TestURLFetcher* backup_url_fetcher =
563 url_fetcher_factory.GetFetcherByID(1);
564 ValidateUpdateFetcherRequest(backup_url_fetcher, kBackupHttpUrlPrefix);
566 // Either one or two calls to RunPendingTasks are needed here. The first run
567 // of RunPendingTasks will run the canceled timeout task associated with
568 // the first Update request. Depending on timing, this will either directly
569 // call the timeout task from the backup request, or schedule another task
570 // to run that in the future.
571 // TODO(cbentzel): Less fragile approach.
572 runner->RunPendingTasks();
573 if (!pm->IsUpdateScheduled())
574 runner->RunPendingTasks();
575 EXPECT_TRUE(pm->IsUpdateScheduled());
578 // Tests what happens when there is a connection error when issuing the update
579 // request, and an error with the backup update request.
580 TEST_F(SafeBrowsingProtocolManagerTest,
581 UpdateResponseConnectionErrorBackupError) {
582 scoped_refptr<base::TestSimpleTaskRunner> runner(
583 new base::TestSimpleTaskRunner());
584 base::ThreadTaskRunnerHandle runner_handler(runner);
585 net::TestURLFetcherFactory url_fetcher_factory;
587 testing::StrictMock<MockProtocolDelegate> test_delegate;
588 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
589 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
590 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
591 std::vector<SBListChunkRanges>(),
592 false)));
593 EXPECT_CALL(test_delegate, UpdateFinished(false)).Times(1);
595 scoped_ptr<SafeBrowsingProtocolManager> pm(
596 CreateProtocolManager(&test_delegate));
598 // Kick off initialization. This returns chunks from the DB synchronously.
599 pm->ForceScheduleNextUpdate(TimeDelta());
600 runner->RunPendingTasks();
602 // We should have an URLFetcher at this point in time.
603 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
604 ValidateUpdateFetcherRequest(url_fetcher);
606 // Go ahead and respond to it.
607 url_fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::FAILED,
608 net::ERR_CONNECTION_RESET));
609 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
611 // There should be a backup URLFetcher now.
612 net::TestURLFetcher* backup_url_fetcher =
613 url_fetcher_factory.GetFetcherByID(1);
614 ValidateUpdateFetcherRequest(backup_url_fetcher,
615 kBackupConnectUrlPrefix);
617 // Respond to the backup unsuccessfully.
618 backup_url_fetcher->set_status(net::URLRequestStatus());
619 backup_url_fetcher->set_response_code(404);
620 backup_url_fetcher->SetResponseString(std::string());
621 backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
623 EXPECT_TRUE(pm->IsUpdateScheduled());
626 // Tests what happens when there is a connection error when issuing the update
627 // request, and a successful response to the backup update request.
628 TEST_F(SafeBrowsingProtocolManagerTest,
629 UpdateResponseConnectionErrorBackupSuccess) {
630 scoped_refptr<base::TestSimpleTaskRunner> runner(
631 new base::TestSimpleTaskRunner());
632 base::ThreadTaskRunnerHandle runner_handler(runner);
633 net::TestURLFetcherFactory url_fetcher_factory;
635 testing::StrictMock<MockProtocolDelegate> test_delegate;
636 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
637 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
638 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
639 std::vector<SBListChunkRanges>(),
640 false)));
641 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
643 scoped_ptr<SafeBrowsingProtocolManager> pm(
644 CreateProtocolManager(&test_delegate));
646 // Kick off initialization. This returns chunks from the DB synchronously.
647 pm->ForceScheduleNextUpdate(TimeDelta());
648 runner->RunPendingTasks();
650 // We should have an URLFetcher at this point in time.
651 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
652 ValidateUpdateFetcherRequest(url_fetcher);
654 // Go ahead and respond to it.
655 url_fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::FAILED,
656 net::ERR_CONNECTION_RESET));
657 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
659 // There should be a backup URLFetcher now.
660 net::TestURLFetcher* backup_url_fetcher =
661 url_fetcher_factory.GetFetcherByID(1);
662 ValidateUpdateFetcherRequest(backup_url_fetcher,
663 kBackupConnectUrlPrefix);
665 // Respond to the backup unsuccessfully.
666 backup_url_fetcher->set_status(net::URLRequestStatus());
667 backup_url_fetcher->set_response_code(200);
668 backup_url_fetcher->SetResponseString(std::string());
669 backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
671 EXPECT_TRUE(pm->IsUpdateScheduled());
673 // Tests what happens when there is a network state error when issuing the
674 // update request, and an error with the backup update request.
675 TEST_F(SafeBrowsingProtocolManagerTest,
676 UpdateResponseNetworkErrorBackupError) {
677 scoped_refptr<base::TestSimpleTaskRunner> runner(
678 new base::TestSimpleTaskRunner());
679 base::ThreadTaskRunnerHandle runner_handler(runner);
680 net::TestURLFetcherFactory url_fetcher_factory;
682 testing::StrictMock<MockProtocolDelegate> test_delegate;
683 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
684 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
685 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
686 std::vector<SBListChunkRanges>(),
687 false)));
688 EXPECT_CALL(test_delegate, UpdateFinished(false)).Times(1);
690 scoped_ptr<SafeBrowsingProtocolManager> pm(
691 CreateProtocolManager(&test_delegate));
693 // Kick off initialization. This returns chunks from the DB synchronously.
694 pm->ForceScheduleNextUpdate(TimeDelta());
695 runner->RunPendingTasks();
697 // We should have an URLFetcher at this point in time.
698 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
699 ValidateUpdateFetcherRequest(url_fetcher);
701 // Go ahead and respond to it.
702 url_fetcher->set_status(
703 net::URLRequestStatus(net::URLRequestStatus::FAILED,
704 net::ERR_INTERNET_DISCONNECTED));
705 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
707 // There should be a backup URLFetcher now.
708 net::TestURLFetcher* backup_url_fetcher =
709 url_fetcher_factory.GetFetcherByID(1);
710 ValidateUpdateFetcherRequest(backup_url_fetcher,
711 kBackupNetworkUrlPrefix);
713 // Respond to the backup unsuccessfully.
714 backup_url_fetcher->set_status(net::URLRequestStatus());
715 backup_url_fetcher->set_response_code(404);
716 backup_url_fetcher->SetResponseString(std::string());
717 backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
719 EXPECT_TRUE(pm->IsUpdateScheduled());
722 // Tests what happens when there is a network state error when issuing the
723 // update request, and a successful response to the backup update request.
724 TEST_F(SafeBrowsingProtocolManagerTest,
725 UpdateResponseNetworkErrorBackupSuccess) {
726 scoped_refptr<base::TestSimpleTaskRunner> runner(
727 new base::TestSimpleTaskRunner());
728 base::ThreadTaskRunnerHandle runner_handler(runner);
729 net::TestURLFetcherFactory url_fetcher_factory;
731 testing::StrictMock<MockProtocolDelegate> test_delegate;
732 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
733 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
734 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
735 std::vector<SBListChunkRanges>(),
736 false)));
737 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
739 scoped_ptr<SafeBrowsingProtocolManager> pm(
740 CreateProtocolManager(&test_delegate));
742 // Kick off initialization. This returns chunks from the DB synchronously.
743 pm->ForceScheduleNextUpdate(TimeDelta());
744 runner->RunPendingTasks();
746 // We should have an URLFetcher at this point in time.
747 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
748 ValidateUpdateFetcherRequest(url_fetcher);
750 // Go ahead and respond to it.
751 url_fetcher->set_status(
752 net::URLRequestStatus(net::URLRequestStatus::FAILED,
753 net::ERR_INTERNET_DISCONNECTED));
754 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
756 // There should be a backup URLFetcher now.
757 net::TestURLFetcher* backup_url_fetcher =
758 url_fetcher_factory.GetFetcherByID(1);
759 ValidateUpdateFetcherRequest(backup_url_fetcher,
760 kBackupNetworkUrlPrefix);
762 // Respond to the backup unsuccessfully.
763 backup_url_fetcher->set_status(net::URLRequestStatus());
764 backup_url_fetcher->set_response_code(200);
765 backup_url_fetcher->SetResponseString(std::string());
766 backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
768 EXPECT_TRUE(pm->IsUpdateScheduled());
771 // Tests what happens when there is a timeout before an update response.
772 TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseTimeoutBackupSuccess) {
773 scoped_refptr<base::TestSimpleTaskRunner> runner(
774 new base::TestSimpleTaskRunner());
775 base::ThreadTaskRunnerHandle runner_handler(runner);
776 net::TestURLFetcherFactory url_fetcher_factory;
778 testing::StrictMock<MockProtocolDelegate> test_delegate;
779 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
780 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
781 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
782 std::vector<SBListChunkRanges>(),
783 false)));
784 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
786 scoped_ptr<SafeBrowsingProtocolManager> pm(
787 CreateProtocolManager(&test_delegate));
789 // Kick off initialization. This returns chunks from the DB synchronously.
790 pm->ForceScheduleNextUpdate(TimeDelta());
791 runner->RunPendingTasks();
793 // We should have an URLFetcher at this point in time.
794 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
795 ValidateUpdateFetcherRequest(url_fetcher);
797 // The first time RunPendingTasks is called above, the update timeout timer is
798 // not handled. This call of RunPendingTasks will handle the update.
799 runner->RunPendingTasks();
801 // There should be a backup URLFetcher now.
802 net::TestURLFetcher* backup_url_fetcher =
803 url_fetcher_factory.GetFetcherByID(1);
804 ValidateUpdateFetcherRequest(backup_url_fetcher,
805 kBackupConnectUrlPrefix);
807 // Respond to the backup unsuccessfully.
808 backup_url_fetcher->set_status(net::URLRequestStatus());
809 backup_url_fetcher->set_response_code(200);
810 backup_url_fetcher->SetResponseString(std::string());
811 backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
813 EXPECT_TRUE(pm->IsUpdateScheduled());
816 // Tests what happens when there is a reset command in the response.
817 TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseReset) {
818 scoped_refptr<base::TestSimpleTaskRunner> runner(
819 new base::TestSimpleTaskRunner());
820 base::ThreadTaskRunnerHandle runner_handler(runner);
821 net::TestURLFetcherFactory url_fetcher_factory;
823 testing::StrictMock<MockProtocolDelegate> test_delegate;
824 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
825 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
826 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
827 std::vector<SBListChunkRanges>(),
828 false)));
829 EXPECT_CALL(test_delegate, ResetDatabase()).Times(1);
830 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
832 scoped_ptr<SafeBrowsingProtocolManager> pm(
833 CreateProtocolManager(&test_delegate));
835 // Kick off initialization. This returns chunks from the DB synchronously.
836 pm->ForceScheduleNextUpdate(TimeDelta());
837 runner->RunPendingTasks();
839 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
840 ValidateUpdateFetcherRequest(url_fetcher);
842 // The update response is successful, and has a reset command.
843 url_fetcher->set_status(net::URLRequestStatus());
844 url_fetcher->set_response_code(200);
845 url_fetcher->SetResponseString("r:pleasereset\n");
846 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
848 EXPECT_TRUE(pm->IsUpdateScheduled());
851 // Tests a single valid update response, followed by a single redirect response
852 // that has an valid, but empty body.
853 TEST_F(SafeBrowsingProtocolManagerTest, EmptyRedirectResponse) {
854 scoped_refptr<base::TestSimpleTaskRunner> runner(
855 new base::TestSimpleTaskRunner());
856 base::ThreadTaskRunnerHandle runner_handler(runner);
857 net::TestURLFetcherFactory url_fetcher_factory;
859 testing::StrictMock<MockProtocolDelegate> test_delegate;
860 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
861 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
862 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
863 std::vector<SBListChunkRanges>(),
864 false)));
865 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
867 scoped_ptr<SafeBrowsingProtocolManager> pm(
868 CreateProtocolManager(&test_delegate));
870 // Kick off initialization. This returns chunks from the DB synchronously.
871 pm->ForceScheduleNextUpdate(TimeDelta());
872 runner->RunPendingTasks();
874 // The update response contains a single redirect command.
875 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
876 ValidateUpdateFetcherRequest(url_fetcher);
877 url_fetcher->set_status(net::URLRequestStatus());
878 url_fetcher->set_response_code(200);
879 url_fetcher->SetResponseString(
880 "i:goog-phish-shavar\n"
881 "u:redirect-server.example.com/path\n");
882 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
884 // The redirect response contains an empty body.
885 net::TestURLFetcher* chunk_url_fetcher =
886 url_fetcher_factory.GetFetcherByID(1);
887 ValidateRedirectFetcherRequest(
888 chunk_url_fetcher, "https://redirect-server.example.com/path");
889 chunk_url_fetcher->set_status(net::URLRequestStatus());
890 chunk_url_fetcher->set_response_code(200);
891 chunk_url_fetcher->SetResponseString(std::string());
892 chunk_url_fetcher->delegate()->OnURLFetchComplete(chunk_url_fetcher);
894 EXPECT_TRUE(pm->IsUpdateScheduled());
897 // Tests a single valid update response, followed by a single redirect response
898 // that has an invalid body.
899 TEST_F(SafeBrowsingProtocolManagerTest, InvalidRedirectResponse) {
900 scoped_refptr<base::TestSimpleTaskRunner> runner(
901 new base::TestSimpleTaskRunner());
902 base::ThreadTaskRunnerHandle runner_handler(runner);
903 net::TestURLFetcherFactory url_fetcher_factory;
905 testing::StrictMock<MockProtocolDelegate> test_delegate;
906 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
907 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
908 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
909 std::vector<SBListChunkRanges>(),
910 false)));
911 EXPECT_CALL(test_delegate, UpdateFinished(false)).Times(1);
913 scoped_ptr<SafeBrowsingProtocolManager> pm(
914 CreateProtocolManager(&test_delegate));
916 // Kick off initialization. This returns chunks from the DB synchronously.
917 pm->ForceScheduleNextUpdate(TimeDelta());
918 runner->RunPendingTasks();
920 // The update response contains a single redirect command.
921 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
922 ValidateUpdateFetcherRequest(url_fetcher);
923 url_fetcher->set_status(net::URLRequestStatus());
924 url_fetcher->set_response_code(200);
925 url_fetcher->SetResponseString(
926 "i:goog-phish-shavar\n"
927 "u:redirect-server.example.com/path\n");
928 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
930 // The redirect response contains an invalid body.
931 net::TestURLFetcher* chunk_url_fetcher =
932 url_fetcher_factory.GetFetcherByID(1);
933 ValidateRedirectFetcherRequest(
934 chunk_url_fetcher, "https://redirect-server.example.com/path");
935 chunk_url_fetcher->set_status(net::URLRequestStatus());
936 chunk_url_fetcher->set_response_code(200);
937 chunk_url_fetcher->SetResponseString("THIS IS AN INVALID RESPONSE");
938 chunk_url_fetcher->delegate()->OnURLFetchComplete(chunk_url_fetcher);
940 EXPECT_TRUE(pm->IsUpdateScheduled());
943 // Tests a single valid update response, followed by a single redirect response
944 // containing chunks.
945 TEST_F(SafeBrowsingProtocolManagerTest, SingleRedirectResponseWithChunks) {
946 scoped_refptr<base::TestSimpleTaskRunner> runner(
947 new base::TestSimpleTaskRunner());
948 base::ThreadTaskRunnerHandle runner_handler(runner);
949 net::TestURLFetcherFactory url_fetcher_factory;
951 testing::StrictMock<MockProtocolDelegate> test_delegate;
952 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
953 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
954 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
955 std::vector<SBListChunkRanges>(),
956 false)));
957 EXPECT_CALL(test_delegate, AddChunks("goog-phish-shavar", _, _)).WillOnce(
958 Invoke(HandleAddChunks));
959 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
961 scoped_ptr<SafeBrowsingProtocolManager> pm(
962 CreateProtocolManager(&test_delegate));
964 // Kick off initialization. This returns chunks from the DB synchronously.
965 pm->ForceScheduleNextUpdate(TimeDelta());
966 runner->RunPendingTasks();
968 // The update response contains a single redirect command.
969 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
970 ValidateUpdateFetcherRequest(url_fetcher);
971 url_fetcher->set_status(net::URLRequestStatus());
972 url_fetcher->set_response_code(200);
973 url_fetcher->SetResponseString(
974 "i:goog-phish-shavar\n"
975 "u:redirect-server.example.com/path\n");
976 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
978 // The redirect response contains a single chunk.
979 net::TestURLFetcher* chunk_url_fetcher =
980 url_fetcher_factory.GetFetcherByID(1);
981 ValidateRedirectFetcherRequest(
982 chunk_url_fetcher, "https://redirect-server.example.com/path");
983 chunk_url_fetcher->set_status(net::URLRequestStatus());
984 chunk_url_fetcher->set_response_code(200);
985 chunk_url_fetcher->SetResponseString(
986 "a:4:4:9\n"
987 "host\1fdaf");
988 chunk_url_fetcher->delegate()->OnURLFetchComplete(chunk_url_fetcher);
990 EXPECT_FALSE(pm->IsUpdateScheduled());
992 // The AddChunksCallback needs to be invoked.
993 runner->RunPendingTasks();
995 EXPECT_TRUE(pm->IsUpdateScheduled());
998 // Tests a single valid update response, followed by multiple redirect responses
999 // containing chunks.
1000 TEST_F(SafeBrowsingProtocolManagerTest, MultipleRedirectResponsesWithChunks) {
1001 scoped_refptr<base::TestSimpleTaskRunner> runner(
1002 new base::TestSimpleTaskRunner());
1003 base::ThreadTaskRunnerHandle runner_handler(runner);
1004 net::TestURLFetcherFactory url_fetcher_factory;
1006 testing::StrictMock<MockProtocolDelegate> test_delegate;
1007 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
1008 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
1009 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
1010 std::vector<SBListChunkRanges>(),
1011 false)));
1012 EXPECT_CALL(test_delegate, AddChunks("goog-phish-shavar", _, _)).
1013 WillRepeatedly(Invoke(HandleAddChunks));
1014 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
1016 scoped_ptr<SafeBrowsingProtocolManager> pm(
1017 CreateProtocolManager(&test_delegate));
1019 // Kick off initialization. This returns chunks from the DB synchronously.
1020 pm->ForceScheduleNextUpdate(TimeDelta());
1021 runner->RunPendingTasks();
1023 // The update response contains multiple redirect commands.
1024 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
1025 ValidateUpdateFetcherRequest(url_fetcher);
1026 url_fetcher->set_status(net::URLRequestStatus());
1027 url_fetcher->set_response_code(200);
1028 url_fetcher->SetResponseString(
1029 "i:goog-phish-shavar\n"
1030 "u:redirect-server.example.com/one\n"
1031 "u:redirect-server.example.com/two\n");
1032 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
1034 // The first redirect response contains a single chunk.
1035 net::TestURLFetcher* first_chunk_url_fetcher =
1036 url_fetcher_factory.GetFetcherByID(1);
1037 ValidateRedirectFetcherRequest(
1038 first_chunk_url_fetcher, "https://redirect-server.example.com/one");
1039 first_chunk_url_fetcher->set_status(net::URLRequestStatus());
1040 first_chunk_url_fetcher->set_response_code(200);
1041 first_chunk_url_fetcher->SetResponseString(
1042 "a:4:4:9\n"
1043 "host\1aaaa");
1044 first_chunk_url_fetcher->delegate()->OnURLFetchComplete(
1045 first_chunk_url_fetcher);
1047 // Invoke the AddChunksCallback to trigger the second request.
1048 runner->RunPendingTasks();
1050 EXPECT_FALSE(pm->IsUpdateScheduled());
1052 // The second redirect response contains a single chunk.
1053 net::TestURLFetcher* second_chunk_url_fetcher =
1054 url_fetcher_factory.GetFetcherByID(2);
1055 ValidateRedirectFetcherRequest(
1056 second_chunk_url_fetcher, "https://redirect-server.example.com/two");
1057 second_chunk_url_fetcher->set_status(net::URLRequestStatus());
1058 second_chunk_url_fetcher->set_response_code(200);
1059 second_chunk_url_fetcher->SetResponseString(
1060 "a:5:4:9\n"
1061 "host\1bbbb");
1062 second_chunk_url_fetcher->delegate()->OnURLFetchComplete(
1063 second_chunk_url_fetcher);
1065 EXPECT_FALSE(pm->IsUpdateScheduled());
1067 // Invoke the AddChunksCallback to finish the update.
1068 runner->RunPendingTasks();
1070 EXPECT_TRUE(pm->IsUpdateScheduled());