Roll src/third_party/WebKit f298044:aa8346d (svn 202628:202629)
[chromium-blink-merge.git] / chrome / browser / safe_browsing / protocol_manager_unittest.cc
blobfae2de19665deef648705ea59f7257cdd3fdd275
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/memory/scoped_ptr.h"
7 #include "base/memory/scoped_vector.h"
8 #include "base/strings/stringprintf.h"
9 #include "base/test/test_simple_task_runner.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "base/time/time.h"
12 #include "chrome/browser/safe_browsing/chunk.pb.h"
13 #include "chrome/browser/safe_browsing/protocol_manager.h"
14 #include "chrome/browser/safe_browsing/safe_browsing_util.h"
15 #include "google_apis/google_api_keys.h"
16 #include "net/base/escape.h"
17 #include "net/base/load_flags.h"
18 #include "net/base/net_errors.h"
19 #include "net/url_request/test_url_fetcher_factory.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gmock_mutant.h"
22 #include "testing/gtest/include/gtest/gtest.h"
24 using base::Time;
25 using base::TimeDelta;
26 using testing::_;
27 using testing::Invoke;
29 namespace {
31 const char kUrlPrefix[] = "https://prefix.com/foo";
32 const char kBackupConnectUrlPrefix[] = "https://alt1-prefix.com/foo";
33 const char kBackupHttpUrlPrefix[] = "https://alt2-prefix.com/foo";
34 const char kBackupNetworkUrlPrefix[] = "https://alt3-prefix.com/foo";
35 const char kClient[] = "unittest";
36 const char kAppVer[] = "1.0";
37 const char kAdditionalQuery[] = "additional_query";
38 const char kUrlSuffix[] = "&ext=0";
40 #if defined(OS_ANDROID)
41 const char kDefaultPhishList[] = "goog-mobilephish-shavar";
42 const char kDefaultMalwareList[] = "goog-mobilemalware-shavar";
43 #else
44 const char kDefaultPhishList[] = "goog-phish-shavar";
45 const char kDefaultMalwareList[] = "goog-malware-shavar";
46 #endif
48 // Add-prefix chunk with single prefix.
49 const char kRawChunkPayload1[] = {
50 '\0', '\0', '\0', '\x08', // 32-bit payload length in network byte order.
51 '\x08', // field 1, wire format varint
52 '\x03', // chunk_number varint 3
53 '\x22', // field 4, wire format length-delimited
54 '\x04', // varint 4 length
55 'a', 'b', 'c', 'd' // 4-byte prefix
57 const std::string kChunkPayload1(kRawChunkPayload1, sizeof(kRawChunkPayload1));
59 // Add-prefix chunk_number 5 with single prefix.
60 const char kRawChunkPayload2[] = {
61 '\0', '\0', '\0', '\x08', // 32-bit payload length in network byte order.
62 '\x08', // field 1, wire format varint
63 '\x05', // chunk_number varint 5
64 '\x22', // field 4, wire format length-delimited
65 '\x04', // varint length 4
66 'e', 'f', 'g', 'h' // 4-byte prefix
68 const std::string kChunkPayload2(kRawChunkPayload2, sizeof(kRawChunkPayload2));
70 } // namespace
72 class SafeBrowsingProtocolManagerTest : public testing::Test {
73 protected:
74 std::string key_param_;
76 void SetUp() override {
77 std::string key = google_apis::GetAPIKey();
78 if (!key.empty()) {
79 key_param_ = base::StringPrintf(
80 "&key=%s",
81 net::EscapeQueryParamValue(key, true).c_str());
85 scoped_ptr<SafeBrowsingProtocolManager> CreateProtocolManager(
86 SafeBrowsingProtocolManagerDelegate* delegate) {
87 SafeBrowsingProtocolConfig config;
88 config.client_name = kClient;
89 config.url_prefix = kUrlPrefix;
90 config.backup_connect_error_url_prefix = kBackupConnectUrlPrefix;
91 config.backup_http_error_url_prefix = kBackupHttpUrlPrefix;
92 config.backup_network_error_url_prefix = kBackupNetworkUrlPrefix;
93 config.version = kAppVer;
94 #if defined(OS_ANDROID)
95 config.disable_connection_check = true;
96 #endif
97 return scoped_ptr<SafeBrowsingProtocolManager>(
98 SafeBrowsingProtocolManager::Create(delegate, NULL, config));
101 void ValidateUpdateFetcherRequest(const net::TestURLFetcher* url_fetcher,
102 const std::string& expected_prefix,
103 const std::string& expected_suffix) {
104 ASSERT_TRUE(url_fetcher);
105 EXPECT_EQ(net::LOAD_DISABLE_CACHE, url_fetcher->GetLoadFlags());
107 std::string expected_lists(base::StringPrintf("%s;\n%s;\n",
108 kDefaultPhishList,
109 kDefaultMalwareList));
110 EXPECT_EQ(expected_lists, url_fetcher->upload_data());
111 EXPECT_EQ(GURL(expected_prefix + "/downloads?client=unittest&appver=1.0"
112 "&pver=3.0" +
113 key_param_ + expected_suffix),
114 url_fetcher->GetOriginalURL());
117 void ValidateUpdateFetcherRequest(const net::TestURLFetcher* url_fetcher) {
118 ValidateUpdateFetcherRequest(url_fetcher, kUrlPrefix, kUrlSuffix);
121 void ValidateRedirectFetcherRequest(const net::TestURLFetcher* url_fetcher,
122 const std::string& expected_url) {
123 ASSERT_TRUE(url_fetcher);
124 EXPECT_EQ(net::LOAD_DISABLE_CACHE, url_fetcher->GetLoadFlags());
125 EXPECT_EQ("", url_fetcher->upload_data());
126 EXPECT_EQ(GURL(expected_url), url_fetcher->GetOriginalURL());
130 // Ensure that we respect section 5 of the SafeBrowsing protocol specification.
131 TEST_F(SafeBrowsingProtocolManagerTest, TestBackOffTimes) {
132 scoped_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL));
134 pm->next_update_interval_ = TimeDelta::FromSeconds(1800);
135 ASSERT_TRUE(pm->back_off_fuzz_ >= 0.0 && pm->back_off_fuzz_ <= 1.0);
137 TimeDelta next;
139 // No errors received so far.
140 next = pm->GetNextUpdateInterval(false);
141 EXPECT_EQ(next, TimeDelta::FromSeconds(1800));
143 // 1 error.
144 next = pm->GetNextUpdateInterval(true);
145 EXPECT_EQ(next, TimeDelta::FromSeconds(60));
147 // 2 errors.
148 next = pm->GetNextUpdateInterval(true);
149 EXPECT_TRUE(next >= TimeDelta::FromMinutes(30) &&
150 next <= TimeDelta::FromMinutes(60));
152 // 3 errors.
153 next = pm->GetNextUpdateInterval(true);
154 EXPECT_TRUE(next >= TimeDelta::FromMinutes(60) &&
155 next <= TimeDelta::FromMinutes(120));
157 // 4 errors.
158 next = pm->GetNextUpdateInterval(true);
159 EXPECT_TRUE(next >= TimeDelta::FromMinutes(120) &&
160 next <= TimeDelta::FromMinutes(240));
162 // 5 errors.
163 next = pm->GetNextUpdateInterval(true);
164 EXPECT_TRUE(next >= TimeDelta::FromMinutes(240) &&
165 next <= TimeDelta::FromMinutes(480));
167 // 6 errors, reached max backoff.
168 next = pm->GetNextUpdateInterval(true);
169 EXPECT_EQ(next, TimeDelta::FromMinutes(480));
171 // 7 errors.
172 next = pm->GetNextUpdateInterval(true);
173 EXPECT_EQ(next, TimeDelta::FromMinutes(480));
175 // Received a successful response.
176 next = pm->GetNextUpdateInterval(false);
177 EXPECT_EQ(next, TimeDelta::FromSeconds(1800));
180 TEST_F(SafeBrowsingProtocolManagerTest, TestChunkStrings) {
181 scoped_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL));
183 // Add and Sub chunks.
184 SBListChunkRanges phish(kDefaultPhishList);
185 phish.adds = "1,4,6,8-20,99";
186 phish.subs = "16,32,64-96";
187 EXPECT_EQ(base::StringPrintf("%s;a:1,4,6,8-20,99:s:16,32,64-96\n",
188 kDefaultPhishList),
189 safe_browsing::FormatList(phish));
191 // Add chunks only.
192 phish.subs = "";
193 EXPECT_EQ(base::StringPrintf("%s;a:1,4,6,8-20,99\n",
194 kDefaultPhishList),
195 safe_browsing::FormatList(phish));
197 // Sub chunks only.
198 phish.adds = "";
199 phish.subs = "16,32,64-96";
200 EXPECT_EQ(base::StringPrintf("%s;s:16,32,64-96\n",
201 kDefaultPhishList),
202 safe_browsing::FormatList(phish));
204 // No chunks of either type.
205 phish.adds = "";
206 phish.subs = "";
207 EXPECT_EQ(base::StringPrintf("%s;\n", kDefaultPhishList),
208 safe_browsing::FormatList(phish));
211 TEST_F(SafeBrowsingProtocolManagerTest, TestGetHashBackOffTimes) {
212 scoped_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL));
214 // No errors or back off time yet.
215 EXPECT_EQ(0U, pm->gethash_error_count_);
216 EXPECT_TRUE(pm->next_gethash_time_.is_null());
218 Time now = Time::Now();
220 // 1 error.
221 pm->HandleGetHashError(now);
222 EXPECT_EQ(1U, pm->gethash_error_count_);
223 TimeDelta margin = TimeDelta::FromSeconds(5); // Fudge factor.
224 Time future = now + TimeDelta::FromMinutes(1);
225 EXPECT_TRUE(pm->next_gethash_time_ >= future - margin &&
226 pm->next_gethash_time_ <= future + margin);
228 // 2 errors.
229 pm->HandleGetHashError(now);
230 EXPECT_EQ(2U, pm->gethash_error_count_);
231 EXPECT_TRUE(pm->next_gethash_time_ >= now + TimeDelta::FromMinutes(30));
232 EXPECT_TRUE(pm->next_gethash_time_ <= now + TimeDelta::FromMinutes(60));
234 // 3 errors.
235 pm->HandleGetHashError(now);
236 EXPECT_EQ(3U, pm->gethash_error_count_);
237 EXPECT_TRUE(pm->next_gethash_time_ >= now + TimeDelta::FromMinutes(60));
238 EXPECT_TRUE(pm->next_gethash_time_ <= now + TimeDelta::FromMinutes(120));
240 // 4 errors.
241 pm->HandleGetHashError(now);
242 EXPECT_EQ(4U, pm->gethash_error_count_);
243 EXPECT_TRUE(pm->next_gethash_time_ >= now + TimeDelta::FromMinutes(120));
244 EXPECT_TRUE(pm->next_gethash_time_ <= now + TimeDelta::FromMinutes(240));
246 // 5 errors.
247 pm->HandleGetHashError(now);
248 EXPECT_EQ(5U, pm->gethash_error_count_);
249 EXPECT_TRUE(pm->next_gethash_time_ >= now + TimeDelta::FromMinutes(240));
250 EXPECT_TRUE(pm->next_gethash_time_ <= now + TimeDelta::FromMinutes(480));
252 // 6 errors, reached max backoff.
253 pm->HandleGetHashError(now);
254 EXPECT_EQ(6U, pm->gethash_error_count_);
255 EXPECT_TRUE(pm->next_gethash_time_ == now + TimeDelta::FromMinutes(480));
257 // 7 errors.
258 pm->HandleGetHashError(now);
259 EXPECT_EQ(7U, pm->gethash_error_count_);
260 EXPECT_TRUE(pm->next_gethash_time_== now + TimeDelta::FromMinutes(480));
263 TEST_F(SafeBrowsingProtocolManagerTest, TestGetHashUrl) {
264 scoped_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL));
266 EXPECT_EQ(
267 "https://prefix.com/foo/gethash?client=unittest&appver=1.0&"
268 "pver=3.0" +
269 key_param_ + "&ext=0",
270 pm->GetHashUrl(false).spec());
272 pm->set_additional_query(kAdditionalQuery);
273 EXPECT_EQ(
274 "https://prefix.com/foo/gethash?client=unittest&appver=1.0&"
275 "pver=3.0" +
276 key_param_ + "&additional_query&ext=1",
277 pm->GetHashUrl(true).spec());
280 TEST_F(SafeBrowsingProtocolManagerTest, TestUpdateUrl) {
281 scoped_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL));
283 EXPECT_EQ(
284 "https://prefix.com/foo/downloads?client=unittest&appver=1.0&"
285 "pver=3.0" +
286 key_param_ + "&ext=1",
287 pm->UpdateUrl(true).spec());
289 pm->set_additional_query(kAdditionalQuery);
290 EXPECT_EQ(
291 "https://prefix.com/foo/downloads?client=unittest&appver=1.0&"
292 "pver=3.0" +
293 key_param_ + "&additional_query&ext=0",
294 pm->UpdateUrl(false).spec());
297 TEST_F(SafeBrowsingProtocolManagerTest, TestNextChunkUrl) {
298 scoped_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL));
300 std::string url_partial = "localhost:1234/foo/bar?foo";
301 std::string url_http_full = "http://localhost:1234/foo/bar?foo";
302 std::string url_https_full = "https://localhost:1234/foo/bar?foo";
303 std::string url_https_no_query = "https://localhost:1234/foo/bar";
305 EXPECT_EQ("https://localhost:1234/foo/bar?foo",
306 pm->NextChunkUrl(url_partial).spec());
307 EXPECT_EQ("http://localhost:1234/foo/bar?foo",
308 pm->NextChunkUrl(url_http_full).spec());
309 EXPECT_EQ("https://localhost:1234/foo/bar?foo",
310 pm->NextChunkUrl(url_https_full).spec());
311 EXPECT_EQ("https://localhost:1234/foo/bar",
312 pm->NextChunkUrl(url_https_no_query).spec());
314 pm->set_additional_query(kAdditionalQuery);
315 EXPECT_EQ("https://localhost:1234/foo/bar?foo&additional_query",
316 pm->NextChunkUrl(url_partial).spec());
317 EXPECT_EQ("http://localhost:1234/foo/bar?foo&additional_query",
318 pm->NextChunkUrl(url_http_full).spec());
319 EXPECT_EQ("https://localhost:1234/foo/bar?foo&additional_query",
320 pm->NextChunkUrl(url_https_full).spec());
321 EXPECT_EQ("https://localhost:1234/foo/bar?additional_query",
322 pm->NextChunkUrl(url_https_no_query).spec());
325 namespace {
327 class MockProtocolDelegate : public SafeBrowsingProtocolManagerDelegate {
328 public:
329 MockProtocolDelegate() {}
330 ~MockProtocolDelegate() override {}
332 MOCK_METHOD0(UpdateStarted, void());
333 MOCK_METHOD1(UpdateFinished, void(bool));
334 MOCK_METHOD0(ResetDatabase, void());
335 MOCK_METHOD1(GetChunks, void(GetChunksCallback));
337 // gmock does not work with scoped_ptr<> at this time. Add a local method to
338 // mock, then call that from an override. Beware of object ownership when
339 // making changes here.
340 MOCK_METHOD3(AddChunksRaw, void(const std::string& lists,
341 const ScopedVector<SBChunkData>& chunks,
342 AddChunksCallback));
343 void AddChunks(const std::string& list,
344 scoped_ptr<ScopedVector<SBChunkData>> chunks,
345 AddChunksCallback callback) override {
346 AddChunksRaw(list, *chunks, callback);
349 // TODO(shess): Actually test this case somewhere.
350 MOCK_METHOD1(DeleteChunksRaw,
351 void(const std::vector<SBChunkDelete>& chunk_deletes));
352 void DeleteChunks(
353 scoped_ptr<std::vector<SBChunkDelete>> chunk_deletes) override {
354 DeleteChunksRaw(*chunk_deletes);
358 // |InvokeGetChunksCallback| is required because GMock's InvokeArgument action
359 // expects to use operator(), and a Callback only provides Run().
360 // TODO(cbentzel): Use ACTION or ACTION_TEMPLATE instead?
361 void InvokeGetChunksCallback(
362 const std::vector<SBListChunkRanges>& ranges,
363 bool database_error,
364 SafeBrowsingProtocolManagerDelegate::GetChunksCallback callback) {
365 callback.Run(ranges, database_error, false);
368 // |HandleAddChunks| deletes the chunks and asynchronously invokes
369 // |callback| since SafeBrowsingProtocolManager is not re-entrant at the time
370 // this is called. This guarantee is part of the
371 // SafeBrowsingProtocolManagerDelegate contract.
372 void HandleAddChunks(
373 const std::string& unused_list,
374 const ScopedVector<SBChunkData>& chunks,
375 SafeBrowsingProtocolManagerDelegate::AddChunksCallback callback) {
376 scoped_refptr<base::SingleThreadTaskRunner> task_runner(
377 base::ThreadTaskRunnerHandle::Get());
378 if (!task_runner.get())
379 return;
380 task_runner->PostTask(FROM_HERE, callback);
383 } // namespace
385 // Tests that the Update protocol will be skipped if there are problems
386 // accessing the database.
387 TEST_F(SafeBrowsingProtocolManagerTest, ProblemAccessingDatabase) {
388 scoped_refptr<base::TestSimpleTaskRunner> runner(
389 new base::TestSimpleTaskRunner());
390 base::ThreadTaskRunnerHandle runner_handler(runner);
392 testing::StrictMock<MockProtocolDelegate> test_delegate;
393 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
394 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
395 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
396 std::vector<SBListChunkRanges>(),
397 true)));
398 EXPECT_CALL(test_delegate, UpdateFinished(false)).Times(1);
400 scoped_ptr<SafeBrowsingProtocolManager> pm(
401 CreateProtocolManager(&test_delegate));
403 pm->ForceScheduleNextUpdate(TimeDelta());
404 runner->RunPendingTasks();
406 EXPECT_TRUE(pm->IsUpdateScheduled());
409 // Tests the contents of the POST body when there are contents in the
410 // local database. This is not exhaustive, as the actual list formatting
411 // is covered by SafeBrowsingProtocolManagerTest.TestChunkStrings.
412 TEST_F(SafeBrowsingProtocolManagerTest, ExistingDatabase) {
413 scoped_refptr<base::TestSimpleTaskRunner> runner(
414 new base::TestSimpleTaskRunner());
415 base::ThreadTaskRunnerHandle runner_handler(runner);
416 net::TestURLFetcherFactory url_fetcher_factory;
418 std::vector<SBListChunkRanges> ranges;
419 SBListChunkRanges range_phish(safe_browsing_util::kPhishingList);
420 range_phish.adds = "adds_phish";
421 range_phish.subs = "subs_phish";
422 ranges.push_back(range_phish);
424 SBListChunkRanges range_unknown("unknown_list");
425 range_unknown.adds = "adds_unknown";
426 range_unknown.subs = "subs_unknown";
427 ranges.push_back(range_unknown);
429 testing::StrictMock<MockProtocolDelegate> test_delegate;
430 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
431 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
432 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
433 ranges,
434 false)));
435 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
437 scoped_ptr<SafeBrowsingProtocolManager> pm(
438 CreateProtocolManager(&test_delegate));
440 // Kick off initialization. This returns chunks from the DB synchronously.
441 pm->ForceScheduleNextUpdate(TimeDelta());
442 runner->RunPendingTasks();
444 // We should have an URLFetcher at this point in time.
445 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
446 ASSERT_TRUE(url_fetcher);
447 EXPECT_EQ(net::LOAD_DISABLE_CACHE, url_fetcher->GetLoadFlags());
448 EXPECT_EQ(base::StringPrintf("%s;a:adds_phish:s:subs_phish\n"
449 "unknown_list;a:adds_unknown:s:subs_unknown\n"
450 "%s;\n",
451 kDefaultPhishList, kDefaultMalwareList),
452 url_fetcher->upload_data());
453 EXPECT_EQ(GURL("https://prefix.com/foo/downloads?client=unittest&appver=1.0"
454 "&pver=3.0" +
455 key_param_ + "&ext=0"),
456 url_fetcher->GetOriginalURL());
458 url_fetcher->set_status(net::URLRequestStatus());
459 url_fetcher->set_response_code(200);
460 url_fetcher->SetResponseString(std::string());
461 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
463 EXPECT_TRUE(pm->IsUpdateScheduled());
466 TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseBadBodyBackupSuccess) {
467 scoped_refptr<base::TestSimpleTaskRunner> runner(
468 new base::TestSimpleTaskRunner());
469 base::ThreadTaskRunnerHandle runner_handler(runner);
470 net::TestURLFetcherFactory url_fetcher_factory;
472 testing::StrictMock<MockProtocolDelegate> test_delegate;
473 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
474 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
475 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
476 std::vector<SBListChunkRanges>(),
477 false)));
478 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
480 scoped_ptr<SafeBrowsingProtocolManager> pm(
481 CreateProtocolManager(&test_delegate));
483 // Kick off initialization. This returns chunks from the DB synchronously.
484 pm->ForceScheduleNextUpdate(TimeDelta());
485 runner->RunPendingTasks();
487 // We should have an URLFetcher at this point in time.
488 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
489 ValidateUpdateFetcherRequest(url_fetcher);
491 // The update response is successful, but an invalid body.
492 url_fetcher->set_status(net::URLRequestStatus());
493 url_fetcher->set_response_code(200);
494 url_fetcher->SetResponseString("THIS_IS_A_BAD_RESPONSE");
495 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
497 // There should now be a backup request.
498 net::TestURLFetcher* backup_url_fetcher =
499 url_fetcher_factory.GetFetcherByID(1);
500 ValidateUpdateFetcherRequest(backup_url_fetcher, kBackupHttpUrlPrefix, "");
502 // Respond to the backup successfully.
503 backup_url_fetcher->set_status(net::URLRequestStatus());
504 backup_url_fetcher->set_response_code(200);
505 backup_url_fetcher->SetResponseString(std::string());
506 backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
508 EXPECT_TRUE(pm->IsUpdateScheduled());
511 // Tests what happens when there is an HTTP error response to the update
512 // request, as well as an error response to the backup update request.
513 TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseHttpErrorBackupError) {
514 scoped_refptr<base::TestSimpleTaskRunner> runner(
515 new base::TestSimpleTaskRunner());
516 base::ThreadTaskRunnerHandle runner_handler(runner);
517 net::TestURLFetcherFactory url_fetcher_factory;
519 testing::StrictMock<MockProtocolDelegate> test_delegate;
520 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
521 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
522 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
523 std::vector<SBListChunkRanges>(),
524 false)));
525 EXPECT_CALL(test_delegate, UpdateFinished(false)).Times(1);
527 scoped_ptr<SafeBrowsingProtocolManager> pm(
528 CreateProtocolManager(&test_delegate));
530 // Kick off initialization. This returns chunks from the DB synchronously.
531 pm->ForceScheduleNextUpdate(TimeDelta());
532 runner->RunPendingTasks();
534 // We should have an URLFetcher at this point in time.
535 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
536 ValidateUpdateFetcherRequest(url_fetcher);
538 // Go ahead and respond to it.
539 url_fetcher->set_status(net::URLRequestStatus());
540 url_fetcher->set_response_code(404);
541 url_fetcher->SetResponseString(std::string());
542 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
544 // There should now be a backup request.
545 net::TestURLFetcher* backup_url_fetcher =
546 url_fetcher_factory.GetFetcherByID(1);
547 ValidateUpdateFetcherRequest(backup_url_fetcher, kBackupHttpUrlPrefix, "");
549 // Respond to the backup unsuccessfully.
550 backup_url_fetcher->set_status(net::URLRequestStatus());
551 backup_url_fetcher->set_response_code(404);
552 backup_url_fetcher->SetResponseString(std::string());
553 backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
555 EXPECT_TRUE(pm->IsUpdateScheduled());
558 // Tests what happens when there is an HTTP error response to the update
559 // request, followed by a successful response to the backup update request.
560 TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseHttpErrorBackupSuccess) {
561 scoped_refptr<base::TestSimpleTaskRunner> runner(
562 new base::TestSimpleTaskRunner());
563 base::ThreadTaskRunnerHandle runner_handler(runner);
564 net::TestURLFetcherFactory url_fetcher_factory;
566 testing::StrictMock<MockProtocolDelegate> test_delegate;
567 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
568 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
569 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
570 std::vector<SBListChunkRanges>(),
571 false)));
572 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
574 scoped_ptr<SafeBrowsingProtocolManager> pm(
575 CreateProtocolManager(&test_delegate));
577 // Kick off initialization. This returns chunks from the DB synchronously.
578 pm->ForceScheduleNextUpdate(TimeDelta());
579 runner->RunPendingTasks();
581 // We should have an URLFetcher at this point in time.
582 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
583 ValidateUpdateFetcherRequest(url_fetcher);
585 // Go ahead and respond to it.
586 url_fetcher->set_status(net::URLRequestStatus());
587 url_fetcher->set_response_code(404);
588 url_fetcher->SetResponseString(std::string());
589 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
591 // There should now be a backup request.
592 net::TestURLFetcher* backup_url_fetcher =
593 url_fetcher_factory.GetFetcherByID(1);
594 ValidateUpdateFetcherRequest(backup_url_fetcher, kBackupHttpUrlPrefix, "");
596 // Respond to the backup successfully.
597 backup_url_fetcher->set_status(net::URLRequestStatus());
598 backup_url_fetcher->set_response_code(200);
599 backup_url_fetcher->SetResponseString(std::string());
600 backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
602 EXPECT_TRUE(pm->IsUpdateScheduled());
605 // Tests what happens when there is an HTTP error response to the update
606 // request, and a timeout on the backup update request.
607 TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseHttpErrorBackupTimeout) {
608 scoped_refptr<base::TestSimpleTaskRunner> runner(
609 new base::TestSimpleTaskRunner());
610 base::ThreadTaskRunnerHandle runner_handler(runner);
611 net::TestURLFetcherFactory url_fetcher_factory;
613 testing::StrictMock<MockProtocolDelegate> test_delegate;
614 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
615 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
616 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
617 std::vector<SBListChunkRanges>(),
618 false)));
619 EXPECT_CALL(test_delegate, UpdateFinished(false)).Times(1);
621 scoped_ptr<SafeBrowsingProtocolManager> pm(
622 CreateProtocolManager(&test_delegate));
624 // Kick off initialization. This returns chunks from the DB synchronously.
625 pm->ForceScheduleNextUpdate(TimeDelta());
626 runner->RunPendingTasks();
628 // We should have an URLFetcher at this point in time.
629 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
630 ValidateUpdateFetcherRequest(url_fetcher);
632 // Go ahead and respond to it.
633 url_fetcher->set_status(net::URLRequestStatus());
634 url_fetcher->set_response_code(404);
635 url_fetcher->SetResponseString(std::string());
636 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
638 // There should now be a backup request.
639 net::TestURLFetcher* backup_url_fetcher =
640 url_fetcher_factory.GetFetcherByID(1);
641 ValidateUpdateFetcherRequest(backup_url_fetcher, kBackupHttpUrlPrefix, "");
643 // Either one or two calls to RunPendingTasks are needed here. The first run
644 // of RunPendingTasks will run the canceled timeout task associated with
645 // the first Update request. Depending on timing, this will either directly
646 // call the timeout task from the backup request, or schedule another task
647 // to run that in the future.
648 // TODO(cbentzel): Less fragile approach.
649 runner->RunPendingTasks();
650 if (!pm->IsUpdateScheduled())
651 runner->RunPendingTasks();
652 EXPECT_TRUE(pm->IsUpdateScheduled());
655 // Tests what happens when there is a connection error when issuing the update
656 // request, and an error with the backup update request.
657 TEST_F(SafeBrowsingProtocolManagerTest,
658 UpdateResponseConnectionErrorBackupError) {
659 scoped_refptr<base::TestSimpleTaskRunner> runner(
660 new base::TestSimpleTaskRunner());
661 base::ThreadTaskRunnerHandle runner_handler(runner);
662 net::TestURLFetcherFactory url_fetcher_factory;
664 testing::StrictMock<MockProtocolDelegate> test_delegate;
665 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
666 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
667 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
668 std::vector<SBListChunkRanges>(),
669 false)));
670 EXPECT_CALL(test_delegate, UpdateFinished(false)).Times(1);
672 scoped_ptr<SafeBrowsingProtocolManager> pm(
673 CreateProtocolManager(&test_delegate));
675 // Kick off initialization. This returns chunks from the DB synchronously.
676 pm->ForceScheduleNextUpdate(TimeDelta());
677 runner->RunPendingTasks();
679 // We should have an URLFetcher at this point in time.
680 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
681 ValidateUpdateFetcherRequest(url_fetcher);
683 // Go ahead and respond to it.
684 url_fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::FAILED,
685 net::ERR_CONNECTION_RESET));
686 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
688 // There should be a backup URLFetcher now.
689 net::TestURLFetcher* backup_url_fetcher =
690 url_fetcher_factory.GetFetcherByID(1);
691 ValidateUpdateFetcherRequest(backup_url_fetcher, kBackupConnectUrlPrefix, "");
693 // Respond to the backup unsuccessfully.
694 backup_url_fetcher->set_status(net::URLRequestStatus());
695 backup_url_fetcher->set_response_code(404);
696 backup_url_fetcher->SetResponseString(std::string());
697 backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
699 EXPECT_TRUE(pm->IsUpdateScheduled());
702 // Tests what happens when there is a connection error when issuing the update
703 // request, and a successful response to the backup update request.
704 TEST_F(SafeBrowsingProtocolManagerTest,
705 UpdateResponseConnectionErrorBackupSuccess) {
706 scoped_refptr<base::TestSimpleTaskRunner> runner(
707 new base::TestSimpleTaskRunner());
708 base::ThreadTaskRunnerHandle runner_handler(runner);
709 net::TestURLFetcherFactory url_fetcher_factory;
711 testing::StrictMock<MockProtocolDelegate> test_delegate;
712 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
713 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
714 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
715 std::vector<SBListChunkRanges>(),
716 false)));
717 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
719 scoped_ptr<SafeBrowsingProtocolManager> pm(
720 CreateProtocolManager(&test_delegate));
722 // Kick off initialization. This returns chunks from the DB synchronously.
723 pm->ForceScheduleNextUpdate(TimeDelta());
724 runner->RunPendingTasks();
726 // We should have an URLFetcher at this point in time.
727 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
728 ValidateUpdateFetcherRequest(url_fetcher);
730 // Go ahead and respond to it.
731 url_fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::FAILED,
732 net::ERR_CONNECTION_RESET));
733 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
735 // There should be a backup URLFetcher now.
736 net::TestURLFetcher* backup_url_fetcher =
737 url_fetcher_factory.GetFetcherByID(1);
738 ValidateUpdateFetcherRequest(backup_url_fetcher, kBackupConnectUrlPrefix, "");
740 // Respond to the backup unsuccessfully.
741 backup_url_fetcher->set_status(net::URLRequestStatus());
742 backup_url_fetcher->set_response_code(200);
743 backup_url_fetcher->SetResponseString(std::string());
744 backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
746 EXPECT_TRUE(pm->IsUpdateScheduled());
748 // Tests what happens when there is a network state error when issuing the
749 // update request, and an error with the backup update request.
750 TEST_F(SafeBrowsingProtocolManagerTest,
751 UpdateResponseNetworkErrorBackupError) {
752 scoped_refptr<base::TestSimpleTaskRunner> runner(
753 new base::TestSimpleTaskRunner());
754 base::ThreadTaskRunnerHandle runner_handler(runner);
755 net::TestURLFetcherFactory url_fetcher_factory;
757 testing::StrictMock<MockProtocolDelegate> test_delegate;
758 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
759 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
760 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
761 std::vector<SBListChunkRanges>(),
762 false)));
763 EXPECT_CALL(test_delegate, UpdateFinished(false)).Times(1);
765 scoped_ptr<SafeBrowsingProtocolManager> pm(
766 CreateProtocolManager(&test_delegate));
768 // Kick off initialization. This returns chunks from the DB synchronously.
769 pm->ForceScheduleNextUpdate(TimeDelta());
770 runner->RunPendingTasks();
772 // We should have an URLFetcher at this point in time.
773 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
774 ValidateUpdateFetcherRequest(url_fetcher);
776 // Go ahead and respond to it.
777 url_fetcher->set_status(
778 net::URLRequestStatus(net::URLRequestStatus::FAILED,
779 net::ERR_INTERNET_DISCONNECTED));
780 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
782 // There should be a backup URLFetcher now.
783 net::TestURLFetcher* backup_url_fetcher =
784 url_fetcher_factory.GetFetcherByID(1);
785 ValidateUpdateFetcherRequest(backup_url_fetcher, kBackupNetworkUrlPrefix, "");
787 // Respond to the backup unsuccessfully.
788 backup_url_fetcher->set_status(net::URLRequestStatus());
789 backup_url_fetcher->set_response_code(404);
790 backup_url_fetcher->SetResponseString(std::string());
791 backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
793 EXPECT_TRUE(pm->IsUpdateScheduled());
796 // Tests what happens when there is a network state error when issuing the
797 // update request, and a successful response to the backup update request.
798 TEST_F(SafeBrowsingProtocolManagerTest,
799 UpdateResponseNetworkErrorBackupSuccess) {
800 scoped_refptr<base::TestSimpleTaskRunner> runner(
801 new base::TestSimpleTaskRunner());
802 base::ThreadTaskRunnerHandle runner_handler(runner);
803 net::TestURLFetcherFactory url_fetcher_factory;
805 testing::StrictMock<MockProtocolDelegate> test_delegate;
806 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
807 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
808 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
809 std::vector<SBListChunkRanges>(),
810 false)));
811 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
813 scoped_ptr<SafeBrowsingProtocolManager> pm(
814 CreateProtocolManager(&test_delegate));
816 // Kick off initialization. This returns chunks from the DB synchronously.
817 pm->ForceScheduleNextUpdate(TimeDelta());
818 runner->RunPendingTasks();
820 // We should have an URLFetcher at this point in time.
821 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
822 ValidateUpdateFetcherRequest(url_fetcher);
824 // Go ahead and respond to it.
825 url_fetcher->set_status(
826 net::URLRequestStatus(net::URLRequestStatus::FAILED,
827 net::ERR_INTERNET_DISCONNECTED));
828 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
830 // There should be a backup URLFetcher now.
831 net::TestURLFetcher* backup_url_fetcher =
832 url_fetcher_factory.GetFetcherByID(1);
833 ValidateUpdateFetcherRequest(backup_url_fetcher, kBackupNetworkUrlPrefix, "");
835 // Respond to the backup unsuccessfully.
836 backup_url_fetcher->set_status(net::URLRequestStatus());
837 backup_url_fetcher->set_response_code(200);
838 backup_url_fetcher->SetResponseString(std::string());
839 backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
841 EXPECT_TRUE(pm->IsUpdateScheduled());
844 // Tests what happens when there is a timeout before an update response.
845 TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseTimeoutBackupSuccess) {
846 scoped_refptr<base::TestSimpleTaskRunner> runner(
847 new base::TestSimpleTaskRunner());
848 base::ThreadTaskRunnerHandle runner_handler(runner);
849 net::TestURLFetcherFactory url_fetcher_factory;
851 testing::StrictMock<MockProtocolDelegate> test_delegate;
852 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
853 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
854 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
855 std::vector<SBListChunkRanges>(),
856 false)));
857 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
859 scoped_ptr<SafeBrowsingProtocolManager> pm(
860 CreateProtocolManager(&test_delegate));
862 // Kick off initialization. This returns chunks from the DB synchronously.
863 pm->ForceScheduleNextUpdate(TimeDelta());
864 runner->RunPendingTasks();
866 // We should have an URLFetcher at this point in time.
867 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
868 ValidateUpdateFetcherRequest(url_fetcher);
870 // The first time RunPendingTasks is called above, the update timeout timer is
871 // not handled. This call of RunPendingTasks will handle the update.
872 runner->RunPendingTasks();
874 // There should be a backup URLFetcher now.
875 net::TestURLFetcher* backup_url_fetcher =
876 url_fetcher_factory.GetFetcherByID(1);
877 ValidateUpdateFetcherRequest(backup_url_fetcher, kBackupConnectUrlPrefix, "");
879 // Respond to the backup unsuccessfully.
880 backup_url_fetcher->set_status(net::URLRequestStatus());
881 backup_url_fetcher->set_response_code(200);
882 backup_url_fetcher->SetResponseString(std::string());
883 backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
885 EXPECT_TRUE(pm->IsUpdateScheduled());
888 // Tests what happens when there is a reset command in the response.
889 TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseReset) {
890 scoped_refptr<base::TestSimpleTaskRunner> runner(
891 new base::TestSimpleTaskRunner());
892 base::ThreadTaskRunnerHandle runner_handler(runner);
893 net::TestURLFetcherFactory url_fetcher_factory;
895 testing::StrictMock<MockProtocolDelegate> test_delegate;
896 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
897 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
898 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
899 std::vector<SBListChunkRanges>(),
900 false)));
901 EXPECT_CALL(test_delegate, ResetDatabase()).Times(1);
902 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
904 scoped_ptr<SafeBrowsingProtocolManager> pm(
905 CreateProtocolManager(&test_delegate));
907 // Kick off initialization. This returns chunks from the DB synchronously.
908 pm->ForceScheduleNextUpdate(TimeDelta());
909 runner->RunPendingTasks();
911 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
912 ValidateUpdateFetcherRequest(url_fetcher);
914 // The update response is successful, and has a reset command.
915 url_fetcher->set_status(net::URLRequestStatus());
916 url_fetcher->set_response_code(200);
917 url_fetcher->SetResponseString("r:pleasereset\n");
918 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
920 EXPECT_TRUE(pm->IsUpdateScheduled());
923 // Tests a single valid update response, followed by a single redirect response
924 // that has an valid, but empty body.
925 TEST_F(SafeBrowsingProtocolManagerTest, EmptyRedirectResponse) {
926 scoped_refptr<base::TestSimpleTaskRunner> runner(
927 new base::TestSimpleTaskRunner());
928 base::ThreadTaskRunnerHandle runner_handler(runner);
929 net::TestURLFetcherFactory url_fetcher_factory;
931 testing::StrictMock<MockProtocolDelegate> test_delegate;
932 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
933 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
934 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
935 std::vector<SBListChunkRanges>(),
936 false)));
937 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
939 scoped_ptr<SafeBrowsingProtocolManager> pm(
940 CreateProtocolManager(&test_delegate));
942 // Kick off initialization. This returns chunks from the DB synchronously.
943 pm->ForceScheduleNextUpdate(TimeDelta());
944 runner->RunPendingTasks();
946 // The update response contains a single redirect command.
947 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
948 ValidateUpdateFetcherRequest(url_fetcher);
949 url_fetcher->set_status(net::URLRequestStatus());
950 url_fetcher->set_response_code(200);
951 url_fetcher->SetResponseString(
952 base::StringPrintf("i:%s\n"
953 "u:redirect-server.example.com/path\n",
954 kDefaultPhishList));
955 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
957 // The redirect response contains an empty body.
958 net::TestURLFetcher* chunk_url_fetcher =
959 url_fetcher_factory.GetFetcherByID(1);
960 ValidateRedirectFetcherRequest(
961 chunk_url_fetcher, "https://redirect-server.example.com/path");
962 chunk_url_fetcher->set_status(net::URLRequestStatus());
963 chunk_url_fetcher->set_response_code(200);
964 chunk_url_fetcher->SetResponseString(std::string());
965 chunk_url_fetcher->delegate()->OnURLFetchComplete(chunk_url_fetcher);
967 EXPECT_TRUE(pm->IsUpdateScheduled());
970 // Tests a single valid update response, followed by a single redirect response
971 // that has an invalid body.
972 TEST_F(SafeBrowsingProtocolManagerTest, InvalidRedirectResponse) {
973 scoped_refptr<base::TestSimpleTaskRunner> runner(
974 new base::TestSimpleTaskRunner());
975 base::ThreadTaskRunnerHandle runner_handler(runner);
976 net::TestURLFetcherFactory url_fetcher_factory;
978 testing::StrictMock<MockProtocolDelegate> test_delegate;
979 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
980 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
981 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
982 std::vector<SBListChunkRanges>(),
983 false)));
984 EXPECT_CALL(test_delegate, UpdateFinished(false)).Times(1);
986 scoped_ptr<SafeBrowsingProtocolManager> pm(
987 CreateProtocolManager(&test_delegate));
989 // Kick off initialization. This returns chunks from the DB synchronously.
990 pm->ForceScheduleNextUpdate(TimeDelta());
991 runner->RunPendingTasks();
993 // The update response contains a single redirect command.
994 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
995 ValidateUpdateFetcherRequest(url_fetcher);
996 url_fetcher->set_status(net::URLRequestStatus());
997 url_fetcher->set_response_code(200);
998 url_fetcher->SetResponseString(
999 base::StringPrintf("i:%s\n"
1000 "u:redirect-server.example.com/path\n",
1001 kDefaultPhishList));
1002 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
1004 // The redirect response contains an invalid body.
1005 net::TestURLFetcher* chunk_url_fetcher =
1006 url_fetcher_factory.GetFetcherByID(1);
1007 ValidateRedirectFetcherRequest(
1008 chunk_url_fetcher, "https://redirect-server.example.com/path");
1009 chunk_url_fetcher->set_status(net::URLRequestStatus());
1010 chunk_url_fetcher->set_response_code(200);
1011 chunk_url_fetcher->SetResponseString("THIS IS AN INVALID RESPONSE");
1012 chunk_url_fetcher->delegate()->OnURLFetchComplete(chunk_url_fetcher);
1014 EXPECT_TRUE(pm->IsUpdateScheduled());
1017 // Tests a single valid update response, followed by a single redirect response
1018 // containing chunks.
1019 TEST_F(SafeBrowsingProtocolManagerTest, SingleRedirectResponseWithChunks) {
1020 scoped_refptr<base::TestSimpleTaskRunner> runner(
1021 new base::TestSimpleTaskRunner());
1022 base::ThreadTaskRunnerHandle runner_handler(runner);
1023 net::TestURLFetcherFactory url_fetcher_factory;
1025 testing::StrictMock<MockProtocolDelegate> test_delegate;
1026 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
1027 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
1028 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
1029 std::vector<SBListChunkRanges>(),
1030 false)));
1031 EXPECT_CALL(test_delegate, AddChunksRaw(kDefaultPhishList, _, _)).WillOnce(
1032 Invoke(HandleAddChunks));
1033 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
1035 scoped_ptr<SafeBrowsingProtocolManager> pm(
1036 CreateProtocolManager(&test_delegate));
1038 // Kick off initialization. This returns chunks from the DB synchronously.
1039 pm->ForceScheduleNextUpdate(TimeDelta());
1040 runner->RunPendingTasks();
1042 // The update response contains a single redirect command.
1043 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
1044 ValidateUpdateFetcherRequest(url_fetcher);
1045 url_fetcher->set_status(net::URLRequestStatus());
1046 url_fetcher->set_response_code(200);
1047 url_fetcher->SetResponseString(
1048 base::StringPrintf("i:%s\n"
1049 "u:redirect-server.example.com/path\n",
1050 kDefaultPhishList));
1051 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
1053 // The redirect response contains a single chunk.
1054 net::TestURLFetcher* chunk_url_fetcher =
1055 url_fetcher_factory.GetFetcherByID(1);
1056 ValidateRedirectFetcherRequest(
1057 chunk_url_fetcher, "https://redirect-server.example.com/path");
1058 chunk_url_fetcher->set_status(net::URLRequestStatus());
1059 chunk_url_fetcher->set_response_code(200);
1060 chunk_url_fetcher->SetResponseString(kChunkPayload1);
1061 chunk_url_fetcher->delegate()->OnURLFetchComplete(chunk_url_fetcher);
1063 EXPECT_FALSE(pm->IsUpdateScheduled());
1065 // The AddChunksCallback needs to be invoked.
1066 runner->RunPendingTasks();
1068 EXPECT_TRUE(pm->IsUpdateScheduled());
1071 // Tests a single valid update response, followed by multiple redirect responses
1072 // containing chunks.
1073 TEST_F(SafeBrowsingProtocolManagerTest, MultipleRedirectResponsesWithChunks) {
1074 scoped_refptr<base::TestSimpleTaskRunner> runner(
1075 new base::TestSimpleTaskRunner());
1076 base::ThreadTaskRunnerHandle runner_handler(runner);
1077 net::TestURLFetcherFactory url_fetcher_factory;
1079 testing::StrictMock<MockProtocolDelegate> test_delegate;
1080 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
1081 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
1082 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
1083 std::vector<SBListChunkRanges>(),
1084 false)));
1085 EXPECT_CALL(test_delegate, AddChunksRaw(kDefaultPhishList, _, _)).
1086 WillRepeatedly(Invoke(HandleAddChunks));
1087 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
1089 scoped_ptr<SafeBrowsingProtocolManager> pm(
1090 CreateProtocolManager(&test_delegate));
1092 // Kick off initialization. This returns chunks from the DB synchronously.
1093 pm->ForceScheduleNextUpdate(TimeDelta());
1094 runner->RunPendingTasks();
1096 // The update response contains multiple redirect commands.
1097 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
1098 ValidateUpdateFetcherRequest(url_fetcher);
1099 url_fetcher->set_status(net::URLRequestStatus());
1100 url_fetcher->set_response_code(200);
1101 url_fetcher->SetResponseString(
1102 base::StringPrintf("i:%s\n"
1103 "u:redirect-server.example.com/one\n"
1104 "u:redirect-server.example.com/two\n",
1105 kDefaultPhishList));
1106 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
1108 // The first redirect response contains a single chunk.
1109 net::TestURLFetcher* first_chunk_url_fetcher =
1110 url_fetcher_factory.GetFetcherByID(1);
1111 ValidateRedirectFetcherRequest(
1112 first_chunk_url_fetcher, "https://redirect-server.example.com/one");
1113 first_chunk_url_fetcher->set_status(net::URLRequestStatus());
1114 first_chunk_url_fetcher->set_response_code(200);
1115 first_chunk_url_fetcher->SetResponseString(kChunkPayload1);
1116 first_chunk_url_fetcher->delegate()->OnURLFetchComplete(
1117 first_chunk_url_fetcher);
1119 // Invoke the AddChunksCallback to trigger the second request.
1120 runner->RunPendingTasks();
1122 EXPECT_FALSE(pm->IsUpdateScheduled());
1124 // The second redirect response contains a single chunk.
1125 net::TestURLFetcher* second_chunk_url_fetcher =
1126 url_fetcher_factory.GetFetcherByID(2);
1127 ValidateRedirectFetcherRequest(
1128 second_chunk_url_fetcher, "https://redirect-server.example.com/two");
1129 second_chunk_url_fetcher->set_status(net::URLRequestStatus());
1130 second_chunk_url_fetcher->set_response_code(200);
1131 second_chunk_url_fetcher->SetResponseString(kChunkPayload2);
1132 second_chunk_url_fetcher->delegate()->OnURLFetchComplete(
1133 second_chunk_url_fetcher);
1135 EXPECT_FALSE(pm->IsUpdateScheduled());
1137 // Invoke the AddChunksCallback to finish the update.
1138 runner->RunPendingTasks();
1140 EXPECT_TRUE(pm->IsUpdateScheduled());