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 // 5 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" 19 20 using base::Time; 21 using base::TimeDelta; 22 using testing::_; 23 using testing::Invoke; 24 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"; 32 33 class SafeBrowsingProtocolManagerTest : public testing::Test { 34 protected: 35 std::string key_param_; 36 37 virtual void SetUp() { 38 std::string key = google_apis::GetAPIKey(); 39 if (!key.empty()) { 40 key_param_ = base::StringPrintf( 41 "&key=%s", 42 net::EscapeQueryParamValue(key, true).c_str()); 43 } 44 } 45 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; 55 56 return scoped_ptr<SafeBrowsingProtocolManager>( 57 SafeBrowsingProtocolManager::Create(delegate, NULL, config)); 58 } 59 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()); 70 } 71 72 void ValidateUpdateFetcherRequest(const net::TestURLFetcher* url_fetcher) { 73 ValidateUpdateFetcherRequest(url_fetcher, kUrlPrefix); 74 } 75 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()); 82 } 83 }; 84 85 // Ensure that we respect section 5 of the SafeBrowsing protocol specification. 86 TEST_F(SafeBrowsingProtocolManagerTest, TestBackOffTimes) { 87 scoped_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL)); 88 89 pm->next_update_interval_ = TimeDelta::FromSeconds(1800); 90 ASSERT_TRUE(pm->back_off_fuzz_ >= 0.0 && pm->back_off_fuzz_ <= 1.0); 91 92 TimeDelta next; 93 94 // No errors received so far. 95 next = pm->GetNextUpdateInterval(false); 96 EXPECT_EQ(next, TimeDelta::FromSeconds(1800)); 97 98 // 1 error. 99 next = pm->GetNextUpdateInterval(true); 100 EXPECT_EQ(next, TimeDelta::FromSeconds(60)); 101 102 // 2 errors. 103 next = pm->GetNextUpdateInterval(true); 104 EXPECT_TRUE(next >= TimeDelta::FromMinutes(30) && 105 next <= TimeDelta::FromMinutes(60)); 106 107 // 3 errors. 108 next = pm->GetNextUpdateInterval(true); 109 EXPECT_TRUE(next >= TimeDelta::FromMinutes(60) && 110 next <= TimeDelta::FromMinutes(120)); 111 112 // 4 errors. 113 next = pm->GetNextUpdateInterval(true); 114 EXPECT_TRUE(next >= TimeDelta::FromMinutes(120) && 115 next <= TimeDelta::FromMinutes(240)); 116 117 // 5 errors. 118 next = pm->GetNextUpdateInterval(true); 119 EXPECT_TRUE(next >= TimeDelta::FromMinutes(240) && 120 next <= TimeDelta::FromMinutes(480)); 121 122 // 6 errors, reached max backoff. 123 next = pm->GetNextUpdateInterval(true); 124 EXPECT_EQ(next, TimeDelta::FromMinutes(480)); 125 126 // 7 errors. 127 next = pm->GetNextUpdateInterval(true); 128 EXPECT_EQ(next, TimeDelta::FromMinutes(480)); 129 130 // Received a successful response. 131 next = pm->GetNextUpdateInterval(false); 132 EXPECT_EQ(next, TimeDelta::FromSeconds(1800)); 133 } 134 135 TEST_F(SafeBrowsingProtocolManagerTest, TestChunkStrings) { 136 scoped_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL)); 137 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"); 144 145 // Add chunks only. 146 phish.subs = ""; 147 EXPECT_EQ(pm->FormatList(phish), "goog-phish-shavar;a:1,4,6,8-20,99\n"); 148 149 // Sub chunks only. 150 phish.adds = ""; 151 phish.subs = "16,32,64-96"; 152 EXPECT_EQ(pm->FormatList(phish), "goog-phish-shavar;s:16,32,64-96\n"); 153 154 // No chunks of either type. 155 phish.adds = ""; 156 phish.subs = ""; 157 EXPECT_EQ(pm->FormatList(phish), "goog-phish-shavar;\n"); 158 } 159 160 TEST_F(SafeBrowsingProtocolManagerTest, TestGetHashBackOffTimes) { 161 scoped_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL)); 162 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()); 166 167 Time now = Time::Now(); 168 169 // 1 error. 170 pm->HandleGetHashError(now); 171 EXPECT_EQ(pm->gethash_error_count_, 1); 172 TimeDelta margin = TimeDelta::FromSeconds(5); // Fudge factor. 173 Time future = now + TimeDelta::FromMinutes(1); 174 EXPECT_TRUE(pm->next_gethash_time_ >= future - margin && 175 pm->next_gethash_time_ <= future + margin); 176 177 // 2 errors. 178 pm->HandleGetHashError(now); 179 EXPECT_EQ(pm->gethash_error_count_, 2); 180 EXPECT_TRUE(pm->next_gethash_time_ >= now + TimeDelta::FromMinutes(30)); 181 EXPECT_TRUE(pm->next_gethash_time_ <= now + TimeDelta::FromMinutes(60)); 182 183 // 3 errors. 184 pm->HandleGetHashError(now); 185 EXPECT_EQ(pm->gethash_error_count_, 3); 186 EXPECT_TRUE(pm->next_gethash_time_ >= now + TimeDelta::FromMinutes(60)); 187 EXPECT_TRUE(pm->next_gethash_time_ <= now + TimeDelta::FromMinutes(120)); 188 189 // 4 errors. 190 pm->HandleGetHashError(now); 191 EXPECT_EQ(pm->gethash_error_count_, 4); 192 EXPECT_TRUE(pm->next_gethash_time_ >= now + TimeDelta::FromMinutes(120)); 193 EXPECT_TRUE(pm->next_gethash_time_ <= now + TimeDelta::FromMinutes(240)); 194 195 // 5 errors. 196 pm->HandleGetHashError(now); 197 EXPECT_EQ(pm->gethash_error_count_, 5); 198 EXPECT_TRUE(pm->next_gethash_time_ >= now + TimeDelta::FromMinutes(240)); 199 EXPECT_TRUE(pm->next_gethash_time_ <= now + TimeDelta::FromMinutes(480)); 200 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)); 205 206 // 7 errors. 207 pm->HandleGetHashError(now); 208 EXPECT_EQ(pm->gethash_error_count_, 7); 209 EXPECT_TRUE(pm->next_gethash_time_== now + TimeDelta::FromMinutes(480)); 210 } 211 212 TEST_F(SafeBrowsingProtocolManagerTest, TestGetHashUrl) { 213 scoped_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL)); 214 215 EXPECT_EQ("https://prefix.com/foo/gethash?client=unittest&appver=1.0&" 216 "pver=2.2" + key_param_, pm->GetHashUrl().spec()); 217 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()); 222 } 223 224 TEST_F(SafeBrowsingProtocolManagerTest, TestUpdateUrl) { 225 scoped_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL)); 226 227 EXPECT_EQ("https://prefix.com/foo/downloads?client=unittest&appver=1.0&" 228 "pver=2.2" + key_param_, pm->UpdateUrl().spec()); 229 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()); 234 } 235 236 TEST_F(SafeBrowsingProtocolManagerTest, TestNextChunkUrl) { 237 scoped_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL)); 238 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"; 243 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()); 252 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()); 262 } 263 264 namespace { 265 266 class MockProtocolDelegate : public SafeBrowsingProtocolManagerDelegate { 267 public: 268 MockProtocolDelegate() {} 269 virtual ~MockProtocolDelegate() {} 270 271 MOCK_METHOD0(UpdateStarted, void()); 272 MOCK_METHOD1(UpdateFinished, void(bool)); 273 MOCK_METHOD0(ResetDatabase, void()); 274 MOCK_METHOD1(GetChunks, void(GetChunksCallback)); 275 MOCK_METHOD3(AddChunks, void(const std::string&, SBChunkList*, 276 AddChunksCallback)); 277 MOCK_METHOD1(DeleteChunks, void(std::vector<SBChunkDelete>*)); 278 }; 279 280 // |InvokeGetChunksCallback| is required because GMock's InvokeArgument action 281 // expects to use operator(), and a Callback only provides Run(). 282 // TODO(cbentzel): Use ACTION or ACTION_TEMPLATE instead? 283 void InvokeGetChunksCallback( 284 const std::vector<SBListChunkRanges>& ranges, 285 bool database_error, 286 SafeBrowsingProtocolManagerDelegate::GetChunksCallback callback) { 287 callback.Run(ranges, database_error); 288 } 289 290 // |HandleAddChunks| deletes the chunks and asynchronously invokes 291 // |callback| since SafeBrowsingProtocolManager is not re-entrant at the time 292 // this is called. This guarantee is part of the 293 // SafeBrowsingProtocolManagerDelegate contract. 294 void HandleAddChunks( 295 const std::string& unused_list, 296 SBChunkList* chunks, 297 SafeBrowsingProtocolManagerDelegate::AddChunksCallback callback) { 298 delete chunks; 299 scoped_refptr<base::SingleThreadTaskRunner> task_runner( 300 base::ThreadTaskRunnerHandle::Get()); 301 if (!task_runner.get()) 302 return; 303 task_runner->PostTask(FROM_HERE, callback); 304 } 305 306 } // namespace 307 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); 314 315 testing::StrictMock<MockProtocolDelegate> test_delegate; 316 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1); 317 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce( 318 Invoke(testing::CreateFunctor(InvokeGetChunksCallback, 319 std::vector<SBListChunkRanges>(), 320 true))); 321 EXPECT_CALL(test_delegate, UpdateFinished(false)).Times(1); 322 323 scoped_ptr<SafeBrowsingProtocolManager> pm( 324 CreateProtocolManager(&test_delegate)); 325 326 pm->ForceScheduleNextUpdate(TimeDelta()); 327 runner->RunPendingTasks(); 328 329 EXPECT_TRUE(pm->IsUpdateScheduled()); 330 } 331 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; 340 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); 346 347 SBListChunkRanges range_unknown("unknown_list"); 348 range_unknown.adds = "adds_unknown"; 349 range_unknown.subs = "subs_unknown"; 350 ranges.push_back(range_unknown); 351 352 testing::StrictMock<MockProtocolDelegate> test_delegate; 353 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1); 354 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce( 355 Invoke(testing::CreateFunctor(InvokeGetChunksCallback, 356 ranges, 357 false))); 358 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1); 359 360 scoped_ptr<SafeBrowsingProtocolManager> pm( 361 CreateProtocolManager(&test_delegate)); 362 363 // Kick off initialization. This returns chunks from the DB synchronously. 364 pm->ForceScheduleNextUpdate(TimeDelta()); 365 runner->RunPendingTasks(); 366 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()); 378 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); 383 384 EXPECT_TRUE(pm->IsUpdateScheduled()); 385 } 386 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; 392 393 testing::StrictMock<MockProtocolDelegate> test_delegate; 394 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1); 395 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce( 396 Invoke(testing::CreateFunctor(InvokeGetChunksCallback, 397 std::vector<SBListChunkRanges>(), 398 false))); 399 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1); 400 401 scoped_ptr<SafeBrowsingProtocolManager> pm( 402 CreateProtocolManager(&test_delegate)); 403 404 // Kick off initialization. This returns chunks from the DB synchronously. 405 pm->ForceScheduleNextUpdate(TimeDelta()); 406 runner->RunPendingTasks(); 407 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); 411 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); 417 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); 423 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); 429 430 EXPECT_TRUE(pm->IsUpdateScheduled()); 431 } 432 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; 440 441 testing::StrictMock<MockProtocolDelegate> test_delegate; 442 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1); 443 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce( 444 Invoke(testing::CreateFunctor(InvokeGetChunksCallback, 445 std::vector<SBListChunkRanges>(), 446 false))); 447 EXPECT_CALL(test_delegate, UpdateFinished(false)).Times(1); 448 449 scoped_ptr<SafeBrowsingProtocolManager> pm( 450 CreateProtocolManager(&test_delegate)); 451 452 // Kick off initialization. This returns chunks from the DB synchronously. 453 pm->ForceScheduleNextUpdate(TimeDelta()); 454 runner->RunPendingTasks(); 455 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); 459 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); 465 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); 470 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); 476 477 EXPECT_TRUE(pm->IsUpdateScheduled()); 478 } 479 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; 487 488 testing::StrictMock<MockProtocolDelegate> test_delegate; 489 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1); 490 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce( 491 Invoke(testing::CreateFunctor(InvokeGetChunksCallback, 492 std::vector<SBListChunkRanges>(), 493 false))); 494 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1); 495 496 scoped_ptr<SafeBrowsingProtocolManager> pm( 497 CreateProtocolManager(&test_delegate)); 498 499 // Kick off initialization. This returns chunks from the DB synchronously. 500 pm->ForceScheduleNextUpdate(TimeDelta()); 501 runner->RunPendingTasks(); 502 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); 506 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); 512 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); 518 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); 524 525 EXPECT_TRUE(pm->IsUpdateScheduled()); 526 } 527 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; 535 536 testing::StrictMock<MockProtocolDelegate> test_delegate; 537 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1); 538 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce( 539 Invoke(testing::CreateFunctor(InvokeGetChunksCallback, 540 std::vector<SBListChunkRanges>(), 541 false))); 542 EXPECT_CALL(test_delegate, UpdateFinished(false)).Times(1); 543 544 scoped_ptr<SafeBrowsingProtocolManager> pm( 545 CreateProtocolManager(&test_delegate)); 546 547 // Kick off initialization. This returns chunks from the DB synchronously. 548 pm->ForceScheduleNextUpdate(TimeDelta()); 549 runner->RunPendingTasks(); 550 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); 554 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); 560 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); 565 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()); 576 } 577 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; 586 587 testing::StrictMock<MockProtocolDelegate> test_delegate; 588 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1); 589 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce( 590 Invoke(testing::CreateFunctor(InvokeGetChunksCallback, 591 std::vector<SBListChunkRanges>(), 592 false))); 593 EXPECT_CALL(test_delegate, UpdateFinished(false)).Times(1); 594 595 scoped_ptr<SafeBrowsingProtocolManager> pm( 596 CreateProtocolManager(&test_delegate)); 597 598 // Kick off initialization. This returns chunks from the DB synchronously. 599 pm->ForceScheduleNextUpdate(TimeDelta()); 600 runner->RunPendingTasks(); 601 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); 605 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); 610 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); 616 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); 622 623 EXPECT_TRUE(pm->IsUpdateScheduled()); 624 } 625 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; 634 635 testing::StrictMock<MockProtocolDelegate> test_delegate; 636 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1); 637 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce( 638 Invoke(testing::CreateFunctor(InvokeGetChunksCallback, 639 std::vector<SBListChunkRanges>(), 640 false))); 641 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1); 642 643 scoped_ptr<SafeBrowsingProtocolManager> pm( 644 CreateProtocolManager(&test_delegate)); 645 646 // Kick off initialization. This returns chunks from the DB synchronously. 647 pm->ForceScheduleNextUpdate(TimeDelta()); 648 runner->RunPendingTasks(); 649 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); 653 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); 658 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); 664 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); 670 671 EXPECT_TRUE(pm->IsUpdateScheduled()); 672 } 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; 681 682 testing::StrictMock<MockProtocolDelegate> test_delegate; 683 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1); 684 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce( 685 Invoke(testing::CreateFunctor(InvokeGetChunksCallback, 686 std::vector<SBListChunkRanges>(), 687 false))); 688 EXPECT_CALL(test_delegate, UpdateFinished(false)).Times(1); 689 690 scoped_ptr<SafeBrowsingProtocolManager> pm( 691 CreateProtocolManager(&test_delegate)); 692 693 // Kick off initialization. This returns chunks from the DB synchronously. 694 pm->ForceScheduleNextUpdate(TimeDelta()); 695 runner->RunPendingTasks(); 696 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); 700 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); 706 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); 712 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); 718 719 EXPECT_TRUE(pm->IsUpdateScheduled()); 720 } 721 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; 730 731 testing::StrictMock<MockProtocolDelegate> test_delegate; 732 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1); 733 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce( 734 Invoke(testing::CreateFunctor(InvokeGetChunksCallback, 735 std::vector<SBListChunkRanges>(), 736 false))); 737 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1); 738 739 scoped_ptr<SafeBrowsingProtocolManager> pm( 740 CreateProtocolManager(&test_delegate)); 741 742 // Kick off initialization. This returns chunks from the DB synchronously. 743 pm->ForceScheduleNextUpdate(TimeDelta()); 744 runner->RunPendingTasks(); 745 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); 749 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); 755 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); 761 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); 767 768 EXPECT_TRUE(pm->IsUpdateScheduled()); 769 } 770 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; 777 778 testing::StrictMock<MockProtocolDelegate> test_delegate; 779 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1); 780 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce( 781 Invoke(testing::CreateFunctor(InvokeGetChunksCallback, 782 std::vector<SBListChunkRanges>(), 783 false))); 784 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1); 785 786 scoped_ptr<SafeBrowsingProtocolManager> pm( 787 CreateProtocolManager(&test_delegate)); 788 789 // Kick off initialization. This returns chunks from the DB synchronously. 790 pm->ForceScheduleNextUpdate(TimeDelta()); 791 runner->RunPendingTasks(); 792 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); 796 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(); 800 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); 806 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); 812 813 EXPECT_TRUE(pm->IsUpdateScheduled()); 814 } 815 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; 822 823 testing::StrictMock<MockProtocolDelegate> test_delegate; 824 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1); 825 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce( 826 Invoke(testing::CreateFunctor(InvokeGetChunksCallback, 827 std::vector<SBListChunkRanges>(), 828 false))); 829 EXPECT_CALL(test_delegate, ResetDatabase()).Times(1); 830 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1); 831 832 scoped_ptr<SafeBrowsingProtocolManager> pm( 833 CreateProtocolManager(&test_delegate)); 834 835 // Kick off initialization. This returns chunks from the DB synchronously. 836 pm->ForceScheduleNextUpdate(TimeDelta()); 837 runner->RunPendingTasks(); 838 839 net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0); 840 ValidateUpdateFetcherRequest(url_fetcher); 841 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); 847 848 EXPECT_TRUE(pm->IsUpdateScheduled()); 849 } 850 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; 858 859 testing::StrictMock<MockProtocolDelegate> test_delegate; 860 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1); 861 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce( 862 Invoke(testing::CreateFunctor(InvokeGetChunksCallback, 863 std::vector<SBListChunkRanges>(), 864 false))); 865 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1); 866 867 scoped_ptr<SafeBrowsingProtocolManager> pm( 868 CreateProtocolManager(&test_delegate)); 869 870 // Kick off initialization. This returns chunks from the DB synchronously. 871 pm->ForceScheduleNextUpdate(TimeDelta()); 872 runner->RunPendingTasks(); 873 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); 883 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); 893 894 EXPECT_TRUE(pm->IsUpdateScheduled()); 895 } 896 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; 904 905 testing::StrictMock<MockProtocolDelegate> test_delegate; 906 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1); 907 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce( 908 Invoke(testing::CreateFunctor(InvokeGetChunksCallback, 909 std::vector<SBListChunkRanges>(), 910 false))); 911 EXPECT_CALL(test_delegate, UpdateFinished(false)).Times(1); 912 913 scoped_ptr<SafeBrowsingProtocolManager> pm( 914 CreateProtocolManager(&test_delegate)); 915 916 // Kick off initialization. This returns chunks from the DB synchronously. 917 pm->ForceScheduleNextUpdate(TimeDelta()); 918 runner->RunPendingTasks(); 919 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); 929 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); 939 940 EXPECT_TRUE(pm->IsUpdateScheduled()); 941 } 942 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; 950 951 testing::StrictMock<MockProtocolDelegate> test_delegate; 952 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1); 953 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce( 954 Invoke(testing::CreateFunctor(InvokeGetChunksCallback, 955 std::vector<SBListChunkRanges>(), 956 false))); 957 EXPECT_CALL(test_delegate, AddChunks("goog-phish-shavar", _, _)).WillOnce( 958 Invoke(HandleAddChunks)); 959 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1); 960 961 scoped_ptr<SafeBrowsingProtocolManager> pm( 962 CreateProtocolManager(&test_delegate)); 963 964 // Kick off initialization. This returns chunks from the DB synchronously. 965 pm->ForceScheduleNextUpdate(TimeDelta()); 966 runner->RunPendingTasks(); 967 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); 977 978 // The redirect response contains a single chunk. 979 net::TestURLFetcher* chunk_url_fetcher = 980 url_fetcher_factory.GetFetcherByID(1); 981 ValidateRedirectFetcherRequest( 982 chunk_url_fetcher, "https://redirect-server.example.com/path"); 983 chunk_url_fetcher->set_status(net::URLRequestStatus()); 984 chunk_url_fetcher->set_response_code(200); 985 chunk_url_fetcher->SetResponseString( 986 "a:4:4:9\n" 987 "host\1fdaf"); 988 chunk_url_fetcher->delegate()->OnURLFetchComplete(chunk_url_fetcher); 989 990 EXPECT_FALSE(pm->IsUpdateScheduled()); 991 992 // The AddChunksCallback needs to be invoked. 993 runner->RunPendingTasks(); 994 995 EXPECT_TRUE(pm->IsUpdateScheduled()); 996 } 997 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; 1005 1006 testing::StrictMock<MockProtocolDelegate> test_delegate; 1007 EXPECT_CALL(test_delegate, UpdateStarted()).Times(1); 1008 EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce( 1009 Invoke(testing::CreateFunctor(InvokeGetChunksCallback, 1010 std::vector<SBListChunkRanges>(), 1011 false))); 1012 EXPECT_CALL(test_delegate, AddChunks("goog-phish-shavar", _, _)). 1013 WillRepeatedly(Invoke(HandleAddChunks)); 1014 EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1); 1015 1016 scoped_ptr<SafeBrowsingProtocolManager> pm( 1017 CreateProtocolManager(&test_delegate)); 1018 1019 // Kick off initialization. This returns chunks from the DB synchronously. 1020 pm->ForceScheduleNextUpdate(TimeDelta()); 1021 runner->RunPendingTasks(); 1022 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); 1033 1034 // The first redirect response contains a single chunk. 1035 net::TestURLFetcher* first_chunk_url_fetcher = 1036 url_fetcher_factory.GetFetcherByID(1); 1037 ValidateRedirectFetcherRequest( 1038 first_chunk_url_fetcher, "https://redirect-server.example.com/one"); 1039 first_chunk_url_fetcher->set_status(net::URLRequestStatus()); 1040 first_chunk_url_fetcher->set_response_code(200); 1041 first_chunk_url_fetcher->SetResponseString( 1042 "a:4:4:9\n" 1043 "host\1aaaa"); 1044 first_chunk_url_fetcher->delegate()->OnURLFetchComplete( 1045 first_chunk_url_fetcher); 1046 1047 // Invoke the AddChunksCallback to trigger the second request. 1048 runner->RunPendingTasks(); 1049 1050 EXPECT_FALSE(pm->IsUpdateScheduled()); 1051 1052 // The second redirect response contains a single chunk. 1053 net::TestURLFetcher* second_chunk_url_fetcher = 1054 url_fetcher_factory.GetFetcherByID(2); 1055 ValidateRedirectFetcherRequest( 1056 second_chunk_url_fetcher, "https://redirect-server.example.com/two"); 1057 second_chunk_url_fetcher->set_status(net::URLRequestStatus()); 1058 second_chunk_url_fetcher->set_response_code(200); 1059 second_chunk_url_fetcher->SetResponseString( 1060 "a:5:4:9\n" 1061 "host\1bbbb"); 1062 second_chunk_url_fetcher->delegate()->OnURLFetchComplete( 1063 second_chunk_url_fetcher); 1064 1065 EXPECT_FALSE(pm->IsUpdateScheduled()); 1066 1067 // Invoke the AddChunksCallback to finish the update. 1068 runner->RunPendingTasks(); 1069 1070 EXPECT_TRUE(pm->IsUpdateScheduled()); 1071 } 1072