Home | History | Annotate | Download | only in safe_browsing
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 //
      5 // Unit tests for the SafeBrowsing storage system.
      6 
      7 #include "chrome/browser/safe_browsing/safe_browsing_database.h"
      8 
      9 #include "base/files/file_util.h"
     10 #include "base/files/scoped_temp_dir.h"
     11 #include "base/logging.h"
     12 #include "base/memory/scoped_vector.h"
     13 #include "base/message_loop/message_loop.h"
     14 #include "base/sha1.h"
     15 #include "base/strings/string_number_conversions.h"
     16 #include "base/strings/string_split.h"
     17 #include "base/time/time.h"
     18 #include "chrome/browser/safe_browsing/chunk.pb.h"
     19 #include "chrome/browser/safe_browsing/safe_browsing_store_file.h"
     20 #include "content/public/test/test_browser_thread_bundle.h"
     21 #include "crypto/sha2.h"
     22 #include "net/base/net_util.h"
     23 #include "sql/connection.h"
     24 #include "sql/statement.h"
     25 #include "testing/gtest/include/gtest/gtest.h"
     26 #include "testing/platform_test.h"
     27 #include "url/gurl.h"
     28 
     29 using base::Time;
     30 using base::TimeDelta;
     31 
     32 namespace {
     33 
     34 const TimeDelta kCacheLifetime = TimeDelta::FromMinutes(45);
     35 
     36 SBPrefix SBPrefixForString(const std::string& str) {
     37   return SBFullHashForString(str).prefix;
     38 }
     39 
     40 // Construct a full hash which has the given prefix, with the given
     41 // suffix data coming after the prefix.
     42 SBFullHash SBFullHashForPrefixAndSuffix(SBPrefix prefix,
     43                                         const base::StringPiece& suffix) {
     44   SBFullHash full_hash;
     45   memset(&full_hash, 0, sizeof(SBFullHash));
     46   full_hash.prefix = prefix;
     47   CHECK_LE(suffix.size() + sizeof(SBPrefix), sizeof(SBFullHash));
     48   memcpy(full_hash.full_hash + sizeof(SBPrefix), suffix.data(), suffix.size());
     49   return full_hash;
     50 }
     51 
     52 std::string HashedIpPrefix(const std::string& ip_prefix, size_t prefix_size) {
     53   net::IPAddressNumber ip_number;
     54   EXPECT_TRUE(net::ParseIPLiteralToNumber(ip_prefix, &ip_number));
     55   EXPECT_EQ(net::kIPv6AddressSize, ip_number.size());
     56   const std::string hashed_ip_prefix = base::SHA1HashString(
     57       net::IPAddressToPackedString(ip_number));
     58   std::string hash(crypto::kSHA256Length, '\0');
     59   hash.replace(0, hashed_ip_prefix.size(), hashed_ip_prefix);
     60   hash[base::kSHA1Length] = static_cast<char>(prefix_size);
     61   return hash;
     62 }
     63 
     64 // Helper to build a chunk.  Caller takes ownership.
     65 SBChunkData* BuildChunk(int chunk_number,
     66                         safe_browsing::ChunkData::ChunkType chunk_type,
     67                         safe_browsing::ChunkData::PrefixType prefix_type,
     68                         const void* data, size_t data_size,
     69                         const std::vector<int>& add_chunk_numbers) {
     70   scoped_ptr<safe_browsing::ChunkData> raw_data(new safe_browsing::ChunkData);
     71   raw_data->set_chunk_number(chunk_number);
     72   raw_data->set_chunk_type(chunk_type);
     73   raw_data->set_prefix_type(prefix_type);
     74   raw_data->set_hashes(data, data_size);
     75   raw_data->clear_add_numbers();
     76   for (size_t i = 0; i < add_chunk_numbers.size(); ++i) {
     77     raw_data->add_add_numbers(add_chunk_numbers[i]);
     78   }
     79 
     80   return new SBChunkData(raw_data.release());
     81 }
     82 
     83 // Create add chunk with a single prefix.
     84 SBChunkData* AddChunkPrefix(int chunk_number,  SBPrefix prefix) {
     85   return BuildChunk(chunk_number, safe_browsing::ChunkData::ADD,
     86                     safe_browsing::ChunkData::PREFIX_4B,
     87                     &prefix, sizeof(prefix),
     88                     std::vector<int>());
     89 }
     90 
     91 // Create add chunk with a single prefix generated from |value|.
     92 SBChunkData* AddChunkPrefixValue(int chunk_number,
     93                                  const std::string& value) {
     94   return AddChunkPrefix(chunk_number, SBPrefixForString(value));
     95 }
     96 
     97 // Generate an add chunk with two prefixes.
     98 SBChunkData* AddChunkPrefix2Value(int chunk_number,
     99                                   const std::string& value1,
    100                                   const std::string& value2) {
    101   const SBPrefix prefixes[2] = {
    102     SBPrefixForString(value1),
    103     SBPrefixForString(value2),
    104   };
    105   return BuildChunk(chunk_number, safe_browsing::ChunkData::ADD,
    106                     safe_browsing::ChunkData::PREFIX_4B,
    107                     &prefixes[0], sizeof(prefixes),
    108                     std::vector<int>());
    109 }
    110 
    111 // Generate an add chunk with four prefixes.
    112 SBChunkData* AddChunkPrefix4Value(int chunk_number,
    113                                   const std::string& value1,
    114                                   const std::string& value2,
    115                                   const std::string& value3,
    116                                   const std::string& value4) {
    117   const SBPrefix prefixes[4] = {
    118     SBPrefixForString(value1),
    119     SBPrefixForString(value2),
    120     SBPrefixForString(value3),
    121     SBPrefixForString(value4),
    122   };
    123   return BuildChunk(chunk_number, safe_browsing::ChunkData::ADD,
    124                     safe_browsing::ChunkData::PREFIX_4B,
    125                     &prefixes[0], sizeof(prefixes),
    126                     std::vector<int>());
    127 }
    128 
    129 // Generate an add chunk with a full hash.
    130 SBChunkData* AddChunkFullHash(int chunk_number, SBFullHash full_hash) {
    131   return BuildChunk(chunk_number, safe_browsing::ChunkData::ADD,
    132                     safe_browsing::ChunkData::FULL_32B,
    133                     &full_hash, sizeof(full_hash),
    134                     std::vector<int>());
    135 }
    136 
    137 // Generate an add chunk with a full hash generated from |value|.
    138 SBChunkData* AddChunkFullHashValue(int chunk_number,
    139                                    const std::string& value) {
    140   return AddChunkFullHash(chunk_number, SBFullHashForString(value));
    141 }
    142 
    143 // Generate an add chunk with two full hashes.
    144 SBChunkData* AddChunkFullHash2Value(int chunk_number,
    145                                    const std::string& value1,
    146                                    const std::string& value2) {
    147   const SBFullHash full_hashes[2] = {
    148     SBFullHashForString(value1),
    149     SBFullHashForString(value2),
    150   };
    151   return BuildChunk(chunk_number, safe_browsing::ChunkData::ADD,
    152                     safe_browsing::ChunkData::FULL_32B,
    153                     &full_hashes[0], sizeof(full_hashes),
    154                     std::vector<int>());
    155 }
    156 
    157 // Generate a sub chunk with a prefix generated from |value|.
    158 SBChunkData* SubChunkPrefixValue(int chunk_number,
    159                                  const std::string& value,
    160                                  int add_chunk_number) {
    161   const SBPrefix prefix = SBPrefixForString(value);
    162   return BuildChunk(chunk_number, safe_browsing::ChunkData::SUB,
    163                     safe_browsing::ChunkData::PREFIX_4B,
    164                     &prefix, sizeof(prefix),
    165                     std::vector<int>(1, add_chunk_number));
    166 }
    167 
    168 // Generate a sub chunk with two prefixes.
    169 SBChunkData* SubChunkPrefix2Value(int chunk_number,
    170                                   const std::string& value1,
    171                                   int add_chunk_number1,
    172                                   const std::string& value2,
    173                                   int add_chunk_number2) {
    174   const SBPrefix prefixes[2] = {
    175     SBPrefixForString(value1),
    176     SBPrefixForString(value2),
    177   };
    178   std::vector<int> add_chunk_numbers;
    179   add_chunk_numbers.push_back(add_chunk_number1);
    180   add_chunk_numbers.push_back(add_chunk_number2);
    181   return BuildChunk(chunk_number, safe_browsing::ChunkData::SUB,
    182                     safe_browsing::ChunkData::PREFIX_4B,
    183                     &prefixes[0], sizeof(prefixes),
    184                     add_chunk_numbers);
    185 }
    186 
    187 // Generate a sub chunk with a full hash.
    188 SBChunkData* SubChunkFullHash(int chunk_number,
    189                               SBFullHash full_hash,
    190                               int add_chunk_number) {
    191   return BuildChunk(chunk_number, safe_browsing::ChunkData::SUB,
    192                     safe_browsing::ChunkData::FULL_32B,
    193                     &full_hash, sizeof(full_hash),
    194                     std::vector<int>(1, add_chunk_number));
    195 }
    196 
    197 // Generate a sub chunk with a full hash generated from |value|.
    198 SBChunkData* SubChunkFullHashValue(int chunk_number,
    199                                    const std::string& value,
    200                                    int add_chunk_number) {
    201   return SubChunkFullHash(chunk_number,
    202                           SBFullHashForString(value),
    203                           add_chunk_number);
    204 }
    205 
    206 // Generate an add chunk with a single full hash for the ip blacklist.
    207 SBChunkData* AddChunkHashedIpValue(int chunk_number,
    208                                    const std::string& ip_str,
    209                                    size_t prefix_size) {
    210   const std::string full_hash_str = HashedIpPrefix(ip_str, prefix_size);
    211   EXPECT_EQ(sizeof(SBFullHash), full_hash_str.size());
    212   SBFullHash full_hash;
    213   std::memcpy(&(full_hash.full_hash), full_hash_str.data(), sizeof(SBFullHash));
    214   return BuildChunk(chunk_number, safe_browsing::ChunkData::ADD,
    215                     safe_browsing::ChunkData::FULL_32B,
    216                     &full_hash, sizeof(full_hash),
    217                     std::vector<int>());
    218 }
    219 
    220 // Prevent DCHECK from killing tests.
    221 // TODO(shess): Pawel disputes the use of this, so the test which uses
    222 // it is DISABLED.  http://crbug.com/56448
    223 class ScopedLogMessageIgnorer {
    224  public:
    225   ScopedLogMessageIgnorer() {
    226     logging::SetLogMessageHandler(&LogMessageIgnorer);
    227   }
    228   ~ScopedLogMessageIgnorer() {
    229     // TODO(shess): Would be better to verify whether anyone else
    230     // changed it, and then restore it to the previous value.
    231     logging::SetLogMessageHandler(NULL);
    232   }
    233 
    234  private:
    235   static bool LogMessageIgnorer(int severity, const char* file, int line,
    236       size_t message_start, const std::string& str) {
    237     // Intercept FATAL, strip the stack backtrace, and log it without
    238     // the crash part.
    239     if (severity == logging::LOG_FATAL) {
    240       size_t newline = str.find('\n');
    241       if (newline != std::string::npos) {
    242         const std::string msg = str.substr(0, newline + 1);
    243         fprintf(stderr, "%s", msg.c_str());
    244         fflush(stderr);
    245       }
    246       return true;
    247     }
    248 
    249     return false;
    250   }
    251 };
    252 
    253 }  // namespace
    254 
    255 class SafeBrowsingDatabaseTest : public PlatformTest {
    256  public:
    257   virtual void SetUp() {
    258     PlatformTest::SetUp();
    259 
    260     // Setup a database in a temporary directory.
    261     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
    262     database_.reset(new SafeBrowsingDatabaseNew);
    263     database_filename_ =
    264         temp_dir_.path().AppendASCII("SafeBrowsingTestDatabase");
    265     database_->Init(database_filename_);
    266   }
    267 
    268   virtual void TearDown() {
    269     database_.reset();
    270 
    271     PlatformTest::TearDown();
    272   }
    273 
    274   void GetListsInfo(std::vector<SBListChunkRanges>* lists) {
    275     lists->clear();
    276     ASSERT_TRUE(database_->UpdateStarted(lists));
    277     database_->UpdateFinished(true);
    278   }
    279 
    280   // Helper function to do an AddDel or SubDel command.
    281   void DelChunk(const std::string& list,
    282                 int chunk_id,
    283                 bool is_sub_del) {
    284     std::vector<SBChunkDelete> deletes;
    285     SBChunkDelete chunk_delete;
    286     chunk_delete.list_name = list;
    287     chunk_delete.is_sub_del = is_sub_del;
    288     chunk_delete.chunk_del.push_back(ChunkRange(chunk_id));
    289     deletes.push_back(chunk_delete);
    290     database_->DeleteChunks(deletes);
    291   }
    292 
    293   void AddDelChunk(const std::string& list, int chunk_id) {
    294     DelChunk(list, chunk_id, false);
    295   }
    296 
    297   void SubDelChunk(const std::string& list, int chunk_id) {
    298     DelChunk(list, chunk_id, true);
    299   }
    300 
    301   // Utility function for setting up the database for the caching test.
    302   void PopulateDatabaseForCacheTest();
    303 
    304   scoped_ptr<SafeBrowsingDatabaseNew> database_;
    305   base::FilePath database_filename_;
    306   base::ScopedTempDir temp_dir_;
    307 };
    308 
    309 // Tests retrieving list name information.
    310 TEST_F(SafeBrowsingDatabaseTest, ListNameForBrowse) {
    311   std::vector<SBListChunkRanges> lists;
    312   ScopedVector<SBChunkData> chunks;
    313 
    314   chunks.push_back(AddChunkPrefixValue(1, "www.evil.com/malware.html"));
    315   chunks.push_back(AddChunkPrefixValue(2, "www.foo.com/malware.html"));
    316   chunks.push_back(AddChunkPrefixValue(3, "www.whatever.com/malware.html"));
    317 
    318   ASSERT_TRUE(database_->UpdateStarted(&lists));
    319   database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
    320   database_->UpdateFinished(true);
    321 
    322   GetListsInfo(&lists);
    323   ASSERT_LE(1U, lists.size());
    324   EXPECT_EQ(safe_browsing_util::kMalwareList, lists[0].name);
    325   EXPECT_EQ("1-3", lists[0].adds);
    326   EXPECT_TRUE(lists[0].subs.empty());
    327 
    328   // Insert a malware sub chunk.
    329   chunks.clear();
    330   chunks.push_back(SubChunkPrefixValue(7, "www.subbed.com/noteveil1.html", 19));
    331 
    332   ASSERT_TRUE(database_->UpdateStarted(&lists));
    333   database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
    334   database_->UpdateFinished(true);
    335 
    336   GetListsInfo(&lists);
    337   ASSERT_LE(1U, lists.size());
    338   EXPECT_EQ(safe_browsing_util::kMalwareList, lists[0].name);
    339   EXPECT_EQ("1-3", lists[0].adds);
    340   EXPECT_EQ("7", lists[0].subs);
    341   if (lists.size() == 2) {
    342     // Old style database won't have the second entry since it creates the lists
    343     // when it receives an update containing that list. The filter-based
    344     // database has these values hard coded.
    345     EXPECT_EQ(safe_browsing_util::kPhishingList, lists[1].name);
    346     EXPECT_TRUE(lists[1].adds.empty());
    347     EXPECT_TRUE(lists[1].subs.empty());
    348   }
    349 
    350   // Add phishing chunks.
    351   chunks.clear();
    352   chunks.push_back(AddChunkPrefixValue(47, "www.evil.com/phishing.html"));
    353   chunks.push_back(
    354       SubChunkPrefixValue(200, "www.phishy.com/notevil1.html", 1999));
    355   chunks.push_back(
    356       SubChunkPrefixValue(201, "www.phishy2.com/notevil1.html", 1999));
    357 
    358   ASSERT_TRUE(database_->UpdateStarted(&lists));
    359   database_->InsertChunks(safe_browsing_util::kPhishingList, chunks.get());
    360   database_->UpdateFinished(true);
    361 
    362   GetListsInfo(&lists);
    363   ASSERT_EQ(2U, lists.size());
    364   EXPECT_EQ(safe_browsing_util::kMalwareList, lists[0].name);
    365   EXPECT_EQ("1-3", lists[0].adds);
    366   EXPECT_EQ("7", lists[0].subs);
    367   EXPECT_EQ(safe_browsing_util::kPhishingList, lists[1].name);
    368   EXPECT_EQ("47", lists[1].adds);
    369   EXPECT_EQ("200-201", lists[1].subs);
    370 }
    371 
    372 TEST_F(SafeBrowsingDatabaseTest, ListNameForBrowseAndDownload) {
    373   database_.reset();
    374   base::MessageLoop loop;
    375   SafeBrowsingStoreFile* browse_store = new SafeBrowsingStoreFile();
    376   SafeBrowsingStoreFile* download_store = new SafeBrowsingStoreFile();
    377   SafeBrowsingStoreFile* csd_whitelist_store = new SafeBrowsingStoreFile();
    378   SafeBrowsingStoreFile* download_whitelist_store = new SafeBrowsingStoreFile();
    379   SafeBrowsingStoreFile* extension_blacklist_store =
    380       new SafeBrowsingStoreFile();
    381   SafeBrowsingStoreFile* ip_blacklist_store = new SafeBrowsingStoreFile();
    382   database_.reset(new SafeBrowsingDatabaseNew(browse_store,
    383                                               download_store,
    384                                               csd_whitelist_store,
    385                                               download_whitelist_store,
    386                                               extension_blacklist_store,
    387                                               NULL,
    388                                               ip_blacklist_store));
    389   database_->Init(database_filename_);
    390 
    391   ScopedVector<SBChunkData> chunks;
    392 
    393   std::vector<SBListChunkRanges> lists;
    394   ASSERT_TRUE(database_->UpdateStarted(&lists));
    395 
    396   // Insert malware, phish, binurl and bindownload add chunks.
    397   chunks.push_back(AddChunkPrefixValue(1, "www.evil.com/malware.html"));
    398   database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
    399 
    400   chunks.clear();
    401   chunks.push_back(AddChunkPrefixValue(2, "www.foo.com/malware.html"));
    402   database_->InsertChunks(safe_browsing_util::kPhishingList, chunks.get());
    403 
    404   chunks.clear();
    405   chunks.push_back(AddChunkPrefixValue(3, "www.whatever.com/download.html"));
    406   database_->InsertChunks(safe_browsing_util::kBinUrlList, chunks.get());
    407 
    408   chunks.clear();
    409   chunks.push_back(AddChunkFullHashValue(5, "www.forwhitelist.com/a.html"));
    410   database_->InsertChunks(safe_browsing_util::kCsdWhiteList, chunks.get());
    411 
    412   chunks.clear();
    413   chunks.push_back(AddChunkFullHashValue(6, "www.download.com/"));
    414   database_->InsertChunks(safe_browsing_util::kDownloadWhiteList, chunks.get());
    415 
    416   chunks.clear();
    417   chunks.push_back(AddChunkFullHashValue(8,
    418                                          "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
    419                                          "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
    420   database_->InsertChunks(safe_browsing_util::kExtensionBlacklist,
    421                           chunks.get());
    422 
    423   chunks.clear();
    424   chunks.push_back(AddChunkHashedIpValue(9, "::ffff:192.168.1.0", 120));
    425   database_->InsertChunks(safe_browsing_util::kIPBlacklist, chunks.get());
    426 
    427   database_->UpdateFinished(true);
    428 
    429   GetListsInfo(&lists);
    430   ASSERT_EQ(7U, lists.size());
    431   EXPECT_EQ(safe_browsing_util::kMalwareList, lists[0].name);
    432   EXPECT_EQ("1", lists[0].adds);
    433   EXPECT_TRUE(lists[0].subs.empty());
    434   EXPECT_EQ(safe_browsing_util::kPhishingList, lists[1].name);
    435   EXPECT_EQ("2", lists[1].adds);
    436   EXPECT_TRUE(lists[1].subs.empty());
    437   EXPECT_EQ(safe_browsing_util::kBinUrlList, lists[2].name);
    438   EXPECT_EQ("3", lists[2].adds);
    439   EXPECT_TRUE(lists[2].subs.empty());
    440   EXPECT_EQ(safe_browsing_util::kCsdWhiteList, lists[3].name);
    441   EXPECT_EQ("5", lists[3].adds);
    442   EXPECT_TRUE(lists[3].subs.empty());
    443   EXPECT_EQ(safe_browsing_util::kDownloadWhiteList, lists[4].name);
    444   EXPECT_EQ("6", lists[4].adds);
    445   EXPECT_TRUE(lists[4].subs.empty());
    446   EXPECT_EQ(safe_browsing_util::kExtensionBlacklist, lists[5].name);
    447   EXPECT_EQ("8", lists[5].adds);
    448   EXPECT_TRUE(lists[5].subs.empty());
    449   EXPECT_EQ(safe_browsing_util::kIPBlacklist, lists[6].name);
    450   EXPECT_EQ("9", lists[6].adds);
    451   EXPECT_TRUE(lists[6].subs.empty());
    452 
    453   database_.reset();
    454 }
    455 
    456 // Checks database reading and writing for browse.
    457 TEST_F(SafeBrowsingDatabaseTest, BrowseDatabase) {
    458   std::vector<SBListChunkRanges> lists;
    459   ScopedVector<SBChunkData> chunks;
    460 
    461   chunks.push_back(AddChunkPrefix2Value(1,
    462                                         "www.evil.com/phishing.html",
    463                                         "www.evil.com/malware.html"));
    464   chunks.push_back(AddChunkPrefix4Value(2,
    465                                         "www.evil.com/notevil1.html",
    466                                         "www.evil.com/notevil2.html",
    467                                         "www.good.com/good1.html",
    468                                         "www.good.com/good2.html"));
    469   chunks.push_back(AddChunkPrefixValue(3, "192.168.0.1/malware.html"));
    470   chunks.push_back(AddChunkFullHashValue(7, "www.evil.com/evil.html"));
    471 
    472   ASSERT_TRUE(database_->UpdateStarted(&lists));
    473   database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
    474   database_->UpdateFinished(true);
    475 
    476   // Make sure they were added correctly.
    477   GetListsInfo(&lists);
    478   ASSERT_LE(1U, lists.size());
    479   EXPECT_EQ(safe_browsing_util::kMalwareList, lists[0].name);
    480   EXPECT_EQ("1-3,7", lists[0].adds);
    481   EXPECT_TRUE(lists[0].subs.empty());
    482 
    483   std::vector<SBPrefix> prefix_hits;
    484   std::vector<SBFullHashResult> cache_hits;
    485   EXPECT_TRUE(database_->ContainsBrowseUrl(
    486       GURL("http://www.evil.com/phishing.html"), &prefix_hits, &cache_hits));
    487   ASSERT_EQ(1U, prefix_hits.size());
    488   EXPECT_EQ(SBPrefixForString("www.evil.com/phishing.html"), prefix_hits[0]);
    489   EXPECT_TRUE(cache_hits.empty());
    490 
    491   EXPECT_TRUE(database_->ContainsBrowseUrl(
    492       GURL("http://www.evil.com/malware.html"), &prefix_hits, &cache_hits));
    493 
    494   EXPECT_TRUE(database_->ContainsBrowseUrl(
    495       GURL("http://www.evil.com/notevil1.html"), &prefix_hits, &cache_hits));
    496 
    497   EXPECT_TRUE(database_->ContainsBrowseUrl(
    498       GURL("http://www.evil.com/notevil2.html"), &prefix_hits, &cache_hits));
    499 
    500   EXPECT_TRUE(database_->ContainsBrowseUrl(
    501       GURL("http://www.good.com/good1.html"), &prefix_hits, &cache_hits));
    502 
    503   EXPECT_TRUE(database_->ContainsBrowseUrl(
    504       GURL("http://www.good.com/good2.html"), &prefix_hits, &cache_hits));
    505 
    506   EXPECT_TRUE(database_->ContainsBrowseUrl(
    507       GURL("http://192.168.0.1/malware.html"), &prefix_hits, &cache_hits));
    508 
    509   EXPECT_FALSE(database_->ContainsBrowseUrl(
    510       GURL("http://www.evil.com/"), &prefix_hits, &cache_hits));
    511   EXPECT_TRUE(prefix_hits.empty());
    512   EXPECT_TRUE(cache_hits.empty());
    513 
    514   EXPECT_FALSE(database_->ContainsBrowseUrl(
    515       GURL("http://www.evil.com/robots.txt"), &prefix_hits, &cache_hits));
    516 
    517   EXPECT_TRUE(database_->ContainsBrowseUrl(
    518       GURL("http://www.evil.com/evil.html"), &prefix_hits, &cache_hits));
    519   ASSERT_EQ(1U, prefix_hits.size());
    520   EXPECT_EQ(SBPrefixForString("www.evil.com/evil.html"), prefix_hits[0]);
    521 
    522   // Attempt to re-add the first chunk (should be a no-op).
    523   // see bug: http://code.google.com/p/chromium/issues/detail?id=4522
    524   chunks.clear();
    525   chunks.push_back(AddChunkPrefix2Value(1,
    526                                         "www.evil.com/phishing.html",
    527                                         "www.evil.com/malware.html"));
    528   ASSERT_TRUE(database_->UpdateStarted(&lists));
    529   database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
    530   database_->UpdateFinished(true);
    531 
    532   GetListsInfo(&lists);
    533   ASSERT_LE(1U, lists.size());
    534   EXPECT_EQ(safe_browsing_util::kMalwareList, lists[0].name);
    535   EXPECT_EQ("1-3,7", lists[0].adds);
    536   EXPECT_TRUE(lists[0].subs.empty());
    537 
    538   // Test removing a single prefix from the add chunk.
    539   chunks.clear();
    540   chunks.push_back(SubChunkPrefixValue(4, "www.evil.com/notevil1.html", 2));
    541   ASSERT_TRUE(database_->UpdateStarted(&lists));
    542   database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
    543   database_->UpdateFinished(true);
    544 
    545   EXPECT_TRUE(database_->ContainsBrowseUrl(
    546       GURL("http://www.evil.com/phishing.html"), &prefix_hits, &cache_hits));
    547   ASSERT_EQ(1U, prefix_hits.size());
    548   EXPECT_EQ(SBPrefixForString("www.evil.com/phishing.html"), prefix_hits[0]);
    549   EXPECT_TRUE(cache_hits.empty());
    550 
    551   EXPECT_FALSE(database_->ContainsBrowseUrl(
    552       GURL("http://www.evil.com/notevil1.html"), &prefix_hits, &cache_hits));
    553   EXPECT_TRUE(prefix_hits.empty());
    554   EXPECT_TRUE(cache_hits.empty());
    555 
    556   EXPECT_TRUE(database_->ContainsBrowseUrl(
    557       GURL("http://www.evil.com/notevil2.html"), &prefix_hits, &cache_hits));
    558 
    559   EXPECT_TRUE(database_->ContainsBrowseUrl(
    560       GURL("http://www.good.com/good1.html"), &prefix_hits, &cache_hits));
    561 
    562   EXPECT_TRUE(database_->ContainsBrowseUrl(
    563       GURL("http://www.good.com/good2.html"), &prefix_hits, &cache_hits));
    564 
    565   GetListsInfo(&lists);
    566   ASSERT_LE(1U, lists.size());
    567   EXPECT_EQ(safe_browsing_util::kMalwareList, lists[0].name);
    568   EXPECT_EQ("1-3,7", lists[0].adds);
    569   EXPECT_EQ("4", lists[0].subs);
    570 
    571   // Test the same sub chunk again.  This should be a no-op.
    572   // see bug: http://code.google.com/p/chromium/issues/detail?id=4522
    573   chunks.clear();
    574   chunks.push_back(SubChunkPrefixValue(4, "www.evil.com/notevil1.html", 2));
    575 
    576   ASSERT_TRUE(database_->UpdateStarted(&lists));
    577   database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
    578   database_->UpdateFinished(true);
    579 
    580   GetListsInfo(&lists);
    581   ASSERT_LE(1U, lists.size());
    582   EXPECT_EQ(safe_browsing_util::kMalwareList, lists[0].name);
    583   EXPECT_EQ("1-3,7", lists[0].adds);
    584   EXPECT_EQ("4", lists[0].subs);
    585 
    586   // Test removing all the prefixes from an add chunk.
    587   ASSERT_TRUE(database_->UpdateStarted(&lists));
    588   AddDelChunk(safe_browsing_util::kMalwareList, 2);
    589   database_->UpdateFinished(true);
    590 
    591   EXPECT_FALSE(database_->ContainsBrowseUrl(
    592       GURL("http://www.evil.com/notevil2.html"), &prefix_hits, &cache_hits));
    593 
    594   EXPECT_FALSE(database_->ContainsBrowseUrl(
    595       GURL("http://www.good.com/good1.html"), &prefix_hits, &cache_hits));
    596 
    597   EXPECT_FALSE(database_->ContainsBrowseUrl(
    598       GURL("http://www.good.com/good2.html"), &prefix_hits, &cache_hits));
    599 
    600   GetListsInfo(&lists);
    601   ASSERT_LE(1U, lists.size());
    602   EXPECT_EQ(safe_browsing_util::kMalwareList, lists[0].name);
    603   EXPECT_EQ("1,3,7", lists[0].adds);
    604   EXPECT_EQ("4", lists[0].subs);
    605 
    606   // The adddel command exposed a bug in the transaction code where any
    607   // transaction after it would fail.  Add a dummy entry and remove it to
    608   // make sure the transcation works fine.
    609   chunks.clear();
    610   chunks.push_back(AddChunkPrefixValue(44, "www.redherring.com/index.html"));
    611   ASSERT_TRUE(database_->UpdateStarted(&lists));
    612   database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
    613 
    614   // Now remove the dummy entry.  If there are any problems with the
    615   // transactions, asserts will fire.
    616   AddDelChunk(safe_browsing_util::kMalwareList, 44);
    617 
    618   // Test the subdel command.
    619   SubDelChunk(safe_browsing_util::kMalwareList, 4);
    620   database_->UpdateFinished(true);
    621 
    622   GetListsInfo(&lists);
    623   ASSERT_LE(1U, lists.size());
    624   EXPECT_EQ(safe_browsing_util::kMalwareList, lists[0].name);
    625   EXPECT_EQ("1,3,7", lists[0].adds);
    626   EXPECT_TRUE(lists[0].subs.empty());
    627 
    628   // Test a sub command coming in before the add.
    629   chunks.clear();
    630   chunks.push_back(SubChunkPrefix2Value(5,
    631                                         "www.notevilanymore.com/index.html",
    632                                         10,
    633                                         "www.notevilanymore.com/good.html",
    634                                         10));
    635   ASSERT_TRUE(database_->UpdateStarted(&lists));
    636   database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
    637   database_->UpdateFinished(true);
    638 
    639   EXPECT_FALSE(database_->ContainsBrowseUrl(
    640       GURL("http://www.notevilanymore.com/index.html"),
    641       &prefix_hits,
    642       &cache_hits));
    643 
    644   // Now insert the tardy add chunk and we don't expect them to appear
    645   // in database because of the previous sub chunk.
    646   chunks.clear();
    647   chunks.push_back(AddChunkPrefix2Value(10,
    648                                         "www.notevilanymore.com/index.html",
    649                                         "www.notevilanymore.com/good.html"));
    650   ASSERT_TRUE(database_->UpdateStarted(&lists));
    651   database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
    652   database_->UpdateFinished(true);
    653 
    654   EXPECT_FALSE(database_->ContainsBrowseUrl(
    655       GURL("http://www.notevilanymore.com/index.html"),
    656       &prefix_hits,
    657       &cache_hits));
    658 
    659   EXPECT_FALSE(database_->ContainsBrowseUrl(
    660       GURL("http://www.notevilanymore.com/good.html"),
    661       &prefix_hits,
    662       &cache_hits));
    663 
    664   // Reset and reload the database.  The database will rely on the prefix set.
    665   database_.reset(new SafeBrowsingDatabaseNew);
    666   database_->Init(database_filename_);
    667 
    668   // Check that a prefix still hits.
    669   EXPECT_TRUE(database_->ContainsBrowseUrl(
    670       GURL("http://www.evil.com/phishing.html"), &prefix_hits, &cache_hits));
    671   ASSERT_EQ(1U, prefix_hits.size());
    672   EXPECT_EQ(SBPrefixForString("www.evil.com/phishing.html"), prefix_hits[0]);
    673 
    674   // Also check that it's not just always returning true in this case.
    675   EXPECT_FALSE(database_->ContainsBrowseUrl(
    676       GURL("http://www.evil.com/"), &prefix_hits, &cache_hits));
    677 
    678   // Check that the full hash is still present.
    679   EXPECT_TRUE(database_->ContainsBrowseUrl(
    680       GURL("http://www.evil.com/evil.html"), &prefix_hits, &cache_hits));
    681   ASSERT_EQ(1U, prefix_hits.size());
    682   EXPECT_EQ(SBPrefixForString("www.evil.com/evil.html"), prefix_hits[0]);
    683 }
    684 
    685 // Test adding zero length chunks to the database.
    686 TEST_F(SafeBrowsingDatabaseTest, ZeroSizeChunk) {
    687   std::vector<SBListChunkRanges> lists;
    688   ScopedVector<SBChunkData> chunks;
    689 
    690   // Populate with a couple of normal chunks.
    691   chunks.push_back(AddChunkPrefix2Value(1,
    692                                         "www.test.com/test1.html",
    693                                         "www.test.com/test2.html"));
    694   chunks.push_back(AddChunkPrefix2Value(10,
    695                                         "www.random.com/random1.html",
    696                                         "www.random.com/random2.html"));
    697 
    698   ASSERT_TRUE(database_->UpdateStarted(&lists));
    699   database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
    700   database_->UpdateFinished(true);
    701 
    702   // Add an empty ADD and SUB chunk.
    703   GetListsInfo(&lists);
    704   ASSERT_LE(1U, lists.size());
    705   EXPECT_EQ(safe_browsing_util::kMalwareList, lists[0].name);
    706   EXPECT_EQ("1,10", lists[0].adds);
    707   EXPECT_TRUE(lists[0].subs.empty());
    708 
    709   chunks.clear();
    710   chunks.push_back(BuildChunk(19, safe_browsing::ChunkData::ADD,
    711                               safe_browsing::ChunkData::PREFIX_4B,
    712                               NULL, 0, std::vector<int>()));
    713   chunks.push_back(BuildChunk(7, safe_browsing::ChunkData::SUB,
    714                               safe_browsing::ChunkData::PREFIX_4B,
    715                               NULL, 0, std::vector<int>()));
    716 
    717   ASSERT_TRUE(database_->UpdateStarted(&lists));
    718   database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
    719   database_->UpdateFinished(true);
    720 
    721   GetListsInfo(&lists);
    722   ASSERT_LE(1U, lists.size());
    723   EXPECT_EQ(safe_browsing_util::kMalwareList, lists[0].name);
    724   EXPECT_EQ("1,10,19", lists[0].adds);
    725   EXPECT_EQ("7", lists[0].subs);
    726 
    727   // Add an empty chunk along with a couple that contain data. This should
    728   // result in the chunk range being reduced in size.
    729   chunks.clear();
    730   chunks.push_back(AddChunkPrefixValue(20, "www.notempty.com/full1.html"));
    731   chunks.push_back(BuildChunk(21, safe_browsing::ChunkData::ADD,
    732                               safe_browsing::ChunkData::PREFIX_4B,
    733                               NULL, 0, std::vector<int>()));
    734   chunks.push_back(AddChunkPrefixValue(22, "www.notempty.com/full2.html"));
    735 
    736   ASSERT_TRUE(database_->UpdateStarted(&lists));
    737   database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
    738   database_->UpdateFinished(true);
    739 
    740   std::vector<SBPrefix> prefix_hits;
    741   std::vector<SBFullHashResult> cache_hits;
    742   EXPECT_TRUE(database_->ContainsBrowseUrl(
    743       GURL("http://www.notempty.com/full1.html"), &prefix_hits, &cache_hits));
    744   EXPECT_TRUE(database_->ContainsBrowseUrl(
    745       GURL("http://www.notempty.com/full2.html"), &prefix_hits, &cache_hits));
    746 
    747   GetListsInfo(&lists);
    748   ASSERT_LE(1U, lists.size());
    749   EXPECT_EQ(safe_browsing_util::kMalwareList, lists[0].name);
    750   EXPECT_EQ("1,10,19-22", lists[0].adds);
    751   EXPECT_EQ("7", lists[0].subs);
    752 
    753   // Handle AddDel and SubDel commands for empty chunks.
    754   ASSERT_TRUE(database_->UpdateStarted(&lists));
    755   AddDelChunk(safe_browsing_util::kMalwareList, 21);
    756   database_->UpdateFinished(true);
    757 
    758   GetListsInfo(&lists);
    759   ASSERT_LE(1U, lists.size());
    760   EXPECT_EQ(safe_browsing_util::kMalwareList, lists[0].name);
    761   EXPECT_EQ("1,10,19-20,22", lists[0].adds);
    762   EXPECT_EQ("7", lists[0].subs);
    763 
    764   ASSERT_TRUE(database_->UpdateStarted(&lists));
    765   SubDelChunk(safe_browsing_util::kMalwareList, 7);
    766   database_->UpdateFinished(true);
    767 
    768   GetListsInfo(&lists);
    769   ASSERT_LE(1U, lists.size());
    770   EXPECT_EQ(safe_browsing_util::kMalwareList, lists[0].name);
    771   EXPECT_EQ("1,10,19-20,22", lists[0].adds);
    772   EXPECT_TRUE(lists[0].subs.empty());
    773 }
    774 
    775 // Utility function for setting up the database for the caching test.
    776 void SafeBrowsingDatabaseTest::PopulateDatabaseForCacheTest() {
    777   // Add a couple prefixes.
    778   ScopedVector<SBChunkData> chunks;
    779   chunks.push_back(AddChunkPrefix2Value(1,
    780                                         "www.evil.com/phishing.html",
    781                                         "www.evil.com/malware.html"));
    782 
    783   std::vector<SBListChunkRanges> lists;
    784   ASSERT_TRUE(database_->UpdateStarted(&lists));
    785   database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
    786   database_->UpdateFinished(true);
    787 
    788   // Cache should be cleared after updating.
    789   EXPECT_TRUE(database_->browse_gethash_cache_.empty());
    790 
    791   SBFullHashResult full_hash;
    792   full_hash.list_id = safe_browsing_util::MALWARE;
    793 
    794   std::vector<SBFullHashResult> results;
    795   std::vector<SBPrefix> prefixes;
    796 
    797   // Add a fullhash result for each prefix.
    798   full_hash.hash = SBFullHashForString("www.evil.com/phishing.html");
    799   results.push_back(full_hash);
    800   prefixes.push_back(full_hash.hash.prefix);
    801 
    802   full_hash.hash = SBFullHashForString("www.evil.com/malware.html");
    803   results.push_back(full_hash);
    804   prefixes.push_back(full_hash.hash.prefix);
    805 
    806   database_->CacheHashResults(prefixes, results, kCacheLifetime);
    807 }
    808 
    809 TEST_F(SafeBrowsingDatabaseTest, HashCaching) {
    810   PopulateDatabaseForCacheTest();
    811 
    812   // We should have both full hashes in the cache.
    813   EXPECT_EQ(2U, database_->browse_gethash_cache_.size());
    814 
    815   // Test the cache lookup for the first prefix.
    816   std::vector<SBPrefix> prefix_hits;
    817   std::vector<SBFullHashResult> cache_hits;
    818   EXPECT_TRUE(database_->ContainsBrowseUrl(
    819       GURL("http://www.evil.com/phishing.html"), &prefix_hits, &cache_hits));
    820   EXPECT_TRUE(prefix_hits.empty());
    821   ASSERT_EQ(1U, cache_hits.size());
    822   EXPECT_TRUE(SBFullHashEqual(
    823       cache_hits[0].hash, SBFullHashForString("www.evil.com/phishing.html")));
    824 
    825   prefix_hits.clear();
    826   cache_hits.clear();
    827 
    828   // Test the cache lookup for the second prefix.
    829   EXPECT_TRUE(database_->ContainsBrowseUrl(
    830       GURL("http://www.evil.com/malware.html"), &prefix_hits, &cache_hits));
    831   EXPECT_TRUE(prefix_hits.empty());
    832   ASSERT_EQ(1U, cache_hits.size());
    833   EXPECT_TRUE(SBFullHashEqual(
    834       cache_hits[0].hash, SBFullHashForString("www.evil.com/malware.html")));
    835 
    836   prefix_hits.clear();
    837   cache_hits.clear();
    838 
    839   // Test removing a prefix via a sub chunk.
    840   ScopedVector<SBChunkData> chunks;
    841   chunks.push_back(SubChunkPrefixValue(2, "www.evil.com/phishing.html", 1));
    842 
    843   std::vector<SBListChunkRanges> lists;
    844   ASSERT_TRUE(database_->UpdateStarted(&lists));
    845   database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
    846   database_->UpdateFinished(true);
    847 
    848   // This prefix should still be there, but cached fullhash should be gone.
    849   EXPECT_TRUE(database_->ContainsBrowseUrl(
    850       GURL("http://www.evil.com/malware.html"), &prefix_hits, &cache_hits));
    851   ASSERT_EQ(1U, prefix_hits.size());
    852   EXPECT_EQ(SBPrefixForString("www.evil.com/malware.html"), prefix_hits[0]);
    853   EXPECT_TRUE(cache_hits.empty());
    854   prefix_hits.clear();
    855   cache_hits.clear();
    856 
    857   // This prefix should be gone.
    858   EXPECT_FALSE(database_->ContainsBrowseUrl(
    859       GURL("http://www.evil.com/phishing.html"), &prefix_hits, &cache_hits));
    860   prefix_hits.clear();
    861   cache_hits.clear();
    862 
    863   // Test that an AddDel for the original chunk removes the last cached entry.
    864   ASSERT_TRUE(database_->UpdateStarted(&lists));
    865   AddDelChunk(safe_browsing_util::kMalwareList, 1);
    866   database_->UpdateFinished(true);
    867   EXPECT_FALSE(database_->ContainsBrowseUrl(
    868       GURL("http://www.evil.com/malware.html"), &prefix_hits, &cache_hits));
    869   EXPECT_TRUE(database_->browse_gethash_cache_.empty());
    870   prefix_hits.clear();
    871   cache_hits.clear();
    872 
    873   // Test that the cache won't return expired values. First we have to adjust
    874   // the cached entries' received time to make them older, since the database
    875   // cache insert uses Time::Now(). First, store some entries.
    876   PopulateDatabaseForCacheTest();
    877 
    878   std::map<SBPrefix, SBCachedFullHashResult>* hash_cache =
    879       &database_->browse_gethash_cache_;
    880   EXPECT_EQ(2U, hash_cache->size());
    881 
    882   // Now adjust one of the entries times to be in the past.
    883   const SBPrefix key = SBPrefixForString("www.evil.com/malware.html");
    884   std::map<SBPrefix, SBCachedFullHashResult>::iterator iter =
    885       hash_cache->find(key);
    886   ASSERT_TRUE(iter != hash_cache->end());
    887   iter->second.expire_after = Time::Now() - TimeDelta::FromMinutes(1);
    888 
    889   EXPECT_TRUE(database_->ContainsBrowseUrl(
    890       GURL("http://www.evil.com/malware.html"), &prefix_hits, &cache_hits));
    891   EXPECT_EQ(1U, prefix_hits.size());
    892   EXPECT_TRUE(cache_hits.empty());
    893   // Expired entry should have been removed from cache.
    894   EXPECT_EQ(1U, hash_cache->size());
    895 
    896   // This entry should still exist.
    897   EXPECT_TRUE(database_->ContainsBrowseUrl(
    898       GURL("http://www.evil.com/phishing.html"), &prefix_hits, &cache_hits));
    899   EXPECT_TRUE(prefix_hits.empty());
    900   EXPECT_EQ(1U, cache_hits.size());
    901 
    902   // Testing prefix miss caching. First, we clear out the existing database,
    903   // Since PopulateDatabaseForCacheTest() doesn't handle adding duplicate
    904   // chunks.
    905   ASSERT_TRUE(database_->UpdateStarted(&lists));
    906   AddDelChunk(safe_browsing_util::kMalwareList, 1);
    907   database_->UpdateFinished(true);
    908 
    909   // Cache should be cleared after updating.
    910   EXPECT_TRUE(hash_cache->empty());
    911 
    912   std::vector<SBPrefix> prefix_misses;
    913   std::vector<SBFullHashResult> empty_full_hash;
    914   prefix_misses.push_back(SBPrefixForString("http://www.bad.com/malware.html"));
    915   prefix_misses.push_back(
    916       SBPrefixForString("http://www.bad.com/phishing.html"));
    917   database_->CacheHashResults(prefix_misses, empty_full_hash, kCacheLifetime);
    918 
    919   // Prefixes with no full results are misses.
    920   EXPECT_EQ(hash_cache->size(), prefix_misses.size());
    921   ASSERT_TRUE(
    922       hash_cache->count(SBPrefixForString("http://www.bad.com/malware.html")));
    923   EXPECT_TRUE(
    924       hash_cache->find(SBPrefixForString("http://www.bad.com/malware.html"))
    925           ->second.full_hashes.empty());
    926   ASSERT_TRUE(
    927       hash_cache->count(SBPrefixForString("http://www.bad.com/phishing.html")));
    928   EXPECT_TRUE(
    929       hash_cache->find(SBPrefixForString("http://www.bad.com/phishing.html"))
    930           ->second.full_hashes.empty());
    931 
    932   // Update the database.
    933   PopulateDatabaseForCacheTest();
    934 
    935   // Cache a GetHash miss for a particular prefix, and even though the prefix is
    936   // in the database, it is flagged as a miss so looking up the associated URL
    937   // will not succeed.
    938   prefix_hits.clear();
    939   cache_hits.clear();
    940   prefix_misses.clear();
    941   empty_full_hash.clear();
    942   prefix_misses.push_back(SBPrefixForString("www.evil.com/phishing.html"));
    943   database_->CacheHashResults(prefix_misses, empty_full_hash, kCacheLifetime);
    944   EXPECT_FALSE(database_->ContainsBrowseUrl(
    945       GURL("http://www.evil.com/phishing.html"), &prefix_hits, &cache_hits));
    946   prefix_hits.clear();
    947   cache_hits.clear();
    948 
    949   // Test receiving a full add chunk.
    950   chunks.clear();
    951   chunks.push_back(AddChunkFullHash2Value(20,
    952                                           "www.fullevil.com/bad1.html",
    953                                           "www.fullevil.com/bad2.html"));
    954   ASSERT_TRUE(database_->UpdateStarted(&lists));
    955   database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
    956   database_->UpdateFinished(true);
    957 
    958   EXPECT_TRUE(database_->ContainsBrowseUrl(
    959       GURL("http://www.fullevil.com/bad1.html"), &prefix_hits, &cache_hits));
    960   ASSERT_EQ(1U, prefix_hits.size());
    961   EXPECT_EQ(SBPrefixForString("www.fullevil.com/bad1.html"), prefix_hits[0]);
    962   EXPECT_TRUE(cache_hits.empty());
    963   prefix_hits.clear();
    964   cache_hits.clear();
    965 
    966   EXPECT_TRUE(database_->ContainsBrowseUrl(
    967       GURL("http://www.fullevil.com/bad2.html"), &prefix_hits, &cache_hits));
    968   ASSERT_EQ(1U, prefix_hits.size());
    969   EXPECT_EQ(SBPrefixForString("www.fullevil.com/bad2.html"), prefix_hits[0]);
    970   EXPECT_TRUE(cache_hits.empty());
    971   prefix_hits.clear();
    972   cache_hits.clear();
    973 
    974   // Test receiving a full sub chunk, which will remove one of the full adds.
    975   chunks.clear();
    976   chunks.push_back(SubChunkFullHashValue(200,
    977                                          "www.fullevil.com/bad1.html",
    978                                          20));
    979   ASSERT_TRUE(database_->UpdateStarted(&lists));
    980   database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
    981   database_->UpdateFinished(true);
    982 
    983   EXPECT_FALSE(database_->ContainsBrowseUrl(
    984       GURL("http://www.fullevil.com/bad1.html"), &prefix_hits, &cache_hits));
    985 
    986   // There should be one remaining full add.
    987   EXPECT_TRUE(database_->ContainsBrowseUrl(
    988       GURL("http://www.fullevil.com/bad2.html"), &prefix_hits, &cache_hits));
    989   ASSERT_EQ(1U, prefix_hits.size());
    990   EXPECT_EQ(SBPrefixForString("www.fullevil.com/bad2.html"), prefix_hits[0]);
    991   EXPECT_TRUE(cache_hits.empty());
    992   prefix_hits.clear();
    993   cache_hits.clear();
    994 
    995   // Now test an AddDel for the remaining full add.
    996   ASSERT_TRUE(database_->UpdateStarted(&lists));
    997   AddDelChunk(safe_browsing_util::kMalwareList, 20);
    998   database_->UpdateFinished(true);
    999 
   1000   EXPECT_FALSE(database_->ContainsBrowseUrl(
   1001       GURL("http://www.fullevil.com/bad1.html"), &prefix_hits, &cache_hits));
   1002   EXPECT_FALSE(database_->ContainsBrowseUrl(
   1003       GURL("http://www.fullevil.com/bad2.html"), &prefix_hits, &cache_hits));
   1004 
   1005   // Add a fullhash which has a prefix collision for a known url.
   1006   static const char kExampleFine[] = "www.example.com/fine.html";
   1007   static const char kExampleCollision[] =
   1008       "www.example.com/3123364814/malware.htm";
   1009   ASSERT_EQ(SBPrefixForString(kExampleFine),
   1010             SBPrefixForString(kExampleCollision));
   1011   ASSERT_TRUE(database_->UpdateStarted(&lists));
   1012   {
   1013     ScopedVector<SBChunkData> chunks;
   1014     chunks.push_back(AddChunkPrefixValue(21, kExampleCollision));
   1015     database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
   1016   }
   1017   database_->UpdateFinished(true);
   1018 
   1019   // Expect a prefix hit due to the collision between |kExampleFine| and
   1020   // |kExampleCollision|.
   1021   EXPECT_TRUE(database_->ContainsBrowseUrl(
   1022       GURL(std::string("http://") + kExampleFine), &prefix_hits, &cache_hits));
   1023   ASSERT_EQ(1U, prefix_hits.size());
   1024   EXPECT_EQ(SBPrefixForString(kExampleFine), prefix_hits[0]);
   1025   EXPECT_TRUE(cache_hits.empty());
   1026 
   1027   // Cache gethash response for |kExampleCollision|.
   1028   {
   1029     SBFullHashResult result;
   1030     result.hash = SBFullHashForString(kExampleCollision);
   1031     result.list_id = safe_browsing_util::MALWARE;
   1032     database_->CacheHashResults(std::vector<SBPrefix>(1, result.hash.prefix),
   1033                                 std::vector<SBFullHashResult>(1, result),
   1034                                 kCacheLifetime);
   1035   }
   1036 
   1037   // The cached response means the collision no longer causes a hit.
   1038   EXPECT_FALSE(database_->ContainsBrowseUrl(
   1039       GURL(std::string("http://") + kExampleFine), &prefix_hits, &cache_hits));
   1040 }
   1041 
   1042 // Test that corrupt databases are appropriately handled, even if the
   1043 // corruption is detected in the midst of the update.
   1044 // TODO(shess): Disabled until ScopedLogMessageIgnorer resolved.
   1045 // http://crbug.com/56448
   1046 TEST_F(SafeBrowsingDatabaseTest, DISABLED_FileCorruptionHandling) {
   1047   // Re-create the database in a captive message loop so that we can
   1048   // influence task-posting.  Database specifically needs to the
   1049   // file-backed.
   1050   database_.reset();
   1051   base::MessageLoop loop;
   1052   SafeBrowsingStoreFile* store = new SafeBrowsingStoreFile();
   1053   database_.reset(new SafeBrowsingDatabaseNew(store, NULL, NULL, NULL, NULL,
   1054                                               NULL, NULL));
   1055   database_->Init(database_filename_);
   1056 
   1057   // This will cause an empty database to be created.
   1058   std::vector<SBListChunkRanges> lists;
   1059   ASSERT_TRUE(database_->UpdateStarted(&lists));
   1060   database_->UpdateFinished(true);
   1061 
   1062   // Create a sub chunk to insert.
   1063   ScopedVector<SBChunkData> chunks;
   1064   chunks.push_back(SubChunkPrefixValue(7,
   1065                                        "www.subbed.com/notevil1.html",
   1066                                        19));
   1067 
   1068   // Corrupt the file by corrupting the checksum, which is not checked
   1069   // until the entire table is read in |UpdateFinished()|.
   1070   FILE* fp = base::OpenFile(database_filename_, "r+");
   1071   ASSERT_TRUE(fp);
   1072   ASSERT_NE(-1, fseek(fp, -8, SEEK_END));
   1073   for (size_t i = 0; i < 8; ++i) {
   1074     fputc('!', fp);
   1075   }
   1076   fclose(fp);
   1077 
   1078   {
   1079     // The following code will cause DCHECKs, so suppress the crashes.
   1080     ScopedLogMessageIgnorer ignorer;
   1081 
   1082     // Start an update.  The insert will fail due to corruption.
   1083     ASSERT_TRUE(database_->UpdateStarted(&lists));
   1084     database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
   1085     database_->UpdateFinished(true);
   1086 
   1087     // Database file still exists until the corruption handler has run.
   1088     EXPECT_TRUE(base::PathExists(database_filename_));
   1089 
   1090     // Flush through the corruption-handler task.
   1091     VLOG(1) << "Expect failed check on: SafeBrowsing database reset";
   1092     base::MessageLoop::current()->RunUntilIdle();
   1093   }
   1094 
   1095   // Database file should not exist.
   1096   EXPECT_FALSE(base::PathExists(database_filename_));
   1097 
   1098   // Run the update again successfully.
   1099   ASSERT_TRUE(database_->UpdateStarted(&lists));
   1100   database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
   1101   database_->UpdateFinished(true);
   1102   EXPECT_TRUE(base::PathExists(database_filename_));
   1103 
   1104   database_.reset();
   1105 }
   1106 
   1107 // Checks database reading and writing.
   1108 TEST_F(SafeBrowsingDatabaseTest, ContainsDownloadUrl) {
   1109   database_.reset();
   1110   base::MessageLoop loop;
   1111   SafeBrowsingStoreFile* browse_store = new SafeBrowsingStoreFile();
   1112   SafeBrowsingStoreFile* download_store = new SafeBrowsingStoreFile();
   1113   SafeBrowsingStoreFile* csd_whitelist_store = new SafeBrowsingStoreFile();
   1114   database_.reset(new SafeBrowsingDatabaseNew(browse_store,
   1115                                               download_store,
   1116                                               csd_whitelist_store,
   1117                                               NULL,
   1118                                               NULL,
   1119                                               NULL,
   1120                                               NULL));
   1121   database_->Init(database_filename_);
   1122 
   1123   const char kEvil1Url1[] = "www.evil1.com/download1/";
   1124   const char kEvil1Url2[] = "www.evil1.com/download2.html";
   1125 
   1126   // Add a simple chunk with one hostkey for download url list.
   1127   ScopedVector<SBChunkData> chunks;
   1128   chunks.push_back(AddChunkPrefix2Value(1, kEvil1Url1, kEvil1Url2));
   1129 
   1130   std::vector<SBListChunkRanges> lists;
   1131   ASSERT_TRUE(database_->UpdateStarted(&lists));
   1132   database_->InsertChunks(safe_browsing_util::kBinUrlList, chunks.get());
   1133   database_->UpdateFinished(true);
   1134 
   1135   std::vector<SBPrefix> prefix_hits;
   1136   std::vector<GURL> urls(1);
   1137 
   1138   urls[0] = GURL(std::string("http://") + kEvil1Url1);
   1139   EXPECT_TRUE(database_->ContainsDownloadUrl(urls, &prefix_hits));
   1140   ASSERT_EQ(1U, prefix_hits.size());
   1141   EXPECT_EQ(SBPrefixForString(kEvil1Url1), prefix_hits[0]);
   1142 
   1143   urls[0] = GURL(std::string("http://") + kEvil1Url2);
   1144   EXPECT_TRUE(database_->ContainsDownloadUrl(urls, &prefix_hits));
   1145   ASSERT_EQ(1U, prefix_hits.size());
   1146   EXPECT_EQ(SBPrefixForString(kEvil1Url2), prefix_hits[0]);
   1147 
   1148   urls[0] = GURL(std::string("https://") + kEvil1Url2);
   1149   EXPECT_TRUE(database_->ContainsDownloadUrl(urls, &prefix_hits));
   1150   ASSERT_EQ(1U, prefix_hits.size());
   1151   EXPECT_EQ(SBPrefixForString(kEvil1Url2), prefix_hits[0]);
   1152 
   1153   urls[0] = GURL(std::string("ftp://") + kEvil1Url2);
   1154   EXPECT_TRUE(database_->ContainsDownloadUrl(urls, &prefix_hits));
   1155   ASSERT_EQ(1U, prefix_hits.size());
   1156   EXPECT_EQ(SBPrefixForString(kEvil1Url2), prefix_hits[0]);
   1157 
   1158   urls[0] = GURL("http://www.randomevil.com");
   1159   EXPECT_FALSE(database_->ContainsDownloadUrl(urls, &prefix_hits));
   1160 
   1161   // Should match with query args stripped.
   1162   urls[0] = GURL(std::string("http://") + kEvil1Url2 + "?blah");
   1163   EXPECT_TRUE(database_->ContainsDownloadUrl(urls, &prefix_hits));
   1164   ASSERT_EQ(1U, prefix_hits.size());
   1165   EXPECT_EQ(SBPrefixForString(kEvil1Url2), prefix_hits[0]);
   1166 
   1167   // Should match with extra path stuff and query args stripped.
   1168   urls[0] = GURL(std::string("http://") + kEvil1Url1 + "foo/bar?blah");
   1169   EXPECT_TRUE(database_->ContainsDownloadUrl(urls, &prefix_hits));
   1170   ASSERT_EQ(1U, prefix_hits.size());
   1171   EXPECT_EQ(SBPrefixForString(kEvil1Url1), prefix_hits[0]);
   1172 
   1173   // First hit in redirect chain is malware.
   1174   urls.clear();
   1175   urls.push_back(GURL(std::string("http://") + kEvil1Url1));
   1176   urls.push_back(GURL("http://www.randomevil.com"));
   1177   EXPECT_TRUE(database_->ContainsDownloadUrl(urls, &prefix_hits));
   1178   ASSERT_EQ(1U, prefix_hits.size());
   1179   EXPECT_EQ(SBPrefixForString(kEvil1Url1), prefix_hits[0]);
   1180 
   1181   // Middle hit in redirect chain is malware.
   1182   urls.clear();
   1183   urls.push_back(GURL("http://www.randomevil.com"));
   1184   urls.push_back(GURL(std::string("http://") + kEvil1Url1));
   1185   urls.push_back(GURL("http://www.randomevil2.com"));
   1186   EXPECT_TRUE(database_->ContainsDownloadUrl(urls, &prefix_hits));
   1187   ASSERT_EQ(1U, prefix_hits.size());
   1188   EXPECT_EQ(SBPrefixForString(kEvil1Url1), prefix_hits[0]);
   1189 
   1190   // Final hit in redirect chain is malware.
   1191   urls.clear();
   1192   urls.push_back(GURL("http://www.randomevil.com"));
   1193   urls.push_back(GURL(std::string("http://") + kEvil1Url1));
   1194   EXPECT_TRUE(database_->ContainsDownloadUrl(urls, &prefix_hits));
   1195   ASSERT_EQ(1U, prefix_hits.size());
   1196   EXPECT_EQ(SBPrefixForString(kEvil1Url1), prefix_hits[0]);
   1197 
   1198   // Multiple hits in redirect chain are in malware list.
   1199   urls.clear();
   1200   urls.push_back(GURL(std::string("http://") + kEvil1Url1));
   1201   urls.push_back(GURL(std::string("https://") + kEvil1Url2));
   1202   EXPECT_TRUE(database_->ContainsDownloadUrl(urls, &prefix_hits));
   1203   ASSERT_EQ(2U, prefix_hits.size());
   1204   EXPECT_EQ(SBPrefixForString(kEvil1Url1), prefix_hits[0]);
   1205   EXPECT_EQ(SBPrefixForString(kEvil1Url2), prefix_hits[1]);
   1206   database_.reset();
   1207 }
   1208 
   1209 // Checks that the whitelists are handled properly.
   1210 TEST_F(SafeBrowsingDatabaseTest, Whitelists) {
   1211   database_.reset();
   1212 
   1213   // We expect all calls to ContainsCsdWhitelistedUrl in particular to be made
   1214   // from the IO thread.  In general the whitelist lookups are thread-safe.
   1215   content::TestBrowserThreadBundle thread_bundle_;
   1216 
   1217   // If the whitelist is disabled everything should match the whitelist.
   1218   database_.reset(new SafeBrowsingDatabaseNew(new SafeBrowsingStoreFile(),
   1219                                               NULL, NULL, NULL, NULL, NULL,
   1220                                               NULL));
   1221   database_->Init(database_filename_);
   1222   EXPECT_TRUE(database_->ContainsDownloadWhitelistedUrl(
   1223       GURL(std::string("http://www.phishing.com/"))));
   1224   EXPECT_TRUE(database_->ContainsDownloadWhitelistedUrl(
   1225       GURL(std::string("http://www.phishing.com/"))));
   1226   EXPECT_TRUE(database_->ContainsDownloadWhitelistedString("asdf"));
   1227 
   1228   SafeBrowsingStoreFile* browse_store = new SafeBrowsingStoreFile();
   1229   SafeBrowsingStoreFile* csd_whitelist_store = new SafeBrowsingStoreFile();
   1230   SafeBrowsingStoreFile* download_whitelist_store = new SafeBrowsingStoreFile();
   1231   SafeBrowsingStoreFile* extension_blacklist_store =
   1232       new SafeBrowsingStoreFile();
   1233   database_.reset(new SafeBrowsingDatabaseNew(browse_store, NULL,
   1234                                               csd_whitelist_store,
   1235                                               download_whitelist_store,
   1236                                               extension_blacklist_store,
   1237                                               NULL, NULL));
   1238   database_->Init(database_filename_);
   1239 
   1240   const char kGood1Host[] = "www.good1.com/";
   1241   const char kGood1Url1[] = "www.good1.com/a/b.html";
   1242   const char kGood1Url2[] = "www.good1.com/b/";
   1243 
   1244   const char kGood2Url1[] = "www.good2.com/c";  // Should match '/c/bla'.
   1245 
   1246   // good3.com/a/b/c/d/e/f/g/ should match because it's a whitelist.
   1247   const char kGood3Url1[] = "good3.com/";
   1248 
   1249   const char kGoodString[] = "good_string";
   1250 
   1251   ScopedVector<SBChunkData> csd_chunks;
   1252   ScopedVector<SBChunkData> download_chunks;
   1253 
   1254   // Add two simple chunks to the csd whitelist.
   1255   csd_chunks.push_back(AddChunkFullHash2Value(1, kGood1Url1, kGood1Url2));
   1256   csd_chunks.push_back(AddChunkFullHashValue(2, kGood2Url1));
   1257   download_chunks.push_back(AddChunkFullHashValue(2, kGood2Url1));
   1258   download_chunks.push_back(AddChunkFullHashValue(3, kGoodString));
   1259   download_chunks.push_back(AddChunkFullHashValue(4, kGood3Url1));
   1260 
   1261   std::vector<SBListChunkRanges> lists;
   1262   ASSERT_TRUE(database_->UpdateStarted(&lists));
   1263   database_->InsertChunks(safe_browsing_util::kCsdWhiteList, csd_chunks.get());
   1264   database_->InsertChunks(safe_browsing_util::kDownloadWhiteList,
   1265                           download_chunks.get());
   1266   database_->UpdateFinished(true);
   1267 
   1268   EXPECT_FALSE(database_->ContainsCsdWhitelistedUrl(
   1269       GURL(std::string("http://") + kGood1Host)));
   1270 
   1271   EXPECT_TRUE(database_->ContainsCsdWhitelistedUrl(
   1272       GURL(std::string("http://") + kGood1Url1)));
   1273   EXPECT_TRUE(database_->ContainsCsdWhitelistedUrl(
   1274       GURL(std::string("http://") + kGood1Url1 + "?a=b")));
   1275 
   1276   EXPECT_TRUE(database_->ContainsCsdWhitelistedUrl(
   1277       GURL(std::string("http://") + kGood1Url2)));
   1278   EXPECT_TRUE(database_->ContainsCsdWhitelistedUrl(
   1279       GURL(std::string("http://") + kGood1Url2 + "/c.html")));
   1280 
   1281   EXPECT_TRUE(database_->ContainsCsdWhitelistedUrl(
   1282       GURL(std::string("https://") + kGood1Url2 + "/c.html")));
   1283 
   1284   EXPECT_TRUE(database_->ContainsCsdWhitelistedUrl(
   1285       GURL(std::string("http://") + kGood2Url1 + "/c")));
   1286   EXPECT_TRUE(database_->ContainsCsdWhitelistedUrl(
   1287       GURL(std::string("http://") + kGood2Url1 + "/c?bla")));
   1288   EXPECT_TRUE(database_->ContainsCsdWhitelistedUrl(
   1289       GURL(std::string("http://") + kGood2Url1 + "/c/bla")));
   1290 
   1291   EXPECT_FALSE(database_->ContainsCsdWhitelistedUrl(
   1292       GURL(std::string("http://www.google.com/"))));
   1293 
   1294   EXPECT_TRUE(database_->ContainsDownloadWhitelistedUrl(
   1295       GURL(std::string("http://") + kGood2Url1 + "/c")));
   1296   EXPECT_TRUE(database_->ContainsDownloadWhitelistedUrl(
   1297       GURL(std::string("http://") + kGood2Url1 + "/c?bla")));
   1298   EXPECT_TRUE(database_->ContainsDownloadWhitelistedUrl(
   1299       GURL(std::string("http://") + kGood2Url1 + "/c/bla")));
   1300 
   1301   EXPECT_TRUE(database_->ContainsDownloadWhitelistedUrl(
   1302       GURL(std::string("http://good3.com/a/b/c/d/e/f/g/"))));
   1303   EXPECT_TRUE(database_->ContainsDownloadWhitelistedUrl(
   1304       GURL(std::string("http://a.b.good3.com/"))));
   1305 
   1306   EXPECT_FALSE(database_->ContainsDownloadWhitelistedString("asdf"));
   1307   EXPECT_TRUE(database_->ContainsDownloadWhitelistedString(kGoodString));
   1308 
   1309   EXPECT_FALSE(database_->ContainsDownloadWhitelistedUrl(
   1310       GURL(std::string("http://www.google.com/"))));
   1311 
   1312   // The CSD whitelist killswitch is not present.
   1313   EXPECT_FALSE(database_->IsCsdWhitelistKillSwitchOn());
   1314 
   1315   // Test only add the malware IP killswitch
   1316   csd_chunks.clear();
   1317   csd_chunks.push_back(AddChunkFullHashValue(
   1318       15, "sb-ssl.google.com/safebrowsing/csd/killswitch_malware"));
   1319 
   1320   ASSERT_TRUE(database_->UpdateStarted(&lists));
   1321   database_->InsertChunks(safe_browsing_util::kCsdWhiteList, csd_chunks.get());
   1322   database_->UpdateFinished(true);
   1323 
   1324   EXPECT_TRUE(database_->IsMalwareIPMatchKillSwitchOn());
   1325   // The CSD whitelist killswitch is not present.
   1326   EXPECT_FALSE(database_->IsCsdWhitelistKillSwitchOn());
   1327 
   1328   // Test that the kill-switch works as intended.
   1329   csd_chunks.clear();
   1330   download_chunks.clear();
   1331   lists.clear();
   1332   csd_chunks.push_back(AddChunkFullHashValue(
   1333       5, "sb-ssl.google.com/safebrowsing/csd/killswitch"));
   1334   download_chunks.push_back(AddChunkFullHashValue(
   1335       5, "sb-ssl.google.com/safebrowsing/csd/killswitch"));
   1336 
   1337   ASSERT_TRUE(database_->UpdateStarted(&lists));
   1338   database_->InsertChunks(safe_browsing_util::kCsdWhiteList, csd_chunks.get());
   1339   database_->InsertChunks(safe_browsing_util::kDownloadWhiteList,
   1340                           download_chunks.get());
   1341   database_->UpdateFinished(true);
   1342 
   1343   // The CSD whitelist killswitch is present.
   1344   EXPECT_TRUE(database_->IsCsdWhitelistKillSwitchOn());
   1345   EXPECT_TRUE(database_->IsMalwareIPMatchKillSwitchOn());
   1346   EXPECT_TRUE(database_->ContainsCsdWhitelistedUrl(
   1347       GURL(std::string("https://") + kGood1Url2 + "/c.html")));
   1348   EXPECT_TRUE(database_->ContainsCsdWhitelistedUrl(
   1349       GURL(std::string("http://www.google.com/"))));
   1350   EXPECT_TRUE(database_->ContainsCsdWhitelistedUrl(
   1351       GURL(std::string("http://www.phishing_url.com/"))));
   1352 
   1353   EXPECT_TRUE(database_->ContainsDownloadWhitelistedUrl(
   1354       GURL(std::string("https://") + kGood1Url2 + "/c.html")));
   1355   EXPECT_TRUE(database_->ContainsDownloadWhitelistedUrl(
   1356       GURL(std::string("http://www.google.com/"))));
   1357   EXPECT_TRUE(database_->ContainsDownloadWhitelistedUrl(
   1358       GURL(std::string("http://www.phishing_url.com/"))));
   1359 
   1360   EXPECT_TRUE(database_->ContainsDownloadWhitelistedString("asdf"));
   1361   EXPECT_TRUE(database_->ContainsDownloadWhitelistedString(kGoodString));
   1362 
   1363   // Remove the kill-switch and verify that we can recover.
   1364   csd_chunks.clear();
   1365   download_chunks.clear();
   1366   lists.clear();
   1367   csd_chunks.push_back(SubChunkFullHashValue(
   1368       1, "sb-ssl.google.com/safebrowsing/csd/killswitch", 5));
   1369   csd_chunks.push_back(SubChunkFullHashValue(
   1370       10, "sb-ssl.google.com/safebrowsing/csd/killswitch_malware", 15));
   1371   download_chunks.push_back(SubChunkFullHashValue(
   1372       1, "sb-ssl.google.com/safebrowsing/csd/killswitch", 5));
   1373 
   1374   ASSERT_TRUE(database_->UpdateStarted(&lists));
   1375   database_->InsertChunks(safe_browsing_util::kCsdWhiteList, csd_chunks.get());
   1376   database_->InsertChunks(safe_browsing_util::kDownloadWhiteList,
   1377                           download_chunks.get());
   1378   database_->UpdateFinished(true);
   1379 
   1380   EXPECT_FALSE(database_->IsMalwareIPMatchKillSwitchOn());
   1381   EXPECT_FALSE(database_->IsCsdWhitelistKillSwitchOn());
   1382   EXPECT_TRUE(database_->ContainsCsdWhitelistedUrl(
   1383       GURL(std::string("https://") + kGood1Url2 + "/c.html")));
   1384   EXPECT_TRUE(database_->ContainsCsdWhitelistedUrl(
   1385       GURL(std::string("https://") + kGood2Url1 + "/c/bla")));
   1386   EXPECT_FALSE(database_->ContainsCsdWhitelistedUrl(
   1387       GURL(std::string("http://www.google.com/"))));
   1388   EXPECT_FALSE(database_->ContainsCsdWhitelistedUrl(
   1389       GURL(std::string("http://www.phishing_url.com/"))));
   1390 
   1391   EXPECT_TRUE(database_->ContainsDownloadWhitelistedUrl(
   1392       GURL(std::string("https://") + kGood2Url1 + "/c/bla")));
   1393   EXPECT_TRUE(database_->ContainsDownloadWhitelistedUrl(
   1394       GURL(std::string("https://good3.com/"))));
   1395   EXPECT_TRUE(database_->ContainsDownloadWhitelistedString(kGoodString));
   1396   EXPECT_FALSE(database_->ContainsDownloadWhitelistedUrl(
   1397       GURL(std::string("http://www.google.com/"))));
   1398   EXPECT_FALSE(database_->ContainsDownloadWhitelistedUrl(
   1399       GURL(std::string("http://www.phishing_url.com/"))));
   1400   EXPECT_FALSE(database_->ContainsDownloadWhitelistedString("asdf"));
   1401 
   1402   database_.reset();
   1403 }
   1404 
   1405 // Test to make sure we could insert chunk list that
   1406 // contains entries for the same host.
   1407 TEST_F(SafeBrowsingDatabaseTest, SameHostEntriesOkay) {
   1408   ScopedVector<SBChunkData> chunks;
   1409 
   1410   // Add a malware add chunk with two entries of the same host.
   1411   chunks.push_back(AddChunkPrefix2Value(1,
   1412                                         "www.evil.com/malware1.html",
   1413                                         "www.evil.com/malware2.html"));
   1414 
   1415   // Insert the testing chunks into database.
   1416   std::vector<SBListChunkRanges> lists;
   1417   ASSERT_TRUE(database_->UpdateStarted(&lists));
   1418   database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
   1419   database_->UpdateFinished(true);
   1420 
   1421   GetListsInfo(&lists);
   1422   ASSERT_LE(1U, lists.size());
   1423   EXPECT_EQ(safe_browsing_util::kMalwareList, lists[0].name);
   1424   EXPECT_EQ("1", lists[0].adds);
   1425   EXPECT_TRUE(lists[0].subs.empty());
   1426 
   1427   // Add a phishing add chunk with two entries of the same host.
   1428   chunks.clear();
   1429   chunks.push_back(AddChunkPrefix2Value(47,
   1430                                         "www.evil.com/phishing1.html",
   1431                                         "www.evil.com/phishing2.html"));
   1432 
   1433   ASSERT_TRUE(database_->UpdateStarted(&lists));
   1434   database_->InsertChunks(safe_browsing_util::kPhishingList, chunks.get());
   1435   database_->UpdateFinished(true);
   1436 
   1437   GetListsInfo(&lists);
   1438   ASSERT_EQ(2U, lists.size());
   1439   EXPECT_EQ(safe_browsing_util::kMalwareList, lists[0].name);
   1440   EXPECT_EQ("1", lists[0].adds);
   1441   EXPECT_TRUE(lists[0].subs.empty());
   1442   EXPECT_EQ(safe_browsing_util::kPhishingList, lists[1].name);
   1443   EXPECT_EQ("47", lists[1].adds);
   1444   EXPECT_TRUE(lists[1].subs.empty());
   1445 
   1446   std::vector<SBPrefix> prefix_hits;
   1447   std::vector<SBFullHashResult> cache_hits;
   1448 
   1449   EXPECT_TRUE(database_->ContainsBrowseUrl(
   1450       GURL("http://www.evil.com/malware1.html"), &prefix_hits, &cache_hits));
   1451   EXPECT_TRUE(database_->ContainsBrowseUrl(
   1452       GURL("http://www.evil.com/malware2.html"), &prefix_hits, &cache_hits));
   1453   EXPECT_TRUE(database_->ContainsBrowseUrl(
   1454       GURL("http://www.evil.com/phishing1.html"), &prefix_hits, &cache_hits));
   1455   EXPECT_TRUE(database_->ContainsBrowseUrl(
   1456       GURL("http://www.evil.com/phishing2.html"), &prefix_hits, &cache_hits));
   1457 
   1458   // Test removing a single prefix from the add chunk.
   1459   // Remove the prefix that added first.
   1460   chunks.clear();
   1461   chunks.push_back(SubChunkPrefixValue(4, "www.evil.com/malware1.html", 1));
   1462   ASSERT_TRUE(database_->UpdateStarted(&lists));
   1463   database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
   1464   database_->UpdateFinished(true);
   1465 
   1466   // Remove the prefix that added last.
   1467   chunks.clear();
   1468   chunks.push_back(SubChunkPrefixValue(5, "www.evil.com/phishing2.html", 47));
   1469   ASSERT_TRUE(database_->UpdateStarted(&lists));
   1470   database_->InsertChunks(safe_browsing_util::kPhishingList, chunks.get());
   1471   database_->UpdateFinished(true);
   1472 
   1473   // Verify that the database contains urls expected.
   1474   EXPECT_FALSE(database_->ContainsBrowseUrl(
   1475       GURL("http://www.evil.com/malware1.html"), &prefix_hits, &cache_hits));
   1476   EXPECT_TRUE(database_->ContainsBrowseUrl(
   1477       GURL("http://www.evil.com/malware2.html"), &prefix_hits, &cache_hits));
   1478   EXPECT_TRUE(database_->ContainsBrowseUrl(
   1479       GURL("http://www.evil.com/phishing1.html"), &prefix_hits, &cache_hits));
   1480   EXPECT_FALSE(database_->ContainsBrowseUrl(
   1481       GURL("http://www.evil.com/phishing2.html"), &prefix_hits, &cache_hits));
   1482 }
   1483 
   1484 // Test that an empty update doesn't actually update the database.
   1485 // This isn't a functionality requirement, but it is a useful
   1486 // optimization.
   1487 TEST_F(SafeBrowsingDatabaseTest, EmptyUpdate) {
   1488   ScopedVector<SBChunkData> chunks;
   1489 
   1490   base::FilePath filename = database_->BrowseDBFilename(database_filename_);
   1491 
   1492   // Prime the database.
   1493   std::vector<SBListChunkRanges> lists;
   1494   ASSERT_TRUE(database_->UpdateStarted(&lists));
   1495   chunks.push_back(AddChunkPrefixValue(1, "www.evil.com/malware.html"));
   1496   database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
   1497   database_->UpdateFinished(true);
   1498 
   1499   // Get an older time to reset the lastmod time for detecting whether
   1500   // the file has been updated.
   1501   base::File::Info before_info, after_info;
   1502   ASSERT_TRUE(base::GetFileInfo(filename, &before_info));
   1503   const Time old_last_modified =
   1504       before_info.last_modified - TimeDelta::FromSeconds(10);
   1505 
   1506   // Inserting another chunk updates the database file.  The sleep is
   1507   // needed because otherwise the entire test can finish w/in the
   1508   // resolution of the lastmod time.
   1509   ASSERT_TRUE(base::TouchFile(filename, old_last_modified, old_last_modified));
   1510   ASSERT_TRUE(base::GetFileInfo(filename, &before_info));
   1511   ASSERT_TRUE(database_->UpdateStarted(&lists));
   1512   chunks.push_back(AddChunkPrefixValue(2, "www.foo.com/malware.html"));
   1513   database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
   1514   database_->UpdateFinished(true);
   1515   ASSERT_TRUE(base::GetFileInfo(filename, &after_info));
   1516   EXPECT_LT(before_info.last_modified, after_info.last_modified);
   1517 
   1518   // Deleting a chunk updates the database file.
   1519   ASSERT_TRUE(base::TouchFile(filename, old_last_modified, old_last_modified));
   1520   ASSERT_TRUE(base::GetFileInfo(filename, &before_info));
   1521   ASSERT_TRUE(database_->UpdateStarted(&lists));
   1522   AddDelChunk(safe_browsing_util::kMalwareList, 2);
   1523   database_->UpdateFinished(true);
   1524   ASSERT_TRUE(base::GetFileInfo(filename, &after_info));
   1525   EXPECT_LT(before_info.last_modified, after_info.last_modified);
   1526 
   1527   // Simply calling |UpdateStarted()| then |UpdateFinished()| does not
   1528   // update the database file.
   1529   ASSERT_TRUE(base::TouchFile(filename, old_last_modified, old_last_modified));
   1530   ASSERT_TRUE(base::GetFileInfo(filename, &before_info));
   1531   ASSERT_TRUE(database_->UpdateStarted(&lists));
   1532   database_->UpdateFinished(true);
   1533   ASSERT_TRUE(base::GetFileInfo(filename, &after_info));
   1534   EXPECT_EQ(before_info.last_modified, after_info.last_modified);
   1535 }
   1536 
   1537 // Test that a filter file is written out during update and read back
   1538 // in during setup.
   1539 TEST_F(SafeBrowsingDatabaseTest, FilterFile) {
   1540   // Create a database with trivial example data and write it out.
   1541   {
   1542     // Prime the database.
   1543     std::vector<SBListChunkRanges> lists;
   1544     ASSERT_TRUE(database_->UpdateStarted(&lists));
   1545 
   1546     ScopedVector<SBChunkData> chunks;
   1547     chunks.push_back(AddChunkPrefixValue(1, "www.evil.com/malware.html"));
   1548     database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
   1549     database_->UpdateFinished(true);
   1550   }
   1551 
   1552   // Find the malware url in the database, don't find a good url.
   1553   std::vector<SBPrefix> prefix_hits;
   1554   std::vector<SBFullHashResult> cache_hits;
   1555   EXPECT_TRUE(database_->ContainsBrowseUrl(
   1556       GURL("http://www.evil.com/malware.html"), &prefix_hits, &cache_hits));
   1557   EXPECT_FALSE(database_->ContainsBrowseUrl(
   1558       GURL("http://www.good.com/goodware.html"), &prefix_hits, &cache_hits));
   1559 
   1560   base::FilePath filter_file = database_->PrefixSetForFilename(
   1561       database_->BrowseDBFilename(database_filename_));
   1562 
   1563   // After re-creating the database, it should have a filter read from
   1564   // a file, so it should find the same results.
   1565   ASSERT_TRUE(base::PathExists(filter_file));
   1566   database_.reset(new SafeBrowsingDatabaseNew);
   1567   database_->Init(database_filename_);
   1568   EXPECT_TRUE(database_->ContainsBrowseUrl(
   1569       GURL("http://www.evil.com/malware.html"), &prefix_hits, &cache_hits));
   1570   EXPECT_FALSE(database_->ContainsBrowseUrl(
   1571       GURL("http://www.good.com/goodware.html"), &prefix_hits, &cache_hits));
   1572 
   1573   // If there is no filter file, the database cannot find malware urls.
   1574   base::DeleteFile(filter_file, false);
   1575   ASSERT_FALSE(base::PathExists(filter_file));
   1576   database_.reset(new SafeBrowsingDatabaseNew);
   1577   database_->Init(database_filename_);
   1578   EXPECT_FALSE(database_->ContainsBrowseUrl(
   1579       GURL("http://www.evil.com/malware.html"), &prefix_hits, &cache_hits));
   1580   EXPECT_FALSE(database_->ContainsBrowseUrl(
   1581       GURL("http://www.good.com/goodware.html"), &prefix_hits, &cache_hits));
   1582 }
   1583 
   1584 TEST_F(SafeBrowsingDatabaseTest, CachedFullMiss) {
   1585   const SBPrefix kPrefix1 = 1001U;
   1586   const SBFullHash kFullHash1_1 =
   1587       SBFullHashForPrefixAndSuffix(kPrefix1, "\x01");
   1588 
   1589   const SBPrefix kPrefix2 = 1002U;
   1590   const SBFullHash kFullHash2_1 =
   1591       SBFullHashForPrefixAndSuffix(kPrefix2, "\x01");
   1592 
   1593   // Insert prefix kPrefix1 and kPrefix2 into database.
   1594   ScopedVector<SBChunkData> chunks;
   1595   chunks.push_back(AddChunkPrefix(1, kPrefix1));
   1596   chunks.push_back(AddChunkPrefix(2, kPrefix2));
   1597 
   1598   std::vector<SBListChunkRanges> lists;
   1599   ASSERT_TRUE(database_->UpdateStarted(&lists));
   1600   database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
   1601   database_->UpdateFinished(true);
   1602 
   1603   {
   1604     // Cache a full miss result for kPrefix1.
   1605     std::vector<SBPrefix> prefixes(1, kPrefix1);
   1606     std::vector<SBFullHashResult> cache_results;
   1607     database_->CacheHashResults(prefixes, cache_results, kCacheLifetime);
   1608   }
   1609 
   1610   {
   1611     // kFullHash1_1 gets no prefix hit because of the cached item, and also does
   1612     // not have a cache hit.
   1613     std::vector<SBFullHash> full_hashes(1, kFullHash1_1);
   1614     std::vector<SBPrefix> prefix_hits;
   1615     std::vector<SBFullHashResult> cache_hits;
   1616     EXPECT_FALSE(database_->ContainsBrowseUrlHashes(
   1617         full_hashes, &prefix_hits, &cache_hits));
   1618 
   1619     // kFullHash2_1 gets a hit from the prefix in the database.
   1620     full_hashes.push_back(kFullHash2_1);
   1621     prefix_hits.clear();
   1622     cache_hits.clear();
   1623     EXPECT_TRUE(database_->ContainsBrowseUrlHashes(
   1624         full_hashes, &prefix_hits, &cache_hits));
   1625     ASSERT_EQ(1U, prefix_hits.size());
   1626     EXPECT_EQ(kPrefix2, prefix_hits[0]);
   1627     EXPECT_TRUE(cache_hits.empty());
   1628   }
   1629 }
   1630 
   1631 TEST_F(SafeBrowsingDatabaseTest, CachedPrefixHitFullMiss) {
   1632   const SBPrefix kPrefix1 = 1001U;
   1633   const SBFullHash kFullHash1_1 =
   1634       SBFullHashForPrefixAndSuffix(kPrefix1, "\x01");
   1635   const SBFullHash kFullHash1_2 =
   1636       SBFullHashForPrefixAndSuffix(kPrefix1, "\x02");
   1637   const SBFullHash kFullHash1_3 =
   1638       SBFullHashForPrefixAndSuffix(kPrefix1, "\x03");
   1639 
   1640   const SBPrefix kPrefix2 = 1002U;
   1641   const SBFullHash kFullHash2_1 =
   1642       SBFullHashForPrefixAndSuffix(kPrefix2, "\x01");
   1643 
   1644   const SBPrefix kPrefix3 = 1003U;
   1645   const SBFullHash kFullHash3_1 =
   1646       SBFullHashForPrefixAndSuffix(kPrefix3, "\x01");
   1647 
   1648   // Insert prefix kPrefix1 and kPrefix2 into database.
   1649   ScopedVector<SBChunkData> chunks;
   1650   chunks.push_back(AddChunkPrefix(1, kPrefix1));
   1651   chunks.push_back(AddChunkPrefix(2, kPrefix2));
   1652 
   1653   std::vector<SBListChunkRanges> lists;
   1654   ASSERT_TRUE(database_->UpdateStarted(&lists));
   1655   database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
   1656   database_->UpdateFinished(true);
   1657 
   1658   {
   1659     // kFullHash1_1 has a prefix hit of kPrefix1.
   1660     std::vector<SBFullHash> full_hashes;
   1661     full_hashes.push_back(kFullHash1_1);
   1662     std::vector<SBPrefix> prefix_hits;
   1663     std::vector<SBFullHashResult> cache_hits;
   1664     EXPECT_TRUE(database_->ContainsBrowseUrlHashes(
   1665         full_hashes, &prefix_hits, &cache_hits));
   1666     ASSERT_EQ(1U, prefix_hits.size());
   1667     EXPECT_EQ(kPrefix1, prefix_hits[0]);
   1668     EXPECT_TRUE(cache_hits.empty());
   1669 
   1670     // kFullHash2_1 has a prefix hit of kPrefix2.
   1671     full_hashes.push_back(kFullHash2_1);
   1672     prefix_hits.clear();
   1673     cache_hits.clear();
   1674     EXPECT_TRUE(database_->ContainsBrowseUrlHashes(
   1675         full_hashes, &prefix_hits, &cache_hits));
   1676     ASSERT_EQ(2U, prefix_hits.size());
   1677     EXPECT_EQ(kPrefix1, prefix_hits[0]);
   1678     EXPECT_EQ(kPrefix2, prefix_hits[1]);
   1679     EXPECT_TRUE(cache_hits.empty());
   1680 
   1681     // kFullHash3_1 has no hits.
   1682     full_hashes.push_back(kFullHash3_1);
   1683     prefix_hits.clear();
   1684     cache_hits.clear();
   1685     EXPECT_TRUE(database_->ContainsBrowseUrlHashes(
   1686         full_hashes, &prefix_hits, &cache_hits));
   1687     ASSERT_EQ(2U, prefix_hits.size());
   1688     EXPECT_EQ(kPrefix1, prefix_hits[0]);
   1689     EXPECT_EQ(kPrefix2, prefix_hits[1]);
   1690     EXPECT_TRUE(cache_hits.empty());
   1691   }
   1692 
   1693   {
   1694     // Cache a fullhash result for two kPrefix1 full hashes.
   1695     std::vector<SBPrefix> prefixes(1, kPrefix1);
   1696     std::vector<SBFullHashResult> cache_results;
   1697 
   1698     SBFullHashResult full_hash_result;
   1699     full_hash_result.list_id = safe_browsing_util::MALWARE;
   1700 
   1701     full_hash_result.hash = kFullHash1_1;
   1702     cache_results.push_back(full_hash_result);
   1703 
   1704     full_hash_result.hash = kFullHash1_3;
   1705     cache_results.push_back(full_hash_result);
   1706 
   1707     database_->CacheHashResults(prefixes, cache_results, kCacheLifetime);
   1708   }
   1709 
   1710   {
   1711     // kFullHash1_1 should now see a cache hit.
   1712     std::vector<SBFullHash> full_hashes(1, kFullHash1_1);
   1713     std::vector<SBPrefix> prefix_hits;
   1714     std::vector<SBFullHashResult> cache_hits;
   1715     EXPECT_TRUE(database_->ContainsBrowseUrlHashes(
   1716         full_hashes, &prefix_hits, &cache_hits));
   1717     EXPECT_TRUE(prefix_hits.empty());
   1718     ASSERT_EQ(1U, cache_hits.size());
   1719     EXPECT_TRUE(SBFullHashEqual(kFullHash1_1, cache_hits[0].hash));
   1720 
   1721     // Adding kFullHash2_1 will see the existing cache hit plus the prefix hit
   1722     // for kPrefix2.
   1723     full_hashes.push_back(kFullHash2_1);
   1724     prefix_hits.clear();
   1725     cache_hits.clear();
   1726     EXPECT_TRUE(database_->ContainsBrowseUrlHashes(
   1727         full_hashes, &prefix_hits, &cache_hits));
   1728     ASSERT_EQ(1U, prefix_hits.size());
   1729     EXPECT_EQ(kPrefix2, prefix_hits[0]);
   1730     ASSERT_EQ(1U, cache_hits.size());
   1731     EXPECT_TRUE(SBFullHashEqual(kFullHash1_1, cache_hits[0].hash));
   1732 
   1733     // kFullHash1_3 also gets a cache hit.
   1734     full_hashes.push_back(kFullHash1_3);
   1735     prefix_hits.clear();
   1736     cache_hits.clear();
   1737     EXPECT_TRUE(database_->ContainsBrowseUrlHashes(
   1738         full_hashes, &prefix_hits, &cache_hits));
   1739     ASSERT_EQ(1U, prefix_hits.size());
   1740     EXPECT_EQ(kPrefix2, prefix_hits[0]);
   1741     ASSERT_EQ(2U, cache_hits.size());
   1742     EXPECT_TRUE(SBFullHashEqual(kFullHash1_1, cache_hits[0].hash));
   1743     EXPECT_TRUE(SBFullHashEqual(kFullHash1_3, cache_hits[1].hash));
   1744   }
   1745 
   1746   {
   1747     // Check if DB contains only kFullHash1_3. Should return a cache hit.
   1748     std::vector<SBFullHash> full_hashes(1, kFullHash1_3);
   1749     std::vector<SBPrefix> prefix_hits;
   1750     std::vector<SBFullHashResult> cache_hits;
   1751     EXPECT_TRUE(database_->ContainsBrowseUrlHashes(
   1752         full_hashes, &prefix_hits, &cache_hits));
   1753     EXPECT_TRUE(prefix_hits.empty());
   1754     ASSERT_EQ(1U, cache_hits.size());
   1755     EXPECT_TRUE(SBFullHashEqual(kFullHash1_3, cache_hits[0].hash));
   1756   }
   1757 
   1758   {
   1759     // kFullHash1_2 has no cache hit, and no prefix hit because of the cache for
   1760     // kPrefix1.
   1761     std::vector<SBFullHash> full_hashes(1, kFullHash1_2);
   1762     std::vector<SBPrefix> prefix_hits;
   1763     std::vector<SBFullHashResult> cache_hits;
   1764     EXPECT_FALSE(database_->ContainsBrowseUrlHashes(
   1765         full_hashes, &prefix_hits, &cache_hits));
   1766 
   1767     // Other prefix hits possible when kFullHash1_2 hits nothing.
   1768     full_hashes.push_back(kFullHash2_1);
   1769     prefix_hits.clear();
   1770     cache_hits.clear();
   1771     EXPECT_TRUE(database_->ContainsBrowseUrlHashes(
   1772         full_hashes, &prefix_hits, &cache_hits));
   1773     ASSERT_EQ(1U, prefix_hits.size());
   1774     EXPECT_EQ(kPrefix2, prefix_hits[0]);
   1775     EXPECT_TRUE(cache_hits.empty());
   1776   }
   1777 }
   1778 
   1779 TEST_F(SafeBrowsingDatabaseTest, BrowseFullHashMatching) {
   1780   const SBPrefix kPrefix1 = 1001U;
   1781   const SBFullHash kFullHash1_1 =
   1782       SBFullHashForPrefixAndSuffix(kPrefix1, "\x01");
   1783   const SBFullHash kFullHash1_2 =
   1784       SBFullHashForPrefixAndSuffix(kPrefix1, "\x02");
   1785   const SBFullHash kFullHash1_3 =
   1786       SBFullHashForPrefixAndSuffix(kPrefix1, "\x03");
   1787 
   1788   // Insert two full hashes with a shared prefix.
   1789   ScopedVector<SBChunkData> chunks;
   1790   chunks.push_back(AddChunkFullHash(1, kFullHash1_1));
   1791   chunks.push_back(AddChunkFullHash(2, kFullHash1_2));
   1792 
   1793   std::vector<SBListChunkRanges> lists;
   1794   ASSERT_TRUE(database_->UpdateStarted(&lists));
   1795   database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
   1796   database_->UpdateFinished(true);
   1797 
   1798   {
   1799     // Check a full hash which isn't present.
   1800     std::vector<SBFullHash> full_hashes(1, kFullHash1_3);
   1801     std::vector<SBPrefix> prefix_hits;
   1802     std::vector<SBFullHashResult> cache_hits;
   1803     EXPECT_FALSE(database_->ContainsBrowseUrlHashes(
   1804         full_hashes, &prefix_hits, &cache_hits));
   1805 
   1806     // Also one which is present, should have a prefix hit.
   1807     full_hashes.push_back(kFullHash1_1);
   1808     prefix_hits.clear();
   1809     cache_hits.clear();
   1810     EXPECT_TRUE(database_->ContainsBrowseUrlHashes(
   1811         full_hashes, &prefix_hits, &cache_hits));
   1812     ASSERT_EQ(1U, prefix_hits.size());
   1813     EXPECT_EQ(kPrefix1, prefix_hits[0]);
   1814     EXPECT_TRUE(cache_hits.empty());
   1815 
   1816     // Two full hash matches with the same prefix should return one prefix hit.
   1817     full_hashes.push_back(kFullHash1_2);
   1818     prefix_hits.clear();
   1819     cache_hits.clear();
   1820     EXPECT_TRUE(database_->ContainsBrowseUrlHashes(
   1821         full_hashes, &prefix_hits, &cache_hits));
   1822     ASSERT_EQ(1U, prefix_hits.size());
   1823     EXPECT_EQ(kPrefix1, prefix_hits[0]);
   1824     EXPECT_TRUE(cache_hits.empty());
   1825   }
   1826 
   1827   {
   1828     // Cache a gethash result for kFullHash1_2.
   1829     SBFullHashResult full_hash_result;
   1830     full_hash_result.list_id = safe_browsing_util::MALWARE;
   1831     full_hash_result.hash = kFullHash1_2;
   1832 
   1833     std::vector<SBPrefix> prefixes(1, kPrefix1);
   1834     std::vector<SBFullHashResult> cache_results(1, full_hash_result);
   1835 
   1836     database_->CacheHashResults(prefixes, cache_results, kCacheLifetime);
   1837   }
   1838 
   1839   {
   1840     // kFullHash1_3 should still return false, because the cached
   1841     // result for kPrefix1 doesn't contain kFullHash1_3.
   1842     std::vector<SBFullHash> full_hashes(1, kFullHash1_3);
   1843     std::vector<SBPrefix> prefix_hits;
   1844     std::vector<SBFullHashResult> cache_hits;
   1845     EXPECT_FALSE(database_->ContainsBrowseUrlHashes(
   1846         full_hashes, &prefix_hits, &cache_hits));
   1847 
   1848     // kFullHash1_1 is also not in the cached result, which takes
   1849     // priority over the database.
   1850     prefix_hits.clear();
   1851     full_hashes.push_back(kFullHash1_1);
   1852     cache_hits.clear();
   1853     EXPECT_FALSE(database_->ContainsBrowseUrlHashes(
   1854         full_hashes, &prefix_hits, &cache_hits));
   1855 
   1856     // kFullHash1_2 is in the cached result.
   1857     full_hashes.push_back(kFullHash1_2);
   1858     prefix_hits.clear();
   1859     cache_hits.clear();
   1860     EXPECT_TRUE(database_->ContainsBrowseUrlHashes(
   1861         full_hashes, &prefix_hits, &cache_hits));
   1862     EXPECT_TRUE(prefix_hits.empty());
   1863     ASSERT_EQ(1U, cache_hits.size());
   1864     EXPECT_TRUE(SBFullHashEqual(kFullHash1_2, cache_hits[0].hash));
   1865   }
   1866 
   1867   // Remove kFullHash1_1 from the database.
   1868   chunks.clear();
   1869   chunks.push_back(SubChunkFullHash(11, kFullHash1_1, 1));
   1870 
   1871   ASSERT_TRUE(database_->UpdateStarted(&lists));
   1872   database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
   1873   database_->UpdateFinished(true);
   1874 
   1875   // Cache should be cleared after updating.
   1876   EXPECT_TRUE(database_->browse_gethash_cache_.empty());
   1877 
   1878   {
   1879     // Now the database doesn't contain kFullHash1_1.
   1880     std::vector<SBFullHash> full_hashes(1, kFullHash1_1);
   1881     std::vector<SBPrefix> prefix_hits;
   1882     std::vector<SBFullHashResult> cache_hits;
   1883     EXPECT_FALSE(database_->ContainsBrowseUrlHashes(
   1884         full_hashes, &prefix_hits, &cache_hits));
   1885 
   1886     // Nor kFullHash1_3.
   1887     full_hashes.push_back(kFullHash1_3);
   1888     prefix_hits.clear();
   1889     cache_hits.clear();
   1890     EXPECT_FALSE(database_->ContainsBrowseUrlHashes(
   1891         full_hashes, &prefix_hits, &cache_hits));
   1892 
   1893     // Still has kFullHash1_2.
   1894     full_hashes.push_back(kFullHash1_2);
   1895     prefix_hits.clear();
   1896     cache_hits.clear();
   1897     EXPECT_TRUE(database_->ContainsBrowseUrlHashes(
   1898         full_hashes, &prefix_hits, &cache_hits));
   1899     ASSERT_EQ(1U, prefix_hits.size());
   1900     EXPECT_EQ(kPrefix1, prefix_hits[0]);
   1901     EXPECT_TRUE(cache_hits.empty());
   1902   }
   1903 
   1904   // Remove kFullHash1_2 from the database.
   1905   chunks.clear();
   1906   chunks.push_back(SubChunkFullHash(12, kFullHash1_2, 2));
   1907 
   1908   ASSERT_TRUE(database_->UpdateStarted(&lists));
   1909   database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
   1910   database_->UpdateFinished(true);
   1911 
   1912   // Cache should be cleared after updating.
   1913   EXPECT_TRUE(database_->browse_gethash_cache_.empty());
   1914 
   1915   {
   1916     // None are present.
   1917     std::vector<SBFullHash> full_hashes;
   1918     std::vector<SBPrefix> prefix_hits;
   1919     std::vector<SBFullHashResult> cache_hits;
   1920     full_hashes.push_back(kFullHash1_1);
   1921     full_hashes.push_back(kFullHash1_2);
   1922     full_hashes.push_back(kFullHash1_3);
   1923     EXPECT_FALSE(database_->ContainsBrowseUrlHashes(
   1924         full_hashes, &prefix_hits, &cache_hits));
   1925   }
   1926 }
   1927 
   1928 TEST_F(SafeBrowsingDatabaseTest, BrowseFullHashAndPrefixMatching) {
   1929   const SBPrefix kPrefix1 = 1001U;
   1930   const SBFullHash kFullHash1_1 =
   1931       SBFullHashForPrefixAndSuffix(kPrefix1, "\x01");
   1932   const SBFullHash kFullHash1_2 =
   1933       SBFullHashForPrefixAndSuffix(kPrefix1, "\x02");
   1934 
   1935   ScopedVector<SBChunkData> chunks;
   1936   chunks.push_back(AddChunkFullHash(1, kFullHash1_1));
   1937 
   1938   std::vector<SBListChunkRanges> lists;
   1939   ASSERT_TRUE(database_->UpdateStarted(&lists));
   1940   database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
   1941   database_->UpdateFinished(true);
   1942 
   1943   {
   1944     // kFullHash1_2 does not match kFullHash1_1.
   1945     std::vector<SBFullHash> full_hashes(1, kFullHash1_2);
   1946     std::vector<SBPrefix> prefix_hits;
   1947     std::vector<SBFullHashResult> cache_hits;
   1948     EXPECT_FALSE(database_->ContainsBrowseUrlHashes(
   1949         full_hashes, &prefix_hits, &cache_hits));
   1950   }
   1951 
   1952   // Add a prefix match.
   1953   chunks.clear();
   1954   chunks.push_back(AddChunkPrefix(2, kPrefix1));
   1955 
   1956   ASSERT_TRUE(database_->UpdateStarted(&lists));
   1957   database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
   1958   database_->UpdateFinished(true);
   1959 
   1960   {
   1961     // kFullHash1_2 does match kPrefix1.
   1962     std::vector<SBFullHash> full_hashes(1, kFullHash1_2);
   1963     std::vector<SBPrefix> prefix_hits;
   1964     std::vector<SBFullHashResult> cache_hits;
   1965     EXPECT_TRUE(database_->ContainsBrowseUrlHashes(
   1966         full_hashes, &prefix_hits, &cache_hits));
   1967     ASSERT_EQ(1U, prefix_hits.size());
   1968     EXPECT_EQ(kPrefix1, prefix_hits[0]);
   1969     EXPECT_TRUE(cache_hits.empty());
   1970   }
   1971 
   1972   // Remove the full hash.
   1973   chunks.clear();
   1974   chunks.push_back(SubChunkFullHash(11, kFullHash1_1, 1));
   1975 
   1976   ASSERT_TRUE(database_->UpdateStarted(&lists));
   1977   database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
   1978   database_->UpdateFinished(true);
   1979 
   1980   {
   1981     // kFullHash1_2 still returns true due to the prefix hit.
   1982     std::vector<SBFullHash> full_hashes(1, kFullHash1_2);
   1983     std::vector<SBPrefix> prefix_hits;
   1984     std::vector<SBFullHashResult> cache_hits;
   1985     EXPECT_TRUE(database_->ContainsBrowseUrlHashes(
   1986         full_hashes, &prefix_hits, &cache_hits));
   1987     ASSERT_EQ(1U, prefix_hits.size());
   1988     EXPECT_EQ(kPrefix1, prefix_hits[0]);
   1989     EXPECT_TRUE(cache_hits.empty());
   1990   }
   1991 }
   1992 
   1993 TEST_F(SafeBrowsingDatabaseTest, MalwareIpBlacklist) {
   1994   database_.reset();
   1995   SafeBrowsingStoreFile* browse_store = new SafeBrowsingStoreFile();
   1996   SafeBrowsingStoreFile* ip_blacklist_store = new SafeBrowsingStoreFile();
   1997   database_.reset(new SafeBrowsingDatabaseNew(browse_store,
   1998                                               NULL,
   1999                                               NULL,
   2000                                               NULL,
   2001                                               NULL,
   2002                                               NULL,
   2003                                               ip_blacklist_store));
   2004   database_->Init(database_filename_);
   2005   std::vector<SBListChunkRanges> lists;
   2006   ASSERT_TRUE(database_->UpdateStarted(&lists));
   2007 
   2008   ScopedVector<SBChunkData> chunks;
   2009 
   2010   // IPv4 prefix match for ::ffff:192.168.1.0/120.
   2011   chunks.push_back(AddChunkHashedIpValue(1, "::ffff:192.168.1.0", 120));
   2012 
   2013   // IPv4 exact match for ::ffff:192.1.1.1.
   2014   chunks.push_back(AddChunkHashedIpValue(2, "::ffff:192.1.1.1", 128));
   2015 
   2016   // IPv6 exact match for: fe80::31a:a0ff:fe10:786e/128.
   2017   chunks.push_back(AddChunkHashedIpValue(3, "fe80::31a:a0ff:fe10:786e", 128));
   2018 
   2019   // IPv6 prefix match for: 2620:0:1000:3103::/64.
   2020   chunks.push_back(AddChunkHashedIpValue(4, "2620:0:1000:3103::", 64));
   2021 
   2022   // IPv4 prefix match for ::ffff:192.1.122.0/119.
   2023   chunks.push_back(AddChunkHashedIpValue(5, "::ffff:192.1.122.0", 119));
   2024 
   2025   // IPv4 prefix match for ::ffff:192.1.128.0/113.
   2026   chunks.push_back(AddChunkHashedIpValue(6, "::ffff:192.1.128.0", 113));
   2027 
   2028   database_->InsertChunks(safe_browsing_util::kIPBlacklist, chunks.get());
   2029   database_->UpdateFinished(true);
   2030 
   2031   EXPECT_FALSE(database_->ContainsMalwareIP("192.168.0.255"));
   2032   EXPECT_TRUE(database_->ContainsMalwareIP("192.168.1.0"));
   2033   EXPECT_TRUE(database_->ContainsMalwareIP("192.168.1.255"));
   2034   EXPECT_TRUE(database_->ContainsMalwareIP("192.168.1.10"));
   2035   EXPECT_TRUE(database_->ContainsMalwareIP("::ffff:192.168.1.2"));
   2036   EXPECT_FALSE(database_->ContainsMalwareIP("192.168.2.0"));
   2037 
   2038   EXPECT_FALSE(database_->ContainsMalwareIP("192.1.1.0"));
   2039   EXPECT_TRUE(database_->ContainsMalwareIP("192.1.1.1"));
   2040   EXPECT_FALSE(database_->ContainsMalwareIP("192.1.1.2"));
   2041 
   2042   EXPECT_FALSE(database_->ContainsMalwareIP(
   2043       "2620:0:1000:3102:ffff:ffff:ffff:ffff"));
   2044   EXPECT_TRUE(database_->ContainsMalwareIP("2620:0:1000:3103::"));
   2045   EXPECT_TRUE(database_->ContainsMalwareIP(
   2046       "2620:0:1000:3103:ffff:ffff:ffff:ffff"));
   2047   EXPECT_FALSE(database_->ContainsMalwareIP("2620:0:1000:3104::"));
   2048 
   2049   EXPECT_FALSE(database_->ContainsMalwareIP("fe80::21a:a0ff:fe10:786d"));
   2050   EXPECT_TRUE(database_->ContainsMalwareIP("fe80::31a:a0ff:fe10:786e"));
   2051   EXPECT_FALSE(database_->ContainsMalwareIP("fe80::21a:a0ff:fe10:786f"));
   2052 
   2053   EXPECT_FALSE(database_->ContainsMalwareIP("192.1.121.255"));
   2054   EXPECT_TRUE(database_->ContainsMalwareIP("192.1.122.0"));
   2055   EXPECT_TRUE(database_->ContainsMalwareIP("::ffff:192.1.122.1"));
   2056   EXPECT_TRUE(database_->ContainsMalwareIP("192.1.122.255"));
   2057   EXPECT_TRUE(database_->ContainsMalwareIP("192.1.123.0"));
   2058   EXPECT_TRUE(database_->ContainsMalwareIP("192.1.123.255"));
   2059   EXPECT_FALSE(database_->ContainsMalwareIP("192.1.124.0"));
   2060 
   2061   EXPECT_FALSE(database_->ContainsMalwareIP("192.1.127.255"));
   2062   EXPECT_TRUE(database_->ContainsMalwareIP("192.1.128.0"));
   2063   EXPECT_TRUE(database_->ContainsMalwareIP("::ffff:192.1.128.1"));
   2064   EXPECT_TRUE(database_->ContainsMalwareIP("192.1.128.255"));
   2065   EXPECT_TRUE(database_->ContainsMalwareIP("192.1.255.0"));
   2066   EXPECT_TRUE(database_->ContainsMalwareIP("192.1.255.255"));
   2067   EXPECT_FALSE(database_->ContainsMalwareIP("192.2.0.0"));
   2068 }
   2069 
   2070 TEST_F(SafeBrowsingDatabaseTest, ContainsBrowseURL) {
   2071   std::vector<SBListChunkRanges> lists;
   2072   ASSERT_TRUE(database_->UpdateStarted(&lists));
   2073 
   2074   // Add a host-level hit.
   2075   {
   2076     ScopedVector<SBChunkData> chunks;
   2077     chunks.push_back(AddChunkPrefixValue(1, "www.evil.com/"));
   2078     database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
   2079   }
   2080 
   2081   // Add a specific fullhash.
   2082   static const char kWhateverMalware[] = "www.whatever.com/malware.html";
   2083   {
   2084     ScopedVector<SBChunkData> chunks;
   2085     chunks.push_back(AddChunkFullHashValue(2, kWhateverMalware));
   2086     database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
   2087   }
   2088 
   2089   // Add a fullhash which has a prefix collision for a known url.
   2090   static const char kExampleFine[] = "www.example.com/fine.html";
   2091   static const char kExampleCollision[] =
   2092       "www.example.com/3123364814/malware.htm";
   2093   ASSERT_EQ(SBPrefixForString(kExampleFine),
   2094             SBPrefixForString(kExampleCollision));
   2095   {
   2096     ScopedVector<SBChunkData> chunks;
   2097     chunks.push_back(AddChunkFullHashValue(3, kExampleCollision));
   2098     database_->InsertChunks(safe_browsing_util::kMalwareList, chunks.get());
   2099   }
   2100 
   2101   database_->UpdateFinished(true);
   2102 
   2103   std::vector<SBPrefix> prefix_hits;
   2104   std::vector<SBFullHashResult> cache_hits;
   2105 
   2106   // Anything will hit the host prefix.
   2107   EXPECT_TRUE(database_->ContainsBrowseUrl(
   2108       GURL("http://www.evil.com/malware.html"), &prefix_hits, &cache_hits));
   2109   ASSERT_EQ(1U, prefix_hits.size());
   2110   EXPECT_EQ(SBPrefixForString("www.evil.com/"), prefix_hits[0]);
   2111   EXPECT_TRUE(cache_hits.empty());
   2112 
   2113   // Hit the specific URL prefix.
   2114   EXPECT_TRUE(database_->ContainsBrowseUrl(
   2115       GURL(std::string("http://") + kWhateverMalware),
   2116       &prefix_hits, &cache_hits));
   2117   ASSERT_EQ(1U, prefix_hits.size());
   2118   EXPECT_EQ(SBPrefixForString(kWhateverMalware), prefix_hits[0]);
   2119   EXPECT_TRUE(cache_hits.empty());
   2120 
   2121   // Other URLs at that host are fine.
   2122   EXPECT_FALSE(database_->ContainsBrowseUrl(
   2123       GURL("http://www.whatever.com/fine.html"), &prefix_hits, &cache_hits));
   2124   EXPECT_TRUE(prefix_hits.empty());
   2125   EXPECT_TRUE(cache_hits.empty());
   2126 
   2127   // Hit the specific URL full hash.
   2128   EXPECT_TRUE(database_->ContainsBrowseUrl(
   2129       GURL(std::string("http://") + kExampleCollision),
   2130       &prefix_hits, &cache_hits));
   2131   ASSERT_EQ(1U, prefix_hits.size());
   2132   EXPECT_EQ(SBPrefixForString(kExampleCollision), prefix_hits[0]);
   2133   EXPECT_TRUE(cache_hits.empty());
   2134 
   2135   // This prefix collides, but no full hash match.
   2136   EXPECT_FALSE(database_->ContainsBrowseUrl(
   2137       GURL(std::string("http://") + kExampleFine), &prefix_hits, &cache_hits));
   2138 }
   2139