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/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"
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 virtual void SetUp() {
258 PlatformTest::SetUp();
260 // Setup a database in a temporary directory.
261 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
262 database_
.reset(new SafeBrowsingDatabaseNew
);
264 temp_dir_
.path().AppendASCII("SafeBrowsingTestDatabase");
265 database_
->Init(database_filename_
);
268 virtual void TearDown() {
271 PlatformTest::TearDown();
274 void GetListsInfo(std::vector
<SBListChunkRanges
>* lists
) {
276 ASSERT_TRUE(database_
->UpdateStarted(lists
));
277 database_
->UpdateFinished(true);
280 // Helper function to do an AddDel or SubDel command.
281 void DelChunk(const std::string
& list
,
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
);
293 void AddDelChunk(const std::string
& list
, int chunk_id
) {
294 DelChunk(list
, chunk_id
, false);
297 void SubDelChunk(const std::string
& list
, int chunk_id
) {
298 DelChunk(list
, chunk_id
, true);
301 // Utility function for setting up the database for the caching test.
302 void PopulateDatabaseForCacheTest();
304 scoped_ptr
<SafeBrowsingDatabaseNew
> database_
;
305 base::FilePath database_filename_
;
306 base::ScopedTempDir temp_dir_
;
309 // Tests retrieving list name information.
310 TEST_F(SafeBrowsingDatabaseTest
, ListNameForBrowse
) {
311 std::vector
<SBListChunkRanges
> lists
;
312 ScopedVector
<SBChunkData
> chunks
;
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"));
318 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
319 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
320 database_
->UpdateFinished(true);
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());
328 // Insert a malware sub chunk.
330 chunks
.push_back(SubChunkPrefixValue(7, "www.subbed.com/noteveil1.html", 19));
332 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
333 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
334 database_
->UpdateFinished(true);
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());
350 // Add phishing chunks.
352 chunks
.push_back(AddChunkPrefixValue(47, "www.evil.com/phishing.html"));
354 SubChunkPrefixValue(200, "www.phishy.com/notevil1.html", 1999));
356 SubChunkPrefixValue(201, "www.phishy2.com/notevil1.html", 1999));
358 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
359 database_
->InsertChunks(safe_browsing_util::kPhishingList
, chunks
.get());
360 database_
->UpdateFinished(true);
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
);
372 TEST_F(SafeBrowsingDatabaseTest
, ListNameForBrowseAndDownload
) {
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
,
385 download_whitelist_store
,
386 extension_blacklist_store
,
388 ip_blacklist_store
));
389 database_
->Init(database_filename_
);
391 ScopedVector
<SBChunkData
> chunks
;
393 std::vector
<SBListChunkRanges
> lists
;
394 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
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());
401 chunks
.push_back(AddChunkPrefixValue(2, "www.foo.com/malware.html"));
402 database_
->InsertChunks(safe_browsing_util::kPhishingList
, chunks
.get());
405 chunks
.push_back(AddChunkPrefixValue(3, "www.whatever.com/download.html"));
406 database_
->InsertChunks(safe_browsing_util::kBinUrlList
, chunks
.get());
409 chunks
.push_back(AddChunkFullHashValue(5, "www.forwhitelist.com/a.html"));
410 database_
->InsertChunks(safe_browsing_util::kCsdWhiteList
, chunks
.get());
413 chunks
.push_back(AddChunkFullHashValue(6, "www.download.com/"));
414 database_
->InsertChunks(safe_browsing_util::kDownloadWhiteList
, chunks
.get());
417 chunks
.push_back(AddChunkFullHashValue(8,
418 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
419 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
420 database_
->InsertChunks(safe_browsing_util::kExtensionBlacklist
,
424 chunks
.push_back(AddChunkHashedIpValue(9, "::ffff:192.168.1.0", 120));
425 database_
->InsertChunks(safe_browsing_util::kIPBlacklist
, chunks
.get());
427 database_
->UpdateFinished(true);
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());
456 // Checks database reading and writing for browse.
457 TEST_F(SafeBrowsingDatabaseTest
, BrowseDatabase
) {
458 std::vector
<SBListChunkRanges
> lists
;
459 ScopedVector
<SBChunkData
> chunks
;
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"));
472 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
473 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
474 database_
->UpdateFinished(true);
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());
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());
491 EXPECT_TRUE(database_
->ContainsBrowseUrl(
492 GURL("http://www.evil.com/malware.html"), &prefix_hits
, &cache_hits
));
494 EXPECT_TRUE(database_
->ContainsBrowseUrl(
495 GURL("http://www.evil.com/notevil1.html"), &prefix_hits
, &cache_hits
));
497 EXPECT_TRUE(database_
->ContainsBrowseUrl(
498 GURL("http://www.evil.com/notevil2.html"), &prefix_hits
, &cache_hits
));
500 EXPECT_TRUE(database_
->ContainsBrowseUrl(
501 GURL("http://www.good.com/good1.html"), &prefix_hits
, &cache_hits
));
503 EXPECT_TRUE(database_
->ContainsBrowseUrl(
504 GURL("http://www.good.com/good2.html"), &prefix_hits
, &cache_hits
));
506 EXPECT_TRUE(database_
->ContainsBrowseUrl(
507 GURL("http://192.168.0.1/malware.html"), &prefix_hits
, &cache_hits
));
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());
514 EXPECT_FALSE(database_
->ContainsBrowseUrl(
515 GURL("http://www.evil.com/robots.txt"), &prefix_hits
, &cache_hits
));
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]);
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
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);
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());
538 // Test removing a single prefix from the add chunk.
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);
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());
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());
556 EXPECT_TRUE(database_
->ContainsBrowseUrl(
557 GURL("http://www.evil.com/notevil2.html"), &prefix_hits
, &cache_hits
));
559 EXPECT_TRUE(database_
->ContainsBrowseUrl(
560 GURL("http://www.good.com/good1.html"), &prefix_hits
, &cache_hits
));
562 EXPECT_TRUE(database_
->ContainsBrowseUrl(
563 GURL("http://www.good.com/good2.html"), &prefix_hits
, &cache_hits
));
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
);
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
574 chunks
.push_back(SubChunkPrefixValue(4, "www.evil.com/notevil1.html", 2));
576 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
577 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
578 database_
->UpdateFinished(true);
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
);
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);
591 EXPECT_FALSE(database_
->ContainsBrowseUrl(
592 GURL("http://www.evil.com/notevil2.html"), &prefix_hits
, &cache_hits
));
594 EXPECT_FALSE(database_
->ContainsBrowseUrl(
595 GURL("http://www.good.com/good1.html"), &prefix_hits
, &cache_hits
));
597 EXPECT_FALSE(database_
->ContainsBrowseUrl(
598 GURL("http://www.good.com/good2.html"), &prefix_hits
, &cache_hits
));
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
);
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.
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());
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);
618 // Test the subdel command.
619 SubDelChunk(safe_browsing_util::kMalwareList
, 4);
620 database_
->UpdateFinished(true);
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());
628 // Test a sub command coming in before the add.
630 chunks
.push_back(SubChunkPrefix2Value(5,
631 "www.notevilanymore.com/index.html",
633 "www.notevilanymore.com/good.html",
635 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
636 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
637 database_
->UpdateFinished(true);
639 EXPECT_FALSE(database_
->ContainsBrowseUrl(
640 GURL("http://www.notevilanymore.com/index.html"),
644 // Now insert the tardy add chunk and we don't expect them to appear
645 // in database because of the previous sub chunk.
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);
654 EXPECT_FALSE(database_
->ContainsBrowseUrl(
655 GURL("http://www.notevilanymore.com/index.html"),
659 EXPECT_FALSE(database_
->ContainsBrowseUrl(
660 GURL("http://www.notevilanymore.com/good.html"),
664 // Reset and reload the database. The database will rely on the prefix set.
665 database_
.reset(new SafeBrowsingDatabaseNew
);
666 database_
->Init(database_filename_
);
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]);
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
));
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]);
685 // Test adding zero length chunks to the database.
686 TEST_F(SafeBrowsingDatabaseTest
, ZeroSizeChunk
) {
687 std::vector
<SBListChunkRanges
> lists
;
688 ScopedVector
<SBChunkData
> chunks
;
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"));
698 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
699 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
700 database_
->UpdateFinished(true);
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());
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>()));
717 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
718 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
719 database_
->UpdateFinished(true);
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
);
727 // Add an empty chunk along with a couple that contain data. This should
728 // result in the chunk range being reduced in size.
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"));
736 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
737 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
738 database_
->UpdateFinished(true);
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
));
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
);
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);
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
);
764 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
765 SubDelChunk(safe_browsing_util::kMalwareList
, 7);
766 database_
->UpdateFinished(true);
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());
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"));
783 std::vector
<SBListChunkRanges
> lists
;
784 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
785 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
786 database_
->UpdateFinished(true);
788 // Cache should be cleared after updating.
789 EXPECT_TRUE(database_
->browse_gethash_cache_
.empty());
791 SBFullHashResult full_hash
;
792 full_hash
.list_id
= safe_browsing_util::MALWARE
;
794 std::vector
<SBFullHashResult
> results
;
795 std::vector
<SBPrefix
> prefixes
;
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
);
802 full_hash
.hash
= SBFullHashForString("www.evil.com/malware.html");
803 results
.push_back(full_hash
);
804 prefixes
.push_back(full_hash
.hash
.prefix
);
806 database_
->CacheHashResults(prefixes
, results
, kCacheLifetime
);
809 TEST_F(SafeBrowsingDatabaseTest
, HashCaching
) {
810 PopulateDatabaseForCacheTest();
812 // We should have both full hashes in the cache.
813 EXPECT_EQ(2U, database_
->browse_gethash_cache_
.size());
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")));
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")));
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));
843 std::vector
<SBListChunkRanges
> lists
;
844 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
845 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
846 database_
->UpdateFinished(true);
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());
857 // This prefix should be gone.
858 EXPECT_FALSE(database_
->ContainsBrowseUrl(
859 GURL("http://www.evil.com/phishing.html"), &prefix_hits
, &cache_hits
));
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());
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();
878 std::map
<SBPrefix
, SBCachedFullHashResult
>* hash_cache
=
879 &database_
->browse_gethash_cache_
;
880 EXPECT_EQ(2U, hash_cache
->size());
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);
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());
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());
902 // Testing prefix miss caching. First, we clear out the existing database,
903 // Since PopulateDatabaseForCacheTest() doesn't handle adding duplicate
905 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
906 AddDelChunk(safe_browsing_util::kMalwareList
, 1);
907 database_
->UpdateFinished(true);
909 // Cache should be cleared after updating.
910 EXPECT_TRUE(hash_cache
->empty());
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
);
919 // Prefixes with no full results are misses.
920 EXPECT_EQ(hash_cache
->size(), prefix_misses
.size());
922 hash_cache
->count(SBPrefixForString("http://www.bad.com/malware.html")));
924 hash_cache
->find(SBPrefixForString("http://www.bad.com/malware.html"))
925 ->second
.full_hashes
.empty());
927 hash_cache
->count(SBPrefixForString("http://www.bad.com/phishing.html")));
929 hash_cache
->find(SBPrefixForString("http://www.bad.com/phishing.html"))
930 ->second
.full_hashes
.empty());
932 // Update the database.
933 PopulateDatabaseForCacheTest();
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
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
));
949 // Test receiving a full add chunk.
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);
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());
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());
974 // Test receiving a full sub chunk, which will remove one of the full adds.
976 chunks
.push_back(SubChunkFullHashValue(200,
977 "www.fullevil.com/bad1.html",
979 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
980 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
981 database_
->UpdateFinished(true);
983 EXPECT_FALSE(database_
->ContainsBrowseUrl(
984 GURL("http://www.fullevil.com/bad1.html"), &prefix_hits
, &cache_hits
));
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());
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);
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
));
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
));
1013 ScopedVector
<SBChunkData
> chunks
;
1014 chunks
.push_back(AddChunkPrefixValue(21, kExampleCollision
));
1015 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
1017 database_
->UpdateFinished(true);
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());
1027 // Cache gethash response for |kExampleCollision|.
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
),
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
));
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
1051 base::MessageLoop loop
;
1052 SafeBrowsingStoreFile
* store
= new SafeBrowsingStoreFile();
1053 database_
.reset(new SafeBrowsingDatabaseNew(store
, NULL
, NULL
, NULL
, NULL
,
1055 database_
->Init(database_filename_
);
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);
1062 // Create a sub chunk to insert.
1063 ScopedVector
<SBChunkData
> chunks
;
1064 chunks
.push_back(SubChunkPrefixValue(7,
1065 "www.subbed.com/notevil1.html",
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+");
1072 ASSERT_NE(-1, fseek(fp
, -8, SEEK_END
));
1073 for (size_t i
= 0; i
< 8; ++i
) {
1079 // The following code will cause DCHECKs, so suppress the crashes.
1080 ScopedLogMessageIgnorer ignorer
;
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);
1087 // Database file still exists until the corruption handler has run.
1088 EXPECT_TRUE(base::PathExists(database_filename_
));
1090 // Flush through the corruption-handler task.
1091 VLOG(1) << "Expect failed check on: SafeBrowsing database reset";
1092 base::MessageLoop::current()->RunUntilIdle();
1095 // Database file should not exist.
1096 EXPECT_FALSE(base::PathExists(database_filename_
));
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_
));
1107 // Checks database reading and writing.
1108 TEST_F(SafeBrowsingDatabaseTest
, ContainsDownloadUrl
) {
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
,
1116 csd_whitelist_store
,
1121 database_
->Init(database_filename_
);
1123 const char kEvil1Url1
[] = "www.evil1.com/download1/";
1124 const char kEvil1Url2
[] = "www.evil1.com/download2.html";
1126 // Add a simple chunk with one hostkey for download url list.
1127 ScopedVector
<SBChunkData
> chunks
;
1128 chunks
.push_back(AddChunkPrefix2Value(1, kEvil1Url1
, kEvil1Url2
));
1130 std::vector
<SBListChunkRanges
> lists
;
1131 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1132 database_
->InsertChunks(safe_browsing_util::kBinUrlList
, chunks
.get());
1133 database_
->UpdateFinished(true);
1135 std::vector
<SBPrefix
> prefix_hits
;
1136 std::vector
<GURL
> urls(1);
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]);
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]);
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]);
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]);
1158 urls
[0] = GURL("http://www.randomevil.com");
1159 EXPECT_FALSE(database_
->ContainsDownloadUrl(urls
, &prefix_hits
));
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]);
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]);
1173 // First hit in redirect chain is malware.
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]);
1181 // Middle hit in redirect chain is malware.
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]);
1190 // Final hit in redirect chain is malware.
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]);
1198 // Multiple hits in redirect chain are in malware list.
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]);
1209 // Checks that the whitelists are handled properly.
1210 TEST_F(SafeBrowsingDatabaseTest
, Whitelists
) {
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_
;
1217 // If the whitelist is disabled everything should match the whitelist.
1218 database_
.reset(new SafeBrowsingDatabaseNew(new SafeBrowsingStoreFile(),
1219 NULL
, NULL
, NULL
, NULL
, 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"));
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
,
1238 database_
->Init(database_filename_
);
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/";
1244 const char kGood2Url1
[] = "www.good2.com/c"; // Should match '/c/bla'.
1246 // good3.com/a/b/c/d/e/f/g/ should match because it's a whitelist.
1247 const char kGood3Url1
[] = "good3.com/";
1249 const char kGoodString
[] = "good_string";
1251 ScopedVector
<SBChunkData
> csd_chunks
;
1252 ScopedVector
<SBChunkData
> download_chunks
;
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
));
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);
1268 EXPECT_FALSE(database_
->ContainsCsdWhitelistedUrl(
1269 GURL(std::string("http://") + kGood1Host
)));
1271 EXPECT_TRUE(database_
->ContainsCsdWhitelistedUrl(
1272 GURL(std::string("http://") + kGood1Url1
)));
1273 EXPECT_TRUE(database_
->ContainsCsdWhitelistedUrl(
1274 GURL(std::string("http://") + kGood1Url1
+ "?a=b")));
1276 EXPECT_TRUE(database_
->ContainsCsdWhitelistedUrl(
1277 GURL(std::string("http://") + kGood1Url2
)));
1278 EXPECT_TRUE(database_
->ContainsCsdWhitelistedUrl(
1279 GURL(std::string("http://") + kGood1Url2
+ "/c.html")));
1281 EXPECT_TRUE(database_
->ContainsCsdWhitelistedUrl(
1282 GURL(std::string("https://") + kGood1Url2
+ "/c.html")));
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")));
1291 EXPECT_FALSE(database_
->ContainsCsdWhitelistedUrl(
1292 GURL(std::string("http://www.google.com/"))));
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")));
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/"))));
1306 EXPECT_FALSE(database_
->ContainsDownloadWhitelistedString("asdf"));
1307 EXPECT_TRUE(database_
->ContainsDownloadWhitelistedString(kGoodString
));
1309 EXPECT_FALSE(database_
->ContainsDownloadWhitelistedUrl(
1310 GURL(std::string("http://www.google.com/"))));
1312 // The CSD whitelist killswitch is not present.
1313 EXPECT_FALSE(database_
->IsCsdWhitelistKillSwitchOn());
1315 // Test only add the malware IP killswitch
1317 csd_chunks
.push_back(AddChunkFullHashValue(
1318 15, "sb-ssl.google.com/safebrowsing/csd/killswitch_malware"));
1320 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1321 database_
->InsertChunks(safe_browsing_util::kCsdWhiteList
, csd_chunks
.get());
1322 database_
->UpdateFinished(true);
1324 EXPECT_TRUE(database_
->IsMalwareIPMatchKillSwitchOn());
1325 // The CSD whitelist killswitch is not present.
1326 EXPECT_FALSE(database_
->IsCsdWhitelistKillSwitchOn());
1328 // Test that the kill-switch works as intended.
1330 download_chunks
.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"));
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);
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/"))));
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/"))));
1360 EXPECT_TRUE(database_
->ContainsDownloadWhitelistedString("asdf"));
1361 EXPECT_TRUE(database_
->ContainsDownloadWhitelistedString(kGoodString
));
1363 // Remove the kill-switch and verify that we can recover.
1365 download_chunks
.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));
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);
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/"))));
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"));
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
;
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"));
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);
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());
1427 // Add a phishing add chunk with two entries of the same host.
1429 chunks
.push_back(AddChunkPrefix2Value(47,
1430 "www.evil.com/phishing1.html",
1431 "www.evil.com/phishing2.html"));
1433 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1434 database_
->InsertChunks(safe_browsing_util::kPhishingList
, chunks
.get());
1435 database_
->UpdateFinished(true);
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());
1446 std::vector
<SBPrefix
> prefix_hits
;
1447 std::vector
<SBFullHashResult
> cache_hits
;
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
));
1458 // Test removing a single prefix from the add chunk.
1459 // Remove the prefix that added first.
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);
1466 // Remove the prefix that added last.
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);
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
));
1484 // Test that an empty update doesn't actually update the database.
1485 // This isn't a functionality requirement, but it is a useful
1487 TEST_F(SafeBrowsingDatabaseTest
, EmptyUpdate
) {
1488 ScopedVector
<SBChunkData
> chunks
;
1490 base::FilePath filename
= database_
->BrowseDBFilename(database_filename_
);
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);
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);
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
);
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
);
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
);
1537 // Test that a filter file is written out during update and read back
1539 TEST_F(SafeBrowsingDatabaseTest
, FilterFile
) {
1540 // Create a database with trivial example data and write it out.
1542 // Prime the database.
1543 std::vector
<SBListChunkRanges
> lists
;
1544 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
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);
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
));
1560 base::FilePath filter_file
= database_
->PrefixSetForFilename(
1561 database_
->BrowseDBFilename(database_filename_
));
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
));
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
));
1584 TEST_F(SafeBrowsingDatabaseTest
, CachedFullMiss
) {
1585 const SBPrefix kPrefix1
= 1001U;
1586 const SBFullHash kFullHash1_1
=
1587 SBFullHashForPrefixAndSuffix(kPrefix1
, "\x01");
1589 const SBPrefix kPrefix2
= 1002U;
1590 const SBFullHash kFullHash2_1
=
1591 SBFullHashForPrefixAndSuffix(kPrefix2
, "\x01");
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
));
1598 std::vector
<SBListChunkRanges
> lists
;
1599 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1600 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
1601 database_
->UpdateFinished(true);
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
);
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
));
1619 // kFullHash2_1 gets a hit from the prefix in the database.
1620 full_hashes
.push_back(kFullHash2_1
);
1621 prefix_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());
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");
1640 const SBPrefix kPrefix2
= 1002U;
1641 const SBFullHash kFullHash2_1
=
1642 SBFullHashForPrefixAndSuffix(kPrefix2
, "\x01");
1644 const SBPrefix kPrefix3
= 1003U;
1645 const SBFullHash kFullHash3_1
=
1646 SBFullHashForPrefixAndSuffix(kPrefix3
, "\x01");
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
));
1653 std::vector
<SBListChunkRanges
> lists
;
1654 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1655 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
1656 database_
->UpdateFinished(true);
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());
1670 // kFullHash2_1 has a prefix hit of kPrefix2.
1671 full_hashes
.push_back(kFullHash2_1
);
1672 prefix_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());
1681 // kFullHash3_1 has no hits.
1682 full_hashes
.push_back(kFullHash3_1
);
1683 prefix_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());
1694 // Cache a fullhash result for two kPrefix1 full hashes.
1695 std::vector
<SBPrefix
> prefixes(1, kPrefix1
);
1696 std::vector
<SBFullHashResult
> cache_results
;
1698 SBFullHashResult full_hash_result
;
1699 full_hash_result
.list_id
= safe_browsing_util::MALWARE
;
1701 full_hash_result
.hash
= kFullHash1_1
;
1702 cache_results
.push_back(full_hash_result
);
1704 full_hash_result
.hash
= kFullHash1_3
;
1705 cache_results
.push_back(full_hash_result
);
1707 database_
->CacheHashResults(prefixes
, cache_results
, kCacheLifetime
);
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
));
1721 // Adding kFullHash2_1 will see the existing cache hit plus the prefix hit
1723 full_hashes
.push_back(kFullHash2_1
);
1724 prefix_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
));
1733 // kFullHash1_3 also gets a cache hit.
1734 full_hashes
.push_back(kFullHash1_3
);
1735 prefix_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
));
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
));
1759 // kFullHash1_2 has no cache hit, and no prefix hit because of the cache for
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
));
1767 // Other prefix hits possible when kFullHash1_2 hits nothing.
1768 full_hashes
.push_back(kFullHash2_1
);
1769 prefix_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());
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");
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
));
1793 std::vector
<SBListChunkRanges
> lists
;
1794 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1795 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
1796 database_
->UpdateFinished(true);
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
));
1806 // Also one which is present, should have a prefix hit.
1807 full_hashes
.push_back(kFullHash1_1
);
1808 prefix_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());
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();
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());
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
;
1833 std::vector
<SBPrefix
> prefixes(1, kPrefix1
);
1834 std::vector
<SBFullHashResult
> cache_results(1, full_hash_result
);
1836 database_
->CacheHashResults(prefixes
, cache_results
, kCacheLifetime
);
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
));
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
);
1853 EXPECT_FALSE(database_
->ContainsBrowseUrlHashes(
1854 full_hashes
, &prefix_hits
, &cache_hits
));
1856 // kFullHash1_2 is in the cached result.
1857 full_hashes
.push_back(kFullHash1_2
);
1858 prefix_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
));
1867 // Remove kFullHash1_1 from the database.
1869 chunks
.push_back(SubChunkFullHash(11, kFullHash1_1
, 1));
1871 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1872 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
1873 database_
->UpdateFinished(true);
1875 // Cache should be cleared after updating.
1876 EXPECT_TRUE(database_
->browse_gethash_cache_
.empty());
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
));
1886 // Nor kFullHash1_3.
1887 full_hashes
.push_back(kFullHash1_3
);
1888 prefix_hits
.clear();
1890 EXPECT_FALSE(database_
->ContainsBrowseUrlHashes(
1891 full_hashes
, &prefix_hits
, &cache_hits
));
1893 // Still has kFullHash1_2.
1894 full_hashes
.push_back(kFullHash1_2
);
1895 prefix_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());
1904 // Remove kFullHash1_2 from the database.
1906 chunks
.push_back(SubChunkFullHash(12, kFullHash1_2
, 2));
1908 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1909 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
1910 database_
->UpdateFinished(true);
1912 // Cache should be cleared after updating.
1913 EXPECT_TRUE(database_
->browse_gethash_cache_
.empty());
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
));
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");
1935 ScopedVector
<SBChunkData
> chunks
;
1936 chunks
.push_back(AddChunkFullHash(1, kFullHash1_1
));
1938 std::vector
<SBListChunkRanges
> lists
;
1939 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1940 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
1941 database_
->UpdateFinished(true);
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
));
1952 // Add a prefix match.
1954 chunks
.push_back(AddChunkPrefix(2, kPrefix1
));
1956 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1957 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
1958 database_
->UpdateFinished(true);
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());
1972 // Remove the full hash.
1974 chunks
.push_back(SubChunkFullHash(11, kFullHash1_1
, 1));
1976 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
1977 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
1978 database_
->UpdateFinished(true);
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());
1993 TEST_F(SafeBrowsingDatabaseTest
, MalwareIpBlacklist
) {
1995 SafeBrowsingStoreFile
* browse_store
= new SafeBrowsingStoreFile();
1996 SafeBrowsingStoreFile
* ip_blacklist_store
= new SafeBrowsingStoreFile();
1997 database_
.reset(new SafeBrowsingDatabaseNew(browse_store
,
2003 ip_blacklist_store
));
2004 database_
->Init(database_filename_
);
2005 std::vector
<SBListChunkRanges
> lists
;
2006 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
2008 ScopedVector
<SBChunkData
> chunks
;
2010 // IPv4 prefix match for ::ffff:192.168.1.0/120.
2011 chunks
.push_back(AddChunkHashedIpValue(1, "::ffff:192.168.1.0", 120));
2013 // IPv4 exact match for ::ffff:192.1.1.1.
2014 chunks
.push_back(AddChunkHashedIpValue(2, "::ffff:192.1.1.1", 128));
2016 // IPv6 exact match for: fe80::31a:a0ff:fe10:786e/128.
2017 chunks
.push_back(AddChunkHashedIpValue(3, "fe80::31a:a0ff:fe10:786e", 128));
2019 // IPv6 prefix match for: 2620:0:1000:3103::/64.
2020 chunks
.push_back(AddChunkHashedIpValue(4, "2620:0:1000:3103::", 64));
2022 // IPv4 prefix match for ::ffff:192.1.122.0/119.
2023 chunks
.push_back(AddChunkHashedIpValue(5, "::ffff:192.1.122.0", 119));
2025 // IPv4 prefix match for ::ffff:192.1.128.0/113.
2026 chunks
.push_back(AddChunkHashedIpValue(6, "::ffff:192.1.128.0", 113));
2028 database_
->InsertChunks(safe_browsing_util::kIPBlacklist
, chunks
.get());
2029 database_
->UpdateFinished(true);
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"));
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"));
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::"));
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"));
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"));
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"));
2070 TEST_F(SafeBrowsingDatabaseTest
, ContainsBrowseURL
) {
2071 std::vector
<SBListChunkRanges
> lists
;
2072 ASSERT_TRUE(database_
->UpdateStarted(&lists
));
2074 // Add a host-level hit.
2076 ScopedVector
<SBChunkData
> chunks
;
2077 chunks
.push_back(AddChunkPrefixValue(1, "www.evil.com/"));
2078 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
2081 // Add a specific fullhash.
2082 static const char kWhateverMalware
[] = "www.whatever.com/malware.html";
2084 ScopedVector
<SBChunkData
> chunks
;
2085 chunks
.push_back(AddChunkFullHashValue(2, kWhateverMalware
));
2086 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
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
));
2096 ScopedVector
<SBChunkData
> chunks
;
2097 chunks
.push_back(AddChunkFullHashValue(3, kExampleCollision
));
2098 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
.get());
2101 database_
->UpdateFinished(true);
2103 std::vector
<SBPrefix
> prefix_hits
;
2104 std::vector
<SBFullHashResult
> cache_hits
;
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());
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());
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());
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());
2135 // This prefix collides, but no full hash match.
2136 EXPECT_FALSE(database_
->ContainsBrowseUrl(
2137 GURL(std::string("http://") + kExampleFine
), &prefix_hits
, &cache_hits
));