blob: efa64f247484be5db39b8837d3c59c6e75668859 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/safe_browsing/local_database_manager.h"
#include <stddef.h>
#include <memory>
#include <string>
#include <vector>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "chrome/browser/safe_browsing/safe_browsing_service.h"
#include "components/safe_browsing/db/v4_get_hash_protocol_manager.h"
#include "components/safe_browsing/db/v4_protocol_manager_util.h"
#include "components/safe_browsing/db/v4_test_util.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
#include "net/url_request/url_request_context_getter.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
#include "url/gurl.h"
using content::TestBrowserThreadBundle;
namespace safe_browsing {
class LocalDatabaseManagerTest : public PlatformTest {
public:
struct HostListPair {
std::string host;
std::string list_type;
};
bool RunSBHashTest(const ListType list_type,
const SBThreatTypeSet& expected_threats,
const std::vector<std::string>& result_lists);
bool RunUrlTest(const GURL& url,
ListType list_type,
const SBThreatTypeSet& expected_threats,
const std::vector<HostListPair>& host_list_results);
// Constant values used in tests.
const SBThreatTypeSet malware_threat_ =
CreateSBThreatTypeSet({SB_THREAT_TYPE_URL_BINARY_MALWARE});
const SBThreatTypeSet multiple_threats_ = CreateSBThreatTypeSet(
{SB_THREAT_TYPE_URL_MALWARE, SB_THREAT_TYPE_URL_PHISHING});
const SBThreatTypeSet unwanted_threat_ =
CreateSBThreatTypeSet({SB_THREAT_TYPE_URL_UNWANTED});
private:
bool RunTest(std::unique_ptr<
LocalSafeBrowsingDatabaseManager::SafeBrowsingCheck> check,
const std::vector<SBFullHashResult>& hash_results);
TestBrowserThreadBundle thread_bundle_;
};
bool LocalDatabaseManagerTest::RunSBHashTest(
const ListType list_type,
const SBThreatTypeSet& expected_threats,
const std::vector<std::string>& result_lists) {
const SBFullHash same_full_hash = {};
std::unique_ptr<LocalSafeBrowsingDatabaseManager::SafeBrowsingCheck> check(
new LocalSafeBrowsingDatabaseManager::SafeBrowsingCheck(
std::vector<GURL>(), std::vector<SBFullHash>(1, same_full_hash), NULL,
list_type, expected_threats));
std::vector<SBFullHashResult> fake_results;
for (const auto& result_list : result_lists) {
const SBFullHashResult full_hash_result = {same_full_hash,
GetListId(result_list)};
fake_results.push_back(full_hash_result);
}
return RunTest(std::move(check), fake_results);
}
bool LocalDatabaseManagerTest::RunUrlTest(
const GURL& url,
ListType list_type,
const SBThreatTypeSet& expected_threats,
const std::vector<HostListPair>& host_list_results) {
std::unique_ptr<LocalSafeBrowsingDatabaseManager::SafeBrowsingCheck> check(
new LocalSafeBrowsingDatabaseManager::SafeBrowsingCheck(
std::vector<GURL>(1, url), std::vector<SBFullHash>(), NULL, list_type,
expected_threats));
std::vector<SBFullHashResult> full_hash_results;
for (const auto& host_list : host_list_results) {
SBFullHashResult hash_result =
{SBFullHashForString(host_list.host), GetListId(host_list.list_type)};
full_hash_results.push_back(hash_result);
}
return RunTest(std::move(check), full_hash_results);
}
bool LocalDatabaseManagerTest::RunTest(
std::unique_ptr<LocalSafeBrowsingDatabaseManager::SafeBrowsingCheck> check,
const std::vector<SBFullHashResult>& hash_results) {
scoped_refptr<SafeBrowsingService> sb_service_(
SafeBrowsingService::CreateSafeBrowsingService());
scoped_refptr<LocalSafeBrowsingDatabaseManager> db_manager_(
new LocalSafeBrowsingDatabaseManager(sb_service_));
LocalSafeBrowsingDatabaseManager::SafeBrowsingCheck* check_ptr = check.get();
db_manager_->checks_[check_ptr] = std::move(check);
bool result = db_manager_->HandleOneCheck(check_ptr, hash_results);
db_manager_->checks_.erase(check_ptr);
return result;
}
TEST_F(LocalDatabaseManagerTest, CheckCorrespondsListTypeForHash) {
EXPECT_FALSE(RunSBHashTest(BINURL, malware_threat_, {kMalwareList}));
EXPECT_TRUE(RunSBHashTest(BINURL, malware_threat_, {kBinUrlList}));
// Check for multiple threats
EXPECT_FALSE(RunSBHashTest(MALWARE, multiple_threats_, {kBinUrlList}));
EXPECT_TRUE(RunSBHashTest(MALWARE, multiple_threats_, {kMalwareList}));
// Check for multiple hash hits
std::vector<std::string> hash_hits = {kMalwareList, kUnwantedUrlList};
EXPECT_TRUE(RunSBHashTest(UNWANTEDURL, unwanted_threat_, hash_hits));
}
TEST_F(LocalDatabaseManagerTest, CheckCorrespondsListTypeForUrl) {
const GURL url("http://www.host.com/index.html");
const std::string host1 = "host.com/";
const std::string host2 = "www.host.com/";
const std::vector<HostListPair> malware_list_result =
{{host1, kMalwareList}};
const std::vector<HostListPair> binurl_list_result =
{{host2, kBinUrlList}};
EXPECT_FALSE(RunUrlTest(url, BINURL, malware_threat_, malware_list_result));
EXPECT_TRUE(RunUrlTest(url, BINURL, malware_threat_, binurl_list_result));
// Check for multiple expected threats
EXPECT_FALSE(RunUrlTest(url, MALWARE, multiple_threats_, binurl_list_result));
EXPECT_TRUE(RunUrlTest(url, MALWARE, multiple_threats_, malware_list_result));
// Check for multiple database hits
std::vector<HostListPair> multiple_results = {
{host1, kMalwareList}, {host2, kUnwantedUrlList}};
EXPECT_TRUE(RunUrlTest(url, UNWANTEDURL, unwanted_threat_, multiple_results));
}
TEST_F(LocalDatabaseManagerTest, GetUrlSeverestThreatType) {
std::vector<SBFullHashResult> full_hashes;
const GURL kMalwareUrl("http://www.malware.com/page.html");
const GURL kPhishingUrl("http://www.phishing.com/page.html");
const GURL kUnwantedUrl("http://www.unwanted.com/page.html");
const GURL kUnwantedAndMalwareUrl(
"http://www.unwantedandmalware.com/page.html");
const GURL kBlacklistedResourceUrl("http://www.blacklisted.com/script.js");
const GURL kUnwantedResourceUrl("http://www.unwantedresource.com/script.js");
const GURL kMalwareResourceUrl("http://www.malwareresource.com/script.js");
const GURL kSafeUrl("http://www.safe.com/page.html");
const SBFullHash kMalwareHostHash = SBFullHashForString("malware.com/");
const SBFullHash kPhishingHostHash = SBFullHashForString("phishing.com/");
const SBFullHash kUnwantedHostHash = SBFullHashForString("unwanted.com/");
const SBFullHash kUnwantedAndMalwareHostHash =
SBFullHashForString("unwantedandmalware.com/");
const SBFullHash kBlacklistedResourceHostHash =
SBFullHashForString("blacklisted.com/");
const SBFullHash kUnwantedResourceHostHash =
SBFullHashForString("unwantedresource.com/");
const SBFullHash kMalwareResourceHostHash =
SBFullHashForString("malwareresource.com/");
const SBFullHash kSafeHostHash = SBFullHashForString("www.safe.com/");
{
SBFullHashResult full_hash;
full_hash.hash = kMalwareHostHash;
full_hash.list_id = static_cast<int>(MALWARE);
full_hashes.push_back(full_hash);
}
{
SBFullHashResult full_hash;
full_hash.hash = kPhishingHostHash;
full_hash.list_id = static_cast<int>(PHISH);
full_hashes.push_back(full_hash);
}
{
SBFullHashResult full_hash;
full_hash.hash = kUnwantedHostHash;
full_hash.list_id = static_cast<int>(UNWANTEDURL);
full_hashes.push_back(full_hash);
}
{
SBFullHashResult full_hash;
full_hash.hash = kBlacklistedResourceHostHash;
full_hash.list_id = static_cast<int>(RESOURCEBLACKLIST);
full_hashes.push_back(full_hash);
}
{
// Add both MALWARE and UNWANTEDURL list IDs for
// kUnwantedAndMalwareHostHash.
SBFullHashResult full_hash_malware;
full_hash_malware.hash = kUnwantedAndMalwareHostHash;
full_hash_malware.list_id = static_cast<int>(MALWARE);
full_hashes.push_back(full_hash_malware);
SBFullHashResult full_hash_unwanted;
full_hash_unwanted.hash = kUnwantedAndMalwareHostHash;
full_hash_unwanted.list_id = static_cast<int>(UNWANTEDURL);
full_hashes.push_back(full_hash_unwanted);
}
{
SBFullHashResult full_hash_unwanted =
{kUnwantedResourceHostHash, static_cast<int>(UNWANTEDURL)};
full_hashes.push_back(full_hash_unwanted);
SBFullHashResult full_hash_resource =
{kUnwantedResourceHostHash, static_cast<int>(RESOURCEBLACKLIST)};
full_hashes.push_back(full_hash_resource);
}
{
SBFullHashResult full_hash_malware =
{kMalwareResourceHostHash, static_cast<int>(MALWARE)};
full_hashes.push_back(full_hash_malware);
SBFullHashResult full_hash_resource =
{kMalwareResourceHostHash, static_cast<int>(RESOURCEBLACKLIST)};
full_hashes.push_back(full_hash_resource);
}
EXPECT_EQ(SB_THREAT_TYPE_URL_MALWARE,
LocalSafeBrowsingDatabaseManager::GetHashSeverestThreatType(
kMalwareHostHash, full_hashes));
EXPECT_EQ(SB_THREAT_TYPE_URL_PHISHING,
LocalSafeBrowsingDatabaseManager::GetHashSeverestThreatType(
kPhishingHostHash, full_hashes));
EXPECT_EQ(SB_THREAT_TYPE_URL_UNWANTED,
LocalSafeBrowsingDatabaseManager::GetHashSeverestThreatType(
kUnwantedHostHash, full_hashes));
EXPECT_EQ(SB_THREAT_TYPE_URL_MALWARE,
LocalSafeBrowsingDatabaseManager::GetHashSeverestThreatType(
kUnwantedAndMalwareHostHash, full_hashes));
EXPECT_EQ(SB_THREAT_TYPE_BLACKLISTED_RESOURCE,
LocalSafeBrowsingDatabaseManager::GetHashSeverestThreatType(
kBlacklistedResourceHostHash, full_hashes));
EXPECT_EQ(SB_THREAT_TYPE_URL_UNWANTED,
LocalSafeBrowsingDatabaseManager::GetHashSeverestThreatType(
kUnwantedResourceHostHash, full_hashes));
EXPECT_EQ(SB_THREAT_TYPE_URL_MALWARE,
LocalSafeBrowsingDatabaseManager::GetHashSeverestThreatType(
kMalwareResourceHostHash, full_hashes));
EXPECT_EQ(SB_THREAT_TYPE_SAFE,
LocalSafeBrowsingDatabaseManager::GetHashSeverestThreatType(
kSafeHostHash, full_hashes));
const size_t kArbitraryValue = 123456U;
size_t index = kArbitraryValue;
EXPECT_EQ(SB_THREAT_TYPE_URL_MALWARE,
LocalSafeBrowsingDatabaseManager::GetUrlSeverestThreatType(
kMalwareUrl, full_hashes, &index));
EXPECT_EQ(0U, index);
EXPECT_EQ(SB_THREAT_TYPE_URL_PHISHING,
LocalSafeBrowsingDatabaseManager::GetUrlSeverestThreatType(
kPhishingUrl, full_hashes, &index));
EXPECT_EQ(1U, index);
EXPECT_EQ(SB_THREAT_TYPE_URL_UNWANTED,
LocalSafeBrowsingDatabaseManager::GetUrlSeverestThreatType(
kUnwantedUrl, full_hashes, &index));
EXPECT_EQ(2U, index);
EXPECT_EQ(SB_THREAT_TYPE_BLACKLISTED_RESOURCE,
LocalSafeBrowsingDatabaseManager::GetUrlSeverestThreatType(
kBlacklistedResourceUrl, full_hashes, &index));
EXPECT_EQ(3U, index);
EXPECT_EQ(SB_THREAT_TYPE_URL_MALWARE,
LocalSafeBrowsingDatabaseManager::GetUrlSeverestThreatType(
kUnwantedAndMalwareUrl, full_hashes, &index));
EXPECT_EQ(4U, index);
EXPECT_EQ(SB_THREAT_TYPE_URL_UNWANTED,
LocalSafeBrowsingDatabaseManager::GetUrlSeverestThreatType(
kUnwantedResourceUrl, full_hashes, &index));
EXPECT_EQ(6U, index);
EXPECT_EQ(SB_THREAT_TYPE_URL_MALWARE,
LocalSafeBrowsingDatabaseManager::GetUrlSeverestThreatType(
kMalwareResourceUrl, full_hashes, &index));
EXPECT_EQ(8U, index);
index = kArbitraryValue;
EXPECT_EQ(SB_THREAT_TYPE_SAFE,
LocalSafeBrowsingDatabaseManager::GetUrlSeverestThreatType(
kSafeUrl, full_hashes, &index));
EXPECT_EQ(kArbitraryValue, index);
}
TEST_F(LocalDatabaseManagerTest, ServiceStopWithPendingChecks) {
scoped_refptr<SafeBrowsingService> sb_service(
SafeBrowsingService::CreateSafeBrowsingService());
scoped_refptr<LocalSafeBrowsingDatabaseManager> db_manager(
new LocalSafeBrowsingDatabaseManager(sb_service));
SafeBrowsingDatabaseManager::Client client;
// Start the service and flush tasks to ensure database is made available.
db_manager->StartOnIOThread(NULL, GetTestV4ProtocolConfig());
content::RunAllTasksUntilIdle();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(db_manager->DatabaseAvailable());
// Start an extension check operation, which is done asynchronously.
std::set<std::string> extension_ids;
extension_ids.insert("testtesttesttesttesttesttesttest");
db_manager->CheckExtensionIDs(extension_ids, &client);
// Stop the service without first flushing above tasks.
db_manager->StopOnIOThread(false);
// Now run posted tasks, whish should include the extension check which has
// been posted to the safe browsing task runner. This should not crash.
content::RunAllTasksUntilIdle();
base::RunLoop().RunUntilIdle();
}
} // namespace safe_browsing