15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
7f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/memory/scoped_vector.h"
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/test/test_simple_task_runner.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/thread_task_runner_handle.h"
11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/browser/safe_browsing/chunk.pb.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/safe_browsing/protocol_manager.h"
14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/browser/safe_browsing/safe_browsing_util.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/google_api_keys.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/escape.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/load_flags.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/net_errors.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/url_request/test_url_fetcher_factory.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gmock_mutant.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::Time;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeDelta;
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using testing::_;
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using testing::Invoke;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace {
30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const char kUrlPrefix[] = "https://prefix.com/foo";
32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const char kBackupConnectUrlPrefix[] = "https://alt1-prefix.com/foo";
33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const char kBackupHttpUrlPrefix[] = "https://alt2-prefix.com/foo";
34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const char kBackupNetworkUrlPrefix[] = "https://alt3-prefix.com/foo";
35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const char kClient[] = "unittest";
36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const char kAppVer[] = "1.0";
37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const char kAdditionalQuery[] = "additional_query";
38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(OS_ANDROID)
405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char kDefaultPhishList[] = "goog-mobilephish-shavar";
415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char kDefaultMalwareList[] = "goog-mobilemalware-shavar";
425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#else
435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char kDefaultPhishList[] = "goog-phish-shavar";
445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char kDefaultMalwareList[] = "goog-malware-shavar";
455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Add-prefix chunk with single prefix.
48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const char kRawChunkPayload1[] = {
49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  '\0', '\0', '\0', '\x08',  // 32-bit payload length in network byte order.
50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  '\x08',                    // field 1, wire format varint
51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  '\x03',                    // chunk_number varint 3
52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  '\x22',                    // field 4, wire format length-delimited
53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  '\x04',                    // varint 4 length
54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  'a', 'b', 'c', 'd'         // 4-byte prefix
55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)};
56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const std::string kChunkPayload1(kRawChunkPayload1, sizeof(kRawChunkPayload1));
57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Add-prefix chunk_number 5 with single prefix.
59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const char kRawChunkPayload2[] = {
60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  '\0', '\0', '\0', '\x08',  // 32-bit payload length in network byte order.
61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  '\x08',                    // field 1, wire format varint
62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  '\x05',                    // chunk_number varint 5
63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  '\x22',                    // field 4, wire format length-delimited
64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  '\x04',                    // varint length 4
65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  'e', 'f', 'g', 'h'         // 4-byte prefix
66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)};
67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const std::string kChunkPayload2(kRawChunkPayload2, sizeof(kRawChunkPayload2));
68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}  // namespace
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SafeBrowsingProtocolManagerTest : public testing::Test {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string key_param_;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string key = google_apis::GetAPIKey();
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!key.empty()) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      key_param_ = base::StringPrintf(
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "&key=%s",
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          net::EscapeQueryParamValue(key, true).c_str());
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SafeBrowsingProtocolManager> CreateProtocolManager(
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SafeBrowsingProtocolManagerDelegate* delegate) {
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SafeBrowsingProtocolConfig config;
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    config.client_name = kClient;
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    config.url_prefix = kUrlPrefix;
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    config.backup_connect_error_url_prefix = kBackupConnectUrlPrefix;
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    config.backup_http_error_url_prefix = kBackupHttpUrlPrefix;
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    config.backup_network_error_url_prefix = kBackupNetworkUrlPrefix;
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    config.version = kAppVer;
93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if defined(OS_ANDROID)
94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    config.disable_connection_check = true;
95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return scoped_ptr<SafeBrowsingProtocolManager>(
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        SafeBrowsingProtocolManager::Create(delegate, NULL, config));
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void ValidateUpdateFetcherRequest(
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const net::TestURLFetcher* url_fetcher,
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const std::string& expected_prefix) {
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_TRUE(url_fetcher);
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(net::LOAD_DISABLE_CACHE, url_fetcher->GetLoadFlags());
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    std::string expected_lists(base::StringPrintf("%s;\n%s;\n",
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                  kDefaultPhishList,
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                  kDefaultMalwareList));
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(expected_lists, url_fetcher->upload_data());
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(GURL(expected_prefix + "/downloads?client=unittest&appver=1.0"
111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                   "&pver=3.0" + key_param_),
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              url_fetcher->GetOriginalURL());
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void ValidateUpdateFetcherRequest(const net::TestURLFetcher* url_fetcher) {
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ValidateUpdateFetcherRequest(url_fetcher, kUrlPrefix);
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void ValidateRedirectFetcherRequest(const net::TestURLFetcher* url_fetcher,
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      const std::string& expected_url) {
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_TRUE(url_fetcher);
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(net::LOAD_DISABLE_CACHE, url_fetcher->GetLoadFlags());
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ("", url_fetcher->upload_data());
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(GURL(expected_url), url_fetcher->GetOriginalURL());
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Ensure that we respect section 5 of the SafeBrowsing protocol specification.
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SafeBrowsingProtocolManagerTest, TestBackOffTimes) {
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL));
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pm->next_update_interval_ = TimeDelta::FromSeconds(1800);
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(pm->back_off_fuzz_ >= 0.0 && pm->back_off_fuzz_ <= 1.0);
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TimeDelta next;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No errors received so far.
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  next = pm->GetNextUpdateInterval(false);
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(next, TimeDelta::FromSeconds(1800));
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1 error.
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  next = pm->GetNextUpdateInterval(true);
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(next, TimeDelta::FromSeconds(60));
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 2 errors.
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  next = pm->GetNextUpdateInterval(true);
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(next >= TimeDelta::FromMinutes(30) &&
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              next <= TimeDelta::FromMinutes(60));
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 3 errors.
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  next = pm->GetNextUpdateInterval(true);
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(next >= TimeDelta::FromMinutes(60) &&
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              next <= TimeDelta::FromMinutes(120));
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 4 errors.
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  next = pm->GetNextUpdateInterval(true);
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(next >= TimeDelta::FromMinutes(120) &&
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              next <= TimeDelta::FromMinutes(240));
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 5 errors.
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  next = pm->GetNextUpdateInterval(true);
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(next >= TimeDelta::FromMinutes(240) &&
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              next <= TimeDelta::FromMinutes(480));
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 6 errors, reached max backoff.
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  next = pm->GetNextUpdateInterval(true);
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(next, TimeDelta::FromMinutes(480));
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 7 errors.
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  next = pm->GetNextUpdateInterval(true);
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(next, TimeDelta::FromMinutes(480));
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Received a successful response.
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  next = pm->GetNextUpdateInterval(false);
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(next, TimeDelta::FromSeconds(1800));
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SafeBrowsingProtocolManagerTest, TestChunkStrings) {
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL));
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add and Sub chunks.
1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SBListChunkRanges phish(kDefaultPhishList);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  phish.adds = "1,4,6,8-20,99";
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  phish.subs = "16,32,64-96";
1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_EQ(base::StringPrintf("%s;a:1,4,6,8-20,99:s:16,32,64-96\n",
1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                               kDefaultPhishList),
187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            safe_browsing::FormatList(phish));
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add chunks only.
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  phish.subs = "";
1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_EQ(base::StringPrintf("%s;a:1,4,6,8-20,99\n",
1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                               kDefaultPhishList),
193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            safe_browsing::FormatList(phish));
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sub chunks only.
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  phish.adds = "";
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  phish.subs = "16,32,64-96";
1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_EQ(base::StringPrintf("%s;s:16,32,64-96\n",
1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                               kDefaultPhishList),
200f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            safe_browsing::FormatList(phish));
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No chunks of either type.
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  phish.adds = "";
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  phish.subs = "";
2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_EQ(base::StringPrintf("%s;\n", kDefaultPhishList),
2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            safe_browsing::FormatList(phish));
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SafeBrowsingProtocolManagerTest, TestGetHashBackOffTimes) {
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL));
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No errors or back off time yet.
213f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_EQ(0U, pm->gethash_error_count_);
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(pm->next_gethash_time_.is_null());
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Time now = Time::Now();
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1 error.
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pm->HandleGetHashError(now);
220f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_EQ(1U, pm->gethash_error_count_);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeDelta margin = TimeDelta::FromSeconds(5);  // Fudge factor.
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Time future = now + TimeDelta::FromMinutes(1);
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(pm->next_gethash_time_ >= future - margin &&
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              pm->next_gethash_time_ <= future + margin);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 2 errors.
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pm->HandleGetHashError(now);
228f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_EQ(2U, pm->gethash_error_count_);
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(pm->next_gethash_time_ >= now + TimeDelta::FromMinutes(30));
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(pm->next_gethash_time_ <= now + TimeDelta::FromMinutes(60));
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 3 errors.
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pm->HandleGetHashError(now);
234f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_EQ(3U, pm->gethash_error_count_);
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(pm->next_gethash_time_ >= now + TimeDelta::FromMinutes(60));
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(pm->next_gethash_time_ <= now + TimeDelta::FromMinutes(120));
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 4 errors.
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pm->HandleGetHashError(now);
240f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_EQ(4U, pm->gethash_error_count_);
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(pm->next_gethash_time_ >= now + TimeDelta::FromMinutes(120));
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(pm->next_gethash_time_ <= now + TimeDelta::FromMinutes(240));
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 5 errors.
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pm->HandleGetHashError(now);
246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_EQ(5U, pm->gethash_error_count_);
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(pm->next_gethash_time_ >= now + TimeDelta::FromMinutes(240));
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(pm->next_gethash_time_ <= now + TimeDelta::FromMinutes(480));
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 6 errors, reached max backoff.
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pm->HandleGetHashError(now);
252f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_EQ(6U, pm->gethash_error_count_);
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(pm->next_gethash_time_ == now + TimeDelta::FromMinutes(480));
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 7 errors.
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pm->HandleGetHashError(now);
257f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_EQ(7U, pm->gethash_error_count_);
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(pm->next_gethash_time_== now + TimeDelta::FromMinutes(480));
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SafeBrowsingProtocolManagerTest, TestGetHashUrl) {
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL));
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("https://prefix.com/foo/gethash?client=unittest&appver=1.0&"
265f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            "pver=3.0" + key_param_, pm->GetHashUrl().spec());
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pm->set_additional_query(kAdditionalQuery);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("https://prefix.com/foo/gethash?client=unittest&appver=1.0&"
269f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            "pver=3.0" + key_param_ + "&additional_query",
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            pm->GetHashUrl().spec());
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SafeBrowsingProtocolManagerTest, TestUpdateUrl) {
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL));
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("https://prefix.com/foo/downloads?client=unittest&appver=1.0&"
277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            "pver=3.0" + key_param_, pm->UpdateUrl().spec());
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pm->set_additional_query(kAdditionalQuery);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("https://prefix.com/foo/downloads?client=unittest&appver=1.0&"
281f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            "pver=3.0" + key_param_ + "&additional_query",
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            pm->UpdateUrl().spec());
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SafeBrowsingProtocolManagerTest, TestNextChunkUrl) {
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL));
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url_partial = "localhost:1234/foo/bar?foo";
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url_http_full = "http://localhost:1234/foo/bar?foo";
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url_https_full = "https://localhost:1234/foo/bar?foo";
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url_https_no_query = "https://localhost:1234/foo/bar";
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("https://localhost:1234/foo/bar?foo",
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            pm->NextChunkUrl(url_partial).spec());
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("http://localhost:1234/foo/bar?foo",
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            pm->NextChunkUrl(url_http_full).spec());
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("https://localhost:1234/foo/bar?foo",
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            pm->NextChunkUrl(url_https_full).spec());
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("https://localhost:1234/foo/bar",
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            pm->NextChunkUrl(url_https_no_query).spec());
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pm->set_additional_query(kAdditionalQuery);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("https://localhost:1234/foo/bar?foo&additional_query",
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            pm->NextChunkUrl(url_partial).spec());
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("http://localhost:1234/foo/bar?foo&additional_query",
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            pm->NextChunkUrl(url_http_full).spec());
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("https://localhost:1234/foo/bar?foo&additional_query",
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            pm->NextChunkUrl(url_https_full).spec());
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("https://localhost:1234/foo/bar?additional_query",
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            pm->NextChunkUrl(url_https_no_query).spec());
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class MockProtocolDelegate : public SafeBrowsingProtocolManagerDelegate {
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockProtocolDelegate() {}
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~MockProtocolDelegate() {}
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MOCK_METHOD0(UpdateStarted, void());
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MOCK_METHOD1(UpdateFinished, void(bool));
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MOCK_METHOD0(ResetDatabase, void());
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MOCK_METHOD1(GetChunks, void(GetChunksCallback));
324f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
325f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // gmock does not work with scoped_ptr<> at this time.  Add a local method to
326f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // mock, then call that from an override.  Beware of object ownership when
327f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // making changes here.
328f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  MOCK_METHOD3(AddChunksRaw, void(const std::string& lists,
329f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                  const ScopedVector<SBChunkData>& chunks,
330f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                  AddChunksCallback));
331f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  virtual void AddChunks(const std::string& list,
332f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                         scoped_ptr<ScopedVector<SBChunkData> > chunks,
333f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                         AddChunksCallback callback) OVERRIDE {
334f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    AddChunksRaw(list, *chunks, callback);
335f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
336f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
337f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // TODO(shess): Actually test this case somewhere.
338f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  MOCK_METHOD1(DeleteChunksRaw,
339f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)               void(const std::vector<SBChunkDelete>& chunk_deletes));
340f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  virtual void DeleteChunks(
341f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      scoped_ptr<std::vector<SBChunkDelete> > chunk_deletes) OVERRIDE{
342f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    DeleteChunksRaw(*chunk_deletes);
343f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |InvokeGetChunksCallback| is required because GMock's InvokeArgument action
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// expects to use operator(), and a Callback only provides Run().
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TODO(cbentzel): Use ACTION or ACTION_TEMPLATE instead?
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void InvokeGetChunksCallback(
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::vector<SBListChunkRanges>& ranges,
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool database_error,
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SafeBrowsingProtocolManagerDelegate::GetChunksCallback callback) {
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback.Run(ranges, database_error);
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |HandleAddChunks| deletes the chunks and asynchronously invokes
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |callback| since SafeBrowsingProtocolManager is not re-entrant at the time
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// this is called. This guarantee is part of the
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// SafeBrowsingProtocolManagerDelegate contract.
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HandleAddChunks(
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& unused_list,
362f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const ScopedVector<SBChunkData>& chunks,
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SafeBrowsingProtocolManagerDelegate::AddChunksCallback callback) {
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<base::SingleThreadTaskRunner> task_runner(
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::ThreadTaskRunnerHandle::Get());
366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!task_runner.get())
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  task_runner->PostTask(FROM_HERE, callback);
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Tests that the Update protocol will be skipped if there are problems
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// accessing the database.
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SafeBrowsingProtocolManagerTest, ProblemAccessingDatabase) {
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<base::TestSimpleTaskRunner> runner(
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new base::TestSimpleTaskRunner());
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ThreadTaskRunnerHandle runner_handler(runner);
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  testing::StrictMock<MockProtocolDelegate> test_delegate;
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    std::vector<SBListChunkRanges>(),
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    true)));
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateFinished(false)).Times(1);
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SafeBrowsingProtocolManager> pm(
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CreateProtocolManager(&test_delegate));
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pm->ForceScheduleNextUpdate(TimeDelta());
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  runner->RunPendingTasks();
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(pm->IsUpdateScheduled());
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Tests the contents of the POST body when there are contents in the
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// local database. This is not exhaustive, as the actual list formatting
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// is covered by SafeBrowsingProtocolManagerTest.TestChunkStrings.
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SafeBrowsingProtocolManagerTest, ExistingDatabase) {
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<base::TestSimpleTaskRunner> runner(
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new base::TestSimpleTaskRunner());
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ThreadTaskRunnerHandle runner_handler(runner);
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcherFactory url_fetcher_factory;
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<SBListChunkRanges> ranges;
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SBListChunkRanges range_phish(safe_browsing_util::kPhishingList);
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  range_phish.adds = "adds_phish";
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  range_phish.subs = "subs_phish";
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ranges.push_back(range_phish);
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SBListChunkRanges range_unknown("unknown_list");
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  range_unknown.adds = "adds_unknown";
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  range_unknown.subs = "subs_unknown";
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ranges.push_back(range_unknown);
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  testing::StrictMock<MockProtocolDelegate> test_delegate;
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    ranges,
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    false)));
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SafeBrowsingProtocolManager> pm(
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CreateProtocolManager(&test_delegate));
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Kick off initialization. This returns chunks from the DB synchronously.
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pm->ForceScheduleNextUpdate(TimeDelta());
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  runner->RunPendingTasks();
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We should have an URLFetcher at this point in time.
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(url_fetcher);
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(net::LOAD_DISABLE_CACHE, url_fetcher->GetLoadFlags());
4365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_EQ(base::StringPrintf("%s;a:adds_phish:s:subs_phish\n"
4375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                               "unknown_list;a:adds_unknown:s:subs_unknown\n"
4385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                               "%s;\n",
4395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                               kDefaultPhishList, kDefaultMalwareList),
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            url_fetcher->upload_data());
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(GURL("https://prefix.com/foo/downloads?client=unittest&appver=1.0"
442f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                 "&pver=3.0" + key_param_),
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            url_fetcher->GetOriginalURL());
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->set_status(net::URLRequestStatus());
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->set_response_code(200);
447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  url_fetcher->SetResponseString(std::string());
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(pm->IsUpdateScheduled());
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseBadBodyBackupSuccess) {
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<base::TestSimpleTaskRunner> runner(
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new base::TestSimpleTaskRunner());
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ThreadTaskRunnerHandle runner_handler(runner);
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcherFactory url_fetcher_factory;
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  testing::StrictMock<MockProtocolDelegate> test_delegate;
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    std::vector<SBListChunkRanges>(),
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    false)));
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SafeBrowsingProtocolManager> pm(
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CreateProtocolManager(&test_delegate));
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Kick off initialization. This returns chunks from the DB synchronously.
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pm->ForceScheduleNextUpdate(TimeDelta());
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  runner->RunPendingTasks();
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We should have an URLFetcher at this point in time.
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ValidateUpdateFetcherRequest(url_fetcher);
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The update response is successful, but an invalid body.
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->set_status(net::URLRequestStatus());
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->set_response_code(200);
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->SetResponseString("THIS_IS_A_BAD_RESPONSE");
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // There should now be a backup request.
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcher* backup_url_fetcher =
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      url_fetcher_factory.GetFetcherByID(1);
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ValidateUpdateFetcherRequest(backup_url_fetcher,
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               kBackupHttpUrlPrefix);
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Respond to the backup successfully.
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backup_url_fetcher->set_status(net::URLRequestStatus());
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backup_url_fetcher->set_response_code(200);
493c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  backup_url_fetcher->SetResponseString(std::string());
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(pm->IsUpdateScheduled());
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Tests what happens when there is an HTTP error response to the update
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// request, as well as an error response to the backup update request.
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseHttpErrorBackupError) {
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<base::TestSimpleTaskRunner> runner(
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new base::TestSimpleTaskRunner());
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ThreadTaskRunnerHandle runner_handler(runner);
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcherFactory url_fetcher_factory;
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  testing::StrictMock<MockProtocolDelegate> test_delegate;
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    std::vector<SBListChunkRanges>(),
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    false)));
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateFinished(false)).Times(1);
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SafeBrowsingProtocolManager> pm(
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CreateProtocolManager(&test_delegate));
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Kick off initialization. This returns chunks from the DB synchronously.
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pm->ForceScheduleNextUpdate(TimeDelta());
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  runner->RunPendingTasks();
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We should have an URLFetcher at this point in time.
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ValidateUpdateFetcherRequest(url_fetcher);
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Go ahead and respond to it.
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->set_status(net::URLRequestStatus());
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->set_response_code(404);
529c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  url_fetcher->SetResponseString(std::string());
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // There should now be a backup request.
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcher* backup_url_fetcher =
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      url_fetcher_factory.GetFetcherByID(1);
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ValidateUpdateFetcherRequest(backup_url_fetcher, kBackupHttpUrlPrefix);
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Respond to the backup unsuccessfully.
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backup_url_fetcher->set_status(net::URLRequestStatus());
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backup_url_fetcher->set_response_code(404);
540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  backup_url_fetcher->SetResponseString(std::string());
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(pm->IsUpdateScheduled());
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Tests what happens when there is an HTTP error response to the update
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// request, followed by a successful response to the backup update request.
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseHttpErrorBackupSuccess) {
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<base::TestSimpleTaskRunner> runner(
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new base::TestSimpleTaskRunner());
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ThreadTaskRunnerHandle runner_handler(runner);
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcherFactory url_fetcher_factory;
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  testing::StrictMock<MockProtocolDelegate> test_delegate;
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    std::vector<SBListChunkRanges>(),
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    false)));
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SafeBrowsingProtocolManager> pm(
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CreateProtocolManager(&test_delegate));
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Kick off initialization. This returns chunks from the DB synchronously.
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pm->ForceScheduleNextUpdate(TimeDelta());
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  runner->RunPendingTasks();
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We should have an URLFetcher at this point in time.
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ValidateUpdateFetcherRequest(url_fetcher);
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Go ahead and respond to it.
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->set_status(net::URLRequestStatus());
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->set_response_code(404);
576c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  url_fetcher->SetResponseString(std::string());
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // There should now be a backup request.
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcher* backup_url_fetcher =
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      url_fetcher_factory.GetFetcherByID(1);
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ValidateUpdateFetcherRequest(backup_url_fetcher,
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               kBackupHttpUrlPrefix);
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Respond to the backup successfully.
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backup_url_fetcher->set_status(net::URLRequestStatus());
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backup_url_fetcher->set_response_code(200);
588c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  backup_url_fetcher->SetResponseString(std::string());
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(pm->IsUpdateScheduled());
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Tests what happens when there is an HTTP error response to the update
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// request, and a timeout on the backup update request.
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseHttpErrorBackupTimeout) {
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<base::TestSimpleTaskRunner> runner(
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new base::TestSimpleTaskRunner());
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ThreadTaskRunnerHandle runner_handler(runner);
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcherFactory url_fetcher_factory;
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  testing::StrictMock<MockProtocolDelegate> test_delegate;
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    std::vector<SBListChunkRanges>(),
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    false)));
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateFinished(false)).Times(1);
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SafeBrowsingProtocolManager> pm(
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CreateProtocolManager(&test_delegate));
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Kick off initialization. This returns chunks from the DB synchronously.
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pm->ForceScheduleNextUpdate(TimeDelta());
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  runner->RunPendingTasks();
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We should have an URLFetcher at this point in time.
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ValidateUpdateFetcherRequest(url_fetcher);
6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Go ahead and respond to it.
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->set_status(net::URLRequestStatus());
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->set_response_code(404);
624c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  url_fetcher->SetResponseString(std::string());
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // There should now be a backup request.
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcher* backup_url_fetcher =
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      url_fetcher_factory.GetFetcherByID(1);
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ValidateUpdateFetcherRequest(backup_url_fetcher, kBackupHttpUrlPrefix);
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Either one or two calls to RunPendingTasks are needed here. The first run
6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // of RunPendingTasks will run the canceled timeout task associated with
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the first Update request. Depending on timing, this will either directly
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // call the timeout task from the backup request, or schedule another task
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // to run that in the future.
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(cbentzel): Less fragile approach.
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  runner->RunPendingTasks();
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!pm->IsUpdateScheduled())
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    runner->RunPendingTasks();
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(pm->IsUpdateScheduled());
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Tests what happens when there is a connection error when issuing the update
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// request, and an error with the backup update request.
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SafeBrowsingProtocolManagerTest,
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       UpdateResponseConnectionErrorBackupError) {
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<base::TestSimpleTaskRunner> runner(
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new base::TestSimpleTaskRunner());
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ThreadTaskRunnerHandle runner_handler(runner);
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcherFactory url_fetcher_factory;
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  testing::StrictMock<MockProtocolDelegate> test_delegate;
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    std::vector<SBListChunkRanges>(),
6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    false)));
6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateFinished(false)).Times(1);
6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SafeBrowsingProtocolManager> pm(
6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CreateProtocolManager(&test_delegate));
6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Kick off initialization. This returns chunks from the DB synchronously.
6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pm->ForceScheduleNextUpdate(TimeDelta());
6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  runner->RunPendingTasks();
6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We should have an URLFetcher at this point in time.
6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ValidateUpdateFetcherRequest(url_fetcher);
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Go ahead and respond to it.
6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::FAILED,
6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                net::ERR_CONNECTION_RESET));
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // There should be a backup URLFetcher now.
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcher* backup_url_fetcher =
6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      url_fetcher_factory.GetFetcherByID(1);
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ValidateUpdateFetcherRequest(backup_url_fetcher,
6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               kBackupConnectUrlPrefix);
6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Respond to the backup unsuccessfully.
6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backup_url_fetcher->set_status(net::URLRequestStatus());
6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backup_url_fetcher->set_response_code(404);
686c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  backup_url_fetcher->SetResponseString(std::string());
6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(pm->IsUpdateScheduled());
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Tests what happens when there is a connection error when issuing the update
6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// request, and a successful response to the backup update request.
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SafeBrowsingProtocolManagerTest,
6952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       UpdateResponseConnectionErrorBackupSuccess) {
6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<base::TestSimpleTaskRunner> runner(
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new base::TestSimpleTaskRunner());
6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ThreadTaskRunnerHandle runner_handler(runner);
6992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcherFactory url_fetcher_factory;
7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  testing::StrictMock<MockProtocolDelegate> test_delegate;
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    std::vector<SBListChunkRanges>(),
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    false)));
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SafeBrowsingProtocolManager> pm(
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CreateProtocolManager(&test_delegate));
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Kick off initialization. This returns chunks from the DB synchronously.
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pm->ForceScheduleNextUpdate(TimeDelta());
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  runner->RunPendingTasks();
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We should have an URLFetcher at this point in time.
7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ValidateUpdateFetcherRequest(url_fetcher);
7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Go ahead and respond to it.
7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::FAILED,
7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                net::ERR_CONNECTION_RESET));
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // There should be a backup URLFetcher now.
7262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcher* backup_url_fetcher =
7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      url_fetcher_factory.GetFetcherByID(1);
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ValidateUpdateFetcherRequest(backup_url_fetcher,
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               kBackupConnectUrlPrefix);
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Respond to the backup unsuccessfully.
7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backup_url_fetcher->set_status(net::URLRequestStatus());
7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backup_url_fetcher->set_response_code(200);
734c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  backup_url_fetcher->SetResponseString(std::string());
7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(pm->IsUpdateScheduled());
7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Tests what happens when there is a network state error when issuing the
7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// update request, and an error with the backup update request.
7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SafeBrowsingProtocolManagerTest,
7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       UpdateResponseNetworkErrorBackupError) {
7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<base::TestSimpleTaskRunner> runner(
7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new base::TestSimpleTaskRunner());
7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ThreadTaskRunnerHandle runner_handler(runner);
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcherFactory url_fetcher_factory;
7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  testing::StrictMock<MockProtocolDelegate> test_delegate;
7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    std::vector<SBListChunkRanges>(),
7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    false)));
7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateFinished(false)).Times(1);
7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SafeBrowsingProtocolManager> pm(
7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CreateProtocolManager(&test_delegate));
7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Kick off initialization. This returns chunks from the DB synchronously.
7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pm->ForceScheduleNextUpdate(TimeDelta());
7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  runner->RunPendingTasks();
7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We should have an URLFetcher at this point in time.
7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ValidateUpdateFetcherRequest(url_fetcher);
7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Go ahead and respond to it.
7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->set_status(
7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      net::URLRequestStatus(net::URLRequestStatus::FAILED,
7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            net::ERR_INTERNET_DISCONNECTED));
7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // There should be a backup URLFetcher now.
7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcher* backup_url_fetcher =
7752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      url_fetcher_factory.GetFetcherByID(1);
7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ValidateUpdateFetcherRequest(backup_url_fetcher,
7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               kBackupNetworkUrlPrefix);
7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Respond to the backup unsuccessfully.
7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backup_url_fetcher->set_status(net::URLRequestStatus());
7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backup_url_fetcher->set_response_code(404);
782c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  backup_url_fetcher->SetResponseString(std::string());
7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(pm->IsUpdateScheduled());
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Tests what happens when there is a network state error when issuing the
7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// update request, and a successful response to the backup update request.
7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SafeBrowsingProtocolManagerTest,
7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       UpdateResponseNetworkErrorBackupSuccess) {
7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<base::TestSimpleTaskRunner> runner(
7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new base::TestSimpleTaskRunner());
7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ThreadTaskRunnerHandle runner_handler(runner);
7952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcherFactory url_fetcher_factory;
7962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  testing::StrictMock<MockProtocolDelegate> test_delegate;
7982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
7992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
8002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
8012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    std::vector<SBListChunkRanges>(),
8022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    false)));
8032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
8042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SafeBrowsingProtocolManager> pm(
8062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CreateProtocolManager(&test_delegate));
8072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Kick off initialization. This returns chunks from the DB synchronously.
8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pm->ForceScheduleNextUpdate(TimeDelta());
8102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  runner->RunPendingTasks();
8112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We should have an URLFetcher at this point in time.
8132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
8142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ValidateUpdateFetcherRequest(url_fetcher);
8152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Go ahead and respond to it.
8172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->set_status(
8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      net::URLRequestStatus(net::URLRequestStatus::FAILED,
8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            net::ERR_INTERNET_DISCONNECTED));
8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // There should be a backup URLFetcher now.
8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcher* backup_url_fetcher =
8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      url_fetcher_factory.GetFetcherByID(1);
8252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ValidateUpdateFetcherRequest(backup_url_fetcher,
8262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               kBackupNetworkUrlPrefix);
8272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Respond to the backup unsuccessfully.
8292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backup_url_fetcher->set_status(net::URLRequestStatus());
8302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backup_url_fetcher->set_response_code(200);
831c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  backup_url_fetcher->SetResponseString(std::string());
8322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
8332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(pm->IsUpdateScheduled());
8352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Tests what happens when there is a timeout before an update response.
8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseTimeoutBackupSuccess) {
8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<base::TestSimpleTaskRunner> runner(
8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new base::TestSimpleTaskRunner());
8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ThreadTaskRunnerHandle runner_handler(runner);
8422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcherFactory url_fetcher_factory;
8432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  testing::StrictMock<MockProtocolDelegate> test_delegate;
8452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
8472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
8482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    std::vector<SBListChunkRanges>(),
8492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    false)));
8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
8512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SafeBrowsingProtocolManager> pm(
8532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CreateProtocolManager(&test_delegate));
8542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Kick off initialization. This returns chunks from the DB synchronously.
8562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pm->ForceScheduleNextUpdate(TimeDelta());
8572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  runner->RunPendingTasks();
8582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We should have an URLFetcher at this point in time.
8602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
8612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ValidateUpdateFetcherRequest(url_fetcher);
8622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The first time RunPendingTasks is called above, the update timeout timer is
8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // not handled. This call of RunPendingTasks will handle the update.
8652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  runner->RunPendingTasks();
8662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // There should be a backup URLFetcher now.
8682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcher* backup_url_fetcher =
8692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      url_fetcher_factory.GetFetcherByID(1);
8702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ValidateUpdateFetcherRequest(backup_url_fetcher,
8712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               kBackupConnectUrlPrefix);
8722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Respond to the backup unsuccessfully.
8742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backup_url_fetcher->set_status(net::URLRequestStatus());
8752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backup_url_fetcher->set_response_code(200);
876c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  backup_url_fetcher->SetResponseString(std::string());
8772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backup_url_fetcher->delegate()->OnURLFetchComplete(backup_url_fetcher);
8782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(pm->IsUpdateScheduled());
8802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Tests what happens when there is a reset command in the response.
8832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseReset) {
8842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<base::TestSimpleTaskRunner> runner(
8852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new base::TestSimpleTaskRunner());
8862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ThreadTaskRunnerHandle runner_handler(runner);
8872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcherFactory url_fetcher_factory;
8882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  testing::StrictMock<MockProtocolDelegate> test_delegate;
8902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
8912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
8922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
8932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    std::vector<SBListChunkRanges>(),
8942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    false)));
8952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, ResetDatabase()).Times(1);
8962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
8972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SafeBrowsingProtocolManager> pm(
8992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CreateProtocolManager(&test_delegate));
9002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Kick off initialization. This returns chunks from the DB synchronously.
9022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pm->ForceScheduleNextUpdate(TimeDelta());
9032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  runner->RunPendingTasks();
9042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
9062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ValidateUpdateFetcherRequest(url_fetcher);
9072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The update response is successful, and has a reset command.
9092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->set_status(net::URLRequestStatus());
9102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->set_response_code(200);
9112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->SetResponseString("r:pleasereset\n");
9122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
9132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(pm->IsUpdateScheduled());
9152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Tests a single valid update response, followed by a single redirect response
9182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// that has an valid, but empty body.
9192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SafeBrowsingProtocolManagerTest, EmptyRedirectResponse) {
9202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<base::TestSimpleTaskRunner> runner(
9212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new base::TestSimpleTaskRunner());
9222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ThreadTaskRunnerHandle runner_handler(runner);
9232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcherFactory url_fetcher_factory;
9242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  testing::StrictMock<MockProtocolDelegate> test_delegate;
9262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
9272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
9282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
9292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    std::vector<SBListChunkRanges>(),
9302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    false)));
9312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
9322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SafeBrowsingProtocolManager> pm(
9342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CreateProtocolManager(&test_delegate));
9352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Kick off initialization. This returns chunks from the DB synchronously.
9372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pm->ForceScheduleNextUpdate(TimeDelta());
9382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  runner->RunPendingTasks();
9392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The update response contains a single redirect command.
9412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
9422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ValidateUpdateFetcherRequest(url_fetcher);
9432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->set_status(net::URLRequestStatus());
9442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->set_response_code(200);
9452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->SetResponseString(
9465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::StringPrintf("i:%s\n"
9475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                         "u:redirect-server.example.com/path\n",
9485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                         kDefaultPhishList));
9492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
9502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The redirect response contains an empty body.
9522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcher* chunk_url_fetcher =
9532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      url_fetcher_factory.GetFetcherByID(1);
9542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ValidateRedirectFetcherRequest(
9552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      chunk_url_fetcher, "https://redirect-server.example.com/path");
9562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  chunk_url_fetcher->set_status(net::URLRequestStatus());
9572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  chunk_url_fetcher->set_response_code(200);
958c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  chunk_url_fetcher->SetResponseString(std::string());
9592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  chunk_url_fetcher->delegate()->OnURLFetchComplete(chunk_url_fetcher);
9602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(pm->IsUpdateScheduled());
9622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Tests a single valid update response, followed by a single redirect response
9652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// that has an invalid body.
9662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SafeBrowsingProtocolManagerTest, InvalidRedirectResponse) {
9672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<base::TestSimpleTaskRunner> runner(
9682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new base::TestSimpleTaskRunner());
9692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ThreadTaskRunnerHandle runner_handler(runner);
9702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcherFactory url_fetcher_factory;
9712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  testing::StrictMock<MockProtocolDelegate> test_delegate;
9732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
9742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
9752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
9762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    std::vector<SBListChunkRanges>(),
9772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    false)));
9782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateFinished(false)).Times(1);
9792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SafeBrowsingProtocolManager> pm(
9812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CreateProtocolManager(&test_delegate));
9822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Kick off initialization. This returns chunks from the DB synchronously.
9842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pm->ForceScheduleNextUpdate(TimeDelta());
9852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  runner->RunPendingTasks();
9862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The update response contains a single redirect command.
9882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
9892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ValidateUpdateFetcherRequest(url_fetcher);
9902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->set_status(net::URLRequestStatus());
9912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->set_response_code(200);
9922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->SetResponseString(
9935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::StringPrintf("i:%s\n"
9945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                         "u:redirect-server.example.com/path\n",
9955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                         kDefaultPhishList));
9962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
9972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The redirect response contains an invalid body.
9992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcher* chunk_url_fetcher =
10002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      url_fetcher_factory.GetFetcherByID(1);
10012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ValidateRedirectFetcherRequest(
10022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      chunk_url_fetcher, "https://redirect-server.example.com/path");
10032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  chunk_url_fetcher->set_status(net::URLRequestStatus());
10042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  chunk_url_fetcher->set_response_code(200);
10052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  chunk_url_fetcher->SetResponseString("THIS IS AN INVALID RESPONSE");
10062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  chunk_url_fetcher->delegate()->OnURLFetchComplete(chunk_url_fetcher);
10072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(pm->IsUpdateScheduled());
10092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Tests a single valid update response, followed by a single redirect response
10122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// containing chunks.
10132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SafeBrowsingProtocolManagerTest, SingleRedirectResponseWithChunks) {
10142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<base::TestSimpleTaskRunner> runner(
10152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new base::TestSimpleTaskRunner());
10162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ThreadTaskRunnerHandle runner_handler(runner);
10172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcherFactory url_fetcher_factory;
10182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  testing::StrictMock<MockProtocolDelegate> test_delegate;
10202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
10212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
10222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
10232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    std::vector<SBListChunkRanges>(),
10242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    false)));
10255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_CALL(test_delegate, AddChunksRaw(kDefaultPhishList, _, _)).WillOnce(
10262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Invoke(HandleAddChunks));
10272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
10282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SafeBrowsingProtocolManager> pm(
10302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CreateProtocolManager(&test_delegate));
10312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Kick off initialization. This returns chunks from the DB synchronously.
10332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pm->ForceScheduleNextUpdate(TimeDelta());
10342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  runner->RunPendingTasks();
10352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The update response contains a single redirect command.
10372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
10382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ValidateUpdateFetcherRequest(url_fetcher);
10392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->set_status(net::URLRequestStatus());
10402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->set_response_code(200);
10412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->SetResponseString(
10425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::StringPrintf("i:%s\n"
10435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                         "u:redirect-server.example.com/path\n",
10445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                         kDefaultPhishList));
10452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
10462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The redirect response contains a single chunk.
10482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcher* chunk_url_fetcher =
10492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      url_fetcher_factory.GetFetcherByID(1);
10502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ValidateRedirectFetcherRequest(
10512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      chunk_url_fetcher, "https://redirect-server.example.com/path");
10522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  chunk_url_fetcher->set_status(net::URLRequestStatus());
10532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  chunk_url_fetcher->set_response_code(200);
1054f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  chunk_url_fetcher->SetResponseString(kChunkPayload1);
10552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  chunk_url_fetcher->delegate()->OnURLFetchComplete(chunk_url_fetcher);
10562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(pm->IsUpdateScheduled());
10582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The AddChunksCallback needs to be invoked.
10602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  runner->RunPendingTasks();
10612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(pm->IsUpdateScheduled());
10632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Tests a single valid update response, followed by multiple redirect responses
10662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// containing chunks.
10672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SafeBrowsingProtocolManagerTest, MultipleRedirectResponsesWithChunks) {
10682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<base::TestSimpleTaskRunner> runner(
10692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new base::TestSimpleTaskRunner());
10702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ThreadTaskRunnerHandle runner_handler(runner);
10712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcherFactory url_fetcher_factory;
10722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  testing::StrictMock<MockProtocolDelegate> test_delegate;
10742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateStarted()).Times(1);
10752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce(
10762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Invoke(testing::CreateFunctor(InvokeGetChunksCallback,
10772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    std::vector<SBListChunkRanges>(),
10782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    false)));
10795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_CALL(test_delegate, AddChunksRaw(kDefaultPhishList, _, _)).
10802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      WillRepeatedly(Invoke(HandleAddChunks));
10812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(test_delegate, UpdateFinished(true)).Times(1);
10822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SafeBrowsingProtocolManager> pm(
10842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CreateProtocolManager(&test_delegate));
10852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Kick off initialization. This returns chunks from the DB synchronously.
10872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pm->ForceScheduleNextUpdate(TimeDelta());
10882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  runner->RunPendingTasks();
10892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The update response contains multiple redirect commands.
10912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0);
10922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ValidateUpdateFetcherRequest(url_fetcher);
10932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->set_status(net::URLRequestStatus());
10942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->set_response_code(200);
10952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->SetResponseString(
10965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::StringPrintf("i:%s\n"
10975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                         "u:redirect-server.example.com/one\n"
10985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                         "u:redirect-server.example.com/two\n",
10995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                         kDefaultPhishList));
11002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
11012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The first redirect response contains a single chunk.
11032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcher* first_chunk_url_fetcher =
11042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      url_fetcher_factory.GetFetcherByID(1);
11052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ValidateRedirectFetcherRequest(
11062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      first_chunk_url_fetcher, "https://redirect-server.example.com/one");
11072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  first_chunk_url_fetcher->set_status(net::URLRequestStatus());
11082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  first_chunk_url_fetcher->set_response_code(200);
1109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  first_chunk_url_fetcher->SetResponseString(kChunkPayload1);
11102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  first_chunk_url_fetcher->delegate()->OnURLFetchComplete(
11112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      first_chunk_url_fetcher);
11122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Invoke the AddChunksCallback to trigger the second request.
11142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  runner->RunPendingTasks();
11152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(pm->IsUpdateScheduled());
11172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The second redirect response contains a single chunk.
11192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::TestURLFetcher* second_chunk_url_fetcher =
11202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      url_fetcher_factory.GetFetcherByID(2);
11212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ValidateRedirectFetcherRequest(
11222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      second_chunk_url_fetcher, "https://redirect-server.example.com/two");
11232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  second_chunk_url_fetcher->set_status(net::URLRequestStatus());
11242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  second_chunk_url_fetcher->set_response_code(200);
1125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  second_chunk_url_fetcher->SetResponseString(kChunkPayload2);
11262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  second_chunk_url_fetcher->delegate()->OnURLFetchComplete(
11272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      second_chunk_url_fetcher);
11282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(pm->IsUpdateScheduled());
11302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Invoke the AddChunksCallback to finish the update.
11322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  runner->RunPendingTasks();
11332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(pm->IsUpdateScheduled());
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1136