Add ICU message format support
[chromium-blink-merge.git] / chrome / browser / safe_browsing / protocol_manager_unittest.cc
blob852a20d420e5316dd357f8a5e2a4346ab9483377
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";
39 #if defined(OS_ANDROID)
40 const char kDefaultPhishList[] = "goog-mobilephish-shavar";
41 const char kDefaultMalwareList[] = "goog-mobilemalware-shavar";
42 #else
43 const char kDefaultPhishList[] = "goog-phish-shavar";
44 const char kDefaultMalwareList[] = "goog-malware-shavar";
45 #endif
47 // Add-prefix chunk with single prefix.
48 const char kRawChunkPayload1[] = {
49 '\0', '\0', '\0', '\x08', // 32-bit payload length in network byte order.
50 '\x08', // field 1, wire format varint
51 '\x03', // chunk_number varint 3
52 '\x22', // field 4, wire format length-delimited
53 '\x04', // varint 4 length
54 'a', 'b', 'c', 'd' // 4-byte prefix
56 const std::string kChunkPayload1(kRawChunkPayload1, sizeof(kRawChunkPayload1));
58 // Add-prefix chunk_number 5 with single prefix.
59 const char kRawChunkPayload2[] = {
60 '\0', '\0', '\0', '\x08', // 32-bit payload length in network byte order.
61 '\x08', // field 1, wire format varint
62 '\x05', // chunk_number varint 5
63 '\x22', // field 4, wire format length-delimited
64 '\x04', // varint length 4
65 'e', 'f', 'g', 'h' // 4-byte prefix
67 const std::string kChunkPayload2(kRawChunkPayload2, sizeof(kRawChunkPayload2));
69 } // namespace
71 class SafeBrowsingProtocolManagerTest : public testing::Test {
72 protected:
73 std::string key_param_;
75 void SetUp() override {
76 std::string key = google_apis::GetAPIKey();
77 if (!key.empty()) {
78 key_param_ = base::StringPrintf(
79 "&key=%s",
80 net::EscapeQueryParamValue(key, true).c_str());
84 scoped_ptr<SafeBrowsingProtocolManager> CreateProtocolManager(
85 SafeBrowsingProtocolManagerDelegate* delegate) {
86 SafeBrowsingProtocolConfig config;
87 config.client_name = kClient;
88 config.url_prefix = kUrlPrefix;
89 config.backup_connect_error_url_prefix = kBackupConnectUrlPrefix;
90 config.backup_http_error_url_prefix = kBackupHttpUrlPrefix;
91 config.backup_network_error_url_prefix = kBackupNetworkUrlPrefix;
92 config.version = kAppVer;
93 #if defined(OS_ANDROID)
94 config.disable_connection_check = true;
95 #endif
96 return scoped_ptr<SafeBrowsingProtocolManager>(
97 SafeBrowsingProtocolManager::Create(delegate, NULL, config));
100 void ValidateUpdateFetcherRequest(
101 const net::TestURLFetcher* url_fetcher,
102 const std::string& expected_prefix) {
103 ASSERT_TRUE(url_fetcher);
104 EXPECT_EQ(net::LOAD_DISABLE_CACHE, url_fetcher->GetLoadFlags());
106 std::string expected_lists(base::StringPrintf("%s;\n%s;\n",
107 kDefaultPhishList,
108 kDefaultMalwareList));
109 EXPECT_EQ(expected_lists, url_fetcher->upload_data());
110 EXPECT_EQ(GURL(expected_prefix + "/downloads?client=unittest&appver=1.0"
111 "&pver=3.0" + key_param_),
112 url_fetcher->GetOriginalURL());
115 void ValidateUpdateFetcherRequest(const net::TestURLFetcher* url_fetcher) {
116 ValidateUpdateFetcherRequest(url_fetcher, kUrlPrefix);
119 void ValidateRedirectFetcherRequest(const net::TestURLFetcher* url_fetcher,
120 const std::string& expected_url) {
121 ASSERT_TRUE(url_fetcher);
122 EXPECT_EQ(net::LOAD_DISABLE_CACHE, url_fetcher->GetLoadFlags());
123 EXPECT_EQ("", url_fetcher->upload_data());
124 EXPECT_EQ(GURL(expected_url), url_fetcher->GetOriginalURL());
128 // Ensure that we respect section 5 of the SafeBrowsing protocol specification.
129 TEST_F(SafeBrowsingProtocolManagerTest, TestBackOffTimes) {
130 scoped_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL));
132 pm->next_update_interval_ = TimeDelta::FromSeconds(1800);
133 ASSERT_TRUE(pm->back_off_fuzz_ >= 0.0 && pm->back_off_fuzz_ <= 1.0);
135 TimeDelta next;
137 // No errors received so far.
138 next = pm->GetNextUpdateInterval(false);
139 EXPECT_EQ(next, TimeDelta::FromSeconds(1800));
141 // 1 error.
142 next = pm->GetNextUpdateInterval(true);
143 EXPECT_EQ(next, TimeDelta::FromSeconds(60));
145 // 2 errors.
146 next = pm->GetNextUpdateInterval(true);
147 EXPECT_TRUE(next >= TimeDelta::FromMinutes(30) &&
148 next <= TimeDelta::FromMinutes(60));
150 // 3 errors.
151 next = pm->GetNextUpdateInterval(true);
152 EXPECT_TRUE(next >= TimeDelta::FromMinutes(60) &&
153 next <= TimeDelta::FromMinutes(120));
155 // 4 errors.
156 next = pm->GetNextUpdateInterval(true);
157 EXPECT_TRUE(next >= TimeDelta::FromMinutes(120) &&
158 next <= TimeDelta::FromMinutes(240));
160 // 5 errors.
161 next = pm->GetNextUpdateInterval(true);
162 EXPECT_TRUE(next >= TimeDelta::FromMinutes(240) &&
163 next <= TimeDelta::FromMinutes(480));
165 // 6 errors, reached max backoff.
166 next = pm->GetNextUpdateInterval(true);
167 EXPECT_EQ(next, TimeDelta::FromMinutes(480));
169 // 7 errors.
170 next = pm->GetNextUpdateInterval(true);
171 EXPECT_EQ(next, TimeDelta::FromMinutes(480));
173 // Received a successful response.
174 next = pm->GetNextUpdateInterval(false);
175 EXPECT_EQ(next, TimeDelta::FromSeconds(1800));
178 TEST_F(SafeBrowsingProtocolManagerTest, TestChunkStrings) {
179 scoped_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL));
181 // Add and Sub chunks.
182 SBListChunkRanges phish(kDefaultPhishList);
183 phish.adds = "1,4,6,8-20,99";
184 phish.subs = "16,32,64-96";
185 EXPECT_EQ(base::StringPrintf("%s;a:1,4,6,8-20,99:s:16,32,64-96\n",
186 kDefaultPhishList),
187 safe_browsing::FormatList(phish));
189 // Add chunks only.
190 phish.subs = "";
191 EXPECT_EQ(base::StringPrintf("%s;a:1,4,6,8-20,99\n",
192 kDefaultPhishList),
193 safe_browsing::FormatList(phish));
195 // Sub chunks only.
196 phish.adds = "";
197 phish.subs = "16,32,64-96";
198 EXPECT_EQ(base::StringPrintf("%s;s:16,32,64-96\n",
199 kDefaultPhishList),
200 safe_browsing::FormatList(phish));
202 // No chunks of either type.
203 phish.adds = "";
204 phish.subs = "";
205 EXPECT_EQ(base::StringPrintf("%s;\n", kDefaultPhishList),
206 safe_browsing::FormatList(phish));
209 TEST_F(SafeBrowsingProtocolManagerTest, TestGetHashBackOffTimes) {
210 scoped_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL));
212 // No errors or back off time yet.
213 EXPECT_EQ(0U, pm->gethash_error_count_);
214 EXPECT_TRUE(pm->next_gethash_time_.is_null());
216 Time now = Time::Now();
218 // 1 error.
219 pm->HandleGetHashError(now);
220 EXPECT_EQ(1U, pm->gethash_error_count_);
221 TimeDelta margin = TimeDelta::FromSeconds(5); // Fudge factor.
222 Time future = now + TimeDelta::FromMinutes(1);
223 EXPECT_TRUE(pm->next_gethash_time_ >= future - margin &&
224 pm->next_gethash_time_ <= future + margin);
226 // 2 errors.
227 pm->HandleGetHashError(now);
228 EXPECT_EQ(2U, pm->gethash_error_count_);
229 EXPECT_TRUE(pm->next_gethash_time_ >= now + TimeDelta::FromMinutes(30));
230 EXPECT_TRUE(pm->next_gethash_time_ <= now + TimeDelta::FromMinutes(60));
232 // 3 errors.
233 pm->HandleGetHashError(now);
234 EXPECT_EQ(3U, pm->gethash_error_count_);
235 EXPECT_TRUE(pm->next_gethash_time_ >= now + TimeDelta::FromMinutes(60));
236 EXPECT_TRUE(pm->next_gethash_time_ <= now + TimeDelta::FromMinutes(120));
238 // 4 errors.
239 pm->HandleGetHashError(now);
240 EXPECT_EQ(4U, pm->gethash_error_count_);
241 EXPECT_TRUE(pm->next_gethash_time_ >= now + TimeDelta::FromMinutes(120));
242 EXPECT_TRUE(pm->next_gethash_time_ <= now + TimeDelta::FromMinutes(240));
244 // 5 errors.
245 pm->HandleGetHashError(now);
246 EXPECT_EQ(5U, pm->gethash_error_count_);
247 EXPECT_TRUE(pm->next_gethash_time_ >= now + TimeDelta::FromMinutes(240));
248 EXPECT_TRUE(pm->next_gethash_time_ <= now + TimeDelta::FromMinutes(480));
250 // 6 errors, reached max backoff.
251 pm->HandleGetHashError(now);
252 EXPECT_EQ(6U, pm->gethash_error_count_);
253 EXPECT_TRUE(pm->next_gethash_time_ == now + TimeDelta::FromMinutes(480));
255 // 7 errors.
256 pm->HandleGetHashError(now);
257 EXPECT_EQ(7U, pm->gethash_error_count_);
258 EXPECT_TRUE(pm->next_gethash_time_== now + TimeDelta::FromMinutes(480));
261 TEST_F(SafeBrowsingProtocolManagerTest, TestGetHashUrl) {
262 scoped_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL));
264 EXPECT_EQ("https://prefix.com/foo/gethash?client=unittest&appver=1.0&"
265 "pver=3.0" + key_param_, pm->GetHashUrl().spec());
267 pm->set_additional_query(kAdditionalQuery);
268 EXPECT_EQ("https://prefix.com/foo/gethash?client=unittest&appver=1.0&"
269 "pver=3.0" + key_param_ + "&additional_query",
270 pm->GetHashUrl().spec());
273 TEST_F(SafeBrowsingProtocolManagerTest, TestUpdateUrl) {
274 scoped_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL));
276 EXPECT_EQ("https://prefix.com/foo/downloads?client=unittest&appver=1.0&"
277 "pver=3.0" + key_param_, pm->UpdateUrl().spec());
279 pm->set_additional_query(kAdditionalQuery);
280 EXPECT_EQ("https://prefix.com/foo/downloads?client=unittest&appver=1.0&"
281 "pver=3.0" + key_param_ + "&additional_query",
282 pm->UpdateUrl().spec());
285 TEST_F(SafeBrowsingProtocolManagerTest, TestNextChunkUrl) {
286 scoped_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL));
288 std::string url_partial = "localhost:1234/foo/bar?foo";
289 std::string url_http_full = "http://localhost:1234/foo/bar?foo";
290 std::string url_https_full = "https://localhost:1234/foo/bar?foo";
291 std::string url_https_no_query = "https://localhost:1234/foo/bar";
293 EXPECT_EQ("https://localhost:1234/foo/bar?foo",
294 pm->NextChunkUrl(url_partial).spec());
295 EXPECT_EQ("http://localhost:1234/foo/bar?foo",
296 pm->NextChunkUrl(url_http_full).spec());
297 EXPECT_EQ("https://localhost:1234/foo/bar?foo",
298 pm->NextChunkUrl(url_https_full).spec());
299 EXPECT_EQ("https://localhost:1234/foo/bar",
300 pm->NextChunkUrl(url_https_no_query).spec());
302 pm->set_additional_query(kAdditionalQuery);
303 EXPECT_EQ("https://localhost:1234/foo/bar?foo&additional_query",
304 pm->NextChunkUrl(url_partial).spec());
305 EXPECT_EQ("http://localhost:1234/foo/bar?foo&additional_query",
306 pm->NextChunkUrl(url_http_full).spec());
307 EXPECT_EQ("https://localhost:1234/foo/bar?foo&additional_query",
308 pm->NextChunkUrl(url_https_full).spec());
309 EXPECT_EQ("https://localhost:1234/foo/bar?additional_query",
310 pm->NextChunkUrl(url_https_no_query).spec());
313 namespace {
315 class MockProtocolDelegate : public SafeBrowsingProtocolManagerDelegate {
316 public:
317 MockProtocolDelegate() {}
318 ~MockProtocolDelegate() override {}
320 MOCK_METHOD0(UpdateStarted, void());
321 MOCK_METHOD1(UpdateFinished, void(bool));
322 MOCK_METHOD0(ResetDatabase, void());
323 MOCK_METHOD1(GetChunks, void(GetChunksCallback));
325 // gmock does not work with scoped_ptr<> at this time. Add a local method to
326 // mock, then call that from an override. Beware of object ownership when
327 // making changes here.
328 MOCK_METHOD3(AddChunksRaw, void(const std::string& lists,
329 const ScopedVector<SBChunkData>& chunks,
330 AddChunksCallback));
331 void AddChunks(const std::string& list,
332 scoped_ptr<ScopedVector<SBChunkData>> chunks,
333 AddChunksCallback callback) override {
334 AddChunksRaw(list, *chunks, callback);
337 // TODO(shess): Actually test this case somewhere.
338 MOCK_METHOD1(DeleteChunksRaw,
339 void(const std::vector<SBChunkDelete>& chunk_deletes));
340 void DeleteChunks(
341 scoped_ptr<std::vector<SBChunkDelete>> chunk_deletes) override {
342 DeleteChunksRaw(*chunk_deletes);
346 // |InvokeGetChunksCallback| is required because GMock's InvokeArgument action
347 // expects to use operator(), and a Callback only provides Run().
348 // TODO(cbentzel): Use ACTION or ACTION_TEMPLATE instead?
349 void InvokeGetChunksCallback(
350 const std::vector<SBListChunkRanges>& ranges,
351 bool database_error,
352 SafeBrowsingProtocolManagerDelegate::GetChunksCallback callback) {
353 callback.Run(ranges, database_error);
356 // |HandleAddChunks| deletes the chunks and asynchronously invokes
357 // |callback| since SafeBrowsingProtocolManager is not re-entrant at the time
358 // this is called. This guarantee is part of the
359 // SafeBrowsingProtocolManagerDelegate contract.
360 void HandleAddChunks(
361 const std::string& unused_list,
362 const ScopedVector<SBChunkData>& chunks,
363 SafeBrowsingProtocolManagerDelegate::AddChunksCallback callback) {
364 scoped_refptr<base::SingleThreadTaskRunner> task_runner(
365 base::ThreadTaskRunnerHandle::Get());
366 if (!task_runner.get())
367 return;
368 task_runner->PostTask(FROM_HERE, callback);
371 } // namespace
373 // Tests that the Update protocol will be skipped if there are problems
374 // accessing the database.
375 TEST_F(SafeBrowsingProtocolManagerTest, ProblemAccessingDatabase) {
376 scoped_refptr<base::TestSimpleTaskRunner> runner(
377 new base::TestSimpleTaskRunner());
378 base::ThreadTaskRunnerHandle runner_handler(runner);
380 testing::StrictMock<MockProtocolDelegate> test_delegate;
381 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
382 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
383 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
384 std::vector<SBListChunkRanges>(),
385 true)));
386 EXPECT_CALL(test_delegate, UpdateFinished(false)).Times(1);
388 scoped_ptr<SafeBrowsingProtocolManager> pm(
389 CreateProtocolManager(&test_delegate));
391 pm->ForceScheduleNextUpdate(TimeDelta());
392 runner->RunPendingTasks();
394 EXPECT_TRUE(pm->IsUpdateScheduled());
397 // Tests the contents of the POST body when there are contents in the
398 // local database. This is not exhaustive, as the actual list formatting
399 // is covered by SafeBrowsingProtocolManagerTest.TestChunkStrings.
400 TEST_F(SafeBrowsingProtocolManagerTest, ExistingDatabase) {
401 scoped_refptr<base::TestSimpleTaskRunner> runner(
402 new base::TestSimpleTaskRunner());
403 base::ThreadTaskRunnerHandle runner_handler(runner);
404 net::TestURLFetcherFactory url_fetcher_factory;
406 std::vector<SBListChunkRanges> ranges;
407 SBListChunkRanges range_phish(safe_browsing_util::kPhishingList);
408 range_phish.adds = "adds_phish";
409 range_phish.subs = "subs_phish";
410 ranges.push_back(range_phish);
412 SBListChunkRanges range_unknown("unknown_list");
413 range_unknown.adds = "adds_unknown";
414 range_unknown.subs = "subs_unknown";
415 ranges.push_back(range_unknown);
417 testing::StrictMock<MockProtocolDelegate> test_delegate;
418 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
419 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
420 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
421 ranges,
422 false)));
423 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
425 scoped_ptr<SafeBrowsingProtocolManager> pm(
426 CreateProtocolManager(&test_delegate));
428 // Kick off initialization. This returns chunks from the DB synchronously.
429 pm->ForceScheduleNextUpdate(TimeDelta());
430 runner->RunPendingTasks();
432 // We should have an URLFetcher at this point in time.
433 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
434 ASSERT_TRUE(url_fetcher);
435 EXPECT_EQ(net::LOAD_DISABLE_CACHE, url_fetcher->GetLoadFlags());
436 EXPECT_EQ(base::StringPrintf("%s;a:adds_phish:s:subs_phish\n"
437 "unknown_list;a:adds_unknown:s:subs_unknown\n"
438 "%s;\n",
439 kDefaultPhishList, kDefaultMalwareList),
440 url_fetcher->upload_data());
441 EXPECT_EQ(GURL("https://prefix.com/foo/downloads?client=unittest&appver=1.0"
442 "&pver=3.0" + key_param_),
443 url_fetcher->GetOriginalURL());
445 url_fetcher->set_status(net::URLRequestStatus());
446 url_fetcher->set_response_code(200);
447 url_fetcher->SetResponseString(std::string());
448 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
450 EXPECT_TRUE(pm->IsUpdateScheduled());
453 TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseBadBodyBackupSuccess) {
454 scoped_refptr<base::TestSimpleTaskRunner> runner(
455 new base::TestSimpleTaskRunner());
456 base::ThreadTaskRunnerHandle runner_handler(runner);
457 net::TestURLFetcherFactory url_fetcher_factory;
459 testing::StrictMock<MockProtocolDelegate> test_delegate;
460 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
461 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
462 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
463 std::vector<SBListChunkRanges>(),
464 false)));
465 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
467 scoped_ptr<SafeBrowsingProtocolManager> pm(
468 CreateProtocolManager(&test_delegate));
470 // Kick off initialization. This returns chunks from the DB synchronously.
471 pm->ForceScheduleNextUpdate(TimeDelta());
472 runner->RunPendingTasks();
474 // We should have an URLFetcher at this point in time.
475 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
476 ValidateUpdateFetcherRequest(url_fetcher);
478 // The update response is successful, but an invalid body.
479 url_fetcher->set_status(net::URLRequestStatus());
480 url_fetcher->set_response_code(200);
481 url_fetcher->SetResponseString("THIS_IS_A_BAD_RESPONSE");
482 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
484 // There should now be a backup request.
485 net::TestURLFetcher* backup_url_fetcher =
486 url_fetcher_factory.GetFetcherByID(1);
487 ValidateUpdateFetcherRequest(backup_url_fetcher,
488 kBackupHttpUrlPrefix);
490 // Respond to the backup successfully.
491 backup_url_fetcher->set_status(net::URLRequestStatus());
492 backup_url_fetcher->set_response_code(200);
493 backup_url_fetcher->SetResponseString(std::string());
494 backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
496 EXPECT_TRUE(pm->IsUpdateScheduled());
499 // Tests what happens when there is an HTTP error response to the update
500 // request, as well as an error response to the backup update request.
501 TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseHttpErrorBackupError) {
502 scoped_refptr<base::TestSimpleTaskRunner> runner(
503 new base::TestSimpleTaskRunner());
504 base::ThreadTaskRunnerHandle runner_handler(runner);
505 net::TestURLFetcherFactory url_fetcher_factory;
507 testing::StrictMock<MockProtocolDelegate> test_delegate;
508 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
509 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
510 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
511 std::vector<SBListChunkRanges>(),
512 false)));
513 EXPECT_CALL(test_delegate, UpdateFinished(false)).Times(1);
515 scoped_ptr<SafeBrowsingProtocolManager> pm(
516 CreateProtocolManager(&test_delegate));
518 // Kick off initialization. This returns chunks from the DB synchronously.
519 pm->ForceScheduleNextUpdate(TimeDelta());
520 runner->RunPendingTasks();
522 // We should have an URLFetcher at this point in time.
523 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
524 ValidateUpdateFetcherRequest(url_fetcher);
526 // Go ahead and respond to it.
527 url_fetcher->set_status(net::URLRequestStatus());
528 url_fetcher->set_response_code(404);
529 url_fetcher->SetResponseString(std::string());
530 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
532 // There should now be a backup request.
533 net::TestURLFetcher* backup_url_fetcher =
534 url_fetcher_factory.GetFetcherByID(1);
535 ValidateUpdateFetcherRequest(backup_url_fetcher, kBackupHttpUrlPrefix);
537 // Respond to the backup unsuccessfully.
538 backup_url_fetcher->set_status(net::URLRequestStatus());
539 backup_url_fetcher->set_response_code(404);
540 backup_url_fetcher->SetResponseString(std::string());
541 backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
543 EXPECT_TRUE(pm->IsUpdateScheduled());
546 // Tests what happens when there is an HTTP error response to the update
547 // request, followed by a successful response to the backup update request.
548 TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseHttpErrorBackupSuccess) {
549 scoped_refptr<base::TestSimpleTaskRunner> runner(
550 new base::TestSimpleTaskRunner());
551 base::ThreadTaskRunnerHandle runner_handler(runner);
552 net::TestURLFetcherFactory url_fetcher_factory;
554 testing::StrictMock<MockProtocolDelegate> test_delegate;
555 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
556 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
557 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
558 std::vector<SBListChunkRanges>(),
559 false)));
560 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
562 scoped_ptr<SafeBrowsingProtocolManager> pm(
563 CreateProtocolManager(&test_delegate));
565 // Kick off initialization. This returns chunks from the DB synchronously.
566 pm->ForceScheduleNextUpdate(TimeDelta());
567 runner->RunPendingTasks();
569 // We should have an URLFetcher at this point in time.
570 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
571 ValidateUpdateFetcherRequest(url_fetcher);
573 // Go ahead and respond to it.
574 url_fetcher->set_status(net::URLRequestStatus());
575 url_fetcher->set_response_code(404);
576 url_fetcher->SetResponseString(std::string());
577 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
579 // There should now be a backup request.
580 net::TestURLFetcher* backup_url_fetcher =
581 url_fetcher_factory.GetFetcherByID(1);
582 ValidateUpdateFetcherRequest(backup_url_fetcher,
583 kBackupHttpUrlPrefix);
585 // Respond to the backup successfully.
586 backup_url_fetcher->set_status(net::URLRequestStatus());
587 backup_url_fetcher->set_response_code(200);
588 backup_url_fetcher->SetResponseString(std::string());
589 backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
591 EXPECT_TRUE(pm->IsUpdateScheduled());
594 // Tests what happens when there is an HTTP error response to the update
595 // request, and a timeout on the backup update request.
596 TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseHttpErrorBackupTimeout) {
597 scoped_refptr<base::TestSimpleTaskRunner> runner(
598 new base::TestSimpleTaskRunner());
599 base::ThreadTaskRunnerHandle runner_handler(runner);
600 net::TestURLFetcherFactory url_fetcher_factory;
602 testing::StrictMock<MockProtocolDelegate> test_delegate;
603 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
604 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
605 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
606 std::vector<SBListChunkRanges>(),
607 false)));
608 EXPECT_CALL(test_delegate, UpdateFinished(false)).Times(1);
610 scoped_ptr<SafeBrowsingProtocolManager> pm(
611 CreateProtocolManager(&test_delegate));
613 // Kick off initialization. This returns chunks from the DB synchronously.
614 pm->ForceScheduleNextUpdate(TimeDelta());
615 runner->RunPendingTasks();
617 // We should have an URLFetcher at this point in time.
618 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
619 ValidateUpdateFetcherRequest(url_fetcher);
621 // Go ahead and respond to it.
622 url_fetcher->set_status(net::URLRequestStatus());
623 url_fetcher->set_response_code(404);
624 url_fetcher->SetResponseString(std::string());
625 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
627 // There should now be a backup request.
628 net::TestURLFetcher* backup_url_fetcher =
629 url_fetcher_factory.GetFetcherByID(1);
630 ValidateUpdateFetcherRequest(backup_url_fetcher, kBackupHttpUrlPrefix);
632 // Either one or two calls to RunPendingTasks are needed here. The first run
633 // of RunPendingTasks will run the canceled timeout task associated with
634 // the first Update request. Depending on timing, this will either directly
635 // call the timeout task from the backup request, or schedule another task
636 // to run that in the future.
637 // TODO(cbentzel): Less fragile approach.
638 runner->RunPendingTasks();
639 if (!pm->IsUpdateScheduled())
640 runner->RunPendingTasks();
641 EXPECT_TRUE(pm->IsUpdateScheduled());
644 // Tests what happens when there is a connection error when issuing the update
645 // request, and an error with the backup update request.
646 TEST_F(SafeBrowsingProtocolManagerTest,
647 UpdateResponseConnectionErrorBackupError) {
648 scoped_refptr<base::TestSimpleTaskRunner> runner(
649 new base::TestSimpleTaskRunner());
650 base::ThreadTaskRunnerHandle runner_handler(runner);
651 net::TestURLFetcherFactory url_fetcher_factory;
653 testing::StrictMock<MockProtocolDelegate> test_delegate;
654 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
655 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
656 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
657 std::vector<SBListChunkRanges>(),
658 false)));
659 EXPECT_CALL(test_delegate, UpdateFinished(false)).Times(1);
661 scoped_ptr<SafeBrowsingProtocolManager> pm(
662 CreateProtocolManager(&test_delegate));
664 // Kick off initialization. This returns chunks from the DB synchronously.
665 pm->ForceScheduleNextUpdate(TimeDelta());
666 runner->RunPendingTasks();
668 // We should have an URLFetcher at this point in time.
669 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
670 ValidateUpdateFetcherRequest(url_fetcher);
672 // Go ahead and respond to it.
673 url_fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::FAILED,
674 net::ERR_CONNECTION_RESET));
675 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
677 // There should be a backup URLFetcher now.
678 net::TestURLFetcher* backup_url_fetcher =
679 url_fetcher_factory.GetFetcherByID(1);
680 ValidateUpdateFetcherRequest(backup_url_fetcher,
681 kBackupConnectUrlPrefix);
683 // Respond to the backup unsuccessfully.
684 backup_url_fetcher->set_status(net::URLRequestStatus());
685 backup_url_fetcher->set_response_code(404);
686 backup_url_fetcher->SetResponseString(std::string());
687 backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
689 EXPECT_TRUE(pm->IsUpdateScheduled());
692 // Tests what happens when there is a connection error when issuing the update
693 // request, and a successful response to the backup update request.
694 TEST_F(SafeBrowsingProtocolManagerTest,
695 UpdateResponseConnectionErrorBackupSuccess) {
696 scoped_refptr<base::TestSimpleTaskRunner> runner(
697 new base::TestSimpleTaskRunner());
698 base::ThreadTaskRunnerHandle runner_handler(runner);
699 net::TestURLFetcherFactory url_fetcher_factory;
701 testing::StrictMock<MockProtocolDelegate> test_delegate;
702 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
703 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
704 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
705 std::vector<SBListChunkRanges>(),
706 false)));
707 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
709 scoped_ptr<SafeBrowsingProtocolManager> pm(
710 CreateProtocolManager(&test_delegate));
712 // Kick off initialization. This returns chunks from the DB synchronously.
713 pm->ForceScheduleNextUpdate(TimeDelta());
714 runner->RunPendingTasks();
716 // We should have an URLFetcher at this point in time.
717 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
718 ValidateUpdateFetcherRequest(url_fetcher);
720 // Go ahead and respond to it.
721 url_fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::FAILED,
722 net::ERR_CONNECTION_RESET));
723 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
725 // There should be a backup URLFetcher now.
726 net::TestURLFetcher* backup_url_fetcher =
727 url_fetcher_factory.GetFetcherByID(1);
728 ValidateUpdateFetcherRequest(backup_url_fetcher,
729 kBackupConnectUrlPrefix);
731 // Respond to the backup unsuccessfully.
732 backup_url_fetcher->set_status(net::URLRequestStatus());
733 backup_url_fetcher->set_response_code(200);
734 backup_url_fetcher->SetResponseString(std::string());
735 backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
737 EXPECT_TRUE(pm->IsUpdateScheduled());
739 // Tests what happens when there is a network state error when issuing the
740 // update request, and an error with the backup update request.
741 TEST_F(SafeBrowsingProtocolManagerTest,
742 UpdateResponseNetworkErrorBackupError) {
743 scoped_refptr<base::TestSimpleTaskRunner> runner(
744 new base::TestSimpleTaskRunner());
745 base::ThreadTaskRunnerHandle runner_handler(runner);
746 net::TestURLFetcherFactory url_fetcher_factory;
748 testing::StrictMock<MockProtocolDelegate> test_delegate;
749 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
750 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
751 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
752 std::vector<SBListChunkRanges>(),
753 false)));
754 EXPECT_CALL(test_delegate, UpdateFinished(false)).Times(1);
756 scoped_ptr<SafeBrowsingProtocolManager> pm(
757 CreateProtocolManager(&test_delegate));
759 // Kick off initialization. This returns chunks from the DB synchronously.
760 pm->ForceScheduleNextUpdate(TimeDelta());
761 runner->RunPendingTasks();
763 // We should have an URLFetcher at this point in time.
764 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
765 ValidateUpdateFetcherRequest(url_fetcher);
767 // Go ahead and respond to it.
768 url_fetcher->set_status(
769 net::URLRequestStatus(net::URLRequestStatus::FAILED,
770 net::ERR_INTERNET_DISCONNECTED));
771 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
773 // There should be a backup URLFetcher now.
774 net::TestURLFetcher* backup_url_fetcher =
775 url_fetcher_factory.GetFetcherByID(1);
776 ValidateUpdateFetcherRequest(backup_url_fetcher,
777 kBackupNetworkUrlPrefix);
779 // Respond to the backup unsuccessfully.
780 backup_url_fetcher->set_status(net::URLRequestStatus());
781 backup_url_fetcher->set_response_code(404);
782 backup_url_fetcher->SetResponseString(std::string());
783 backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
785 EXPECT_TRUE(pm->IsUpdateScheduled());
788 // Tests what happens when there is a network state error when issuing the
789 // update request, and a successful response to the backup update request.
790 TEST_F(SafeBrowsingProtocolManagerTest,
791 UpdateResponseNetworkErrorBackupSuccess) {
792 scoped_refptr<base::TestSimpleTaskRunner> runner(
793 new base::TestSimpleTaskRunner());
794 base::ThreadTaskRunnerHandle runner_handler(runner);
795 net::TestURLFetcherFactory url_fetcher_factory;
797 testing::StrictMock<MockProtocolDelegate> test_delegate;
798 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
799 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
800 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
801 std::vector<SBListChunkRanges>(),
802 false)));
803 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
805 scoped_ptr<SafeBrowsingProtocolManager> pm(
806 CreateProtocolManager(&test_delegate));
808 // Kick off initialization. This returns chunks from the DB synchronously.
809 pm->ForceScheduleNextUpdate(TimeDelta());
810 runner->RunPendingTasks();
812 // We should have an URLFetcher at this point in time.
813 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
814 ValidateUpdateFetcherRequest(url_fetcher);
816 // Go ahead and respond to it.
817 url_fetcher->set_status(
818 net::URLRequestStatus(net::URLRequestStatus::FAILED,
819 net::ERR_INTERNET_DISCONNECTED));
820 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
822 // There should be a backup URLFetcher now.
823 net::TestURLFetcher* backup_url_fetcher =
824 url_fetcher_factory.GetFetcherByID(1);
825 ValidateUpdateFetcherRequest(backup_url_fetcher,
826 kBackupNetworkUrlPrefix);
828 // Respond to the backup unsuccessfully.
829 backup_url_fetcher->set_status(net::URLRequestStatus());
830 backup_url_fetcher->set_response_code(200);
831 backup_url_fetcher->SetResponseString(std::string());
832 backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
834 EXPECT_TRUE(pm->IsUpdateScheduled());
837 // Tests what happens when there is a timeout before an update response.
838 TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseTimeoutBackupSuccess) {
839 scoped_refptr<base::TestSimpleTaskRunner> runner(
840 new base::TestSimpleTaskRunner());
841 base::ThreadTaskRunnerHandle runner_handler(runner);
842 net::TestURLFetcherFactory url_fetcher_factory;
844 testing::StrictMock<MockProtocolDelegate> test_delegate;
845 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
846 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
847 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
848 std::vector<SBListChunkRanges>(),
849 false)));
850 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
852 scoped_ptr<SafeBrowsingProtocolManager> pm(
853 CreateProtocolManager(&test_delegate));
855 // Kick off initialization. This returns chunks from the DB synchronously.
856 pm->ForceScheduleNextUpdate(TimeDelta());
857 runner->RunPendingTasks();
859 // We should have an URLFetcher at this point in time.
860 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
861 ValidateUpdateFetcherRequest(url_fetcher);
863 // The first time RunPendingTasks is called above, the update timeout timer is
864 // not handled. This call of RunPendingTasks will handle the update.
865 runner->RunPendingTasks();
867 // There should be a backup URLFetcher now.
868 net::TestURLFetcher* backup_url_fetcher =
869 url_fetcher_factory.GetFetcherByID(1);
870 ValidateUpdateFetcherRequest(backup_url_fetcher,
871 kBackupConnectUrlPrefix);
873 // Respond to the backup unsuccessfully.
874 backup_url_fetcher->set_status(net::URLRequestStatus());
875 backup_url_fetcher->set_response_code(200);
876 backup_url_fetcher->SetResponseString(std::string());
877 backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
879 EXPECT_TRUE(pm->IsUpdateScheduled());
882 // Tests what happens when there is a reset command in the response.
883 TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseReset) {
884 scoped_refptr<base::TestSimpleTaskRunner> runner(
885 new base::TestSimpleTaskRunner());
886 base::ThreadTaskRunnerHandle runner_handler(runner);
887 net::TestURLFetcherFactory url_fetcher_factory;
889 testing::StrictMock<MockProtocolDelegate> test_delegate;
890 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
891 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
892 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
893 std::vector<SBListChunkRanges>(),
894 false)));
895 EXPECT_CALL(test_delegate, ResetDatabase()).Times(1);
896 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
898 scoped_ptr<SafeBrowsingProtocolManager> pm(
899 CreateProtocolManager(&test_delegate));
901 // Kick off initialization. This returns chunks from the DB synchronously.
902 pm->ForceScheduleNextUpdate(TimeDelta());
903 runner->RunPendingTasks();
905 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
906 ValidateUpdateFetcherRequest(url_fetcher);
908 // The update response is successful, and has a reset command.
909 url_fetcher->set_status(net::URLRequestStatus());
910 url_fetcher->set_response_code(200);
911 url_fetcher->SetResponseString("r:pleasereset\n");
912 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
914 EXPECT_TRUE(pm->IsUpdateScheduled());
917 // Tests a single valid update response, followed by a single redirect response
918 // that has an valid, but empty body.
919 TEST_F(SafeBrowsingProtocolManagerTest, EmptyRedirectResponse) {
920 scoped_refptr<base::TestSimpleTaskRunner> runner(
921 new base::TestSimpleTaskRunner());
922 base::ThreadTaskRunnerHandle runner_handler(runner);
923 net::TestURLFetcherFactory url_fetcher_factory;
925 testing::StrictMock<MockProtocolDelegate> test_delegate;
926 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
927 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
928 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
929 std::vector<SBListChunkRanges>(),
930 false)));
931 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
933 scoped_ptr<SafeBrowsingProtocolManager> pm(
934 CreateProtocolManager(&test_delegate));
936 // Kick off initialization. This returns chunks from the DB synchronously.
937 pm->ForceScheduleNextUpdate(TimeDelta());
938 runner->RunPendingTasks();
940 // The update response contains a single redirect command.
941 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
942 ValidateUpdateFetcherRequest(url_fetcher);
943 url_fetcher->set_status(net::URLRequestStatus());
944 url_fetcher->set_response_code(200);
945 url_fetcher->SetResponseString(
946 base::StringPrintf("i:%s\n"
947 "u:redirect-server.example.com/path\n",
948 kDefaultPhishList));
949 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
951 // The redirect response contains an empty body.
952 net::TestURLFetcher* chunk_url_fetcher =
953 url_fetcher_factory.GetFetcherByID(1);
954 ValidateRedirectFetcherRequest(
955 chunk_url_fetcher, "https://redirect-server.example.com/path");
956 chunk_url_fetcher->set_status(net::URLRequestStatus());
957 chunk_url_fetcher->set_response_code(200);
958 chunk_url_fetcher->SetResponseString(std::string());
959 chunk_url_fetcher->delegate()->OnURLFetchComplete(chunk_url_fetcher);
961 EXPECT_TRUE(pm->IsUpdateScheduled());
964 // Tests a single valid update response, followed by a single redirect response
965 // that has an invalid body.
966 TEST_F(SafeBrowsingProtocolManagerTest, InvalidRedirectResponse) {
967 scoped_refptr<base::TestSimpleTaskRunner> runner(
968 new base::TestSimpleTaskRunner());
969 base::ThreadTaskRunnerHandle runner_handler(runner);
970 net::TestURLFetcherFactory url_fetcher_factory;
972 testing::StrictMock<MockProtocolDelegate> test_delegate;
973 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
974 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
975 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
976 std::vector<SBListChunkRanges>(),
977 false)));
978 EXPECT_CALL(test_delegate, UpdateFinished(false)).Times(1);
980 scoped_ptr<SafeBrowsingProtocolManager> pm(
981 CreateProtocolManager(&test_delegate));
983 // Kick off initialization. This returns chunks from the DB synchronously.
984 pm->ForceScheduleNextUpdate(TimeDelta());
985 runner->RunPendingTasks();
987 // The update response contains a single redirect command.
988 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
989 ValidateUpdateFetcherRequest(url_fetcher);
990 url_fetcher->set_status(net::URLRequestStatus());
991 url_fetcher->set_response_code(200);
992 url_fetcher->SetResponseString(
993 base::StringPrintf("i:%s\n"
994 "u:redirect-server.example.com/path\n",
995 kDefaultPhishList));
996 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
998 // The redirect response contains an invalid body.
999 net::TestURLFetcher* chunk_url_fetcher =
1000 url_fetcher_factory.GetFetcherByID(1);
1001 ValidateRedirectFetcherRequest(
1002 chunk_url_fetcher, "https://redirect-server.example.com/path");
1003 chunk_url_fetcher->set_status(net::URLRequestStatus());
1004 chunk_url_fetcher->set_response_code(200);
1005 chunk_url_fetcher->SetResponseString("THIS IS AN INVALID RESPONSE");
1006 chunk_url_fetcher->delegate()->OnURLFetchComplete(chunk_url_fetcher);
1008 EXPECT_TRUE(pm->IsUpdateScheduled());
1011 // Tests a single valid update response, followed by a single redirect response
1012 // containing chunks.
1013 TEST_F(SafeBrowsingProtocolManagerTest, SingleRedirectResponseWithChunks) {
1014 scoped_refptr<base::TestSimpleTaskRunner> runner(
1015 new base::TestSimpleTaskRunner());
1016 base::ThreadTaskRunnerHandle runner_handler(runner);
1017 net::TestURLFetcherFactory url_fetcher_factory;
1019 testing::StrictMock<MockProtocolDelegate> test_delegate;
1020 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
1021 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
1022 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
1023 std::vector<SBListChunkRanges>(),
1024 false)));
1025 EXPECT_CALL(test_delegate, AddChunksRaw(kDefaultPhishList, _, _)).WillOnce(
1026 Invoke(HandleAddChunks));
1027 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
1029 scoped_ptr<SafeBrowsingProtocolManager> pm(
1030 CreateProtocolManager(&test_delegate));
1032 // Kick off initialization. This returns chunks from the DB synchronously.
1033 pm->ForceScheduleNextUpdate(TimeDelta());
1034 runner->RunPendingTasks();
1036 // The update response contains a single redirect command.
1037 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
1038 ValidateUpdateFetcherRequest(url_fetcher);
1039 url_fetcher->set_status(net::URLRequestStatus());
1040 url_fetcher->set_response_code(200);
1041 url_fetcher->SetResponseString(
1042 base::StringPrintf("i:%s\n"
1043 "u:redirect-server.example.com/path\n",
1044 kDefaultPhishList));
1045 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
1047 // The redirect response contains a single chunk.
1048 net::TestURLFetcher* chunk_url_fetcher =
1049 url_fetcher_factory.GetFetcherByID(1);
1050 ValidateRedirectFetcherRequest(
1051 chunk_url_fetcher, "https://redirect-server.example.com/path");
1052 chunk_url_fetcher->set_status(net::URLRequestStatus());
1053 chunk_url_fetcher->set_response_code(200);
1054 chunk_url_fetcher->SetResponseString(kChunkPayload1);
1055 chunk_url_fetcher->delegate()->OnURLFetchComplete(chunk_url_fetcher);
1057 EXPECT_FALSE(pm->IsUpdateScheduled());
1059 // The AddChunksCallback needs to be invoked.
1060 runner->RunPendingTasks();
1062 EXPECT_TRUE(pm->IsUpdateScheduled());
1065 // Tests a single valid update response, followed by multiple redirect responses
1066 // containing chunks.
1067 TEST_F(SafeBrowsingProtocolManagerTest, MultipleRedirectResponsesWithChunks) {
1068 scoped_refptr<base::TestSimpleTaskRunner> runner(
1069 new base::TestSimpleTaskRunner());
1070 base::ThreadTaskRunnerHandle runner_handler(runner);
1071 net::TestURLFetcherFactory url_fetcher_factory;
1073 testing::StrictMock<MockProtocolDelegate> test_delegate;
1074 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
1075 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
1076 Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
1077 std::vector<SBListChunkRanges>(),
1078 false)));
1079 EXPECT_CALL(test_delegate, AddChunksRaw(kDefaultPhishList, _, _)).
1080 WillRepeatedly(Invoke(HandleAddChunks));
1081 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
1083 scoped_ptr<SafeBrowsingProtocolManager> pm(
1084 CreateProtocolManager(&test_delegate));
1086 // Kick off initialization. This returns chunks from the DB synchronously.
1087 pm->ForceScheduleNextUpdate(TimeDelta());
1088 runner->RunPendingTasks();
1090 // The update response contains multiple redirect commands.
1091 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
1092 ValidateUpdateFetcherRequest(url_fetcher);
1093 url_fetcher->set_status(net::URLRequestStatus());
1094 url_fetcher->set_response_code(200);
1095 url_fetcher->SetResponseString(
1096 base::StringPrintf("i:%s\n"
1097 "u:redirect-server.example.com/one\n"
1098 "u:redirect-server.example.com/two\n",
1099 kDefaultPhishList));
1100 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
1102 // The first redirect response contains a single chunk.
1103 net::TestURLFetcher* first_chunk_url_fetcher =
1104 url_fetcher_factory.GetFetcherByID(1);
1105 ValidateRedirectFetcherRequest(
1106 first_chunk_url_fetcher, "https://redirect-server.example.com/one");
1107 first_chunk_url_fetcher->set_status(net::URLRequestStatus());
1108 first_chunk_url_fetcher->set_response_code(200);
1109 first_chunk_url_fetcher->SetResponseString(kChunkPayload1);
1110 first_chunk_url_fetcher->delegate()->OnURLFetchComplete(
1111 first_chunk_url_fetcher);
1113 // Invoke the AddChunksCallback to trigger the second request.
1114 runner->RunPendingTasks();
1116 EXPECT_FALSE(pm->IsUpdateScheduled());
1118 // The second redirect response contains a single chunk.
1119 net::TestURLFetcher* second_chunk_url_fetcher =
1120 url_fetcher_factory.GetFetcherByID(2);
1121 ValidateRedirectFetcherRequest(
1122 second_chunk_url_fetcher, "https://redirect-server.example.com/two");
1123 second_chunk_url_fetcher->set_status(net::URLRequestStatus());
1124 second_chunk_url_fetcher->set_response_code(200);
1125 second_chunk_url_fetcher->SetResponseString(kChunkPayload2);
1126 second_chunk_url_fetcher->delegate()->OnURLFetchComplete(
1127 second_chunk_url_fetcher);
1129 EXPECT_FALSE(pm->IsUpdateScheduled());
1131 // Invoke the AddChunksCallback to finish the update.
1132 runner->RunPendingTasks();
1134 EXPECT_TRUE(pm->IsUpdateScheduled());