summaryrefslogtreecommitdiffstats
path: root/chrome/browser/safe_browsing/safe_browsing_service.cc
diff options
context:
space:
mode:
authorpkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-13 00:28:54 +0000
committerpkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-13 00:28:54 +0000
commit90a3b24080e8432726dde4b4f72821e49416180e (patch)
tree0fd94921b79a9452b78eef78ceb0e01bb152ca51 /chrome/browser/safe_browsing/safe_browsing_service.cc
parent9eda5b7490cb3463435287b003058d6d486a83b3 (diff)
downloadchromium_src-90a3b24080e8432726dde4b4f72821e49416180e.zip
chromium_src-90a3b24080e8432726dde4b4f72821e49416180e.tar.gz
chromium_src-90a3b24080e8432726dde4b4f72821e49416180e.tar.bz2
Minor cleanup to safe_browsing_service.*; no code change.
* Eliminate header files that aren't needed * Eliminate function declarations that are never defined * Reorder header slightly for Google C++ Style Guide compliance and to make more functions private * Move above-function comments like "Called on IO thread" from definitions to declarations for added visibility * Reorder function definitions to match declaration order BUG=none TEST=none Review URL: http://codereview.chromium.org/391039 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@31863 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/safe_browsing/safe_browsing_service.cc')
-rw-r--r--chrome/browser/safe_browsing/safe_browsing_service.cc775
1 files changed, 379 insertions, 396 deletions
diff --git a/chrome/browser/safe_browsing/safe_browsing_service.cc b/chrome/browser/safe_browsing/safe_browsing_service.cc
index 164547e..3f2d7d8 100644
--- a/chrome/browser/safe_browsing/safe_browsing_service.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_service.cc
@@ -5,31 +5,25 @@
#include "chrome/browser/safe_browsing/safe_browsing_service.h"
-#include "base/command_line.h"
-#include "base/histogram.h"
-#include "base/logging.h"
-#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/string_util.h"
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/net/url_request_context_getter.h"
#include "chrome/browser/profile_manager.h"
#include "chrome/browser/safe_browsing/protocol_manager.h"
#include "chrome/browser/safe_browsing/safe_browsing_blocking_page.h"
#include "chrome/browser/safe_browsing/safe_browsing_database.h"
-#include "chrome/browser/tab_contents/navigation_entry.h"
#include "chrome/browser/tab_contents/tab_util.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/pref_names.h"
-#include "chrome/common/pref_service.h"
#include "chrome/common/url_constants.h"
+#include "net/base/registry_controlled_domain.h"
+
#if defined(OS_WIN)
#include "chrome/installer/util/browser_distribution.h"
#endif
-#include "net/base/registry_controlled_domain.h"
using base::Time;
using base::TimeDelta;
@@ -50,10 +44,6 @@ SafeBrowsingService::SafeBrowsingService()
update_in_progress_(false) {
}
-SafeBrowsingService::~SafeBrowsingService() {
-}
-
-// Only called on the UI thread.
void SafeBrowsingService::Initialize() {
// Get the profile's preference for SafeBrowsing.
PrefService* pref_service = GetDefaultProfile()->GetPrefs();
@@ -61,138 +51,12 @@ void SafeBrowsingService::Initialize() {
Start();
}
-// Start up SafeBrowsing objects. This can be called at browser start, or when
-// the user checks the "Enable SafeBrowsing" option in the Advanced options UI.
-void SafeBrowsingService::Start() {
- DCHECK(!safe_browsing_thread_.get());
- safe_browsing_thread_.reset(new base::Thread("Chrome_SafeBrowsingThread"));
- if (!safe_browsing_thread_->Start())
- return;
-
- // Retrieve client MAC keys.
- PrefService* local_state = g_browser_process->local_state();
- std::string client_key, wrapped_key;
- if (local_state) {
- client_key =
- WideToASCII(local_state->GetString(prefs::kSafeBrowsingClientKey));
- wrapped_key =
- WideToASCII(local_state->GetString(prefs::kSafeBrowsingWrappedKey));
- }
-
- // We will issue network fetches using the default profile's request context.
- URLRequestContextGetter* request_context_getter =
- GetDefaultProfile()->GetRequestContext();
- request_context_getter->AddRef(); // Balanced in OnIOInitialize.
-
- ChromeThread::PostTask(
- ChromeThread::IO, FROM_HERE,
- NewRunnableMethod(
- this, &SafeBrowsingService::OnIOInitialize, client_key, wrapped_key,
- request_context_getter));
-
- safe_browsing_thread_->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
- this, &SafeBrowsingService::OnDBInitialize));
-}
-
void SafeBrowsingService::ShutDown() {
ChromeThread::PostTask(
ChromeThread::IO, FROM_HERE,
NewRunnableMethod(this, &SafeBrowsingService::OnIOShutdown));
}
-void SafeBrowsingService::OnIOInitialize(
- const std::string& client_key,
- const std::string& wrapped_key,
- URLRequestContextGetter* request_context_getter) {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
- enabled_ = true;
-
- // On Windows, get the safe browsing client name from the browser
- // distribution classes in installer util. These classes don't yet have
- // an analog on non-Windows builds so just keep the name specified here.
-#if defined(OS_WIN)
- BrowserDistribution* dist = BrowserDistribution::GetDistribution();
- std::string client_name(dist->GetSafeBrowsingName());
-#else
-#if defined(GOOGLE_CHROME_BUILD)
- std::string client_name("googlechrome");
-#else
- std::string client_name("chromium");
-#endif
-#endif
-
- protocol_manager_ = new SafeBrowsingProtocolManager(this,
- client_name,
- client_key,
- wrapped_key,
- request_context_getter);
-
- // Balance the reference added by Start().
- request_context_getter->Release();
-
- // We want to initialize the protocol manager only after the database has
- // loaded, which we'll receive asynchronously (DatabaseLoadComplete). If
- // database_loaded_ isn't true, we'll wait for that notification to do the
- // init.
- if (database_loaded_)
- protocol_manager_->Initialize();
-}
-
-void SafeBrowsingService::OnDBInitialize() {
- DCHECK(MessageLoop::current() == safe_browsing_thread_->message_loop());
- GetDatabase();
-}
-
-void SafeBrowsingService::OnIOShutdown() {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
- if (!enabled_)
- return;
-
- enabled_ = false;
- resetting_ = false;
-
- // This cancels all in-flight GetHash requests.
- delete protocol_manager_;
- protocol_manager_ = NULL;
-
- if (safe_browsing_thread_.get())
- safe_browsing_thread_->message_loop()->DeleteSoon(FROM_HERE, database_);
-
- // Flush the database thread. Any in-progress database check results will be
- // ignored and cleaned up below.
- safe_browsing_thread_.reset(NULL);
-
- database_ = NULL;
- database_loaded_ = false;
-
- // Delete queued and pending checks once the database thread is done, calling
- // back any clients with 'URL_SAFE'.
- while (!queued_checks_.empty()) {
- QueuedCheck check = queued_checks_.front();
- if (check.client)
- check.client->OnUrlCheckResult(check.url, URL_SAFE);
- queued_checks_.pop_front();
- }
-
- for (CurrentChecks::iterator it = checks_.begin();
- it != checks_.end(); ++it) {
- if ((*it)->client)
- (*it)->client->OnUrlCheckResult((*it)->url, URL_SAFE);
- delete *it;
- }
- checks_.clear();
-
- gethash_requests_.clear();
-}
-
-// Runs on the UI thread.
-void SafeBrowsingService::OnEnable(bool enabled) {
- if (enabled)
- Start();
- else
- ShutDown();
-}
-
bool SafeBrowsingService::CanCheckUrl(const GURL& url) const {
return url.SchemeIs(chrome::kHttpScheme) ||
url.SchemeIs(chrome::kHttpsScheme);
@@ -242,6 +106,25 @@ bool SafeBrowsingService::CheckUrl(const GURL& url, Client* client) {
return false;
}
+void SafeBrowsingService::CancelCheck(Client* client) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+
+ for (CurrentChecks::iterator i = checks_.begin(); i != checks_.end(); ++i) {
+ if ((*i)->client == client)
+ (*i)->client = NULL;
+ }
+
+ // Scan the queued clients store. Clients may be here if they requested a URL
+ // check before the database has finished loading or resetting.
+ if (!database_loaded_ || resetting_) {
+ std::deque<QueuedCheck>::iterator it = queued_checks_.begin();
+ for (; it != queued_checks_.end(); ++it) {
+ if (it->client == client)
+ it->client = NULL;
+ }
+ }
+}
+
void SafeBrowsingService::DisplayBlockingPage(const GURL& url,
ResourceType::Type resource_type,
UrlCheckResult result,
@@ -279,143 +162,6 @@ void SafeBrowsingService::DisplayBlockingPage(const GURL& url,
this, &SafeBrowsingService::DoDisplayBlockingPage, resource));
}
-// Invoked on the UI thread.
-void SafeBrowsingService::DoDisplayBlockingPage(
- const UnsafeResource& resource) {
- // The tab might have been closed.
- TabContents* wc =
- tab_util::GetTabContentsByID(resource.render_process_host_id,
- resource.render_view_id);
-
- if (!wc) {
- // The tab is gone and we did not have a chance at showing the interstitial.
- // Just act as "Don't Proceed" was chosen.
- std::vector<UnsafeResource> resources;
- resources.push_back(resource);
- ChromeThread::PostTask(
- ChromeThread::IO, FROM_HERE,
- NewRunnableMethod(
- this, &SafeBrowsingService::OnBlockingPageDone, resources, false));
- return;
- }
-
- // Report the malware sub-resource to the SafeBrowsing servers if we have a
- // malware sub-resource on a safe page and only if the user has opted in to
- // reporting statistics.
- PrefService* prefs = g_browser_process->local_state();
- DCHECK(prefs);
- if (prefs && prefs->GetBoolean(prefs::kMetricsReportingEnabled) &&
- resource.resource_type != ResourceType::MAIN_FRAME &&
- resource.threat_type == SafeBrowsingService::URL_MALWARE) {
- GURL page_url = wc->GetURL();
- GURL referrer_url;
- NavigationEntry* entry = wc->controller().GetActiveEntry();
- if (entry)
- referrer_url = entry->referrer();
- ChromeThread::PostTask(
- ChromeThread::IO, FROM_HERE,
- NewRunnableMethod(this,
- &SafeBrowsingService::ReportMalware,
- resource.url,
- page_url,
- referrer_url));
- }
-
- SafeBrowsingBlockingPage::ShowBlockingPage(this, resource);
-}
-
-void SafeBrowsingService::CancelCheck(Client* client) {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
-
- for (CurrentChecks::iterator i = checks_.begin(); i != checks_.end(); ++i) {
- if ((*i)->client == client)
- (*i)->client = NULL;
- }
-
- // Scan the queued clients store. Clients may be here if they requested a URL
- // check before the database has finished loading or resetting.
- if (!database_loaded_ || resetting_) {
- std::deque<QueuedCheck>::iterator it = queued_checks_.begin();
- for (; it != queued_checks_.end(); ++it) {
- if (it->client == client)
- it->client = NULL;
- }
- }
-}
-
-void SafeBrowsingService::OnCheckDone(SafeBrowsingCheck* check) {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
-
- // If we've been shutdown during the database lookup, this check will already
- // have been deleted (in OnIOShutdown).
- if (!enabled_ || checks_.find(check) == checks_.end())
- return;
-
- if (check->client && check->need_get_hash) {
- // We have a partial match so we need to query Google for the full hash.
- // Clean up will happen in HandleGetHashResults.
-
- // See if we have a GetHash request already in progress for this particular
- // prefix. If so, we just append ourselves to the list of interested parties
- // when the results arrive. We only do this for checks involving one prefix,
- // since that is the common case (multiple prefixes will issue the request
- // as normal).
- if (check->prefix_hits.size() == 1) {
- SBPrefix prefix = check->prefix_hits[0];
- GetHashRequests::iterator it = gethash_requests_.find(prefix);
- if (it != gethash_requests_.end()) {
- // There's already a request in progress.
- it->second.push_back(check);
- return;
- }
-
- // No request in progress, so we're the first for this prefix.
- GetHashRequestors requestors;
- requestors.push_back(check);
- gethash_requests_[prefix] = requestors;
- }
-
- // Reset the start time so that we can measure the network time without the
- // database time.
- check->start = Time::Now();
- protocol_manager_->GetFullHash(check, check->prefix_hits);
- } else {
- // We may have cached results for previous GetHash queries.
- HandleOneCheck(check, check->full_hits);
- }
-}
-
-SafeBrowsingDatabase* SafeBrowsingService::GetDatabase() {
- DCHECK(MessageLoop::current() == safe_browsing_thread_->message_loop());
- if (database_)
- return database_;
-
- FilePath path;
- bool result = PathService::Get(chrome::DIR_USER_DATA, &path);
- DCHECK(result);
- path = path.Append(chrome::kSafeBrowsingFilename);
-
- Time before = Time::Now();
- SafeBrowsingDatabase* database = SafeBrowsingDatabase::Create();
- Callback0::Type* chunk_callback =
- NewCallback(this, &SafeBrowsingService::ChunkInserted);
- database->Init(path, chunk_callback);
- database_ = database;
-
- ChromeThread::PostTask(
- ChromeThread::IO, FROM_HERE,
- NewRunnableMethod(this, &SafeBrowsingService::DatabaseLoadComplete));
-
- TimeDelta open_time = Time::Now() - before;
- SB_DLOG(INFO) << "SafeBrowsing database open took " <<
- open_time.InMilliseconds() << " ms.";
-
- return database_;
-}
-
-// Public API called only on the IO thread.
-// The SafeBrowsingProtocolManager has received the full hash results for
-// prefix hits detected in the database.
void SafeBrowsingService::HandleGetHashResults(
SafeBrowsingCheck* check,
const std::vector<SBFullHashResult>& full_hashes,
@@ -436,48 +182,20 @@ void SafeBrowsingService::HandleGetHashResults(
}
}
-void SafeBrowsingService::OnHandleGetHashResults(
- SafeBrowsingCheck* check,
- const std::vector<SBFullHashResult>& full_hashes) {
- SBPrefix prefix = check->prefix_hits[0];
- GetHashRequests::iterator it = gethash_requests_.find(prefix);
- if (check->prefix_hits.size() > 1 || it == gethash_requests_.end()) {
- HandleOneCheck(check, full_hashes);
- return;
- }
-
- // Call back all interested parties.
- GetHashRequestors& requestors = it->second;
- for (GetHashRequestors::iterator r = requestors.begin();
- r != requestors.end(); ++r) {
- HandleOneCheck(*r, full_hashes);
- }
-
- gethash_requests_.erase(it);
+void SafeBrowsingService::HandleChunk(const std::string& list,
+ std::deque<SBChunk>* chunks) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ DCHECK(enabled_);
+ safe_browsing_thread_->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
+ this, &SafeBrowsingService::HandleChunkForDatabase, list, chunks));
}
-void SafeBrowsingService::HandleOneCheck(
- SafeBrowsingCheck* check,
- const std::vector<SBFullHashResult>& full_hashes) {
- if (check->client) {
- UrlCheckResult result = URL_SAFE;
- int index = safe_browsing_util::CompareFullHashes(check->url, full_hashes);
- if (index != -1) {
- result = GetResultFromListname(full_hashes[index].list_name);
- } else {
- // Log the case where the SafeBrowsing servers return full hashes in the
- // GetHash response that match the prefix we're looking up, but don't
- // match the full hash of the URL.
- if (!full_hashes.empty())
- UMA_HISTOGRAM_COUNTS("SB2.GetHashServerMiss", 1);
- }
-
- // Let the client continue handling the original request.
- check->client->OnUrlCheckResult(check->url, result);
- }
-
- checks_.erase(check);
- delete check;
+void SafeBrowsingService::HandleChunkDelete(
+ std::vector<SBChunkDelete>* chunk_deletes) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ DCHECK(enabled_);
+ safe_browsing_thread_->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
+ this, &SafeBrowsingService::DeleteChunks, chunk_deletes));
}
void SafeBrowsingService::UpdateStarted() {
@@ -501,12 +219,6 @@ void SafeBrowsingService::UpdateFinished(bool update_succeeded) {
}
}
-void SafeBrowsingService::DatabaseUpdateFinished(bool update_succeeded) {
- DCHECK(MessageLoop::current() == safe_browsing_thread_->message_loop());
- if (GetDatabase())
- GetDatabase()->UpdateFinished(update_succeeded);
-}
-
void SafeBrowsingService::OnBlockingPageDone(
const std::vector<UnsafeResource>& resources,
bool proceed) {
@@ -528,12 +240,6 @@ void SafeBrowsingService::OnBlockingPageDone(
}
}
-void SafeBrowsingService::NotifyClientBlockingComplete(Client* client,
- bool proceed) {
- client->OnBlockingPageComplete(proceed);
-}
-
-// This method runs on the UI loop to access the prefs.
void SafeBrowsingService::OnNewMacKeys(const std::string& client_key,
const std::string& wrapped_key) {
PrefService* prefs = g_browser_process->local_state();
@@ -543,32 +249,11 @@ void SafeBrowsingService::OnNewMacKeys(const std::string& client_key,
}
}
-void SafeBrowsingService::ChunkInserted() {
- DCHECK(MessageLoop::current() == safe_browsing_thread_->message_loop());
- ChromeThread::PostTask(
- ChromeThread::IO, FROM_HERE,
- NewRunnableMethod(this, &SafeBrowsingService::OnChunkInserted));
-}
-
-void SafeBrowsingService::OnChunkInserted() {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
- if (enabled_)
- protocol_manager_->OnChunkInserted();
-}
-
-void SafeBrowsingService::DatabaseLoadComplete() {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
- if (!enabled_)
- return;
-
- database_loaded_ = true;
-
- if (protocol_manager_)
- protocol_manager_->Initialize();
-
- // If we have any queued requests, we can now check them.
- if (!resetting_)
- RunQueuedClients();
+void SafeBrowsingService::OnEnable(bool enabled) {
+ if (enabled)
+ Start();
+ else
+ ShutDown();
}
// static
@@ -584,55 +269,168 @@ void SafeBrowsingService::ResetDatabase() {
this, &SafeBrowsingService::OnResetDatabase));
}
-void SafeBrowsingService::OnResetDatabase() {
- DCHECK(MessageLoop::current() == safe_browsing_thread_->message_loop());
- GetDatabase()->ResetDatabase();
- ChromeThread::PostTask(
- ChromeThread::IO, FROM_HERE,
- NewRunnableMethod(this, &SafeBrowsingService::OnResetComplete));
+void SafeBrowsingService::LogPauseDelay(TimeDelta time) {
+ UMA_HISTOGRAM_LONG_TIMES("SB2.Delay", time);
}
-void SafeBrowsingService::OnResetComplete() {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
- if (enabled_) {
- resetting_ = false;
- database_loaded_ = true;
- RunQueuedClients();
- }
+SafeBrowsingService::~SafeBrowsingService() {
}
-void SafeBrowsingService::HandleChunk(const std::string& list,
- std::deque<SBChunk>* chunks) {
+void SafeBrowsingService::OnIOInitialize(
+ const std::string& client_key,
+ const std::string& wrapped_key,
+ URLRequestContextGetter* request_context_getter) {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
- DCHECK(enabled_);
- safe_browsing_thread_->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
- this, &SafeBrowsingService::HandleChunkForDatabase, list, chunks));
+ enabled_ = true;
+
+ // On Windows, get the safe browsing client name from the browser
+ // distribution classes in installer util. These classes don't yet have
+ // an analog on non-Windows builds so just keep the name specified here.
+#if defined(OS_WIN)
+ BrowserDistribution* dist = BrowserDistribution::GetDistribution();
+ std::string client_name(dist->GetSafeBrowsingName());
+#else
+#if defined(GOOGLE_CHROME_BUILD)
+ std::string client_name("googlechrome");
+#else
+ std::string client_name("chromium");
+#endif
+#endif
+
+ protocol_manager_ = new SafeBrowsingProtocolManager(this,
+ client_name,
+ client_key,
+ wrapped_key,
+ request_context_getter);
+
+ // Balance the reference added by Start().
+ request_context_getter->Release();
+
+ // We want to initialize the protocol manager only after the database has
+ // loaded, which we'll receive asynchronously (DatabaseLoadComplete). If
+ // database_loaded_ isn't true, we'll wait for that notification to do the
+ // init.
+ if (database_loaded_)
+ protocol_manager_->Initialize();
}
-void SafeBrowsingService::HandleChunkForDatabase(
- const std::string& list_name,
- std::deque<SBChunk>* chunks) {
+void SafeBrowsingService::OnDBInitialize() {
DCHECK(MessageLoop::current() == safe_browsing_thread_->message_loop());
-
- GetDatabase()->InsertChunks(list_name, chunks);
+ GetDatabase();
}
-void SafeBrowsingService::HandleChunkDelete(
- std::vector<SBChunkDelete>* chunk_deletes) {
+void SafeBrowsingService::OnIOShutdown() {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
- DCHECK(enabled_);
- safe_browsing_thread_->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
- this, &SafeBrowsingService::DeleteChunks, chunk_deletes));
+ if (!enabled_)
+ return;
+
+ enabled_ = false;
+ resetting_ = false;
+
+ // This cancels all in-flight GetHash requests.
+ delete protocol_manager_;
+ protocol_manager_ = NULL;
+
+ if (safe_browsing_thread_.get())
+ safe_browsing_thread_->message_loop()->DeleteSoon(FROM_HERE, database_);
+
+ // Flush the database thread. Any in-progress database check results will be
+ // ignored and cleaned up below.
+ safe_browsing_thread_.reset(NULL);
+
+ database_ = NULL;
+ database_loaded_ = false;
+
+ // Delete queued and pending checks once the database thread is done, calling
+ // back any clients with 'URL_SAFE'.
+ while (!queued_checks_.empty()) {
+ QueuedCheck check = queued_checks_.front();
+ if (check.client)
+ check.client->OnUrlCheckResult(check.url, URL_SAFE);
+ queued_checks_.pop_front();
+ }
+
+ for (CurrentChecks::iterator it = checks_.begin();
+ it != checks_.end(); ++it) {
+ if ((*it)->client)
+ (*it)->client->OnUrlCheckResult((*it)->url, URL_SAFE);
+ delete *it;
+ }
+ checks_.clear();
+
+ gethash_requests_.clear();
}
-void SafeBrowsingService::DeleteChunks(
- std::vector<SBChunkDelete>* chunk_deletes) {
+SafeBrowsingDatabase* SafeBrowsingService::GetDatabase() {
DCHECK(MessageLoop::current() == safe_browsing_thread_->message_loop());
+ if (database_)
+ return database_;
- GetDatabase()->DeleteChunks(chunk_deletes);
+ FilePath path;
+ bool result = PathService::Get(chrome::DIR_USER_DATA, &path);
+ DCHECK(result);
+ path = path.Append(chrome::kSafeBrowsingFilename);
+
+ Time before = Time::Now();
+ SafeBrowsingDatabase* database = SafeBrowsingDatabase::Create();
+ Callback0::Type* chunk_callback =
+ NewCallback(this, &SafeBrowsingService::ChunkInserted);
+ database->Init(path, chunk_callback);
+ database_ = database;
+
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(this, &SafeBrowsingService::DatabaseLoadComplete));
+
+ TimeDelta open_time = Time::Now() - before;
+ SB_DLOG(INFO) << "SafeBrowsing database open took " <<
+ open_time.InMilliseconds() << " ms.";
+
+ return database_;
+}
+
+void SafeBrowsingService::OnCheckDone(SafeBrowsingCheck* check) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+
+ // If we've been shutdown during the database lookup, this check will already
+ // have been deleted (in OnIOShutdown).
+ if (!enabled_ || checks_.find(check) == checks_.end())
+ return;
+
+ if (check->client && check->need_get_hash) {
+ // We have a partial match so we need to query Google for the full hash.
+ // Clean up will happen in HandleGetHashResults.
+
+ // See if we have a GetHash request already in progress for this particular
+ // prefix. If so, we just append ourselves to the list of interested parties
+ // when the results arrive. We only do this for checks involving one prefix,
+ // since that is the common case (multiple prefixes will issue the request
+ // as normal).
+ if (check->prefix_hits.size() == 1) {
+ SBPrefix prefix = check->prefix_hits[0];
+ GetHashRequests::iterator it = gethash_requests_.find(prefix);
+ if (it != gethash_requests_.end()) {
+ // There's already a request in progress.
+ it->second.push_back(check);
+ return;
+ }
+
+ // No request in progress, so we're the first for this prefix.
+ GetHashRequestors requestors;
+ requestors.push_back(check);
+ gethash_requests_[prefix] = requestors;
+ }
+
+ // Reset the start time so that we can measure the network time without the
+ // database time.
+ check->start = Time::Now();
+ protocol_manager_->GetFullHash(check, check->prefix_hits);
+ } else {
+ // We may have cached results for previous GetHash queries.
+ HandleOneCheck(check, check->full_hits);
+ }
}
-// Database worker function.
void SafeBrowsingService::GetAllChunksFromDatabase() {
DCHECK(MessageLoop::current() == safe_browsing_thread_->message_loop());
bool database_error = true;
@@ -653,7 +451,6 @@ void SafeBrowsingService::GetAllChunksFromDatabase() {
database_error));
}
-// Called on the io thread with the results of all chunks.
void SafeBrowsingService::OnGetAllChunksFromDatabase(
const std::vector<SBListChunkRanges>& lists, bool database_error) {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
@@ -661,6 +458,49 @@ void SafeBrowsingService::OnGetAllChunksFromDatabase(
protocol_manager_->OnGetChunksComplete(lists, database_error);
}
+void SafeBrowsingService::ChunkInserted() {
+ DCHECK(MessageLoop::current() == safe_browsing_thread_->message_loop());
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(this, &SafeBrowsingService::OnChunkInserted));
+}
+
+void SafeBrowsingService::OnChunkInserted() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ if (enabled_)
+ protocol_manager_->OnChunkInserted();
+}
+
+void SafeBrowsingService::DatabaseLoadComplete() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ if (!enabled_)
+ return;
+
+ database_loaded_ = true;
+
+ if (protocol_manager_)
+ protocol_manager_->Initialize();
+
+ // If we have any queued requests, we can now check them.
+ if (!resetting_)
+ RunQueuedClients();
+}
+
+void SafeBrowsingService::HandleChunkForDatabase(
+ const std::string& list_name,
+ std::deque<SBChunk>* chunks) {
+ DCHECK(MessageLoop::current() == safe_browsing_thread_->message_loop());
+
+ GetDatabase()->InsertChunks(list_name, chunks);
+}
+
+void SafeBrowsingService::DeleteChunks(
+ std::vector<SBChunkDelete>* chunk_deletes) {
+ DCHECK(MessageLoop::current() == safe_browsing_thread_->message_loop());
+
+ GetDatabase()->DeleteChunks(chunk_deletes);
+}
+
SafeBrowsingService::UrlCheckResult SafeBrowsingService::GetResultFromListname(
const std::string& list_name) {
if (safe_browsing_util::IsPhishingList(list_name)) {
@@ -675,8 +515,63 @@ SafeBrowsingService::UrlCheckResult SafeBrowsingService::GetResultFromListname(
return URL_SAFE;
}
-void SafeBrowsingService::LogPauseDelay(TimeDelta time) {
- UMA_HISTOGRAM_LONG_TIMES("SB2.Delay", time);
+void SafeBrowsingService::NotifyClientBlockingComplete(Client* client,
+ bool proceed) {
+ client->OnBlockingPageComplete(proceed);
+}
+
+void SafeBrowsingService::DatabaseUpdateFinished(bool update_succeeded) {
+ DCHECK(MessageLoop::current() == safe_browsing_thread_->message_loop());
+ if (GetDatabase())
+ GetDatabase()->UpdateFinished(update_succeeded);
+}
+
+void SafeBrowsingService::Start() {
+ DCHECK(!safe_browsing_thread_.get());
+ safe_browsing_thread_.reset(new base::Thread("Chrome_SafeBrowsingThread"));
+ if (!safe_browsing_thread_->Start())
+ return;
+
+ // Retrieve client MAC keys.
+ PrefService* local_state = g_browser_process->local_state();
+ std::string client_key, wrapped_key;
+ if (local_state) {
+ client_key =
+ WideToASCII(local_state->GetString(prefs::kSafeBrowsingClientKey));
+ wrapped_key =
+ WideToASCII(local_state->GetString(prefs::kSafeBrowsingWrappedKey));
+ }
+
+ // We will issue network fetches using the default profile's request context.
+ URLRequestContextGetter* request_context_getter =
+ GetDefaultProfile()->GetRequestContext();
+ request_context_getter->AddRef(); // Balanced in OnIOInitialize.
+
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(
+ this, &SafeBrowsingService::OnIOInitialize, client_key, wrapped_key,
+ request_context_getter));
+
+ safe_browsing_thread_->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
+ this, &SafeBrowsingService::OnDBInitialize));
+}
+
+void SafeBrowsingService::OnResetDatabase() {
+ DCHECK(MessageLoop::current() == safe_browsing_thread_->message_loop());
+ GetDatabase()->ResetDatabase();
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(this, &SafeBrowsingService::OnResetComplete));
+}
+
+void SafeBrowsingService::OnResetComplete() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ if (enabled_) {
+ resetting_ = false;
+ database_loaded_ = true;
+ RunQueuedClients();
+ }
}
void SafeBrowsingService::CacheHashResults(
@@ -686,15 +581,92 @@ void SafeBrowsingService::CacheHashResults(
GetDatabase()->CacheHashResults(prefixes, full_hashes);
}
-void SafeBrowsingService::RunQueuedClients() {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
- HISTOGRAM_COUNTS("SB.QueueDepth", queued_checks_.size());
- while (!queued_checks_.empty()) {
- QueuedCheck check = queued_checks_.front();
- HISTOGRAM_TIMES("SB.QueueDelay", Time::Now() - check.start);
- CheckUrl(check.url, check.client);
- queued_checks_.pop_front();
+void SafeBrowsingService::OnHandleGetHashResults(
+ SafeBrowsingCheck* check,
+ const std::vector<SBFullHashResult>& full_hashes) {
+ SBPrefix prefix = check->prefix_hits[0];
+ GetHashRequests::iterator it = gethash_requests_.find(prefix);
+ if (check->prefix_hits.size() > 1 || it == gethash_requests_.end()) {
+ HandleOneCheck(check, full_hashes);
+ return;
+ }
+
+ // Call back all interested parties.
+ GetHashRequestors& requestors = it->second;
+ for (GetHashRequestors::iterator r = requestors.begin();
+ r != requestors.end(); ++r) {
+ HandleOneCheck(*r, full_hashes);
+ }
+
+ gethash_requests_.erase(it);
+}
+
+void SafeBrowsingService::HandleOneCheck(
+ SafeBrowsingCheck* check,
+ const std::vector<SBFullHashResult>& full_hashes) {
+ if (check->client) {
+ UrlCheckResult result = URL_SAFE;
+ int index = safe_browsing_util::CompareFullHashes(check->url, full_hashes);
+ if (index != -1) {
+ result = GetResultFromListname(full_hashes[index].list_name);
+ } else {
+ // Log the case where the SafeBrowsing servers return full hashes in the
+ // GetHash response that match the prefix we're looking up, but don't
+ // match the full hash of the URL.
+ if (!full_hashes.empty())
+ UMA_HISTOGRAM_COUNTS("SB2.GetHashServerMiss", 1);
+ }
+
+ // Let the client continue handling the original request.
+ check->client->OnUrlCheckResult(check->url, result);
+ }
+
+ checks_.erase(check);
+ delete check;
+}
+
+void SafeBrowsingService::DoDisplayBlockingPage(
+ const UnsafeResource& resource) {
+ // The tab might have been closed.
+ TabContents* wc =
+ tab_util::GetTabContentsByID(resource.render_process_host_id,
+ resource.render_view_id);
+
+ if (!wc) {
+ // The tab is gone and we did not have a chance at showing the interstitial.
+ // Just act as "Don't Proceed" was chosen.
+ std::vector<UnsafeResource> resources;
+ resources.push_back(resource);
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(
+ this, &SafeBrowsingService::OnBlockingPageDone, resources, false));
+ return;
}
+
+ // Report the malware sub-resource to the SafeBrowsing servers if we have a
+ // malware sub-resource on a safe page and only if the user has opted in to
+ // reporting statistics.
+ PrefService* prefs = g_browser_process->local_state();
+ DCHECK(prefs);
+ if (prefs && prefs->GetBoolean(prefs::kMetricsReportingEnabled) &&
+ resource.resource_type != ResourceType::MAIN_FRAME &&
+ resource.threat_type == SafeBrowsingService::URL_MALWARE) {
+ GURL page_url = wc->GetURL();
+ GURL referrer_url;
+ NavigationEntry* entry = wc->controller().GetActiveEntry();
+ if (entry)
+ referrer_url = entry->referrer();
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(this,
+ &SafeBrowsingService::ReportMalware,
+ resource.url,
+ page_url,
+ referrer_url));
+ }
+
+ SafeBrowsingBlockingPage::ShowBlockingPage(this, resource);
}
void SafeBrowsingService::ReportMalware(const GURL& malware_url,
@@ -716,3 +688,14 @@ void SafeBrowsingService::ReportMalware(const GURL& malware_url,
if (full_hits.empty())
protocol_manager_->ReportMalware(malware_url, page_url, referrer_url);
}
+
+void SafeBrowsingService::RunQueuedClients() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ HISTOGRAM_COUNTS("SB.QueueDepth", queued_checks_.size());
+ while (!queued_checks_.empty()) {
+ QueuedCheck check = queued_checks_.front();
+ HISTOGRAM_TIMES("SB.QueueDelay", Time::Now() - check.start);
+ CheckUrl(check.url, check.client);
+ queued_checks_.pop_front();
+ }
+}