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.
5 // Unit tests for the SafeBrowsing storage system.
7 #include "chrome/browser/safe_browsing/safe_browsing_database.h"
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/test/test_simple_task_runner.h"
18 #include "base/time/time.h"
19 #include "chrome/browser/safe_browsing/chunk.pb.h"
20 #include "chrome/browser/safe_browsing/safe_browsing_store_file.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"
30 using base::TimeDelta
;
34 const TimeDelta kCacheLifetime
= TimeDelta::FromMinutes(45);
36 SBPrefix
SBPrefixForString(const std::string
& str
) {
37 return SBFullHashForString(str
).prefix
;
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
) {
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());
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
);
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
]);
80 return new SBChunkData(raw_data
.release());
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
),
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
));
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
),
105 return BuildChunk(chunk_number
, safe_browsing::ChunkData::ADD
,
106 safe_browsing::ChunkData::PREFIX_4B
,
107 &prefixes
[0], sizeof(prefixes
),
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
),
123 return BuildChunk(chunk_number
, safe_browsing::ChunkData::ADD
,
124 safe_browsing::ChunkData::PREFIX_4B
,
125 &prefixes
[0], sizeof(prefixes
),
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
),
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
));
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
),
151 return BuildChunk(chunk_number
, safe_browsing::ChunkData::ADD
,
152 safe_browsing::ChunkData::FULL_32B
,
153 &full_hashes
[0], sizeof(full_hashes
),
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
));
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
),
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
),
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
));
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
),
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
),
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
{
225 ScopedLogMessageIgnorer() {
226 logging::SetLogMessageHandler(&LogMessageIgnorer
);
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
);
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
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());
255 class SafeBrowsingDatabaseTest
: public PlatformTest
{
257 SafeBrowsingDatabaseTest() : task_runner_(new base::TestSimpleTaskRunner
) {}
259 void SetUp() override
{
260 PlatformTest::SetUp();
262 // Setup a database in a temporary directory.
263 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
265 temp_dir_
.path().AppendASCII("SafeBrowsingTestDatabase");
267 ResetAndReloadFullDatabase();
270 void TearDown() override
{
273 PlatformTest::TearDown();
276 // Reloads the |database_| in a new SafeBrowsingDatabaseNew object with all
278 void ResetAndReloadFullDatabase() {
279 SafeBrowsingStoreFile
* browse_store
=
280 new SafeBrowsingStoreFile(task_runner_
);
281 SafeBrowsingStoreFile
* download_store
=
282 new SafeBrowsingStoreFile(task_runner_
);
283 SafeBrowsingStoreFile
* csd_whitelist_store
=
284 new SafeBrowsingStoreFile(task_runner_
);
285 SafeBrowsingStoreFile
* download_whitelist_store
=
286 new SafeBrowsingStoreFile(task_runner_
);
287 SafeBrowsingStoreFile
* inclusion_whitelist_store
=
288 new SafeBrowsingStoreFile(task_runner_
);
289 SafeBrowsingStoreFile
* extension_blacklist_store
=
290 new SafeBrowsingStoreFile(task_runner_
);
291 SafeBrowsingStoreFile
* side_effect_free_whitelist_store
=
292 new SafeBrowsingStoreFile(task_runner_
);
293 SafeBrowsingStoreFile
* ip_blacklist_store
=
294 new SafeBrowsingStoreFile(task_runner_
);
295 SafeBrowsingStoreFile
* unwanted_software_store
=
296 new SafeBrowsingStoreFile(task_runner_
);
297 database_
.reset(new SafeBrowsingDatabaseNew(
298 task_runner_
, browse_store
, download_store
, csd_whitelist_store
,
299 download_whitelist_store
, inclusion_whitelist_store
,
300 extension_blacklist_store
, side_effect_free_whitelist_store
,
301 ip_blacklist_store
, unwanted_software_store
));
302 database_
->Init(database_filename_
);
305 bool ContainsDownloadUrl(const std::vector
<GURL
>& urls
,
306 std::vector
<SBPrefix
>* prefix_hits
) {
307 std::vector
<SBPrefix
> prefixes
;
308 SafeBrowsingDatabase::GetDownloadUrlPrefixes(urls
, &prefixes
);
309 return database_
->ContainsDownloadUrlPrefixes(prefixes
, prefix_hits
);
312 void GetListsInfo(std::vector
<SBListChunkRanges
>* lists
) {
314 ASSERT_TRUE(database_
->UpdateStarted(lists
));
315 database_
->UpdateFinished(true);
318 // Helper function to do an AddDel or SubDel command.
319 void DelChunk(const std::string
& list
,
322 std::vector
<SBChunkDelete
> deletes
;
323 SBChunkDelete chunk_delete
;
324 chunk_delete
.list_name
= list
;
325 chunk_delete
.is_sub_del
= is_sub_del
;
326 chunk_delete
.chunk_del
.push_back(ChunkRange(chunk_id
));
327 deletes
.push_back(chunk_delete
);
328 database_
->DeleteChunks(deletes
);
331 void AddDelChunk(const std::string
& list
, int chunk_id
) {
332 DelChunk(list
, chunk_id
, false);
335 void SubDelChunk(const std::string
& list
, int chunk_id
) {
336 DelChunk(list
, chunk_id
, true);
339 // Utility function for setting up the database for the caching test.
340 void PopulateDatabaseForCacheTest();
342 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner_
;
343 scoped_ptr
<SafeBrowsingDatabaseNew
> database_
;
344 base::FilePath database_filename_
;
345 base::ScopedTempDir temp_dir_
;
348 // Tests retrieving list name information.
349 TEST_F(SafeBrowsingDatabaseTest
, BrowseListsInfo
) {
350 std::vector
<SBListChunkRanges
> lists
;
351 ScopedVector
<SBChunkData
> chunks
;
353 chunks
.push_back(AddChunkPrefixValue(1, "www.evil.com/malware.html"));
354 chunks
.push_back(AddChunkPrefixValue(2, "www.foo.com/malware.html"));
355 chunks
.push_back(AddChunkPrefixValue(3, "www.whatever.com/malware.html"));
357 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
358 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
359 database_
->UpdateFinished(true);
361 GetListsInfo(&lists
);
362 ASSERT_LE(1U, lists
.size());
363 EXPECT_EQ(safe_browsing_util::kMalwareList
, lists
[0].name
);
364 EXPECT_EQ("1-3", lists
[0].adds
);
365 EXPECT_TRUE(lists
[0].subs
.empty());
367 // Insert a malware sub chunk.
369 chunks
.push_back(SubChunkPrefixValue(7, "www.subbed.com/noteveil1.html", 19));
371 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
372 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
373 database_
->UpdateFinished(true);
375 GetListsInfo(&lists
);
376 ASSERT_LE(1U, lists
.size());
377 EXPECT_EQ(safe_browsing_util::kMalwareList
, lists
[0].name
);
378 EXPECT_EQ("1-3", lists
[0].adds
);
379 EXPECT_EQ("7", lists
[0].subs
);
380 if (lists
.size() == 2) {
381 // Old style database won't have the second entry since it creates the lists
382 // when it receives an update containing that list. The filter-based
383 // database has these values hard coded.
384 EXPECT_EQ(safe_browsing_util::kPhishingList
, lists
[1].name
);
385 EXPECT_TRUE(lists
[1].adds
.empty());
386 EXPECT_TRUE(lists
[1].subs
.empty());
389 // Add phishing chunks.
391 chunks
.push_back(AddChunkPrefixValue(47, "www.evil.com/phishing.html"));
393 SubChunkPrefixValue(200, "www.phishy.com/notevil1.html", 1999));
395 SubChunkPrefixValue(201, "www.phishy2.com/notevil1.html", 1999));
397 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
398 database_
->InsertChunks(safe_browsing_util::kPhishingList
, chunks
.get());
399 database_
->UpdateFinished(true);
401 GetListsInfo(&lists
);
402 ASSERT_LE(2U, lists
.size());
403 EXPECT_EQ(safe_browsing_util::kMalwareList
, lists
[0].name
);
404 EXPECT_EQ("1-3", lists
[0].adds
);
405 EXPECT_EQ("7", lists
[0].subs
);
406 EXPECT_EQ(safe_browsing_util::kPhishingList
, lists
[1].name
);
407 EXPECT_EQ("47", lists
[1].adds
);
408 EXPECT_EQ("200-201", lists
[1].subs
);
411 TEST_F(SafeBrowsingDatabaseTest
, ListNames
) {
412 ScopedVector
<SBChunkData
> chunks
;
414 std::vector
<SBListChunkRanges
> lists
;
415 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
417 // Insert malware, phish, binurl and bindownload add chunks.
418 chunks
.push_back(AddChunkPrefixValue(1, "www.evil.com/malware.html"));
419 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
422 chunks
.push_back(AddChunkPrefixValue(2, "www.foo.com/malware.html"));
423 database_
->InsertChunks(safe_browsing_util::kPhishingList
, chunks
.get());
426 chunks
.push_back(AddChunkPrefixValue(3, "www.whatever.com/download.html"));
427 database_
->InsertChunks(safe_browsing_util::kBinUrlList
, chunks
.get());
430 chunks
.push_back(AddChunkFullHashValue(5, "www.forwhitelist.com/a.html"));
431 database_
->InsertChunks(safe_browsing_util::kCsdWhiteList
, chunks
.get());
434 chunks
.push_back(AddChunkFullHashValue(6, "www.download.com/"));
435 database_
->InsertChunks(safe_browsing_util::kDownloadWhiteList
, chunks
.get());
438 chunks
.push_back(AddChunkFullHashValue(7, "www.inclusion.com/"));
439 database_
->InsertChunks(safe_browsing_util::kInclusionWhitelist
,
443 chunks
.push_back(AddChunkFullHashValue(8,
444 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
445 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
446 database_
->InsertChunks(safe_browsing_util::kExtensionBlacklist
,
450 chunks
.push_back(AddChunkFullHashValue(9, "www.sideeffectfree.com"));
451 database_
->InsertChunks(safe_browsing_util::kSideEffectFreeWhitelist
,
455 chunks
.push_back(AddChunkHashedIpValue(10, "::ffff:192.168.1.0", 120));
456 database_
->InsertChunks(safe_browsing_util::kIPBlacklist
, chunks
.get());
459 chunks
.push_back(AddChunkPrefixValue(11, "www.unwanted.com/software.html"));
460 database_
->InsertChunks(safe_browsing_util::kUnwantedUrlList
, chunks
.get());
462 database_
->UpdateFinished(true);
464 GetListsInfo(&lists
);
465 ASSERT_EQ(10U, lists
.size());
466 EXPECT_EQ(safe_browsing_util::kMalwareList
, lists
[0].name
);
467 EXPECT_EQ("1", lists
[0].adds
);
468 EXPECT_TRUE(lists
[0].subs
.empty());
469 EXPECT_EQ(safe_browsing_util::kPhishingList
, lists
[1].name
);
470 EXPECT_EQ("2", lists
[1].adds
);
471 EXPECT_TRUE(lists
[1].subs
.empty());
472 EXPECT_EQ(safe_browsing_util::kBinUrlList
, lists
[2].name
);
473 EXPECT_EQ("3", lists
[2].adds
);
474 EXPECT_TRUE(lists
[2].subs
.empty());
475 EXPECT_EQ(safe_browsing_util::kCsdWhiteList
, lists
[3].name
);
476 EXPECT_EQ("5", lists
[3].adds
);
477 EXPECT_TRUE(lists
[3].subs
.empty());
478 EXPECT_EQ(safe_browsing_util::kDownloadWhiteList
, lists
[4].name
);
479 EXPECT_EQ("6", lists
[4].adds
);
480 EXPECT_TRUE(lists
[4].subs
.empty());
481 EXPECT_EQ(safe_browsing_util::kInclusionWhitelist
, lists
[5].name
);
482 EXPECT_EQ("7", lists
[5].adds
);
483 EXPECT_TRUE(lists
[5].subs
.empty());
484 EXPECT_EQ(safe_browsing_util::kExtensionBlacklist
, lists
[6].name
);
485 EXPECT_EQ("8", lists
[6].adds
);
486 EXPECT_TRUE(lists
[6].subs
.empty());
487 EXPECT_EQ(safe_browsing_util::kSideEffectFreeWhitelist
, lists
[7].name
);
488 EXPECT_EQ("9", lists
[7].adds
);
489 EXPECT_TRUE(lists
[7].subs
.empty());
490 EXPECT_EQ(safe_browsing_util::kIPBlacklist
, lists
[8].name
);
491 EXPECT_EQ("10", lists
[8].adds
);
492 EXPECT_TRUE(lists
[8].subs
.empty());
493 EXPECT_EQ(safe_browsing_util::kUnwantedUrlList
, lists
[9].name
);
494 EXPECT_EQ("11", lists
[9].adds
);
495 EXPECT_TRUE(lists
[9].subs
.empty());
500 // Checks database reading and writing for browse and unwanted PrefixSets.
501 TEST_F(SafeBrowsingDatabaseTest
, BrowseAndUnwantedDatabasesAndPrefixSets
) {
503 using TestListContainsBadUrl
= bool (SafeBrowsingDatabase::*)(
505 std::vector
<SBPrefix
>* prefix_hits
,
506 std::vector
<SBFullHashResult
>* cache_hits
);
508 const char* test_list_name
;
509 size_t expected_list_index
;
510 TestListContainsBadUrl test_list_contains_bad_url
;
511 } const kTestCases
[] {
512 { safe_browsing_util::kMalwareList
, 0U,
513 &SafeBrowsingDatabase::ContainsBrowseUrl
},
514 { safe_browsing_util::kPhishingList
, 1U,
515 &SafeBrowsingDatabase::ContainsBrowseUrl
},
516 { safe_browsing_util::kUnwantedUrlList
, 9U,
517 &SafeBrowsingDatabase::ContainsUnwantedSoftwareUrl
},
520 for (const auto& test_case
: kTestCases
) {
521 SCOPED_TRACE(std::string("Tested list at fault => ") +
522 test_case
.test_list_name
);
524 std::vector
<SBListChunkRanges
> lists
;
525 ScopedVector
<SBChunkData
> chunks
;
527 chunks
.push_back(AddChunkPrefix2Value(1,
528 "www.evil.com/phishing.html",
529 "www.evil.com/malware.html"));
530 chunks
.push_back(AddChunkPrefix4Value(2,
531 "www.evil.com/notevil1.html",
532 "www.evil.com/notevil2.html",
533 "www.good.com/good1.html",
534 "www.good.com/good2.html"));
535 chunks
.push_back(AddChunkPrefixValue(3, "192.168.0.1/malware.html"));
536 chunks
.push_back(AddChunkFullHashValue(7, "www.evil.com/evil.html"));
538 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
539 database_
->InsertChunks(test_case
.test_list_name
, chunks
.get());
540 database_
->UpdateFinished(true);
542 // Make sure they were added correctly.
543 GetListsInfo(&lists
);
545 ASSERT_LE(1U, lists
.size());
546 EXPECT_EQ(test_case
.test_list_name
,
547 lists
[test_case
.expected_list_index
].name
);
548 EXPECT_EQ("1-3,7", lists
[test_case
.expected_list_index
].adds
);
549 EXPECT_TRUE(lists
[test_case
.expected_list_index
].subs
.empty());
551 std::vector
<SBPrefix
> prefix_hits
;
552 std::vector
<SBFullHashResult
> cache_hits
;
553 EXPECT_TRUE((database_
.get()->*test_case
.test_list_contains_bad_url
)(
554 GURL("http://www.evil.com/phishing.html"), &prefix_hits
, &cache_hits
));
555 ASSERT_EQ(1U, prefix_hits
.size());
556 EXPECT_EQ(SBPrefixForString("www.evil.com/phishing.html"), prefix_hits
[0]);
557 EXPECT_TRUE(cache_hits
.empty());
559 EXPECT_TRUE((database_
.get()->*test_case
.test_list_contains_bad_url
)(
560 GURL("http://www.evil.com/malware.html"), &prefix_hits
, &cache_hits
));
562 EXPECT_TRUE((database_
.get()->*test_case
.test_list_contains_bad_url
)(
563 GURL("http://www.evil.com/notevil1.html"), &prefix_hits
, &cache_hits
));
565 EXPECT_TRUE((database_
.get()->*test_case
.test_list_contains_bad_url
)(
566 GURL("http://www.evil.com/notevil2.html"), &prefix_hits
, &cache_hits
));
568 EXPECT_TRUE((database_
.get()->*test_case
.test_list_contains_bad_url
)(
569 GURL("http://www.good.com/good1.html"), &prefix_hits
, &cache_hits
));
571 EXPECT_TRUE((database_
.get()->*test_case
.test_list_contains_bad_url
)(
572 GURL("http://www.good.com/good2.html"), &prefix_hits
, &cache_hits
));
574 EXPECT_TRUE((database_
.get()->*test_case
.test_list_contains_bad_url
)(
575 GURL("http://192.168.0.1/malware.html"), &prefix_hits
, &cache_hits
));
577 EXPECT_FALSE((database_
.get()->*test_case
.test_list_contains_bad_url
)(
578 GURL("http://www.evil.com/"), &prefix_hits
, &cache_hits
));
579 EXPECT_TRUE(prefix_hits
.empty());
580 EXPECT_TRUE(cache_hits
.empty());
582 EXPECT_FALSE((database_
.get()->*test_case
.test_list_contains_bad_url
)(
583 GURL("http://www.evil.com/robots.txt"), &prefix_hits
, &cache_hits
));
585 EXPECT_TRUE((database_
.get()->*test_case
.test_list_contains_bad_url
)(
586 GURL("http://www.evil.com/evil.html"), &prefix_hits
, &cache_hits
));
587 ASSERT_EQ(1U, prefix_hits
.size());
588 EXPECT_EQ(SBPrefixForString("www.evil.com/evil.html"), prefix_hits
[0]);
590 // Attempt to re-add the first chunk (should be a no-op).
591 // see bug: http://code.google.com/p/chromium/issues/detail?id=4522
593 chunks
.push_back(AddChunkPrefix2Value(1,
594 "www.evil.com/phishing.html",
595 "www.evil.com/malware.html"));
596 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
597 database_
->InsertChunks(test_case
.test_list_name
, chunks
.get());
598 database_
->UpdateFinished(true);
600 GetListsInfo(&lists
);
601 ASSERT_LE(1U, lists
.size());
602 EXPECT_EQ(test_case
.test_list_name
,
603 lists
[test_case
.expected_list_index
].name
);
604 EXPECT_EQ("1-3,7", lists
[test_case
.expected_list_index
].adds
);
605 EXPECT_TRUE(lists
[test_case
.expected_list_index
].subs
.empty());
607 // Test removing a single prefix from the add chunk.
609 chunks
.push_back(SubChunkPrefixValue(4, "www.evil.com/notevil1.html", 2));
610 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
611 database_
->InsertChunks(test_case
.test_list_name
, chunks
.get());
612 database_
->UpdateFinished(true);
614 EXPECT_TRUE((database_
.get()->*test_case
.test_list_contains_bad_url
)(
615 GURL("http://www.evil.com/phishing.html"), &prefix_hits
, &cache_hits
));
616 ASSERT_EQ(1U, prefix_hits
.size());
617 EXPECT_EQ(SBPrefixForString("www.evil.com/phishing.html"), prefix_hits
[0]);
618 EXPECT_TRUE(cache_hits
.empty());
620 EXPECT_FALSE((database_
.get()->*test_case
.test_list_contains_bad_url
)(
621 GURL("http://www.evil.com/notevil1.html"), &prefix_hits
, &cache_hits
));
622 EXPECT_TRUE(prefix_hits
.empty());
623 EXPECT_TRUE(cache_hits
.empty());
625 EXPECT_TRUE((database_
.get()->*test_case
.test_list_contains_bad_url
)(
626 GURL("http://www.evil.com/notevil2.html"), &prefix_hits
, &cache_hits
));
628 EXPECT_TRUE((database_
.get()->*test_case
.test_list_contains_bad_url
)(
629 GURL("http://www.good.com/good1.html"), &prefix_hits
, &cache_hits
));
631 EXPECT_TRUE((database_
.get()->*test_case
.test_list_contains_bad_url
)(
632 GURL("http://www.good.com/good2.html"), &prefix_hits
, &cache_hits
));
634 GetListsInfo(&lists
);
635 ASSERT_LE(1U, lists
.size());
636 EXPECT_EQ(test_case
.test_list_name
,
637 lists
[test_case
.expected_list_index
].name
);
638 EXPECT_EQ("1-3,7", lists
[test_case
.expected_list_index
].adds
);
639 EXPECT_EQ("4", lists
[test_case
.expected_list_index
].subs
);
641 // Test the same sub chunk again. This should be a no-op.
642 // see bug: http://code.google.com/p/chromium/issues/detail?id=4522
644 chunks
.push_back(SubChunkPrefixValue(4, "www.evil.com/notevil1.html", 2));
646 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
647 database_
->InsertChunks(test_case
.test_list_name
, chunks
.get());
648 database_
->UpdateFinished(true);
650 GetListsInfo(&lists
);
651 ASSERT_LE(1U, lists
.size());
652 EXPECT_EQ(test_case
.test_list_name
,
653 lists
[test_case
.expected_list_index
].name
);
654 EXPECT_EQ("1-3,7", lists
[test_case
.expected_list_index
].adds
);
655 EXPECT_EQ("4", lists
[test_case
.expected_list_index
].subs
);
657 // Test removing all the prefixes from an add chunk.
658 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
659 AddDelChunk(test_case
.test_list_name
, 2);
660 database_
->UpdateFinished(true);
662 EXPECT_FALSE((database_
.get()->*test_case
.test_list_contains_bad_url
)(
663 GURL("http://www.evil.com/notevil2.html"), &prefix_hits
, &cache_hits
));
665 EXPECT_FALSE((database_
.get()->*test_case
.test_list_contains_bad_url
)(
666 GURL("http://www.good.com/good1.html"), &prefix_hits
, &cache_hits
));
668 EXPECT_FALSE((database_
.get()->*test_case
.test_list_contains_bad_url
)(
669 GURL("http://www.good.com/good2.html"), &prefix_hits
, &cache_hits
));
671 GetListsInfo(&lists
);
672 ASSERT_LE(1U, lists
.size());
673 EXPECT_EQ(test_case
.test_list_name
,
674 lists
[test_case
.expected_list_index
].name
);
675 EXPECT_EQ("1,3,7", lists
[test_case
.expected_list_index
].adds
);
676 EXPECT_EQ("4", lists
[test_case
.expected_list_index
].subs
);
678 // The adddel command exposed a bug in the transaction code where any
679 // transaction after it would fail. Add a dummy entry and remove it to
680 // make sure the transcation works fine.
682 chunks
.push_back(AddChunkPrefixValue(44, "www.redherring.com/index.html"));
683 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
684 database_
->InsertChunks(test_case
.test_list_name
, chunks
.get());
686 // Now remove the dummy entry. If there are any problems with the
687 // transactions, asserts will fire.
688 AddDelChunk(test_case
.test_list_name
, 44);
690 // Test the subdel command.
691 SubDelChunk(test_case
.test_list_name
, 4);
692 database_
->UpdateFinished(true);
694 GetListsInfo(&lists
);
695 ASSERT_LE(1U, lists
.size());
696 EXPECT_EQ(test_case
.test_list_name
,
697 lists
[test_case
.expected_list_index
].name
);
698 EXPECT_EQ("1,3,7", lists
[test_case
.expected_list_index
].adds
);
699 EXPECT_TRUE(lists
[test_case
.expected_list_index
].subs
.empty());
701 // Test a sub command coming in before the add.
703 chunks
.push_back(SubChunkPrefix2Value(5,
704 "www.notevilanymore.com/index.html",
706 "www.notevilanymore.com/good.html",
708 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
709 database_
->InsertChunks(test_case
.test_list_name
, chunks
.get());
710 database_
->UpdateFinished(true);
712 EXPECT_FALSE((database_
.get()->*test_case
.test_list_contains_bad_url
)(
713 GURL("http://www.notevilanymore.com/index.html"),
717 // Now insert the tardy add chunk and we don't expect them to appear
718 // in database because of the previous sub chunk.
720 chunks
.push_back(AddChunkPrefix2Value(10,
721 "www.notevilanymore.com/index.html",
722 "www.notevilanymore.com/good.html"));
723 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
724 database_
->InsertChunks(test_case
.test_list_name
, chunks
.get());
725 database_
->UpdateFinished(true);
727 EXPECT_FALSE((database_
.get()->*test_case
.test_list_contains_bad_url
)(
728 GURL("http://www.notevilanymore.com/index.html"),
732 EXPECT_FALSE((database_
.get()->*test_case
.test_list_contains_bad_url
)(
733 GURL("http://www.notevilanymore.com/good.html"),
737 // Reset and reload the database. The database will rely on the prefix set.
738 ResetAndReloadFullDatabase();
740 // Check that a prefix still hits.
741 EXPECT_TRUE((database_
.get()->*test_case
.test_list_contains_bad_url
)(
742 GURL("http://www.evil.com/phishing.html"), &prefix_hits
, &cache_hits
));
743 ASSERT_EQ(1U, prefix_hits
.size());
744 EXPECT_EQ(SBPrefixForString("www.evil.com/phishing.html"), prefix_hits
[0]);
746 // Also check that it's not just always returning true in this case.
747 EXPECT_FALSE((database_
.get()->*test_case
.test_list_contains_bad_url
)(
748 GURL("http://www.evil.com/"), &prefix_hits
, &cache_hits
));
750 // Check that the full hash is still present.
751 EXPECT_TRUE((database_
.get()->*test_case
.test_list_contains_bad_url
)(
752 GURL("http://www.evil.com/evil.html"), &prefix_hits
, &cache_hits
));
753 ASSERT_EQ(1U, prefix_hits
.size());
754 EXPECT_EQ(SBPrefixForString("www.evil.com/evil.html"), prefix_hits
[0]);
758 // Test adding zero length chunks to the database.
759 TEST_F(SafeBrowsingDatabaseTest
, ZeroSizeChunk
) {
760 std::vector
<SBListChunkRanges
> lists
;
761 ScopedVector
<SBChunkData
> chunks
;
763 // Populate with a couple of normal chunks.
764 chunks
.push_back(AddChunkPrefix2Value(1,
765 "www.test.com/test1.html",
766 "www.test.com/test2.html"));
767 chunks
.push_back(AddChunkPrefix2Value(10,
768 "www.random.com/random1.html",
769 "www.random.com/random2.html"));
771 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
772 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
773 database_
->UpdateFinished(true);
775 // Add an empty ADD and SUB chunk.
776 GetListsInfo(&lists
);
777 ASSERT_LE(1U, lists
.size());
778 EXPECT_EQ(safe_browsing_util::kMalwareList
, lists
[0].name
);
779 EXPECT_EQ("1,10", lists
[0].adds
);
780 EXPECT_TRUE(lists
[0].subs
.empty());
783 chunks
.push_back(BuildChunk(19, safe_browsing::ChunkData::ADD
,
784 safe_browsing::ChunkData::PREFIX_4B
,
785 NULL
, 0, std::vector
<int>()));
786 chunks
.push_back(BuildChunk(7, safe_browsing::ChunkData::SUB
,
787 safe_browsing::ChunkData::PREFIX_4B
,
788 NULL
, 0, std::vector
<int>()));
790 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
791 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
792 database_
->UpdateFinished(true);
794 GetListsInfo(&lists
);
795 ASSERT_LE(1U, lists
.size());
796 EXPECT_EQ(safe_browsing_util::kMalwareList
, lists
[0].name
);
797 EXPECT_EQ("1,10,19", lists
[0].adds
);
798 EXPECT_EQ("7", lists
[0].subs
);
800 // Add an empty chunk along with a couple that contain data. This should
801 // result in the chunk range being reduced in size.
803 chunks
.push_back(AddChunkPrefixValue(20, "www.notempty.com/full1.html"));
804 chunks
.push_back(BuildChunk(21, safe_browsing::ChunkData::ADD
,
805 safe_browsing::ChunkData::PREFIX_4B
,
806 NULL
, 0, std::vector
<int>()));
807 chunks
.push_back(AddChunkPrefixValue(22, "www.notempty.com/full2.html"));
809 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
810 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
811 database_
->UpdateFinished(true);
813 std::vector
<SBPrefix
> prefix_hits
;
814 std::vector
<SBFullHashResult
> cache_hits
;
815 EXPECT_TRUE(database_
->ContainsBrowseUrl(
816 GURL("http://www.notempty.com/full1.html"), &prefix_hits
, &cache_hits
));
817 EXPECT_TRUE(database_
->ContainsBrowseUrl(
818 GURL("http://www.notempty.com/full2.html"), &prefix_hits
, &cache_hits
));
820 GetListsInfo(&lists
);
821 ASSERT_LE(1U, lists
.size());
822 EXPECT_EQ(safe_browsing_util::kMalwareList
, lists
[0].name
);
823 EXPECT_EQ("1,10,19-22", lists
[0].adds
);
824 EXPECT_EQ("7", lists
[0].subs
);
826 // Handle AddDel and SubDel commands for empty chunks.
827 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
828 AddDelChunk(safe_browsing_util::kMalwareList
, 21);
829 database_
->UpdateFinished(true);
831 GetListsInfo(&lists
);
832 ASSERT_LE(1U, lists
.size());
833 EXPECT_EQ(safe_browsing_util::kMalwareList
, lists
[0].name
);
834 EXPECT_EQ("1,10,19-20,22", lists
[0].adds
);
835 EXPECT_EQ("7", lists
[0].subs
);
837 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
838 SubDelChunk(safe_browsing_util::kMalwareList
, 7);
839 database_
->UpdateFinished(true);
841 GetListsInfo(&lists
);
842 ASSERT_LE(1U, lists
.size());
843 EXPECT_EQ(safe_browsing_util::kMalwareList
, lists
[0].name
);
844 EXPECT_EQ("1,10,19-20,22", lists
[0].adds
);
845 EXPECT_TRUE(lists
[0].subs
.empty());
848 // Utility function for setting up the database for the caching test.
849 void SafeBrowsingDatabaseTest::PopulateDatabaseForCacheTest() {
850 // Add a couple prefixes.
851 ScopedVector
<SBChunkData
> chunks
;
852 chunks
.push_back(AddChunkPrefix2Value(1,
853 "www.evil.com/phishing.html",
854 "www.evil.com/malware.html"));
856 std::vector
<SBListChunkRanges
> lists
;
857 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
858 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
859 database_
->UpdateFinished(true);
861 // Cache should be cleared after updating.
863 database_
->GetUnsynchronizedPrefixGetHashCacheForTesting()->empty());
865 SBFullHashResult full_hash
;
866 full_hash
.list_id
= safe_browsing_util::MALWARE
;
868 std::vector
<SBFullHashResult
> results
;
869 std::vector
<SBPrefix
> prefixes
;
871 // Add a fullhash result for each prefix.
872 full_hash
.hash
= SBFullHashForString("www.evil.com/phishing.html");
873 results
.push_back(full_hash
);
874 prefixes
.push_back(full_hash
.hash
.prefix
);
876 full_hash
.hash
= SBFullHashForString("www.evil.com/malware.html");
877 results
.push_back(full_hash
);
878 prefixes
.push_back(full_hash
.hash
.prefix
);
880 database_
->CacheHashResults(prefixes
, results
, kCacheLifetime
);
883 TEST_F(SafeBrowsingDatabaseTest
, HashCaching
) {
884 PopulateDatabaseForCacheTest();
886 // We should have both full hashes in the cache.
888 database_
->GetUnsynchronizedPrefixGetHashCacheForTesting()->size());
890 // Test the cache lookup for the first prefix.
891 std::vector
<SBPrefix
> prefix_hits
;
892 std::vector
<SBFullHashResult
> cache_hits
;
893 EXPECT_TRUE(database_
->ContainsBrowseUrl(
894 GURL("http://www.evil.com/phishing.html"), &prefix_hits
, &cache_hits
));
895 EXPECT_TRUE(prefix_hits
.empty());
896 ASSERT_EQ(1U, cache_hits
.size());
897 EXPECT_TRUE(SBFullHashEqual(
898 cache_hits
[0].hash
, SBFullHashForString("www.evil.com/phishing.html")));
903 // Test the cache lookup for the second prefix.
904 EXPECT_TRUE(database_
->ContainsBrowseUrl(
905 GURL("http://www.evil.com/malware.html"), &prefix_hits
, &cache_hits
));
906 EXPECT_TRUE(prefix_hits
.empty());
907 ASSERT_EQ(1U, cache_hits
.size());
908 EXPECT_TRUE(SBFullHashEqual(
909 cache_hits
[0].hash
, SBFullHashForString("www.evil.com/malware.html")));
914 // Test removing a prefix via a sub chunk.
915 ScopedVector
<SBChunkData
> chunks
;
916 chunks
.push_back(SubChunkPrefixValue(2, "www.evil.com/phishing.html", 1));
918 std::vector
<SBListChunkRanges
> lists
;
919 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
920 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
921 database_
->UpdateFinished(true);
923 // This prefix should still be there, but cached fullhash should be gone.
924 EXPECT_TRUE(database_
->ContainsBrowseUrl(
925 GURL("http://www.evil.com/malware.html"), &prefix_hits
, &cache_hits
));
926 ASSERT_EQ(1U, prefix_hits
.size());
927 EXPECT_EQ(SBPrefixForString("www.evil.com/malware.html"), prefix_hits
[0]);
928 EXPECT_TRUE(cache_hits
.empty());
932 // This prefix should be gone.
933 EXPECT_FALSE(database_
->ContainsBrowseUrl(
934 GURL("http://www.evil.com/phishing.html"), &prefix_hits
, &cache_hits
));
938 // Test that an AddDel for the original chunk removes the last cached entry.
939 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
940 AddDelChunk(safe_browsing_util::kMalwareList
, 1);
941 database_
->UpdateFinished(true);
942 EXPECT_FALSE(database_
->ContainsBrowseUrl(
943 GURL("http://www.evil.com/malware.html"), &prefix_hits
, &cache_hits
));
945 database_
->GetUnsynchronizedPrefixGetHashCacheForTesting()->empty());
949 // Test that the cache won't return expired values. First we have to adjust
950 // the cached entries' received time to make them older, since the database
951 // cache insert uses Time::Now(). First, store some entries.
952 PopulateDatabaseForCacheTest();
954 SafeBrowsingDatabaseNew::PrefixGetHashCache
* hash_cache
=
955 database_
->GetUnsynchronizedPrefixGetHashCacheForTesting();
956 EXPECT_EQ(2U, hash_cache
->size());
958 // Now adjust one of the entries times to be in the past.
959 const SBPrefix key
= SBPrefixForString("www.evil.com/malware.html");
960 SafeBrowsingDatabaseNew::PrefixGetHashCache::iterator iter
=
961 hash_cache
->find(key
);
962 ASSERT_TRUE(iter
!= hash_cache
->end());
963 iter
->second
.expire_after
= Time::Now() - TimeDelta::FromMinutes(1);
965 EXPECT_TRUE(database_
->ContainsBrowseUrl(
966 GURL("http://www.evil.com/malware.html"), &prefix_hits
, &cache_hits
));
967 EXPECT_EQ(1U, prefix_hits
.size());
968 EXPECT_TRUE(cache_hits
.empty());
969 // Expired entry should have been removed from cache.
970 EXPECT_EQ(1U, hash_cache
->size());
972 // This entry should still exist.
973 EXPECT_TRUE(database_
->ContainsBrowseUrl(
974 GURL("http://www.evil.com/phishing.html"), &prefix_hits
, &cache_hits
));
975 EXPECT_TRUE(prefix_hits
.empty());
976 EXPECT_EQ(1U, cache_hits
.size());
978 // Testing prefix miss caching. First, we clear out the existing database,
979 // Since PopulateDatabaseForCacheTest() doesn't handle adding duplicate
981 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
982 AddDelChunk(safe_browsing_util::kMalwareList
, 1);
983 database_
->UpdateFinished(true);
985 // Cache should be cleared after updating.
986 EXPECT_TRUE(hash_cache
->empty());
988 std::vector
<SBPrefix
> prefix_misses
;
989 std::vector
<SBFullHashResult
> empty_full_hash
;
990 prefix_misses
.push_back(SBPrefixForString("http://www.bad.com/malware.html"));
991 prefix_misses
.push_back(
992 SBPrefixForString("http://www.bad.com/phishing.html"));
993 database_
->CacheHashResults(prefix_misses
, empty_full_hash
, kCacheLifetime
);
995 // Prefixes with no full results are misses.
996 EXPECT_EQ(hash_cache
->size(), prefix_misses
.size());
998 hash_cache
->count(SBPrefixForString("http://www.bad.com/malware.html")));
1000 hash_cache
->find(SBPrefixForString("http://www.bad.com/malware.html"))
1001 ->second
.full_hashes
.empty());
1003 hash_cache
->count(SBPrefixForString("http://www.bad.com/phishing.html")));
1005 hash_cache
->find(SBPrefixForString("http://www.bad.com/phishing.html"))
1006 ->second
.full_hashes
.empty());
1008 // Update the database.
1009 PopulateDatabaseForCacheTest();
1011 // Cache a GetHash miss for a particular prefix, and even though the prefix is
1012 // in the database, it is flagged as a miss so looking up the associated URL
1013 // will not succeed.
1014 prefix_hits
.clear();
1016 prefix_misses
.clear();
1017 empty_full_hash
.clear();
1018 prefix_misses
.push_back(SBPrefixForString("www.evil.com/phishing.html"));
1019 database_
->CacheHashResults(prefix_misses
, empty_full_hash
, kCacheLifetime
);
1020 EXPECT_FALSE(database_
->ContainsBrowseUrl(
1021 GURL("http://www.evil.com/phishing.html"), &prefix_hits
, &cache_hits
));
1022 prefix_hits
.clear();
1025 // Test receiving a full add chunk.
1027 chunks
.push_back(AddChunkFullHash2Value(20,
1028 "www.fullevil.com/bad1.html",
1029 "www.fullevil.com/bad2.html"));
1030 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1031 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
1032 database_
->UpdateFinished(true);
1034 EXPECT_TRUE(database_
->ContainsBrowseUrl(
1035 GURL("http://www.fullevil.com/bad1.html"), &prefix_hits
, &cache_hits
));
1036 ASSERT_EQ(1U, prefix_hits
.size());
1037 EXPECT_EQ(SBPrefixForString("www.fullevil.com/bad1.html"), prefix_hits
[0]);
1038 EXPECT_TRUE(cache_hits
.empty());
1039 prefix_hits
.clear();
1042 EXPECT_TRUE(database_
->ContainsBrowseUrl(
1043 GURL("http://www.fullevil.com/bad2.html"), &prefix_hits
, &cache_hits
));
1044 ASSERT_EQ(1U, prefix_hits
.size());
1045 EXPECT_EQ(SBPrefixForString("www.fullevil.com/bad2.html"), prefix_hits
[0]);
1046 EXPECT_TRUE(cache_hits
.empty());
1047 prefix_hits
.clear();
1050 // Test receiving a full sub chunk, which will remove one of the full adds.
1052 chunks
.push_back(SubChunkFullHashValue(200,
1053 "www.fullevil.com/bad1.html",
1055 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1056 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
1057 database_
->UpdateFinished(true);
1059 EXPECT_FALSE(database_
->ContainsBrowseUrl(
1060 GURL("http://www.fullevil.com/bad1.html"), &prefix_hits
, &cache_hits
));
1062 // There should be one remaining full add.
1063 EXPECT_TRUE(database_
->ContainsBrowseUrl(
1064 GURL("http://www.fullevil.com/bad2.html"), &prefix_hits
, &cache_hits
));
1065 ASSERT_EQ(1U, prefix_hits
.size());
1066 EXPECT_EQ(SBPrefixForString("www.fullevil.com/bad2.html"), prefix_hits
[0]);
1067 EXPECT_TRUE(cache_hits
.empty());
1068 prefix_hits
.clear();
1071 // Now test an AddDel for the remaining full add.
1072 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1073 AddDelChunk(safe_browsing_util::kMalwareList
, 20);
1074 database_
->UpdateFinished(true);
1076 EXPECT_FALSE(database_
->ContainsBrowseUrl(
1077 GURL("http://www.fullevil.com/bad1.html"), &prefix_hits
, &cache_hits
));
1078 EXPECT_FALSE(database_
->ContainsBrowseUrl(
1079 GURL("http://www.fullevil.com/bad2.html"), &prefix_hits
, &cache_hits
));
1081 // Add a fullhash which has a prefix collision for a known url.
1082 static const char kExampleFine
[] = "www.example.com/fine.html";
1083 static const char kExampleCollision
[] =
1084 "www.example.com/3123364814/malware.htm";
1085 ASSERT_EQ(SBPrefixForString(kExampleFine
),
1086 SBPrefixForString(kExampleCollision
));
1087 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1089 ScopedVector
<SBChunkData
> chunks
;
1090 chunks
.push_back(AddChunkPrefixValue(21, kExampleCollision
));
1091 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
1093 database_
->UpdateFinished(true);
1095 // Expect a prefix hit due to the collision between |kExampleFine| and
1096 // |kExampleCollision|.
1097 EXPECT_TRUE(database_
->ContainsBrowseUrl(
1098 GURL(std::string("http://") + kExampleFine
), &prefix_hits
, &cache_hits
));
1099 ASSERT_EQ(1U, prefix_hits
.size());
1100 EXPECT_EQ(SBPrefixForString(kExampleFine
), prefix_hits
[0]);
1101 EXPECT_TRUE(cache_hits
.empty());
1103 // Cache gethash response for |kExampleCollision|.
1105 SBFullHashResult result
;
1106 result
.hash
= SBFullHashForString(kExampleCollision
);
1107 result
.list_id
= safe_browsing_util::MALWARE
;
1108 database_
->CacheHashResults(std::vector
<SBPrefix
>(1, result
.hash
.prefix
),
1109 std::vector
<SBFullHashResult
>(1, result
),
1113 // The cached response means the collision no longer causes a hit.
1114 EXPECT_FALSE(database_
->ContainsBrowseUrl(
1115 GURL(std::string("http://") + kExampleFine
), &prefix_hits
, &cache_hits
));
1118 // Test that corrupt databases are appropriately handled, even if the
1119 // corruption is detected in the midst of the update.
1120 // TODO(shess): Disabled until ScopedLogMessageIgnorer resolved.
1121 // http://crbug.com/56448
1122 TEST_F(SafeBrowsingDatabaseTest
, DISABLED_FileCorruptionHandling
) {
1123 // Re-create the database in a captive message loop so that we can
1124 // influence task-posting. Database specifically needs to the
1127 base::MessageLoop loop
;
1128 SafeBrowsingStoreFile
* store
= new SafeBrowsingStoreFile(task_runner_
);
1129 database_
.reset(new SafeBrowsingDatabaseNew(
1130 task_runner_
, store
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
));
1131 database_
->Init(database_filename_
);
1133 // This will cause an empty database to be created.
1134 std::vector
<SBListChunkRanges
> lists
;
1135 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1136 database_
->UpdateFinished(true);
1138 // Create a sub chunk to insert.
1139 ScopedVector
<SBChunkData
> chunks
;
1140 chunks
.push_back(SubChunkPrefixValue(7,
1141 "www.subbed.com/notevil1.html",
1144 // Corrupt the file by corrupting the checksum, which is not checked
1145 // until the entire table is read in |UpdateFinished()|.
1146 FILE* fp
= base::OpenFile(database_filename_
, "r+");
1148 ASSERT_NE(-1, fseek(fp
, -8, SEEK_END
));
1149 for (size_t i
= 0; i
< 8; ++i
) {
1155 // The following code will cause DCHECKs, so suppress the crashes.
1156 ScopedLogMessageIgnorer ignorer
;
1158 // Start an update. The insert will fail due to corruption.
1159 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1160 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
1161 database_
->UpdateFinished(true);
1163 // Database file still exists until the corruption handler has run.
1164 EXPECT_TRUE(base::PathExists(database_filename_
));
1166 // Flush through the corruption-handler task.
1167 DVLOG(1) << "Expect failed check on: SafeBrowsing database reset";
1168 base::MessageLoop::current()->RunUntilIdle();
1171 // Database file should not exist.
1172 EXPECT_FALSE(base::PathExists(database_filename_
));
1174 // Run the update again successfully.
1175 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1176 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
1177 database_
->UpdateFinished(true);
1178 EXPECT_TRUE(base::PathExists(database_filename_
));
1183 // Checks database reading and writing.
1184 TEST_F(SafeBrowsingDatabaseTest
, ContainsDownloadUrlPrefixes
) {
1185 const char kEvil1Url1
[] = "www.evil1.com/download1/";
1186 const char kEvil1Url2
[] = "www.evil1.com/download2.html";
1188 // Add a simple chunk with one hostkey for download url list.
1189 ScopedVector
<SBChunkData
> chunks
;
1190 chunks
.push_back(AddChunkPrefix2Value(1, kEvil1Url1
, kEvil1Url2
));
1192 std::vector
<SBListChunkRanges
> lists
;
1193 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1194 database_
->InsertChunks(safe_browsing_util::kBinUrlList
, chunks
.get());
1195 database_
->UpdateFinished(true);
1197 std::vector
<SBPrefix
> prefix_hits
;
1198 std::vector
<GURL
> urls(1);
1200 urls
[0] = GURL(std::string("http://") + kEvil1Url1
);
1201 EXPECT_TRUE(ContainsDownloadUrl(urls
, &prefix_hits
));
1202 ASSERT_EQ(1U, prefix_hits
.size());
1203 EXPECT_EQ(SBPrefixForString(kEvil1Url1
), prefix_hits
[0]);
1205 urls
[0] = GURL(std::string("http://") + kEvil1Url2
);
1206 EXPECT_TRUE(ContainsDownloadUrl(urls
, &prefix_hits
));
1207 ASSERT_EQ(1U, prefix_hits
.size());
1208 EXPECT_EQ(SBPrefixForString(kEvil1Url2
), prefix_hits
[0]);
1210 urls
[0] = GURL(std::string("https://") + kEvil1Url2
);
1211 EXPECT_TRUE(ContainsDownloadUrl(urls
, &prefix_hits
));
1212 ASSERT_EQ(1U, prefix_hits
.size());
1213 EXPECT_EQ(SBPrefixForString(kEvil1Url2
), prefix_hits
[0]);
1215 urls
[0] = GURL(std::string("ftp://") + kEvil1Url2
);
1216 EXPECT_TRUE(ContainsDownloadUrl(urls
, &prefix_hits
));
1217 ASSERT_EQ(1U, prefix_hits
.size());
1218 EXPECT_EQ(SBPrefixForString(kEvil1Url2
), prefix_hits
[0]);
1220 urls
[0] = GURL("http://www.randomevil.com");
1221 EXPECT_FALSE(ContainsDownloadUrl(urls
, &prefix_hits
));
1223 // Should match with query args stripped.
1224 urls
[0] = GURL(std::string("http://") + kEvil1Url2
+ "?blah");
1225 EXPECT_TRUE(ContainsDownloadUrl(urls
, &prefix_hits
));
1226 ASSERT_EQ(1U, prefix_hits
.size());
1227 EXPECT_EQ(SBPrefixForString(kEvil1Url2
), prefix_hits
[0]);
1229 // Should match with extra path stuff and query args stripped.
1230 urls
[0] = GURL(std::string("http://") + kEvil1Url1
+ "foo/bar?blah");
1231 EXPECT_TRUE(ContainsDownloadUrl(urls
, &prefix_hits
));
1232 ASSERT_EQ(1U, prefix_hits
.size());
1233 EXPECT_EQ(SBPrefixForString(kEvil1Url1
), prefix_hits
[0]);
1235 // First hit in redirect chain is malware.
1237 urls
.push_back(GURL(std::string("http://") + kEvil1Url1
));
1238 urls
.push_back(GURL("http://www.randomevil.com"));
1239 EXPECT_TRUE(ContainsDownloadUrl(urls
, &prefix_hits
));
1240 ASSERT_EQ(1U, prefix_hits
.size());
1241 EXPECT_EQ(SBPrefixForString(kEvil1Url1
), prefix_hits
[0]);
1243 // Middle hit in redirect chain is malware.
1245 urls
.push_back(GURL("http://www.randomevil.com"));
1246 urls
.push_back(GURL(std::string("http://") + kEvil1Url1
));
1247 urls
.push_back(GURL("http://www.randomevil2.com"));
1248 EXPECT_TRUE(ContainsDownloadUrl(urls
, &prefix_hits
));
1249 ASSERT_EQ(1U, prefix_hits
.size());
1250 EXPECT_EQ(SBPrefixForString(kEvil1Url1
), prefix_hits
[0]);
1252 // Final hit in redirect chain is malware.
1254 urls
.push_back(GURL("http://www.randomevil.com"));
1255 urls
.push_back(GURL(std::string("http://") + kEvil1Url1
));
1256 EXPECT_TRUE(ContainsDownloadUrl(urls
, &prefix_hits
));
1257 ASSERT_EQ(1U, prefix_hits
.size());
1258 EXPECT_EQ(SBPrefixForString(kEvil1Url1
), prefix_hits
[0]);
1260 // Multiple hits in redirect chain are in malware list.
1262 urls
.push_back(GURL(std::string("http://") + kEvil1Url1
));
1263 urls
.push_back(GURL(std::string("https://") + kEvil1Url2
));
1264 EXPECT_TRUE(ContainsDownloadUrl(urls
, &prefix_hits
));
1265 ASSERT_EQ(2U, prefix_hits
.size());
1266 EXPECT_EQ(SBPrefixForString(kEvil1Url1
), prefix_hits
[0]);
1267 EXPECT_EQ(SBPrefixForString(kEvil1Url2
), prefix_hits
[1]);
1271 // Checks that the whitelists are handled properly.
1272 TEST_F(SafeBrowsingDatabaseTest
, Whitelists
) {
1274 using TestListContainsWhitelistedUrl
=
1275 bool (SafeBrowsingDatabase::*)(const GURL
& url
);
1276 using TestListContainsWhitelistedString
=
1277 bool (SafeBrowsingDatabase::*)(const std::string
& str
);
1279 // Returns true if strings should be tested in this test case (i.e.
1280 // |test_list_contains_whitelisted_string| is not null).
1281 bool TestStrings() const {
1282 return test_list_contains_whitelisted_string
!= nullptr;
1285 const char* test_list_name
;
1286 TestListContainsWhitelistedUrl test_list_contains_whitelisted_url
;
1287 // Optional test case field, if set the tested whitelist will also be tested
1289 TestListContainsWhitelistedString test_list_contains_whitelisted_string
;
1290 } const kTestCases
[]{
1291 {safe_browsing_util::kCsdWhiteList
,
1292 &SafeBrowsingDatabase::ContainsCsdWhitelistedUrl
,
1294 {safe_browsing_util::kDownloadWhiteList
,
1295 &SafeBrowsingDatabase::ContainsDownloadWhitelistedUrl
,
1296 &SafeBrowsingDatabase::ContainsDownloadWhitelistedString
},
1297 {safe_browsing_util::kInclusionWhitelist
,
1298 &SafeBrowsingDatabase::ContainsInclusionWhitelistedUrl
,
1302 // If the whitelist is disabled everything should match the whitelist.
1303 database_
.reset(new SafeBrowsingDatabaseNew(
1304 task_runner_
, new SafeBrowsingStoreFile(task_runner_
), NULL
, NULL
, NULL
,
1305 NULL
, NULL
, NULL
, NULL
, NULL
));
1306 database_
->Init(database_filename_
);
1307 for (const auto& test_case
: kTestCases
) {
1308 SCOPED_TRACE(std::string("Tested list at fault => ") +
1309 test_case
.test_list_name
);
1312 (database_
.get()->*test_case
.test_list_contains_whitelisted_url
)(
1313 GURL(std::string("http://www.phishing.com/"))));
1314 if (test_case
.TestStrings()) {
1316 (database_
.get()->*test_case
.test_list_contains_whitelisted_string
)(
1320 ResetAndReloadFullDatabase();
1322 // Now test every whitelist one-by-one; intentionally not resetting the
1323 // database in-between to further stress potential inter-dependencies.
1324 for (const auto& test_case
: kTestCases
) {
1325 SCOPED_TRACE(std::string("Tested list at fault => ") +
1326 test_case
.test_list_name
);
1328 const char kGood1Host
[] = "www.good1.com/";
1329 const char kGood1Url1
[] = "www.good1.com/a/b.html";
1330 const char kGood1Url2
[] = "www.good1.com/b/";
1332 const char kGood2Url1
[] = "www.good2.com/c"; // Should match '/c/bla'.
1334 // good3.com/a/b/c/d/e/f/g/ should match because it's a whitelist.
1335 const char kGood3Url1
[] = "good3.com/";
1337 const char kGoodString
[] = "good_string";
1339 // Nothing should be whitelisted before the database receives the chunks.
1341 (database_
.get()->*test_case
.test_list_contains_whitelisted_url
)(
1342 GURL(std::string("http://") + kGood1Host
)));
1344 (database_
.get()->*test_case
.test_list_contains_whitelisted_url
)(
1345 GURL(std::string("http://") + kGood1Url1
)));
1347 (database_
.get()->*test_case
.test_list_contains_whitelisted_url
)(
1348 GURL(std::string("http://") + kGood1Url2
)));
1350 (database_
.get()->*test_case
.test_list_contains_whitelisted_url
)(
1351 GURL(std::string("http://") + kGood2Url1
)));
1353 (database_
.get()->*test_case
.test_list_contains_whitelisted_url
)(
1354 GURL(std::string("http://") + kGood3Url1
)));
1355 if (test_case
.TestStrings()) {
1357 (database_
.get()->*test_case
.test_list_contains_whitelisted_string
)(
1361 ScopedVector
<SBChunkData
> chunks
;
1363 // Add a few test chunks to the whitelist under test.
1364 chunks
.push_back(AddChunkFullHash2Value(1, kGood1Url1
, kGood1Url2
));
1365 chunks
.push_back(AddChunkFullHashValue(2, kGood2Url1
));
1366 if (test_case
.TestStrings())
1367 chunks
.push_back(AddChunkFullHashValue(3, kGoodString
));
1368 chunks
.push_back(AddChunkFullHashValue(4, kGood3Url1
));
1370 std::vector
<SBListChunkRanges
> lists
;
1371 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1372 database_
->InsertChunks(test_case
.test_list_name
, chunks
.get());
1373 database_
->UpdateFinished(true);
1376 (database_
.get()->*test_case
.test_list_contains_whitelisted_url
)(
1377 GURL(std::string("http://") + kGood1Host
)));
1380 (database_
.get()->*test_case
.test_list_contains_whitelisted_url
)(
1381 GURL(std::string("http://") + kGood1Url1
)));
1383 (database_
.get()->*test_case
.test_list_contains_whitelisted_url
)(
1384 GURL(std::string("http://") + kGood1Url1
+ "?a=b")));
1387 (database_
.get()->*test_case
.test_list_contains_whitelisted_url
)(
1388 GURL(std::string("http://") + kGood1Url2
)));
1390 (database_
.get()->*test_case
.test_list_contains_whitelisted_url
)(
1391 GURL(std::string("http://") + kGood1Url2
+ "/c.html")));
1394 (database_
.get()->*test_case
.test_list_contains_whitelisted_url
)(
1395 GURL(std::string("https://") + kGood1Url2
+ "/c.html")));
1398 (database_
.get()->*test_case
.test_list_contains_whitelisted_url
)(
1399 GURL(std::string("http://") + kGood2Url1
+ "/c")));
1401 (database_
.get()->*test_case
.test_list_contains_whitelisted_url
)(
1402 GURL(std::string("http://") + kGood2Url1
+ "/c?bla")));
1404 (database_
.get()->*test_case
.test_list_contains_whitelisted_url
)(
1405 GURL(std::string("http://") + kGood2Url1
+ "/c/bla")));
1408 (database_
.get()->*test_case
.test_list_contains_whitelisted_url
)(
1409 GURL(std::string("http://www.google.com/"))));
1412 (database_
.get()->*test_case
.test_list_contains_whitelisted_url
)(
1413 GURL(std::string("http://") + kGood3Url1
+ "a/b/c/d/e/f/g/")));
1415 (database_
.get()->*test_case
.test_list_contains_whitelisted_url
)(
1416 GURL(std::string("http://a.b.") + kGood3Url1
)));
1418 if (test_case
.TestStrings()) {
1420 (database_
.get()->*test_case
.test_list_contains_whitelisted_string
)(
1423 (database_
.get()->*test_case
.test_list_contains_whitelisted_string
)(
1428 (database_
.get()->*test_case
.test_list_contains_whitelisted_url
)(
1429 GURL(std::string("http://www.google.com/"))));
1431 // The malware kill switch is for the CSD whitelist only.
1432 if (test_case
.test_list_name
== safe_browsing_util::kCsdWhiteList
) {
1433 // The CSD whitelist killswitch is not present.
1434 EXPECT_FALSE(database_
->IsCsdWhitelistKillSwitchOn());
1436 // Test only add the malware IP killswitch
1438 chunks
.push_back(AddChunkFullHashValue(
1439 15, "sb-ssl.google.com/safebrowsing/csd/killswitch_malware"));
1441 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1442 database_
->InsertChunks(safe_browsing_util::kCsdWhiteList
, chunks
.get());
1443 database_
->UpdateFinished(true);
1445 EXPECT_TRUE(database_
->IsMalwareIPMatchKillSwitchOn());
1446 // The CSD whitelist killswitch is not present.
1447 EXPECT_FALSE(database_
->IsCsdWhitelistKillSwitchOn());
1450 // Test that the generic whitelist kill-switch works as intended.
1453 chunks
.push_back(AddChunkFullHashValue(
1454 5, "sb-ssl.google.com/safebrowsing/csd/killswitch"));
1456 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1457 database_
->InsertChunks(test_case
.test_list_name
, chunks
.get());
1458 database_
->UpdateFinished(true);
1460 // Test CSD whitelist specific methods.
1461 if (test_case
.test_list_name
== safe_browsing_util::kCsdWhiteList
) {
1462 // The CSD whitelist killswitch is present.
1463 EXPECT_TRUE(database_
->IsCsdWhitelistKillSwitchOn());
1464 EXPECT_TRUE(database_
->IsMalwareIPMatchKillSwitchOn());
1468 (database_
.get()->*test_case
.test_list_contains_whitelisted_url
)(
1469 GURL(std::string("https://") + kGood1Url2
+ "/c.html")));
1471 (database_
.get()->*test_case
.test_list_contains_whitelisted_url
)(
1472 GURL(std::string("http://www.google.com/"))));
1474 (database_
.get()->*test_case
.test_list_contains_whitelisted_url
)(
1475 GURL(std::string("http://www.phishing_url.com/"))));
1477 if (test_case
.TestStrings()) {
1479 (database_
.get()->*test_case
.test_list_contains_whitelisted_string
)(
1482 (database_
.get()->*test_case
.test_list_contains_whitelisted_string
)(
1486 // Remove the kill-switch and verify that we can recover.
1489 chunks
.push_back(SubChunkFullHashValue(
1490 1, "sb-ssl.google.com/safebrowsing/csd/killswitch", 5));
1491 if (test_case
.test_list_name
== safe_browsing_util::kCsdWhiteList
) {
1492 chunks
.push_back(SubChunkFullHashValue(
1493 10, "sb-ssl.google.com/safebrowsing/csd/killswitch_malware", 15));
1496 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1497 database_
->InsertChunks(test_case
.test_list_name
, chunks
.get());
1498 database_
->UpdateFinished(true);
1500 if (test_case
.test_list_name
== safe_browsing_util::kCsdWhiteList
) {
1501 EXPECT_FALSE(database_
->IsMalwareIPMatchKillSwitchOn());
1502 EXPECT_FALSE(database_
->IsCsdWhitelistKillSwitchOn());
1505 (database_
.get()->*test_case
.test_list_contains_whitelisted_url
)(
1506 GURL(std::string("https://") + kGood1Url2
+ "/c.html")));
1508 (database_
.get()->*test_case
.test_list_contains_whitelisted_url
)(
1509 GURL(std::string("https://") + kGood2Url1
+ "/c/bla")));
1511 (database_
.get()->*test_case
.test_list_contains_whitelisted_url
)(
1512 GURL(std::string("https://") + kGood3Url1
)));
1514 (database_
.get()->*test_case
.test_list_contains_whitelisted_url
)(
1515 GURL(std::string("http://www.google.com/"))));
1517 (database_
.get()->*test_case
.test_list_contains_whitelisted_url
)(
1518 GURL(std::string("http://www.phishing_url.com/"))));
1519 if (test_case
.TestStrings()) {
1521 (database_
.get()->*test_case
.test_list_contains_whitelisted_string
)(
1524 (database_
.get()->*test_case
.test_list_contains_whitelisted_string
)(
1530 // Test to make sure we could insert chunk list that
1531 // contains entries for the same host.
1532 TEST_F(SafeBrowsingDatabaseTest
, SameHostEntriesOkay
) {
1533 ScopedVector
<SBChunkData
> chunks
;
1535 // Add a malware add chunk with two entries of the same host.
1536 chunks
.push_back(AddChunkPrefix2Value(1,
1537 "www.evil.com/malware1.html",
1538 "www.evil.com/malware2.html"));
1540 // Insert the testing chunks into database.
1541 std::vector
<SBListChunkRanges
> lists
;
1542 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1543 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
1544 database_
->UpdateFinished(true);
1546 GetListsInfo(&lists
);
1547 ASSERT_LE(1U, lists
.size());
1548 EXPECT_EQ(safe_browsing_util::kMalwareList
, lists
[0].name
);
1549 EXPECT_EQ("1", lists
[0].adds
);
1550 EXPECT_TRUE(lists
[0].subs
.empty());
1552 // Add a phishing add chunk with two entries of the same host.
1554 chunks
.push_back(AddChunkPrefix2Value(47,
1555 "www.evil.com/phishing1.html",
1556 "www.evil.com/phishing2.html"));
1558 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1559 database_
->InsertChunks(safe_browsing_util::kPhishingList
, chunks
.get());
1560 database_
->UpdateFinished(true);
1562 GetListsInfo(&lists
);
1563 ASSERT_LE(2U, lists
.size());
1564 EXPECT_EQ(safe_browsing_util::kMalwareList
, lists
[0].name
);
1565 EXPECT_EQ("1", lists
[0].adds
);
1566 EXPECT_TRUE(lists
[0].subs
.empty());
1567 EXPECT_EQ(safe_browsing_util::kPhishingList
, lists
[1].name
);
1568 EXPECT_EQ("47", lists
[1].adds
);
1569 EXPECT_TRUE(lists
[1].subs
.empty());
1571 std::vector
<SBPrefix
> prefix_hits
;
1572 std::vector
<SBFullHashResult
> cache_hits
;
1574 EXPECT_TRUE(database_
->ContainsBrowseUrl(
1575 GURL("http://www.evil.com/malware1.html"), &prefix_hits
, &cache_hits
));
1576 EXPECT_TRUE(database_
->ContainsBrowseUrl(
1577 GURL("http://www.evil.com/malware2.html"), &prefix_hits
, &cache_hits
));
1578 EXPECT_TRUE(database_
->ContainsBrowseUrl(
1579 GURL("http://www.evil.com/phishing1.html"), &prefix_hits
, &cache_hits
));
1580 EXPECT_TRUE(database_
->ContainsBrowseUrl(
1581 GURL("http://www.evil.com/phishing2.html"), &prefix_hits
, &cache_hits
));
1583 // Test removing a single prefix from the add chunk.
1584 // Remove the prefix that added first.
1586 chunks
.push_back(SubChunkPrefixValue(4, "www.evil.com/malware1.html", 1));
1587 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1588 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
1589 database_
->UpdateFinished(true);
1591 // Remove the prefix that added last.
1593 chunks
.push_back(SubChunkPrefixValue(5, "www.evil.com/phishing2.html", 47));
1594 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1595 database_
->InsertChunks(safe_browsing_util::kPhishingList
, chunks
.get());
1596 database_
->UpdateFinished(true);
1598 // Verify that the database contains urls expected.
1599 EXPECT_FALSE(database_
->ContainsBrowseUrl(
1600 GURL("http://www.evil.com/malware1.html"), &prefix_hits
, &cache_hits
));
1601 EXPECT_TRUE(database_
->ContainsBrowseUrl(
1602 GURL("http://www.evil.com/malware2.html"), &prefix_hits
, &cache_hits
));
1603 EXPECT_TRUE(database_
->ContainsBrowseUrl(
1604 GURL("http://www.evil.com/phishing1.html"), &prefix_hits
, &cache_hits
));
1605 EXPECT_FALSE(database_
->ContainsBrowseUrl(
1606 GURL("http://www.evil.com/phishing2.html"), &prefix_hits
, &cache_hits
));
1609 // Test that an empty update doesn't actually update the database.
1610 // This isn't a functionality requirement, but it is a useful
1612 TEST_F(SafeBrowsingDatabaseTest
, EmptyUpdate
) {
1613 ScopedVector
<SBChunkData
> chunks
;
1615 base::FilePath filename
= database_
->BrowseDBFilename(database_filename_
);
1617 // Prime the database.
1618 std::vector
<SBListChunkRanges
> lists
;
1619 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1620 chunks
.push_back(AddChunkPrefixValue(1, "www.evil.com/malware.html"));
1621 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
1622 database_
->UpdateFinished(true);
1624 // Get an older time to reset the lastmod time for detecting whether
1625 // the file has been updated.
1626 base::File::Info before_info
, after_info
;
1627 ASSERT_TRUE(base::GetFileInfo(filename
, &before_info
));
1628 const Time old_last_modified
=
1629 before_info
.last_modified
- TimeDelta::FromSeconds(10);
1631 // Inserting another chunk updates the database file. The sleep is
1632 // needed because otherwise the entire test can finish w/in the
1633 // resolution of the lastmod time.
1634 ASSERT_TRUE(base::TouchFile(filename
, old_last_modified
, old_last_modified
));
1635 ASSERT_TRUE(base::GetFileInfo(filename
, &before_info
));
1636 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1637 chunks
.push_back(AddChunkPrefixValue(2, "www.foo.com/malware.html"));
1638 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
1639 database_
->UpdateFinished(true);
1640 ASSERT_TRUE(base::GetFileInfo(filename
, &after_info
));
1641 EXPECT_LT(before_info
.last_modified
, after_info
.last_modified
);
1643 // Deleting a chunk updates the database file.
1644 ASSERT_TRUE(base::TouchFile(filename
, old_last_modified
, old_last_modified
));
1645 ASSERT_TRUE(base::GetFileInfo(filename
, &before_info
));
1646 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1647 AddDelChunk(safe_browsing_util::kMalwareList
, 2);
1648 database_
->UpdateFinished(true);
1649 ASSERT_TRUE(base::GetFileInfo(filename
, &after_info
));
1650 EXPECT_LT(before_info
.last_modified
, after_info
.last_modified
);
1652 // Simply calling |UpdateStarted()| then |UpdateFinished()| does not
1653 // update the database file.
1654 ASSERT_TRUE(base::TouchFile(filename
, old_last_modified
, old_last_modified
));
1655 ASSERT_TRUE(base::GetFileInfo(filename
, &before_info
));
1656 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1657 database_
->UpdateFinished(true);
1658 ASSERT_TRUE(base::GetFileInfo(filename
, &after_info
));
1659 EXPECT_EQ(before_info
.last_modified
, after_info
.last_modified
);
1662 // Test that a filter file is written out during update and read back
1664 TEST_F(SafeBrowsingDatabaseTest
, FilterFile
) {
1665 // Create a database with trivial example data and write it out.
1667 // Prime the database.
1668 std::vector
<SBListChunkRanges
> lists
;
1669 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1671 ScopedVector
<SBChunkData
> chunks
;
1672 chunks
.push_back(AddChunkPrefixValue(1, "www.evil.com/malware.html"));
1673 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
1674 database_
->UpdateFinished(true);
1677 // Find the malware url in the database, don't find a good url.
1678 std::vector
<SBPrefix
> prefix_hits
;
1679 std::vector
<SBFullHashResult
> cache_hits
;
1680 EXPECT_TRUE(database_
->ContainsBrowseUrl(
1681 GURL("http://www.evil.com/malware.html"), &prefix_hits
, &cache_hits
));
1682 EXPECT_FALSE(database_
->ContainsBrowseUrl(
1683 GURL("http://www.good.com/goodware.html"), &prefix_hits
, &cache_hits
));
1685 base::FilePath filter_file
= database_
->PrefixSetForFilename(
1686 database_
->BrowseDBFilename(database_filename_
));
1688 // After re-creating the database, it should have a filter read from
1689 // a file, so it should find the same results.
1690 ASSERT_TRUE(base::PathExists(filter_file
));
1691 ResetAndReloadFullDatabase();
1692 EXPECT_TRUE(database_
->ContainsBrowseUrl(
1693 GURL("http://www.evil.com/malware.html"), &prefix_hits
, &cache_hits
));
1694 EXPECT_FALSE(database_
->ContainsBrowseUrl(
1695 GURL("http://www.good.com/goodware.html"), &prefix_hits
, &cache_hits
));
1697 // If there is no filter file, the database cannot find malware urls.
1698 base::DeleteFile(filter_file
, false);
1699 ASSERT_FALSE(base::PathExists(filter_file
));
1700 ResetAndReloadFullDatabase();
1701 EXPECT_FALSE(database_
->ContainsBrowseUrl(
1702 GURL("http://www.evil.com/malware.html"), &prefix_hits
, &cache_hits
));
1703 EXPECT_FALSE(database_
->ContainsBrowseUrl(
1704 GURL("http://www.good.com/goodware.html"), &prefix_hits
, &cache_hits
));
1707 TEST_F(SafeBrowsingDatabaseTest
, CachedFullMiss
) {
1708 const SBPrefix kPrefix1
= 1001U;
1709 const SBFullHash kFullHash1_1
=
1710 SBFullHashForPrefixAndSuffix(kPrefix1
, "\x01");
1712 const SBPrefix kPrefix2
= 1002U;
1713 const SBFullHash kFullHash2_1
=
1714 SBFullHashForPrefixAndSuffix(kPrefix2
, "\x01");
1716 // Insert prefix kPrefix1 and kPrefix2 into database.
1717 ScopedVector
<SBChunkData
> chunks
;
1718 chunks
.push_back(AddChunkPrefix(1, kPrefix1
));
1719 chunks
.push_back(AddChunkPrefix(2, kPrefix2
));
1721 std::vector
<SBListChunkRanges
> lists
;
1722 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1723 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
1724 database_
->UpdateFinished(true);
1727 // Cache a full miss result for kPrefix1.
1728 std::vector
<SBPrefix
> prefixes(1, kPrefix1
);
1729 std::vector
<SBFullHashResult
> cache_results
;
1730 database_
->CacheHashResults(prefixes
, cache_results
, kCacheLifetime
);
1734 // kFullHash1_1 gets no prefix hit because of the cached item, and also does
1735 // not have a cache hit.
1736 std::vector
<SBFullHash
> full_hashes(1, kFullHash1_1
);
1737 std::vector
<SBPrefix
> prefix_hits
;
1738 std::vector
<SBFullHashResult
> cache_hits
;
1739 EXPECT_FALSE(database_
->ContainsBrowseUrlHashesForTesting(
1740 full_hashes
, &prefix_hits
, &cache_hits
));
1742 // kFullHash2_1 gets a hit from the prefix in the database.
1743 full_hashes
.push_back(kFullHash2_1
);
1744 prefix_hits
.clear();
1746 EXPECT_TRUE(database_
->ContainsBrowseUrlHashesForTesting(
1747 full_hashes
, &prefix_hits
, &cache_hits
));
1748 ASSERT_EQ(1U, prefix_hits
.size());
1749 EXPECT_EQ(kPrefix2
, prefix_hits
[0]);
1750 EXPECT_TRUE(cache_hits
.empty());
1754 TEST_F(SafeBrowsingDatabaseTest
, CachedPrefixHitFullMiss
) {
1755 const SBPrefix kPrefix1
= 1001U;
1756 const SBFullHash kFullHash1_1
=
1757 SBFullHashForPrefixAndSuffix(kPrefix1
, "\x01");
1758 const SBFullHash kFullHash1_2
=
1759 SBFullHashForPrefixAndSuffix(kPrefix1
, "\x02");
1760 const SBFullHash kFullHash1_3
=
1761 SBFullHashForPrefixAndSuffix(kPrefix1
, "\x03");
1763 const SBPrefix kPrefix2
= 1002U;
1764 const SBFullHash kFullHash2_1
=
1765 SBFullHashForPrefixAndSuffix(kPrefix2
, "\x01");
1767 const SBPrefix kPrefix3
= 1003U;
1768 const SBFullHash kFullHash3_1
=
1769 SBFullHashForPrefixAndSuffix(kPrefix3
, "\x01");
1771 // Insert prefix kPrefix1 and kPrefix2 into database.
1772 ScopedVector
<SBChunkData
> chunks
;
1773 chunks
.push_back(AddChunkPrefix(1, kPrefix1
));
1774 chunks
.push_back(AddChunkPrefix(2, kPrefix2
));
1776 std::vector
<SBListChunkRanges
> lists
;
1777 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1778 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
1779 database_
->UpdateFinished(true);
1782 // kFullHash1_1 has a prefix hit of kPrefix1.
1783 std::vector
<SBFullHash
> full_hashes
;
1784 full_hashes
.push_back(kFullHash1_1
);
1785 std::vector
<SBPrefix
> prefix_hits
;
1786 std::vector
<SBFullHashResult
> cache_hits
;
1787 EXPECT_TRUE(database_
->ContainsBrowseUrlHashesForTesting(
1788 full_hashes
, &prefix_hits
, &cache_hits
));
1789 ASSERT_EQ(1U, prefix_hits
.size());
1790 EXPECT_EQ(kPrefix1
, prefix_hits
[0]);
1791 EXPECT_TRUE(cache_hits
.empty());
1793 // kFullHash2_1 has a prefix hit of kPrefix2.
1794 full_hashes
.push_back(kFullHash2_1
);
1795 prefix_hits
.clear();
1797 EXPECT_TRUE(database_
->ContainsBrowseUrlHashesForTesting(
1798 full_hashes
, &prefix_hits
, &cache_hits
));
1799 ASSERT_EQ(2U, prefix_hits
.size());
1800 EXPECT_EQ(kPrefix1
, prefix_hits
[0]);
1801 EXPECT_EQ(kPrefix2
, prefix_hits
[1]);
1802 EXPECT_TRUE(cache_hits
.empty());
1804 // kFullHash3_1 has no hits.
1805 full_hashes
.push_back(kFullHash3_1
);
1806 prefix_hits
.clear();
1808 EXPECT_TRUE(database_
->ContainsBrowseUrlHashesForTesting(
1809 full_hashes
, &prefix_hits
, &cache_hits
));
1810 ASSERT_EQ(2U, prefix_hits
.size());
1811 EXPECT_EQ(kPrefix1
, prefix_hits
[0]);
1812 EXPECT_EQ(kPrefix2
, prefix_hits
[1]);
1813 EXPECT_TRUE(cache_hits
.empty());
1817 // Cache a fullhash result for two kPrefix1 full hashes.
1818 std::vector
<SBPrefix
> prefixes(1, kPrefix1
);
1819 std::vector
<SBFullHashResult
> cache_results
;
1821 SBFullHashResult full_hash_result
;
1822 full_hash_result
.list_id
= safe_browsing_util::MALWARE
;
1824 full_hash_result
.hash
= kFullHash1_1
;
1825 cache_results
.push_back(full_hash_result
);
1827 full_hash_result
.hash
= kFullHash1_3
;
1828 cache_results
.push_back(full_hash_result
);
1830 database_
->CacheHashResults(prefixes
, cache_results
, kCacheLifetime
);
1834 // kFullHash1_1 should now see a cache hit.
1835 std::vector
<SBFullHash
> full_hashes(1, kFullHash1_1
);
1836 std::vector
<SBPrefix
> prefix_hits
;
1837 std::vector
<SBFullHashResult
> cache_hits
;
1838 EXPECT_TRUE(database_
->ContainsBrowseUrlHashesForTesting(
1839 full_hashes
, &prefix_hits
, &cache_hits
));
1840 EXPECT_TRUE(prefix_hits
.empty());
1841 ASSERT_EQ(1U, cache_hits
.size());
1842 EXPECT_TRUE(SBFullHashEqual(kFullHash1_1
, cache_hits
[0].hash
));
1844 // Adding kFullHash2_1 will see the existing cache hit plus the prefix hit
1846 full_hashes
.push_back(kFullHash2_1
);
1847 prefix_hits
.clear();
1849 EXPECT_TRUE(database_
->ContainsBrowseUrlHashesForTesting(
1850 full_hashes
, &prefix_hits
, &cache_hits
));
1851 ASSERT_EQ(1U, prefix_hits
.size());
1852 EXPECT_EQ(kPrefix2
, prefix_hits
[0]);
1853 ASSERT_EQ(1U, cache_hits
.size());
1854 EXPECT_TRUE(SBFullHashEqual(kFullHash1_1
, cache_hits
[0].hash
));
1856 // kFullHash1_3 also gets a cache hit.
1857 full_hashes
.push_back(kFullHash1_3
);
1858 prefix_hits
.clear();
1860 EXPECT_TRUE(database_
->ContainsBrowseUrlHashesForTesting(
1861 full_hashes
, &prefix_hits
, &cache_hits
));
1862 ASSERT_EQ(1U, prefix_hits
.size());
1863 EXPECT_EQ(kPrefix2
, prefix_hits
[0]);
1864 ASSERT_EQ(2U, cache_hits
.size());
1865 EXPECT_TRUE(SBFullHashEqual(kFullHash1_1
, cache_hits
[0].hash
));
1866 EXPECT_TRUE(SBFullHashEqual(kFullHash1_3
, cache_hits
[1].hash
));
1870 // Check if DB contains only kFullHash1_3. Should return a cache hit.
1871 std::vector
<SBFullHash
> full_hashes(1, kFullHash1_3
);
1872 std::vector
<SBPrefix
> prefix_hits
;
1873 std::vector
<SBFullHashResult
> cache_hits
;
1874 EXPECT_TRUE(database_
->ContainsBrowseUrlHashesForTesting(
1875 full_hashes
, &prefix_hits
, &cache_hits
));
1876 EXPECT_TRUE(prefix_hits
.empty());
1877 ASSERT_EQ(1U, cache_hits
.size());
1878 EXPECT_TRUE(SBFullHashEqual(kFullHash1_3
, cache_hits
[0].hash
));
1882 // kFullHash1_2 has no cache hit, and no prefix hit because of the cache for
1884 std::vector
<SBFullHash
> full_hashes(1, kFullHash1_2
);
1885 std::vector
<SBPrefix
> prefix_hits
;
1886 std::vector
<SBFullHashResult
> cache_hits
;
1887 EXPECT_FALSE(database_
->ContainsBrowseUrlHashesForTesting(
1888 full_hashes
, &prefix_hits
, &cache_hits
));
1890 // Other prefix hits possible when kFullHash1_2 hits nothing.
1891 full_hashes
.push_back(kFullHash2_1
);
1892 prefix_hits
.clear();
1894 EXPECT_TRUE(database_
->ContainsBrowseUrlHashesForTesting(
1895 full_hashes
, &prefix_hits
, &cache_hits
));
1896 ASSERT_EQ(1U, prefix_hits
.size());
1897 EXPECT_EQ(kPrefix2
, prefix_hits
[0]);
1898 EXPECT_TRUE(cache_hits
.empty());
1902 TEST_F(SafeBrowsingDatabaseTest
, BrowseFullHashMatching
) {
1903 const SBPrefix kPrefix1
= 1001U;
1904 const SBFullHash kFullHash1_1
=
1905 SBFullHashForPrefixAndSuffix(kPrefix1
, "\x01");
1906 const SBFullHash kFullHash1_2
=
1907 SBFullHashForPrefixAndSuffix(kPrefix1
, "\x02");
1908 const SBFullHash kFullHash1_3
=
1909 SBFullHashForPrefixAndSuffix(kPrefix1
, "\x03");
1911 // Insert two full hashes with a shared prefix.
1912 ScopedVector
<SBChunkData
> chunks
;
1913 chunks
.push_back(AddChunkFullHash(1, kFullHash1_1
));
1914 chunks
.push_back(AddChunkFullHash(2, kFullHash1_2
));
1916 std::vector
<SBListChunkRanges
> lists
;
1917 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1918 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
1919 database_
->UpdateFinished(true);
1922 // Check a full hash which isn't present.
1923 std::vector
<SBFullHash
> full_hashes(1, kFullHash1_3
);
1924 std::vector
<SBPrefix
> prefix_hits
;
1925 std::vector
<SBFullHashResult
> cache_hits
;
1926 EXPECT_FALSE(database_
->ContainsBrowseUrlHashesForTesting(
1927 full_hashes
, &prefix_hits
, &cache_hits
));
1929 // Also one which is present, should have a prefix hit.
1930 full_hashes
.push_back(kFullHash1_1
);
1931 prefix_hits
.clear();
1933 EXPECT_TRUE(database_
->ContainsBrowseUrlHashesForTesting(
1934 full_hashes
, &prefix_hits
, &cache_hits
));
1935 ASSERT_EQ(1U, prefix_hits
.size());
1936 EXPECT_EQ(kPrefix1
, prefix_hits
[0]);
1937 EXPECT_TRUE(cache_hits
.empty());
1939 // Two full hash matches with the same prefix should return one prefix hit.
1940 full_hashes
.push_back(kFullHash1_2
);
1941 prefix_hits
.clear();
1943 EXPECT_TRUE(database_
->ContainsBrowseUrlHashesForTesting(
1944 full_hashes
, &prefix_hits
, &cache_hits
));
1945 ASSERT_EQ(1U, prefix_hits
.size());
1946 EXPECT_EQ(kPrefix1
, prefix_hits
[0]);
1947 EXPECT_TRUE(cache_hits
.empty());
1951 // Cache a gethash result for kFullHash1_2.
1952 SBFullHashResult full_hash_result
;
1953 full_hash_result
.list_id
= safe_browsing_util::MALWARE
;
1954 full_hash_result
.hash
= kFullHash1_2
;
1956 std::vector
<SBPrefix
> prefixes(1, kPrefix1
);
1957 std::vector
<SBFullHashResult
> cache_results(1, full_hash_result
);
1959 database_
->CacheHashResults(prefixes
, cache_results
, kCacheLifetime
);
1963 // kFullHash1_3 should still return false, because the cached
1964 // result for kPrefix1 doesn't contain kFullHash1_3.
1965 std::vector
<SBFullHash
> full_hashes(1, kFullHash1_3
);
1966 std::vector
<SBPrefix
> prefix_hits
;
1967 std::vector
<SBFullHashResult
> cache_hits
;
1968 EXPECT_FALSE(database_
->ContainsBrowseUrlHashesForTesting(
1969 full_hashes
, &prefix_hits
, &cache_hits
));
1971 // kFullHash1_1 is also not in the cached result, which takes
1972 // priority over the database.
1973 prefix_hits
.clear();
1974 full_hashes
.push_back(kFullHash1_1
);
1976 EXPECT_FALSE(database_
->ContainsBrowseUrlHashesForTesting(
1977 full_hashes
, &prefix_hits
, &cache_hits
));
1979 // kFullHash1_2 is in the cached result.
1980 full_hashes
.push_back(kFullHash1_2
);
1981 prefix_hits
.clear();
1983 EXPECT_TRUE(database_
->ContainsBrowseUrlHashesForTesting(
1984 full_hashes
, &prefix_hits
, &cache_hits
));
1985 EXPECT_TRUE(prefix_hits
.empty());
1986 ASSERT_EQ(1U, cache_hits
.size());
1987 EXPECT_TRUE(SBFullHashEqual(kFullHash1_2
, cache_hits
[0].hash
));
1990 // Remove kFullHash1_1 from the database.
1992 chunks
.push_back(SubChunkFullHash(11, kFullHash1_1
, 1));
1994 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1995 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
1996 database_
->UpdateFinished(true);
1998 // Cache should be cleared after updating.
2000 database_
->GetUnsynchronizedPrefixGetHashCacheForTesting()->empty());
2003 // Now the database doesn't contain kFullHash1_1.
2004 std::vector
<SBFullHash
> full_hashes(1, kFullHash1_1
);
2005 std::vector
<SBPrefix
> prefix_hits
;
2006 std::vector
<SBFullHashResult
> cache_hits
;
2007 EXPECT_FALSE(database_
->ContainsBrowseUrlHashesForTesting(
2008 full_hashes
, &prefix_hits
, &cache_hits
));
2010 // Nor kFullHash1_3.
2011 full_hashes
.push_back(kFullHash1_3
);
2012 prefix_hits
.clear();
2014 EXPECT_FALSE(database_
->ContainsBrowseUrlHashesForTesting(
2015 full_hashes
, &prefix_hits
, &cache_hits
));
2017 // Still has kFullHash1_2.
2018 full_hashes
.push_back(kFullHash1_2
);
2019 prefix_hits
.clear();
2021 EXPECT_TRUE(database_
->ContainsBrowseUrlHashesForTesting(
2022 full_hashes
, &prefix_hits
, &cache_hits
));
2023 ASSERT_EQ(1U, prefix_hits
.size());
2024 EXPECT_EQ(kPrefix1
, prefix_hits
[0]);
2025 EXPECT_TRUE(cache_hits
.empty());
2028 // Remove kFullHash1_2 from the database.
2030 chunks
.push_back(SubChunkFullHash(12, kFullHash1_2
, 2));
2032 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
2033 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
2034 database_
->UpdateFinished(true);
2036 // Cache should be cleared after updating.
2038 database_
->GetUnsynchronizedPrefixGetHashCacheForTesting()->empty());
2041 // None are present.
2042 std::vector
<SBFullHash
> full_hashes
;
2043 std::vector
<SBPrefix
> prefix_hits
;
2044 std::vector
<SBFullHashResult
> cache_hits
;
2045 full_hashes
.push_back(kFullHash1_1
);
2046 full_hashes
.push_back(kFullHash1_2
);
2047 full_hashes
.push_back(kFullHash1_3
);
2048 EXPECT_FALSE(database_
->ContainsBrowseUrlHashesForTesting(
2049 full_hashes
, &prefix_hits
, &cache_hits
));
2053 TEST_F(SafeBrowsingDatabaseTest
, BrowseFullHashAndPrefixMatching
) {
2054 const SBPrefix kPrefix1
= 1001U;
2055 const SBFullHash kFullHash1_1
=
2056 SBFullHashForPrefixAndSuffix(kPrefix1
, "\x01");
2057 const SBFullHash kFullHash1_2
=
2058 SBFullHashForPrefixAndSuffix(kPrefix1
, "\x02");
2060 ScopedVector
<SBChunkData
> chunks
;
2061 chunks
.push_back(AddChunkFullHash(1, kFullHash1_1
));
2063 std::vector
<SBListChunkRanges
> lists
;
2064 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
2065 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
2066 database_
->UpdateFinished(true);
2069 // kFullHash1_2 does not match kFullHash1_1.
2070 std::vector
<SBFullHash
> full_hashes(1, kFullHash1_2
);
2071 std::vector
<SBPrefix
> prefix_hits
;
2072 std::vector
<SBFullHashResult
> cache_hits
;
2073 EXPECT_FALSE(database_
->ContainsBrowseUrlHashesForTesting(
2074 full_hashes
, &prefix_hits
, &cache_hits
));
2077 // Add a prefix match.
2079 chunks
.push_back(AddChunkPrefix(2, kPrefix1
));
2081 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
2082 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
2083 database_
->UpdateFinished(true);
2086 // kFullHash1_2 does match kPrefix1.
2087 std::vector
<SBFullHash
> full_hashes(1, kFullHash1_2
);
2088 std::vector
<SBPrefix
> prefix_hits
;
2089 std::vector
<SBFullHashResult
> cache_hits
;
2090 EXPECT_TRUE(database_
->ContainsBrowseUrlHashesForTesting(
2091 full_hashes
, &prefix_hits
, &cache_hits
));
2092 ASSERT_EQ(1U, prefix_hits
.size());
2093 EXPECT_EQ(kPrefix1
, prefix_hits
[0]);
2094 EXPECT_TRUE(cache_hits
.empty());
2097 // Remove the full hash.
2099 chunks
.push_back(SubChunkFullHash(11, kFullHash1_1
, 1));
2101 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
2102 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
2103 database_
->UpdateFinished(true);
2106 // kFullHash1_2 still returns true due to the prefix hit.
2107 std::vector
<SBFullHash
> full_hashes(1, kFullHash1_2
);
2108 std::vector
<SBPrefix
> prefix_hits
;
2109 std::vector
<SBFullHashResult
> cache_hits
;
2110 EXPECT_TRUE(database_
->ContainsBrowseUrlHashesForTesting(
2111 full_hashes
, &prefix_hits
, &cache_hits
));
2112 ASSERT_EQ(1U, prefix_hits
.size());
2113 EXPECT_EQ(kPrefix1
, prefix_hits
[0]);
2114 EXPECT_TRUE(cache_hits
.empty());
2118 TEST_F(SafeBrowsingDatabaseTest
, MalwareIpBlacklist
) {
2119 std::vector
<SBListChunkRanges
> lists
;
2120 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
2122 ScopedVector
<SBChunkData
> chunks
;
2124 // IPv4 prefix match for ::ffff:192.168.1.0/120.
2125 chunks
.push_back(AddChunkHashedIpValue(1, "::ffff:192.168.1.0", 120));
2127 // IPv4 exact match for ::ffff:192.1.1.1.
2128 chunks
.push_back(AddChunkHashedIpValue(2, "::ffff:192.1.1.1", 128));
2130 // IPv6 exact match for: fe80::31a:a0ff:fe10:786e/128.
2131 chunks
.push_back(AddChunkHashedIpValue(3, "fe80::31a:a0ff:fe10:786e", 128));
2133 // IPv6 prefix match for: 2620:0:1000:3103::/64.
2134 chunks
.push_back(AddChunkHashedIpValue(4, "2620:0:1000:3103::", 64));
2136 // IPv4 prefix match for ::ffff:192.1.122.0/119.
2137 chunks
.push_back(AddChunkHashedIpValue(5, "::ffff:192.1.122.0", 119));
2139 // IPv4 prefix match for ::ffff:192.1.128.0/113.
2140 chunks
.push_back(AddChunkHashedIpValue(6, "::ffff:192.1.128.0", 113));
2142 database_
->InsertChunks(safe_browsing_util::kIPBlacklist
, chunks
.get());
2143 database_
->UpdateFinished(true);
2145 EXPECT_FALSE(database_
->ContainsMalwareIP("192.168.0.255"));
2146 EXPECT_TRUE(database_
->ContainsMalwareIP("192.168.1.0"));
2147 EXPECT_TRUE(database_
->ContainsMalwareIP("192.168.1.255"));
2148 EXPECT_TRUE(database_
->ContainsMalwareIP("192.168.1.10"));
2149 EXPECT_TRUE(database_
->ContainsMalwareIP("::ffff:192.168.1.2"));
2150 EXPECT_FALSE(database_
->ContainsMalwareIP("192.168.2.0"));
2152 EXPECT_FALSE(database_
->ContainsMalwareIP("192.1.1.0"));
2153 EXPECT_TRUE(database_
->ContainsMalwareIP("192.1.1.1"));
2154 EXPECT_FALSE(database_
->ContainsMalwareIP("192.1.1.2"));
2156 EXPECT_FALSE(database_
->ContainsMalwareIP(
2157 "2620:0:1000:3102:ffff:ffff:ffff:ffff"));
2158 EXPECT_TRUE(database_
->ContainsMalwareIP("2620:0:1000:3103::"));
2159 EXPECT_TRUE(database_
->ContainsMalwareIP(
2160 "2620:0:1000:3103:ffff:ffff:ffff:ffff"));
2161 EXPECT_FALSE(database_
->ContainsMalwareIP("2620:0:1000:3104::"));
2163 EXPECT_FALSE(database_
->ContainsMalwareIP("fe80::21a:a0ff:fe10:786d"));
2164 EXPECT_TRUE(database_
->ContainsMalwareIP("fe80::31a:a0ff:fe10:786e"));
2165 EXPECT_FALSE(database_
->ContainsMalwareIP("fe80::21a:a0ff:fe10:786f"));
2167 EXPECT_FALSE(database_
->ContainsMalwareIP("192.1.121.255"));
2168 EXPECT_TRUE(database_
->ContainsMalwareIP("192.1.122.0"));
2169 EXPECT_TRUE(database_
->ContainsMalwareIP("::ffff:192.1.122.1"));
2170 EXPECT_TRUE(database_
->ContainsMalwareIP("192.1.122.255"));
2171 EXPECT_TRUE(database_
->ContainsMalwareIP("192.1.123.0"));
2172 EXPECT_TRUE(database_
->ContainsMalwareIP("192.1.123.255"));
2173 EXPECT_FALSE(database_
->ContainsMalwareIP("192.1.124.0"));
2175 EXPECT_FALSE(database_
->ContainsMalwareIP("192.1.127.255"));
2176 EXPECT_TRUE(database_
->ContainsMalwareIP("192.1.128.0"));
2177 EXPECT_TRUE(database_
->ContainsMalwareIP("::ffff:192.1.128.1"));
2178 EXPECT_TRUE(database_
->ContainsMalwareIP("192.1.128.255"));
2179 EXPECT_TRUE(database_
->ContainsMalwareIP("192.1.255.0"));
2180 EXPECT_TRUE(database_
->ContainsMalwareIP("192.1.255.255"));
2181 EXPECT_FALSE(database_
->ContainsMalwareIP("192.2.0.0"));
2184 TEST_F(SafeBrowsingDatabaseTest
, ContainsBrowseURL
) {
2185 std::vector
<SBListChunkRanges
> lists
;
2186 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
2188 // Add a host-level hit.
2190 ScopedVector
<SBChunkData
> chunks
;
2191 chunks
.push_back(AddChunkPrefixValue(1, "www.evil.com/"));
2192 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
2195 // Add a specific fullhash.
2196 static const char kWhateverMalware
[] = "www.whatever.com/malware.html";
2198 ScopedVector
<SBChunkData
> chunks
;
2199 chunks
.push_back(AddChunkFullHashValue(2, kWhateverMalware
));
2200 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
2203 // Add a fullhash which has a prefix collision for a known url.
2204 static const char kExampleFine
[] = "www.example.com/fine.html";
2205 static const char kExampleCollision
[] =
2206 "www.example.com/3123364814/malware.htm";
2207 ASSERT_EQ(SBPrefixForString(kExampleFine
),
2208 SBPrefixForString(kExampleCollision
));
2210 ScopedVector
<SBChunkData
> chunks
;
2211 chunks
.push_back(AddChunkFullHashValue(3, kExampleCollision
));
2212 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
2215 database_
->UpdateFinished(true);
2217 std::vector
<SBPrefix
> prefix_hits
;
2218 std::vector
<SBFullHashResult
> cache_hits
;
2220 // Anything will hit the host prefix.
2221 EXPECT_TRUE(database_
->ContainsBrowseUrl(
2222 GURL("http://www.evil.com/malware.html"), &prefix_hits
, &cache_hits
));
2223 ASSERT_EQ(1U, prefix_hits
.size());
2224 EXPECT_EQ(SBPrefixForString("www.evil.com/"), prefix_hits
[0]);
2225 EXPECT_TRUE(cache_hits
.empty());
2227 // Hit the specific URL prefix.
2228 EXPECT_TRUE(database_
->ContainsBrowseUrl(
2229 GURL(std::string("http://") + kWhateverMalware
),
2230 &prefix_hits
, &cache_hits
));
2231 ASSERT_EQ(1U, prefix_hits
.size());
2232 EXPECT_EQ(SBPrefixForString(kWhateverMalware
), prefix_hits
[0]);
2233 EXPECT_TRUE(cache_hits
.empty());
2235 // Other URLs at that host are fine.
2236 EXPECT_FALSE(database_
->ContainsBrowseUrl(
2237 GURL("http://www.whatever.com/fine.html"), &prefix_hits
, &cache_hits
));
2238 EXPECT_TRUE(prefix_hits
.empty());
2239 EXPECT_TRUE(cache_hits
.empty());
2241 // Hit the specific URL full hash.
2242 EXPECT_TRUE(database_
->ContainsBrowseUrl(
2243 GURL(std::string("http://") + kExampleCollision
),
2244 &prefix_hits
, &cache_hits
));
2245 ASSERT_EQ(1U, prefix_hits
.size());
2246 EXPECT_EQ(SBPrefixForString(kExampleCollision
), prefix_hits
[0]);
2247 EXPECT_TRUE(cache_hits
.empty());
2249 // This prefix collides, but no full hash match.
2250 EXPECT_FALSE(database_
->ContainsBrowseUrl(
2251 GURL(std::string("http://") + kExampleFine
), &prefix_hits
, &cache_hits
));