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.
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"
21 using base::TimeDelta
;
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
{
35 std::string key_param_
;
37 virtual void SetUp() {
38 std::string key
= google_apis::GetAPIKey();
40 key_param_
= base::StringPrintf(
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);
94 // No errors received so far.
95 next
= pm
->GetNextUpdateInterval(false);
96 EXPECT_EQ(next
, TimeDelta::FromSeconds(1800));
99 next
= pm
->GetNextUpdateInterval(true);
100 EXPECT_EQ(next
, TimeDelta::FromSeconds(60));
103 next
= pm
->GetNextUpdateInterval(true);
104 EXPECT_TRUE(next
>= TimeDelta::FromMinutes(30) &&
105 next
<= TimeDelta::FromMinutes(60));
108 next
= pm
->GetNextUpdateInterval(true);
109 EXPECT_TRUE(next
>= TimeDelta::FromMinutes(60) &&
110 next
<= TimeDelta::FromMinutes(120));
113 next
= pm
->GetNextUpdateInterval(true);
114 EXPECT_TRUE(next
>= TimeDelta::FromMinutes(120) &&
115 next
<= TimeDelta::FromMinutes(240));
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));
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");
147 EXPECT_EQ(pm
->FormatList(phish
), "goog-phish-shavar;a:1,4,6,8-20,99\n");
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.
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();
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
);
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));
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));
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));
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));
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());
266 class MockProtocolDelegate
: public SafeBrowsingProtocolManagerDelegate
{
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
*,
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
,
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
,
297 SafeBrowsingProtocolManagerDelegate::AddChunksCallback callback
) {
299 scoped_refptr
<base::SingleThreadTaskRunner
> task_runner(
300 base::ThreadTaskRunnerHandle::Get());
301 if (!task_runner
.get())
303 task_runner
->PostTask(FROM_HERE
, callback
);
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
>(),
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
,
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
>(),
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
>(),
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
>(),
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
>(),
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
>(),
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
>(),
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
>(),
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
>(),
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
>(),
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
>(),
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
>(),
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
>(),
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
>(),
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(
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
>(),
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(
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(
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());