summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlzheng@chromium.org <lzheng@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-16 01:59:11 +0000
committerlzheng@chromium.org <lzheng@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-16 01:59:11 +0000
commit9cadfb34adaf42ad30e398b24ab06e5bc587e57a (patch)
treefeac40cac461f17b3b8decd17f3696de43e0043c
parent58d1666040e4750a0d5662d35b44ab22c891c57c (diff)
downloadchromium_src-9cadfb34adaf42ad30e398b24ab06e5bc587e57a.zip
chromium_src-9cadfb34adaf42ad30e398b24ab06e5bc587e57a.tar.gz
chromium_src-9cadfb34adaf42ad30e398b24ab06e5bc587e57a.tar.bz2
Lookup hash prefix in safebrowsing service.
To achieve that, added an interface in safe browsing database and safe browsing service. TEST=safe_browsing_service_browsertest, safe_browsing_util_unittest, safe_browsing_database_unittest BUG=60822 Review URL: http://codereview.chromium.org/6299007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@75049 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/renderer_host/download_resource_handler.cc2
-rw-r--r--chrome/browser/renderer_host/safe_browsing_resource_handler.cc10
-rw-r--r--chrome/browser/safe_browsing/protocol_manager.cc16
-rw-r--r--chrome/browser/safe_browsing/protocol_manager.h6
-rw-r--r--chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc20
-rw-r--r--chrome/browser/safe_browsing/safe_browsing_database.cc47
-rw-r--r--chrome/browser/safe_browsing/safe_browsing_database.h21
-rw-r--r--chrome/browser/safe_browsing/safe_browsing_database_unittest.cc39
-rw-r--r--chrome/browser/safe_browsing/safe_browsing_service.cc184
-rw-r--r--chrome/browser/safe_browsing/safe_browsing_service.h82
-rw-r--r--chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc151
-rw-r--r--chrome/browser/safe_browsing/safe_browsing_test.cc2
-rw-r--r--chrome/browser/safe_browsing/safe_browsing_util.cc44
-rw-r--r--chrome/browser/safe_browsing/safe_browsing_util.h10
-rw-r--r--chrome/browser/safe_browsing/safe_browsing_util_unittest.cc15
15 files changed, 463 insertions, 186 deletions
diff --git a/chrome/browser/renderer_host/download_resource_handler.cc b/chrome/browser/renderer_host/download_resource_handler.cc
index a297244..246b995 100644
--- a/chrome/browser/renderer_host/download_resource_handler.cc
+++ b/chrome/browser/renderer_host/download_resource_handler.cc
@@ -74,7 +74,7 @@ void DownloadResourceHandler::OnDownloadUrlCheckResult(
UMA_HISTOGRAM_TIMES("SB2.DownloadUrlCheckDuration",
base::TimeTicks::Now() - download_start_time_);
- if (result == SafeBrowsingService::BINARY_MALWARE) {
+ if (result == SafeBrowsingService::BINARY_MALWARE_URL) {
// TODO(lzheng): More UI work to show warnings properly on download shelf.
DLOG(WARNING) << "This url leads to a malware downloading: "
<< url.spec();
diff --git a/chrome/browser/renderer_host/safe_browsing_resource_handler.cc b/chrome/browser/renderer_host/safe_browsing_resource_handler.cc
index a8b171e..32d4a59 100644
--- a/chrome/browser/renderer_host/safe_browsing_resource_handler.cc
+++ b/chrome/browser/renderer_host/safe_browsing_resource_handler.cc
@@ -29,7 +29,7 @@ SafeBrowsingResourceHandler::SafeBrowsingResourceHandler(
ResourceDispatcherHost* resource_dispatcher_host)
: state_(STATE_NONE),
defer_state_(DEFERRED_NONE),
- safe_browsing_result_(SafeBrowsingService::URL_SAFE),
+ safe_browsing_result_(SafeBrowsingService::SAFE),
deferred_request_id_(-1),
next_handler_(handler),
render_process_host_id_(render_process_host_id),
@@ -89,7 +89,7 @@ void SafeBrowsingResourceHandler::OnCheckUrlTimeout() {
CHECK(state_ == STATE_CHECKING_URL);
CHECK(defer_state_ != DEFERRED_NONE);
safe_browsing_->CancelCheck(this);
- OnBrowseUrlCheckResult(deferred_url_, SafeBrowsingService::URL_SAFE);
+ OnBrowseUrlCheckResult(deferred_url_, SafeBrowsingService::SAFE);
}
bool SafeBrowsingResourceHandler::OnWillStart(int request_id,
@@ -149,7 +149,7 @@ void SafeBrowsingResourceHandler::OnBrowseUrlCheckResult(
safe_browsing_result_ = result;
state_ = STATE_NONE;
- if (result == SafeBrowsingService::URL_SAFE) {
+ if (result == SafeBrowsingService::SAFE) {
// Log how much time the safe browsing check cost us.
base::TimeDelta pause_delta;
pause_delta = base::TimeTicks::Now() - url_check_start_time_;
@@ -195,7 +195,7 @@ void SafeBrowsingResourceHandler::OnBlockingPageComplete(bool proceed) {
state_ = STATE_NONE;
if (proceed) {
- safe_browsing_result_ = SafeBrowsingService::URL_SAFE;
+ safe_browsing_result_ = SafeBrowsingService::SAFE;
ResumeRequest();
} else {
rdh_->CancelRequest(render_process_host_id_, deferred_request_id_, false);
@@ -219,7 +219,7 @@ bool SafeBrowsingResourceHandler::CheckUrl(const GURL& url) {
CHECK(state_ == STATE_NONE);
bool succeeded_synchronously = safe_browsing_->CheckBrowseUrl(url, this);
if (succeeded_synchronously) {
- safe_browsing_result_ = SafeBrowsingService::URL_SAFE;
+ safe_browsing_result_ = SafeBrowsingService::SAFE;
safe_browsing_->LogPauseDelay(base::TimeDelta()); // No delay.
return true;
}
diff --git a/chrome/browser/safe_browsing/protocol_manager.cc b/chrome/browser/safe_browsing/protocol_manager.cc
index 2ff5f4c..5e61eca 100644
--- a/chrome/browser/safe_browsing/protocol_manager.cc
+++ b/chrome/browser/safe_browsing/protocol_manager.cc
@@ -126,9 +126,15 @@ SafeBrowsingProtocolManager::SafeBrowsingProtocolManager(
}
// static
-void SafeBrowsingProtocolManager::RecordGetHashResult(ResultType result_type) {
- UMA_HISTOGRAM_ENUMERATION("SB2.GetHashResult", result_type,
- GET_HASH_RESULT_MAX);
+void SafeBrowsingProtocolManager::RecordGetHashResult(
+ bool is_download, ResultType result_type) {
+ if (is_download) {
+ UMA_HISTOGRAM_ENUMERATION("SB2.GetHashResultDownload", result_type,
+ GET_HASH_RESULT_MAX);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION("SB2.GetHashResult", result_type,
+ GET_HASH_RESULT_MAX);
+ }
}
SafeBrowsingProtocolManager::~SafeBrowsingProtocolManager() {
@@ -231,9 +237,9 @@ void SafeBrowsingProtocolManager::OnURLFetchComplete(
// For tracking our GetHash false positive (204) rate, compared to real
// (200) responses.
if (response_code == 200)
- RecordGetHashResult(GET_HASH_STATUS_200);
+ RecordGetHashResult(check->is_download, GET_HASH_STATUS_200);
else
- RecordGetHashResult(GET_HASH_STATUS_204);
+ RecordGetHashResult(check->is_download, GET_HASH_STATUS_204);
can_cache = true;
gethash_error_count_ = 0;
gethash_back_off_mult_ = 1;
diff --git a/chrome/browser/safe_browsing/protocol_manager.h b/chrome/browser/safe_browsing/protocol_manager.h
index 7205b53..994849a 100644
--- a/chrome/browser/safe_browsing/protocol_manager.h
+++ b/chrome/browser/safe_browsing/protocol_manager.h
@@ -188,8 +188,10 @@ class SafeBrowsingProtocolManager : public URLFetcher::Delegate {
GET_HASH_RESULT_MAX
};
- // Record a GetHash result.
- static void RecordGetHashResult(ResultType result_type);
+ // Record a GetHash result. |is_download| indicates if the get
+ // hash is triggered by download related lookup.
+ static void RecordGetHashResult(bool is_download,
+ ResultType result_type);
protected:
// Constructs a SafeBrowsingProtocolManager for |sb_service| that issues
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc
index 318e6ac..0138224 100644
--- a/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc
@@ -35,21 +35,24 @@ class FakeSafeBrowsingService : public SafeBrowsingService {
// can synchronously determine that the url is safe, CheckUrl returns true.
// Otherwise it returns false, and "client" is called asynchronously with the
// result when it is ready.
- // Overrides SafeBrowsingService::CheckUrl.
+ // Overrides SafeBrowsingService::CheckBrowseUrl.
virtual bool CheckBrowseUrl(const GURL& gurl, Client* client) {
- const std::string& url = gurl.spec();
- if (badurls[url] == URL_SAFE)
+ if (badurls[gurl.spec()] == SAFE)
return true;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- NewRunnableMethod(this, &FakeSafeBrowsingService::OnCheckDone,
- url, client));
+ NewRunnableMethod(this, &FakeSafeBrowsingService::OnCheckBrowseURLDone,
+ gurl, client));
return false;
}
- void OnCheckDone(std::string url, Client* client) {
- client->OnSafeBrowsingResult(GURL(url), badurls[url]);
+ void OnCheckBrowseURLDone(const GURL& gurl, Client* client) {
+ SafeBrowsingService::SafeBrowsingCheck check;
+ check.url.reset(new GURL(gurl));
+ check.client = client;
+ check.result = badurls[gurl.spec()];
+ client->OnSafeBrowsingResult(check);
}
void AddURLResult(const GURL& url, UrlCheckResult checkresult) {
@@ -114,8 +117,9 @@ class SafeBrowsingBlockingPageTest : public InProcessBrowserTest,
// SafeBrowsingService::Client implementation.
virtual void OnSafeBrowsingResult(
- const GURL& url, SafeBrowsingService::UrlCheckResult result) {
+ const SafeBrowsingService::SafeBrowsingCheck& check) {
}
+
virtual void OnBlockingPageComplete(bool proceed) {
}
diff --git a/chrome/browser/safe_browsing/safe_browsing_database.cc b/chrome/browser/safe_browsing/safe_browsing_database.cc
index 92ef562..c142907 100644
--- a/chrome/browser/safe_browsing/safe_browsing_database.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_database.cc
@@ -427,30 +427,49 @@ bool SafeBrowsingDatabaseNew::ContainsBrowseUrl(
return true;
}
-bool SafeBrowsingDatabaseNew::ContainsDownloadUrl(
- const GURL& url, std::vector<SBPrefix>* prefix_hits) {
- DCHECK_EQ(creation_loop_, MessageLoop::current());
- prefix_hits->clear();
-
- // Ignore this check when download checking is not enabled.
- if (!download_store_.get()) return false;
-
- SBPrefix prefix;
- GetDownloadUrlPrefix(url, &prefix);
-
+bool SafeBrowsingDatabaseNew::MatchDownloadAddPrefixes(
+ int list_bit, const SBPrefix& prefix, SBPrefix* prefix_hit) {
std::vector<SBAddPrefix> add_prefixes;
download_store_->GetAddPrefixes(&add_prefixes);
for (size_t i = 0; i < add_prefixes.size(); ++i) {
if (prefix == add_prefixes[i].prefix &&
- GetListIdBit(add_prefixes[i].chunk_id) ==
- safe_browsing_util::BINURL % 2) {
- prefix_hits->push_back(prefix);
+ GetListIdBit(add_prefixes[i].chunk_id) == list_bit) {
+ *prefix_hit = prefix;
return true;
}
}
return false;
}
+bool SafeBrowsingDatabaseNew::ContainsDownloadUrl(const GURL& url,
+ SBPrefix* prefix_hit) {
+ DCHECK_EQ(creation_loop_, MessageLoop::current());
+
+ // Ignore this check when download checking is not enabled.
+ if (!download_store_.get())
+ return false;
+
+ SBPrefix prefix;
+ GetDownloadUrlPrefix(url, &prefix);
+ return MatchDownloadAddPrefixes(safe_browsing_util::BINURL % 2,
+ prefix,
+ prefix_hit);
+}
+
+bool SafeBrowsingDatabaseNew::ContainsDownloadHashPrefix(
+ const SBPrefix& prefix) {
+ DCHECK_EQ(creation_loop_, MessageLoop::current());
+
+ // Ignore this check when download store is not available.
+ if (!download_store_.get())
+ return false;
+
+ SBPrefix prefix_hit;
+ return MatchDownloadAddPrefixes(safe_browsing_util::BINHASH % 2,
+ prefix,
+ &prefix_hit);
+}
+
// Helper to insert entries for all of the prefixes or full hashes in
// |entry| into the store.
void SafeBrowsingDatabaseNew::InsertAdd(int chunk_id, SBPrefix host,
diff --git a/chrome/browser/safe_browsing/safe_browsing_database.h b/chrome/browser/safe_browsing/safe_browsing_database.h
index d233ec6..b1712f0 100644
--- a/chrome/browser/safe_browsing/safe_browsing_database.h
+++ b/chrome/browser/safe_browsing/safe_browsing_database.h
@@ -85,10 +85,14 @@ class SafeBrowsingDatabase {
base::Time last_update) = 0;
// Returns false if |url| is not in Download database. If it returns true,
- // |prefix_hits| should contain the prefix for |url|.
+ // |prefix_hit| should contain the prefix for |url|.
// This function could ONLY be accessed from creation thread.
virtual bool ContainsDownloadUrl(const GURL& url,
- std::vector<SBPrefix>* prefix_hits) = 0;
+ SBPrefix* prefix_hit) = 0;
+
+ // Returns false if |prefix| is not in Download database.
+ // This function could ONLY be accessed from creation thread.
+ virtual bool ContainsDownloadHashPrefix(const SBPrefix& prefix) = 0;
// A database transaction should look like:
//
@@ -188,8 +192,8 @@ class SafeBrowsingDatabaseNew : public SafeBrowsingDatabase {
std::vector<SBFullHashResult>* full_hits,
base::Time last_update);
virtual bool ContainsDownloadUrl(const GURL& url,
- std::vector<SBPrefix>* prefix_hits);
-
+ SBPrefix* prefix_hit);
+ virtual bool ContainsDownloadHashPrefix(const SBPrefix& prefix);
virtual bool UpdateStarted(std::vector<SBListChunkRanges>* lists);
virtual void InsertChunks(const std::string& list_name,
const SBChunkList& chunks);
@@ -233,6 +237,15 @@ class SafeBrowsingDatabaseNew : public SafeBrowsingDatabase {
void UpdateDownloadStore();
void UpdateBrowseStore();
+ // Helper function to compare addprefixes in download_store_ with prefix.
+ // The |list_bit| indicates which list (download url or download hash)
+ // to compare.
+ // Returns true if there is a match, |*prefix_hit| will contain the actual
+ // matching prefix.
+ bool MatchDownloadAddPrefixes(int list_bit,
+ const SBPrefix& prefix,
+ SBPrefix* prefix_hit);
+
// Used to verify that various calls are made from the thread the
// object was created on.
MessageLoop* creation_loop_;
diff --git a/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc b/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc
index 8491212..a71a797 100644
--- a/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc
@@ -1131,32 +1131,27 @@ TEST_F(SafeBrowsingDatabaseTest, ContainsDownloadUrl) {
database_->UpdateFinished(true);
const Time now = Time::Now();
- std::vector<SBPrefix> prefix_hits;
+ SBPrefix prefix_hit;
std::string matching_list;
EXPECT_TRUE(database_->ContainsDownloadUrl(
- GURL(std::string("http://") + kEvil1Url1), &prefix_hits));
- EXPECT_EQ(prefix_hits[0], Sha256Prefix(kEvil1Url1));
- EXPECT_EQ(prefix_hits.size(), 1U);
+ GURL(std::string("http://") + kEvil1Url1), &prefix_hit));
+ EXPECT_EQ(prefix_hit, Sha256Prefix(kEvil1Url1));
EXPECT_TRUE(database_->ContainsDownloadUrl(
- GURL(std::string("http://") + kEvil1Url2), &prefix_hits));
- EXPECT_EQ(prefix_hits[0], Sha256Prefix(kEvil1Url2));
- EXPECT_EQ(prefix_hits.size(), 1U);
+ GURL(std::string("http://") + kEvil1Url2), &prefix_hit));
+ EXPECT_EQ(prefix_hit, Sha256Prefix(kEvil1Url2));
EXPECT_TRUE(database_->ContainsDownloadUrl(
- GURL(std::string("https://") + kEvil1Url2), &prefix_hits));
- EXPECT_EQ(prefix_hits[0], Sha256Prefix(kEvil1Url2));
- EXPECT_EQ(prefix_hits.size(), 1U);
+ GURL(std::string("https://") + kEvil1Url2), &prefix_hit));
+ EXPECT_EQ(prefix_hit, Sha256Prefix(kEvil1Url2));
EXPECT_TRUE(database_->ContainsDownloadUrl(
- GURL(std::string("ftp://") + kEvil1Url2), &prefix_hits));
- EXPECT_EQ(prefix_hits[0], Sha256Prefix(kEvil1Url2));
- EXPECT_EQ(prefix_hits.size(), 1U);
+ GURL(std::string("ftp://") + kEvil1Url2), &prefix_hit));
+ EXPECT_EQ(prefix_hit, Sha256Prefix(kEvil1Url2));
EXPECT_FALSE(database_->ContainsDownloadUrl(GURL("http://www.randomevil.com"),
- &prefix_hits));
- EXPECT_EQ(prefix_hits.size(), 0U);
+ &prefix_hit));
database_.reset();
}
@@ -1259,7 +1254,10 @@ TEST_F(SafeBrowsingDatabaseTest, SameHostEntriesOkay) {
&listname, &prefixes, &full_hashes, now));
}
-TEST_F(SafeBrowsingDatabaseTest, BinHashEntries) {
+TEST_F(SafeBrowsingDatabaseTest, BinHashInsertLookup) {
+ const SBPrefix kPrefix1 = 0x31313131;
+ const SBPrefix kPrefix2 = 0x32323232;
+ const SBPrefix kPrefix3 = 0x33333333;
database_.reset();
MessageLoop loop(MessageLoop::TYPE_DEFAULT);
SafeBrowsingStoreFile* browse_store = new SafeBrowsingStoreFile();
@@ -1270,9 +1268,9 @@ TEST_F(SafeBrowsingDatabaseTest, BinHashEntries) {
SBChunkList chunks;
SBChunk chunk;
// Insert one host.
- InsertAddChunkHostPrefixValue(&chunk, 1, 0, 0x31313131);
+ InsertAddChunkHostPrefixValue(&chunk, 1, 0, kPrefix1);
// Insert a second host, which has the same host prefix as the first one.
- InsertAddChunkHostPrefixValue(&chunk, 1, 0, 0x32323232);
+ InsertAddChunkHostPrefixValue(&chunk, 1, 0, kPrefix2);
chunks.push_back(chunk);
// Insert the testing chunks into database.
@@ -1287,8 +1285,9 @@ TEST_F(SafeBrowsingDatabaseTest, BinHashEntries) {
EXPECT_EQ("1", lists[3].adds);
EXPECT_TRUE(lists[3].subs.empty());
- // TODO(lzheng): Query database and verifies the prefixes once that API
- // database is available in database.
+ EXPECT_TRUE(database_->ContainsDownloadHashPrefix(kPrefix1));
+ EXPECT_TRUE(database_->ContainsDownloadHashPrefix(kPrefix2));
+ EXPECT_FALSE(database_->ContainsDownloadHashPrefix(kPrefix3));
database_.reset();
}
diff --git a/chrome/browser/safe_browsing/safe_browsing_service.cc b/chrome/browser/safe_browsing/safe_browsing_service.cc
index 11d0657..e1e1efd 100644
--- a/chrome/browser/safe_browsing/safe_browsing_service.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_service.cc
@@ -8,6 +8,7 @@
#include "base/command_line.h"
#include "base/lazy_instance.h"
#include "base/path_service.h"
+#include "base/stl_util-inl.h"
#include "base/string_util.h"
#include "base/threading/thread_restrictions.h"
#include "chrome/browser/browser_process.h"
@@ -59,7 +60,9 @@ Profile* GetDefaultProfile() {
// Records disposition information about the check. |hit| should be
// |true| if there were any prefix hits in |full_hashes|.
void RecordGetHashCheckStatus(
- bool hit, const std::vector<SBFullHashResult>& full_hashes) {
+ bool hit,
+ bool is_download,
+ const std::vector<SBFullHashResult>& full_hashes) {
SafeBrowsingProtocolManager::ResultType result;
if (full_hashes.empty()) {
result = SafeBrowsingProtocolManager::GET_HASH_FULL_HASH_EMPTY;
@@ -68,7 +71,7 @@ void RecordGetHashCheckStatus(
} else {
result = SafeBrowsingProtocolManager::GET_HASH_FULL_HASH_MISS;
}
- SafeBrowsingProtocolManager::RecordGetHashResult(result);
+ SafeBrowsingProtocolManager::RecordGetHashResult(is_download, result);
}
} // namespace
@@ -104,7 +107,7 @@ struct SafeBrowsingService::WhiteListedEntry {
SafeBrowsingService::UnsafeResource::UnsafeResource()
: resource_type(ResourceType::MAIN_FRAME),
- threat_type(URL_SAFE),
+ threat_type(SAFE),
client(NULL),
render_process_host_id(-1),
render_view_id(-1) {
@@ -113,13 +116,29 @@ SafeBrowsingService::UnsafeResource::UnsafeResource()
SafeBrowsingService::UnsafeResource::~UnsafeResource() {}
SafeBrowsingService::SafeBrowsingCheck::SafeBrowsingCheck()
- : client(NULL),
+ : url(NULL),
+ full_hash(NULL),
+ client(NULL),
need_get_hash(false),
- result(URL_SAFE) {
+ result(SAFE),
+ is_download(false) {
}
SafeBrowsingService::SafeBrowsingCheck::~SafeBrowsingCheck() {}
+void SafeBrowsingService::Client::OnSafeBrowsingResult(
+ const SafeBrowsingCheck& check) {
+ if (check.url.get()) {
+ DCHECK(!check.full_hash.get());
+ OnBrowseUrlCheckResult(*(check.url), check.result);
+ OnDownloadUrlCheckResult(*(check.url), check.result);
+ } else if (check.full_hash.get()) {
+ OnDownloadHashCheckResult(*(check.full_hash), check.result);
+ } else {
+ NOTREACHED();
+ }
+}
+
/* static */
SafeBrowsingService* SafeBrowsingService::CreateSafeBrowsingService() {
if (!factory_)
@@ -170,36 +189,81 @@ bool SafeBrowsingService::DownloadBinHashNeeded() const {
return enable_download_protection_ && CanReportStats();
}
-void SafeBrowsingService::CheckDownloadUrlDone(
- SafeBrowsingCheck* check, UrlCheckResult result) {
+void SafeBrowsingService::CheckDownloadUrlDone(SafeBrowsingCheck* check) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(enable_download_protection_);
- VLOG(1) << "CheckDownloadUrlDone: " << result;
+ DCHECK(check);
- if (checks_.find(check) == checks_.end() || !check->client)
+ if (!enabled_)
return;
- check->client->OnSafeBrowsingResult(check->url, result);
+
+ VLOG(1) << "CheckDownloadUrlDone: " << check->result;
+ DCHECK(checks_.find(check) != checks_.end());
+ if (check->client)
+ check->client->OnSafeBrowsingResult(*check);
checks_.erase(check);
+ delete check;
}
void SafeBrowsingService::CheckDownloadUrlOnSBThread(SafeBrowsingCheck* check) {
DCHECK_EQ(MessageLoop::current(), safe_browsing_thread_->message_loop());
DCHECK(enable_download_protection_);
- std::vector<SBPrefix> prefix_hits;
+ SBPrefix prefix_hit;
- if (!database_->ContainsDownloadUrl(check->url, &prefix_hits)) {
+ if (!database_->ContainsDownloadUrl(*(check->url), &prefix_hit)) {
// Good, we don't have hash for this url prefix.
+ check->result = SAFE;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
NewRunnableMethod(this,
&SafeBrowsingService::CheckDownloadUrlDone,
- check, URL_SAFE));
+ check));
return;
}
check->need_get_hash = true;
- check->prefix_hits.swap(prefix_hits);
+ check->prefix_hits.clear();
+ check->prefix_hits.push_back(prefix_hit);
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ NewRunnableMethod(this, &SafeBrowsingService::OnCheckDone, check));
+}
+
+void SafeBrowsingService::CheckDownloadHashDone(SafeBrowsingCheck* check) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(enable_download_protection_);
+ DCHECK(check);
+
+ if (!enabled_)
+ return;
+
+ VLOG(1) << "CheckDownloadHashDone: " << check->result;
+ DCHECK(checks_.find(check) != checks_.end());
+ if (check->client)
+ check->client->OnSafeBrowsingResult(*check);
+ checks_.erase(check);
+ delete check;
+}
+
+void SafeBrowsingService::CheckDownloadHashOnSBThread(
+ SafeBrowsingCheck* check) {
+ DCHECK_EQ(MessageLoop::current(), safe_browsing_thread_->message_loop());
+ DCHECK(enable_download_protection_);
+
+ if (!database_->ContainsDownloadHashPrefix(check->full_hash->prefix)) {
+ // Good, we don't have hash for this url prefix.
+ check->result = SAFE;
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ NewRunnableMethod(this,
+ &SafeBrowsingService::CheckDownloadHashDone,
+ check));
+ return;
+ }
+
+ check->need_get_hash = true;
+ check->prefix_hits.push_back(check->full_hash->prefix);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
NewRunnableMethod(this, &SafeBrowsingService::OnCheckDone, check));
@@ -215,9 +279,10 @@ bool SafeBrowsingService::CheckDownloadUrl(const GURL& url,
// from the safebrowsing backends. These need to be asynchronous.
SafeBrowsingCheck* check = new SafeBrowsingCheck();
- check->url = url;
+ check->url.reset(new GURL(url));
check->client = client;
- check->result = URL_SAFE;
+ check->result = SAFE;
+ check->is_download = true;
checks_.insert(check);
safe_browsing_thread_->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
this, &SafeBrowsingService::CheckDownloadUrlOnSBThread, check));
@@ -225,6 +290,28 @@ bool SafeBrowsingService::CheckDownloadUrl(const GURL& url,
return false;
}
+bool SafeBrowsingService::CheckDownloadHash(const std::string& full_hash,
+ Client* client) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (!enabled_ || !enable_download_protection_)
+ return true;
+
+ // We need to check the database for url prefix, and later may fetch the url
+ // from the safebrowsing backends. These need to be asynchronous.
+ SafeBrowsingCheck* check = new SafeBrowsingCheck();
+
+ check->full_hash.reset(new SBFullHash);
+ safe_browsing_util::StringToSBFullHash(full_hash, check->full_hash.get());
+ check->client = client;
+ check->result = SAFE;
+ check->is_download = false;
+ checks_.insert(check);
+ safe_browsing_thread_->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
+ this, &SafeBrowsingService::CheckDownloadHashOnSBThread, check));
+
+ return false;
+}
+
bool SafeBrowsingService::CheckBrowseUrl(const GURL& url,
Client* client) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
@@ -259,9 +346,10 @@ bool SafeBrowsingService::CheckBrowseUrl(const GURL& url,
// Needs to be asynchronous, since we could be in the constructor of a
// ResourceDispatcherHost event handler which can't pause there.
SafeBrowsingCheck* check = new SafeBrowsingCheck();
- check->url = url;
+ check->url.reset(new GURL(url));
check->client = client;
- check->result = URL_SAFE;
+ check->result = SAFE;
+ check->is_download = false;
check->need_get_hash = full_hits.empty();
check->prefix_hits.swap(prefix_hits);
check->full_hits.swap(full_hits);
@@ -558,12 +646,17 @@ void SafeBrowsingService::OnIOShutdown() {
delete protocol_manager_;
protocol_manager_ = NULL;
- // Delete queued checks, calling back any clients with 'URL_SAFE'.
+ // Delete queued checks, calling back any clients with 'SAFE'.
// If we don't do this here we may fail to close the database below.
while (!queued_checks_.empty()) {
- QueuedCheck check = queued_checks_.front();
- if (check.client)
- check.client->OnSafeBrowsingResult(check.url, URL_SAFE);
+ QueuedCheck queued = queued_checks_.front();
+ if (queued.client) {
+ SafeBrowsingCheck sb_check;
+ sb_check.url.reset(new GURL(queued.url));
+ sb_check.client = queued.client;
+ sb_check.result = SAFE;
+ queued.client->OnSafeBrowsingResult(sb_check);
+ }
queued_checks_.pop_front();
}
@@ -586,16 +679,18 @@ void SafeBrowsingService::OnIOShutdown() {
safe_browsing_thread_.reset();
}
- // Delete pending checks, calling back any clients with 'URL_SAFE'. We have
+ // Delete pending checks, calling back any clients with 'SAFE'. We have
// to do this after the db thread returns because methods on it can have
// copies of these pointers, so deleting them might lead to accessing garbage.
for (CurrentChecks::iterator it = checks_.begin();
it != checks_.end(); ++it) {
- if ((*it)->client)
- (*it)->client->OnSafeBrowsingResult((*it)->url, URL_SAFE);
- delete *it;
+ SafeBrowsingCheck* check = *it;
+ if (check->client) {
+ check->result = SAFE;
+ check->client->OnSafeBrowsingResult(*check);
+ }
}
- checks_.clear();
+ STLDeleteElements(&checks_);
gethash_requests_.clear();
}
@@ -741,8 +836,13 @@ void SafeBrowsingService::DatabaseLoadComplete() {
// If CheckUrl() determines the URL is safe immediately, it doesn't call the
// client's handler function (because normally it's being directly called by
// the client). Since we're not the client, we have to convey this result.
- if (check.client && CheckBrowseUrl(check.url, check.client))
- check.client->OnSafeBrowsingResult(check.url, URL_SAFE);
+ if (check.client && CheckBrowseUrl(check.url, check.client)) {
+ SafeBrowsingCheck sb_check;
+ sb_check.url.reset(new GURL(check.url));
+ sb_check.client = check.client;
+ sb_check.result = SAFE;
+ check.client->OnSafeBrowsingResult(sb_check);
+ }
queued_checks_.pop_front();
}
}
@@ -779,11 +879,15 @@ SafeBrowsingService::UrlCheckResult SafeBrowsingService::GetResultFromListname(
}
if (safe_browsing_util::IsBadbinurlList(list_name)) {
- return BINARY_MALWARE;
+ return BINARY_MALWARE_URL;
+ }
+
+ if (safe_browsing_util::IsBadbinhashList(list_name)) {
+ return BINARY_MALWARE_HASH;
}
DVLOG(1) << "Unknown safe browsing list " << list_name;
- return URL_SAFE;
+ return SAFE;
}
void SafeBrowsingService::NotifyClientBlockingComplete(Client* client,
@@ -858,11 +962,12 @@ void SafeBrowsingService::OnHandleGetHashResults(
SafeBrowsingCheck* check,
const std::vector<SBFullHashResult>& full_hashes) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ bool is_download = check->is_download;
SBPrefix prefix = check->prefix_hits[0];
GetHashRequests::iterator it = gethash_requests_.find(prefix);
if (check->prefix_hits.size() > 1 || it == gethash_requests_.end()) {
const bool hit = HandleOneCheck(check, full_hashes);
- RecordGetHashCheckStatus(hit, full_hashes);
+ RecordGetHashCheckStatus(hit, is_download, full_hashes);
return;
}
@@ -874,7 +979,7 @@ void SafeBrowsingService::OnHandleGetHashResults(
if (HandleOneCheck(*r, full_hashes))
hit = true;
}
- RecordGetHashCheckStatus(hit, full_hashes);
+ RecordGetHashCheckStatus(hit, is_download, full_hashes);
gethash_requests_.erase(it);
}
@@ -883,18 +988,23 @@ bool SafeBrowsingService::HandleOneCheck(
SafeBrowsingCheck* check,
const std::vector<SBFullHashResult>& full_hashes) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(check);
// Always calculate the index, for recording hits.
- int index = safe_browsing_util::CompareFullHashes(check->url, full_hashes);
+ int index = -1;
+ if (check->url.get() != NULL)
+ index = safe_browsing_util::GetUrlHashIndex(*(check->url), full_hashes);
+ else
+ index = safe_browsing_util::GetHashIndex(*(check->full_hash), full_hashes);
// |client| is NULL if the request was cancelled.
if (check->client) {
- UrlCheckResult result = URL_SAFE;
+ check->result = SAFE;
if (index != -1)
- result = GetResultFromListname(full_hashes[index].list_name);
+ check->result = GetResultFromListname(full_hashes[index].list_name);
// Let the client continue handling the original request.
- check->client->OnSafeBrowsingResult(check->url, result);
+ check->client->OnSafeBrowsingResult(*check);
}
checks_.erase(check);
diff --git a/chrome/browser/safe_browsing/safe_browsing_service.h b/chrome/browser/safe_browsing/safe_browsing_service.h
index abebc32..ae4a7c3 100644
--- a/chrome/browser/safe_browsing/safe_browsing_service.h
+++ b/chrome/browser/safe_browsing/safe_browsing_service.h
@@ -38,42 +38,15 @@ class Thread;
class SafeBrowsingService
: public base::RefCountedThreadSafe<SafeBrowsingService> {
public:
+ class Client;
// Users of this service implement this interface to be notified
// asynchronously of the result.
enum UrlCheckResult {
- URL_SAFE,
+ SAFE,
URL_PHISHING,
URL_MALWARE,
- BINARY_MALWARE, // This binary is a malware.
- };
-
- class Client {
- public:
- virtual ~Client() {}
-
- void OnSafeBrowsingResult(const GURL& url, UrlCheckResult result) {
- OnBrowseUrlCheckResult(url, result);
- OnDownloadUrlCheckResult(url, result);
- // TODO(lzheng): This is not implemented yet.
- // OnDownloadHashCheckResult(url, result);
- }
-
- // Called when the user has made a decision about how to handle the
- // SafeBrowsing interstitial page.
- virtual void OnBlockingPageComplete(bool proceed) {}
-
- protected:
- // Called when the result of checking a browse URL is known.
- virtual void OnBrowseUrlCheckResult(const GURL& url,
- UrlCheckResult result) {}
-
- // Called when the result of checking a download URL is known.
- virtual void OnDownloadUrlCheckResult(const GURL& url,
- UrlCheckResult result) {}
-
- // Called when the result of checking a download binary hash is known.
- virtual void OnDownloadHashCheckResult(const GURL& url,
- UrlCheckResult result) {}
+ BINARY_MALWARE_URL, // Binary url leads to a malware.
+ BINARY_MALWARE_HASH, // Binary hash indicates this is a malware.
};
// Structure used to pass parameters between the IO and UI thread when
@@ -92,16 +65,20 @@ class SafeBrowsingService
int render_view_id;
};
- // Bundle of SafeBrowsing state for one URL check.
+ // Bundle of SafeBrowsing state for one URL or hash prefix check.
struct SafeBrowsingCheck {
SafeBrowsingCheck();
~SafeBrowsingCheck();
- GURL url;
+ // Either |url| or |prefix| is used to lookup database.
+ scoped_ptr<GURL> url;
+ scoped_ptr<SBFullHash> full_hash;
+
Client* client;
bool need_get_hash;
base::Time start; // Time that check was sent to SB service.
UrlCheckResult result;
+ bool is_download; // If this check for download url or hash.
std::vector<SBPrefix> prefix_hits;
std::vector<SBFullHashResult> full_hits;
@@ -109,6 +86,31 @@ class SafeBrowsingService
DISALLOW_COPY_AND_ASSIGN(SafeBrowsingCheck);
};
+ class Client {
+ public:
+ virtual ~Client() {}
+
+ void OnSafeBrowsingResult(const SafeBrowsingCheck& check);
+
+ // Called when the user has made a decision about how to handle the
+ // SafeBrowsing interstitial page.
+ virtual void OnBlockingPageComplete(bool proceed) {}
+
+ protected:
+ // Called when the result of checking a browse URL is known.
+ virtual void OnBrowseUrlCheckResult(const GURL& url,
+ UrlCheckResult result) {}
+
+ // Called when the result of checking a download URL is known.
+ virtual void OnDownloadUrlCheckResult(const GURL& url,
+ UrlCheckResult result) {}
+
+ // Called when the result of checking a download binary hash is known.
+ virtual void OnDownloadHashCheckResult(const SBFullHash& hash,
+ UrlCheckResult result) {}
+ };
+
+
// Makes the passed |factory| the factory used to instanciate
// a SafeBrowsingService. Useful for tests.
static void RegisterFactory(SafeBrowsingServiceFactory* factory) {
@@ -145,6 +147,10 @@ class SafeBrowsingService
// Result will be passed to callback in |client|.
bool CheckDownloadUrl(const GURL& url, Client* client);
+ // Check if the prefix for |full_hash| is in safebrowsing binhash add lists.
+ // Result will be passed to callback in |client|.
+ virtual bool CheckDownloadHash(const std::string& full_hash, Client* client);
+
// Called on the IO thread to cancel a pending check if the result is no
// longer needed.
void CancelCheck(Client* client);
@@ -333,12 +339,18 @@ class SafeBrowsingService
bool is_subresource,
UrlCheckResult threat_type);
+ // Checks the download hash on safe_browsing_thread_.
+ void CheckDownloadHashOnSBThread(SafeBrowsingCheck* check);
+
// Invoked by CheckDownloadUrl. It checks the download URL on
// safe_browsing_thread_.
void CheckDownloadUrlOnSBThread(SafeBrowsingCheck* check);
- // Call the Client's callback in IO thread after CheckDownloadUrl finishes.
- void CheckDownloadUrlDone(SafeBrowsingCheck* check, UrlCheckResult result);
+ // Calls the Client's callback on IO thread after CheckDownloadUrl finishes.
+ void CheckDownloadUrlDone(SafeBrowsingCheck* check);
+
+ // Calls the Client's callback on IO thread after CheckDownloadHash finishes.
+ void CheckDownloadHashDone(SafeBrowsingCheck* check);
// The factory used to instanciate a SafeBrowsingService object.
// Useful for tests, so they can provide their own implementation of
diff --git a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
index 0b44a250..4bff659 100644
--- a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
@@ -57,15 +57,22 @@ class TestSafeBrowsingDatabase : public SafeBrowsingDatabase {
safe_browsing_util::kPhishingList,
url, prefix_hits, full_hits);
}
-
virtual bool ContainsDownloadUrl(const GURL& url,
- std::vector<SBPrefix>* prefix_hits) {
+ SBPrefix* prefix_hit) {
std::vector<SBFullHashResult> full_hits;
- return ContainsUrl(safe_browsing_util::kBinUrlList,
- safe_browsing_util::kBinHashList,
- url, prefix_hits, &full_hits);
+ std::vector<SBPrefix> prefix_hits;
+ bool found = ContainsUrl(safe_browsing_util::kBinUrlList,
+ safe_browsing_util::kBinHashList,
+ url, &prefix_hits, &full_hits);
+ if (!found)
+ return false;
+ DCHECK_EQ(1U, prefix_hits.size());
+ *prefix_hit = prefix_hits[0];
+ return true;
+ }
+ virtual bool ContainsDownloadHashPrefix(const SBPrefix& prefix) {
+ return download_digest_prefix_.count(prefix) > 0;
}
-
virtual bool UpdateStarted(std::vector<SBListChunkRanges>* lists) {
ADD_FAILURE() << "Not implemented.";
return false;
@@ -96,6 +103,11 @@ class TestSafeBrowsingDatabase : public SafeBrowsingDatabase {
badurls_[url.spec()].full_hits = full_hits;
}
+ // Fill up the database with test hash digest.
+ void AddDownloadPrefix(SBPrefix prefix) {
+ download_digest_prefix_.insert(prefix);
+ }
+
private:
struct Hits {
std::string list_name;
@@ -125,6 +137,7 @@ class TestSafeBrowsingDatabase : public SafeBrowsingDatabase {
}
base::hash_map<std::string, Hits> badurls_;
+ base::hash_set<SBPrefix> download_digest_prefix_;
};
// Factory that creates TestSafeBrowsingDatabase instances.
@@ -172,25 +185,23 @@ class TestProtocolManager : public SafeBrowsingProtocolManager {
// server's response.
virtual void GetFullHash(SafeBrowsingService::SafeBrowsingCheck* check,
const std::vector<SBPrefix>& prefixes) {
- // The hash result should be inserted to the full_hashes_.
- ASSERT_TRUE(full_hashes_.find(check->url.spec()) != full_hashes_.end());
// When we get a valid response, always cache the result.
bool cancache = true;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
NewRunnableMethod(
sb_service_, &SafeBrowsingService::HandleGetHashResults,
- check, full_hashes_[check->url.spec()], cancache));
+ check, full_hashes_, cancache));
}
- // Prepare the GetFullHash results for |url|.
- void SetGetFullHashResponse(const GURL& url,
- const SBFullHashResult& full_hash_result) {
- full_hashes_[url.spec()].push_back(full_hash_result);
+ // Prepare the GetFullHash results for the next request.
+ void SetGetFullHashResponse(const SBFullHashResult& full_hash_result) {
+ full_hashes_.clear();
+ full_hashes_.push_back(full_hash_result);
}
private:
- base::hash_map<std::string, std::vector<SBFullHashResult> > full_hashes_;
+ std::vector<SBFullHashResult> full_hashes_;
SafeBrowsingService* sb_service_;
};
@@ -229,10 +240,10 @@ class SafeBrowsingServiceTest : public InProcessBrowserTest {
SafeBrowsingServiceTest() {
}
- static void GenerateFullhashResult(const GURL& url,
- const std::string& list_name,
- int add_chunk_id,
- SBFullHashResult* full_hash) {
+ static void GenUrlFullhashResult(const GURL& url,
+ const std::string& list_name,
+ int add_chunk_id,
+ SBFullHashResult* full_hash) {
std::string host;
std::string path;
safe_browsing_util::CanonicalizeUrl(url, &host, &path, NULL);
@@ -242,6 +253,15 @@ class SafeBrowsingServiceTest : public InProcessBrowserTest {
full_hash->add_chunk_id = add_chunk_id;
}
+ static void GenDigestFullhashResult(const std::string& full_digest,
+ const std::string& list_name,
+ int add_chunk_id,
+ SBFullHashResult* full_hash) {
+ safe_browsing_util::StringToSBFullHash(full_digest, &full_hash->hash);
+ full_hash->list_name = list_name;
+ full_hash->add_chunk_id = add_chunk_id;
+ }
+
virtual void SetUp() {
// InProcessBrowserTest::SetUp() intantiates SafebrowsingService and
// RegisterFactory has to be called before SafeBrowsingService is created.
@@ -273,10 +293,9 @@ class SafeBrowsingServiceTest : public InProcessBrowserTest {
ASSERT_TRUE(test_server()->Start());
}
- // This will setup the prefix in database and prepare protocol manager
+ // This will setup the "url" prefix in database and prepare protocol manager
// to response with |full_hash| for get full hash request.
- void SetupResponseForUrl(const GURL& url,
- const SBFullHashResult& full_hash) {
+ void SetupResponseForUrl(const GURL& url, const SBFullHashResult& full_hash) {
std::vector<SBPrefix> prefix_hits;
prefix_hits.push_back(full_hash.hash.prefix);
@@ -287,7 +306,20 @@ class SafeBrowsingServiceTest : public InProcessBrowserTest {
db->AddUrl(url, full_hash.list_name, prefix_hits, empty_full_hits);
TestProtocolManager* pm = pm_factory_.GetProtocolManager();
- pm->SetGetFullHashResponse(url, full_hash);
+ pm->SetGetFullHashResponse(full_hash);
+ }
+
+ // This will setup the binary digest prefix in database and prepare protocol
+ // manager to response with |full_hash| for get full hash request.
+ void SetupResponseForDigest(const std::string& digest,
+ const SBFullHashResult& hash_result) {
+ TestSafeBrowsingDatabase* db = db_factory_.GetDb();
+ SBFullHash full_hash;
+ safe_browsing_util::StringToSBFullHash(digest, &full_hash);
+ db->AddDownloadPrefix(full_hash.prefix);
+
+ TestProtocolManager* pm = pm_factory_.GetProtocolManager();
+ pm->SetGetFullHashResponse(hash_result);
}
bool ShowingInterstitialPage() {
@@ -316,8 +348,8 @@ IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, Malware) {
// we should see the interstitial page.
SBFullHashResult malware_full_hash;
int chunk_id = 0;
- GenerateFullhashResult(url, safe_browsing_util::kMalwareList, chunk_id,
- &malware_full_hash);
+ GenUrlFullhashResult(url, safe_browsing_util::kMalwareList, chunk_id,
+ &malware_full_hash);
SetupResponseForUrl(url, malware_full_hash);
ui_test_utils::NavigateToURL(browser(), url);
EXPECT_TRUE(ShowingInterstitialPage());
@@ -329,7 +361,7 @@ class TestSBClient
: public base::RefCountedThreadSafe<TestSBClient>,
public SafeBrowsingService::Client {
public:
- TestSBClient() : result_(SafeBrowsingService::URL_SAFE),
+ TestSBClient() : result_(SafeBrowsingService::SAFE),
safe_browsing_service_(g_browser_process->
resource_dispatcher_host()->
safe_browsing_service()) {
@@ -339,27 +371,50 @@ class TestSBClient
return result_;
}
- void CheckUrl(const GURL& url) {
+ void CheckDownloadUrl(const GURL& url) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- NewRunnableMethod(this, &TestSBClient::CheckUrlOnIOThread, url));
+ NewRunnableMethod(this,
+ &TestSBClient::CheckDownloadUrlOnIOThread,
+ url));
ui_test_utils::RunMessageLoop(); // Will stop in OnDownloadUrlCheckResult.
}
+ void CheckDownloadHash(const std::string& full_hash) {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ NewRunnableMethod(this,
+ &TestSBClient::CheckDownloadHashOnIOThread,
+ full_hash));
+ ui_test_utils::RunMessageLoop(); // Will stop in OnDownloadHashCheckResult.
+ }
+
private:
- void CheckUrlOnIOThread(const GURL& url) {
+ void CheckDownloadUrlOnIOThread(const GURL& url) {
safe_browsing_service_->CheckDownloadUrl(url, this);
}
+ void CheckDownloadHashOnIOThread(const std::string& full_hash) {
+ safe_browsing_service_->CheckDownloadHash(full_hash, this);
+ }
+
// Called when the result of checking a download URL is known.
void OnDownloadUrlCheckResult(const GURL& url,
SafeBrowsingService::UrlCheckResult result) {
result_ = result;
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- NewRunnableMethod(this, &TestSBClient::DownloadUrlCheckDone));
+ NewRunnableMethod(this, &TestSBClient::DownloadCheckDone));
}
- void DownloadUrlCheckDone() {
+ // Called when the result of checking a download hash is known.
+ void OnDownloadHashCheckResult(const SBFullHash& hash,
+ SafeBrowsingService::UrlCheckResult result) {
+ result_ = result;
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &TestSBClient::DownloadCheckDone));
+ }
+
+ void DownloadCheckDone() {
MessageLoopForUI::current()->Quit();
}
@@ -373,21 +428,41 @@ IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, CheckDownloadUrl) {
GURL badbin_url = test_server()->GetURL(kMalwareFile);
scoped_refptr<TestSBClient> client(new TestSBClient);
- client->CheckUrl(badbin_url);
+ client->CheckDownloadUrl(badbin_url);
// Since badbin_url is not in database, it is considered to be safe.
- EXPECT_EQ(SafeBrowsingService::URL_SAFE, client->GetResult());
+ EXPECT_EQ(SafeBrowsingService::SAFE, client->GetResult());
- SBFullHashResult badbinurl_full_hash;
+ SBFullHashResult full_hash_result;
int chunk_id = 0;
- GenerateFullhashResult(badbin_url, safe_browsing_util::kBinUrlList,
- chunk_id, &badbinurl_full_hash);
- SetupResponseForUrl(badbin_url, badbinurl_full_hash);
+ GenUrlFullhashResult(badbin_url, safe_browsing_util::kBinUrlList,
+ chunk_id, &full_hash_result);
+ SetupResponseForUrl(badbin_url, full_hash_result);
- client->CheckUrl(badbin_url);
+ client->CheckDownloadUrl(badbin_url);
// Now, the badbin_url is not safe since it is added to download database.
- EXPECT_EQ(SafeBrowsingService::BINARY_MALWARE, client->GetResult());
+ EXPECT_EQ(SafeBrowsingService::BINARY_MALWARE_URL, client->GetResult());
}
+IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, CheckDownloadHash) {
+ const std::string full_hash = "12345678902234567890323456789012";
+
+ scoped_refptr<TestSBClient> client(new TestSBClient);
+ client->CheckDownloadHash(full_hash);
+
+ // Since badbin_url is not in database, it is considered to be safe.
+ EXPECT_EQ(SafeBrowsingService::SAFE, client->GetResult());
+
+ SBFullHashResult full_hash_result;
+ int chunk_id = 0;
+ GenDigestFullhashResult(full_hash, safe_browsing_util::kBinHashList,
+ chunk_id, &full_hash_result);
+ SetupResponseForDigest(full_hash, full_hash_result);
+
+ client->CheckDownloadHash(full_hash);
+
+ // Now, the badbin_url is not safe since it is added to download database.
+ EXPECT_EQ(SafeBrowsingService::BINARY_MALWARE_HASH, client->GetResult());
+}
} // namespace
diff --git a/chrome/browser/safe_browsing/safe_browsing_test.cc b/chrome/browser/safe_browsing/safe_browsing_test.cc
index fb48e28..d921026 100644
--- a/chrome/browser/safe_browsing/safe_browsing_test.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_test.cc
@@ -350,7 +350,7 @@ class SafeBrowsingServiceTestHelper
EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
EXPECT_TRUE(safe_browsing_test_->is_checked_url_in_db());
safe_browsing_test_->set_is_checked_url_safe(
- result == SafeBrowsingService::URL_SAFE);
+ result == SafeBrowsingService::SAFE);
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
NewRunnableMethod(this,
&SafeBrowsingServiceTestHelper::OnCheckUrlDone));
diff --git a/chrome/browser/safe_browsing/safe_browsing_util.cc b/chrome/browser/safe_browsing/safe_browsing_util.cc
index 3e449e0..06a18ca 100644
--- a/chrome/browser/safe_browsing/safe_browsing_util.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_util.cc
@@ -162,12 +162,19 @@ void SBEntry::SetFullHashAt(int index, const SBFullHash& full_hash) {
namespace safe_browsing_util {
+// Listnames that browser can process.
const char kMalwareList[] = "goog-malware-shavar";
const char kPhishingList[] = "goog-phish-shavar";
-
const char kBinUrlList[] = "goog-badbinurl-shavar";
const char kBinHashList[] = "goog-badbinhash-shavar";
+// Keywords to identify a list type from listname.
+// TODO(lzheng): check if this can be replaced by full listnames.
+const char kMalwareListKey[] = "-malware-";
+const char kPhishingListKey[] = "-phish-";
+const char kBinUrlListKey[] = "-badbinurl-";
+const char kBinHashListKey[] = "-badbinhash-";
+
int GetListId(const std::string& name) {
int id;
if (name == safe_browsing_util::kMalwareList) {
@@ -409,8 +416,17 @@ void GeneratePathsToCheck(const GURL& url, std::vector<std::string>* paths) {
paths->push_back(path + "?" + query);
}
-int CompareFullHashes(const GURL& url,
- const std::vector<SBFullHashResult>& full_hashes) {
+int GetHashIndex(const SBFullHash& hash,
+ const std::vector<SBFullHashResult>& full_hashes) {
+ for (size_t i = 0; i < full_hashes.size(); ++i) {
+ if (hash == full_hashes[i].hash)
+ return static_cast<int>(i);
+ }
+ return -1;
+}
+
+int GetUrlHashIndex(const GURL& url,
+ const std::vector<SBFullHashResult>& full_hashes) {
if (full_hashes.empty())
return -1;
@@ -424,11 +440,8 @@ int CompareFullHashes(const GURL& url,
base::SHA256HashString(hosts[h] + paths[p],
key.full_hash,
sizeof(SBFullHash));
-
- for (size_t i = 0; i < full_hashes.size(); ++i) {
- if (key == full_hashes[i].hash)
- return static_cast<int>(i);
- }
+ int index = GetHashIndex(key, full_hashes);
+ if (index != -1) return index;
}
}
@@ -436,15 +449,19 @@ int CompareFullHashes(const GURL& url,
}
bool IsPhishingList(const std::string& list_name) {
- return list_name.find("-phish-") != std::string::npos;
+ return list_name.find(kPhishingListKey) != std::string::npos;
}
bool IsMalwareList(const std::string& list_name) {
- return list_name.find("-malware-") != std::string::npos;
+ return list_name.find(kMalwareListKey) != std::string::npos;
}
bool IsBadbinurlList(const std::string& list_name) {
- return list_name.find("-badbinurl-") != std::string::npos;
+ return list_name.find(kBinUrlListKey) != std::string::npos;
+}
+
+bool IsBadbinhashList(const std::string& list_name) {
+ return list_name.find(kBinHashListKey) != std::string::npos;
}
static void DecodeWebSafe(std::string* decoded) {
@@ -503,4 +520,9 @@ GURL GeneratePhishingReportUrl(const std::string& report_page,
return google_util::AppendGoogleLocaleParam(report_url);
}
+void StringToSBFullHash(const std::string& hash_in, SBFullHash* hash_out) {
+ DCHECK_EQ(static_cast<size_t>(base::SHA256_LENGTH), hash_in.size());
+ memcpy(hash_out->full_hash, hash_in.data(), base::SHA256_LENGTH);
+}
+
} // namespace safe_browsing_util
diff --git a/chrome/browser/safe_browsing/safe_browsing_util.h b/chrome/browser/safe_browsing/safe_browsing_util.h
index 85a79ef..5b01b44 100644
--- a/chrome/browser/safe_browsing/safe_browsing_util.h
+++ b/chrome/browser/safe_browsing/safe_browsing_util.h
@@ -289,15 +289,19 @@ void GenerateHostsToCheck(const GURL& url, std::vector<std::string>* hosts);
// Given a URL, returns all the paths we need to check.
void GeneratePathsToCheck(const GURL& url, std::vector<std::string>* paths);
+int GetHashIndex(const SBFullHash& hash,
+ const std::vector<SBFullHashResult>& full_hashes);
+
// Given a URL, compare all the possible host + path full hashes to the set of
// provided full hashes. Returns the index of the match if one is found, or -1
// otherwise.
-int CompareFullHashes(const GURL& url,
- const std::vector<SBFullHashResult>& full_hashes);
+int GetUrlHashIndex(const GURL& url,
+ const std::vector<SBFullHashResult>& full_hashes);
bool IsPhishingList(const std::string& list_name);
bool IsMalwareList(const std::string& list_name);
bool IsBadbinurlList(const std::string& list_name);
+bool IsBadbinhashList(const std::string& list_name);
// Returns 'true' if 'mac' can be verified using 'key' and 'data'.
bool VerifyMAC(const std::string& key,
@@ -308,6 +312,8 @@ bool VerifyMAC(const std::string& key,
GURL GeneratePhishingReportUrl(const std::string& report_page,
const std::string& url_to_report);
+void StringToSBFullHash(const std::string& hash_in, SBFullHash* hash_out);
+
} // namespace safe_browsing_util
#endif // CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_UTIL_H_
diff --git a/chrome/browser/safe_browsing/safe_browsing_util_unittest.cc b/chrome/browser/safe_browsing/safe_browsing_util_unittest.cc
index 7bf7efc..a12c3ff 100644
--- a/chrome/browser/safe_browsing/safe_browsing_util_unittest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_util_unittest.cc
@@ -280,7 +280,7 @@ TEST(SafeBrowsingUtilTest, CanonicalizeUrl) {
}
}
-TEST(SafeBrowsingUtilTest, FullHashCompare) {
+TEST(SafeBrowsingUtilTest, GetUrlHashIndex) {
GURL url("http://www.evil.com/phish.html");
SBFullHashResult full_hash;
base::SHA256HashString(url.host() + url.path(),
@@ -289,10 +289,10 @@ TEST(SafeBrowsingUtilTest, FullHashCompare) {
std::vector<SBFullHashResult> full_hashes;
full_hashes.push_back(full_hash);
- EXPECT_EQ(safe_browsing_util::CompareFullHashes(url, full_hashes), 0);
+ EXPECT_EQ(safe_browsing_util::GetUrlHashIndex(url, full_hashes), 0);
url = GURL("http://www.evil.com/okay_path.html");
- EXPECT_EQ(safe_browsing_util::CompareFullHashes(url, full_hashes), -1);
+ EXPECT_EQ(safe_browsing_util::GetUrlHashIndex(url, full_hashes), -1);
}
TEST(SafeBrowsingUtilTest, ListIdListNameConversion) {
@@ -334,3 +334,12 @@ TEST(SafeBrowsingUtilTest, ListIdVerification) {
EXPECT_EQ(0, safe_browsing_util::BINURL %2);
EXPECT_EQ(1, safe_browsing_util::BINHASH % 2);
}
+
+TEST(SafeBrowsingUtilTest, StringToSBFullHash) {
+ // 31 chars plus the last \0 as full_hash.
+ const std::string hash_in = "12345678902234567890323456789012";
+ SBFullHash hash_out;
+ safe_browsing_util::StringToSBFullHash(hash_in, &hash_out);
+ EXPECT_EQ(0x34333231, hash_out.prefix);
+ EXPECT_EQ(0, memcmp(hash_in.data(), hash_out.full_hash, sizeof(SBFullHash)));
+}