summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/base.gyp1
-rw-r--r--base/scoped_bool.h24
-rw-r--r--chrome/browser/safe_browsing/safe_browsing_database_bloom.cc40
-rw-r--r--chrome/browser/safe_browsing/safe_browsing_database_bloom.h10
-rw-r--r--chrome/browser/safe_browsing/safe_browsing_service.cc34
-rw-r--r--chrome/browser/safe_browsing/safe_browsing_service.h3
6 files changed, 73 insertions, 39 deletions
diff --git a/base/base.gyp b/base/base.gyp
index b954e3b..51aa6c8 100644
--- a/base/base.gyp
+++ b/base/base.gyp
@@ -251,6 +251,7 @@
'resource_util.h',
'safe_strerror_posix.cc',
'safe_strerror_posix.h',
+ 'scoped_bool.h',
'scoped_bstr_win.cc',
'scoped_bstr_win.h',
'scoped_cftyperef.h',
diff --git a/base/scoped_bool.h b/base/scoped_bool.h
new file mode 100644
index 0000000..0622f967
--- /dev/null
+++ b/base/scoped_bool.h
@@ -0,0 +1,24 @@
+// Copyright (c) 2009 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.
+
+#ifndef BASE_SCOPED_BOOL_H_
+#define BASE_SCOPED_BOOL_H_
+
+// ScopedBool is useful for setting a flag only during a particular scope. If
+// you have code that has to add "var = false;" at all the exit points of a
+// function, for example, you would benefit from using this instead.
+
+class ScopedBool {
+ public:
+ explicit ScopedBool(bool* scoped_bool) : scoped_bool_(scoped_bool) {
+ *scoped_bool_ = true;
+ }
+ ~ScopedBool() { *scoped_bool_ = false; }
+
+ private:
+ bool* scoped_bool_;
+ DISALLOW_COPY_AND_ASSIGN(ScopedBool);
+};
+
+#endif // BASE_SCOPED_BOOL_H_
diff --git a/chrome/browser/safe_browsing/safe_browsing_database_bloom.cc b/chrome/browser/safe_browsing/safe_browsing_database_bloom.cc
index 1f4d943..650f556 100644
--- a/chrome/browser/safe_browsing/safe_browsing_database_bloom.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_database_bloom.cc
@@ -10,6 +10,7 @@
#include "base/message_loop.h"
#include "base/platform_thread.h"
#include "base/process_util.h"
+#include "base/scoped_bool.h"
#include "base/sha2.h"
#include "base/stats_counters.h"
#include "base/string_util.h"
@@ -38,9 +39,9 @@ static const FilePath::CharType kBloomFilterFileSuffix[] =
SafeBrowsingDatabaseBloom::SafeBrowsingDatabaseBloom()
: db_(NULL),
- init_(false),
ALLOW_THIS_IN_INITIALIZER_LIST(reset_factory_(this)),
- add_count_(0) {
+ add_count_(0),
+ performing_reset_(false) {
}
SafeBrowsingDatabaseBloom::~SafeBrowsingDatabaseBloom() {
@@ -49,16 +50,17 @@ SafeBrowsingDatabaseBloom::~SafeBrowsingDatabaseBloom() {
void SafeBrowsingDatabaseBloom::Init(const FilePath& filename,
Callback0::Type* chunk_inserted_callback) {
- DCHECK(!init_ && filename_.empty());
+ DCHECK(filename_.empty()); // Ensure we haven't been run before.
filename_ = FilePath(filename.value() + kBloomFilterFileSuffix);
bloom_filter_filename_ = BloomFilterFilename(filename_);
+ // NOTE: There is no need to grab the lock in this function, since until it
+ // returns, there are no pointers to this class on other threads.
hash_cache_.reset(new HashCache);
LoadBloomFilter();
- init_ = true;
chunk_inserted_callback_.reset(chunk_inserted_callback);
}
@@ -186,26 +188,33 @@ bool SafeBrowsingDatabaseBloom::CreateTables() {
return true;
}
-// The SafeBrowsing service assumes this operation is run synchronously on the
-// database thread. Any URLs that the service needs to check when this is
-// running are queued up and run once the reset is done.
bool SafeBrowsingDatabaseBloom::ResetDatabase() {
- hash_cache_->clear();
- ClearUpdateCaches();
+ // Open() can call us when trying to handle potential database corruption.
+ // Because we call Open() at the bottom of the function, we need to guard
+ // against recursion here.
+ if (performing_reset_)
+ return false; // Don't recurse.
+
+ ScopedBool preforming_reset_scope_(&performing_reset_);
+ // Delete files on disk.
bool rv = Close();
DCHECK(rv);
-
if (!file_util::Delete(filename_, false)) {
NOTREACHED();
return false;
}
-
DeleteBloomFilter();
- bloom_filter_ = new BloomFilter(BloomFilter::kBloomFilterMinSize *
- BloomFilter::kBloomFilterSizeRatio);
- // TODO(paulg): Fix potential infinite recursion between Open and Reset.
+ // Reset objects in memory.
+ {
+ AutoLock lock(lookup_lock_);
+ hash_cache_->clear();
+ ClearUpdateCaches();
+ bloom_filter_ = new BloomFilter(BloomFilter::kBloomFilterMinSize *
+ BloomFilter::kBloomFilterSizeRatio);
+ }
+
return Open();
}
@@ -225,6 +234,7 @@ bool SafeBrowsingDatabaseBloom::CheckCompatibleVersion() {
}
void SafeBrowsingDatabaseBloom::ClearUpdateCaches() {
+ AutoLock lock(lookup_lock_);
add_del_cache_.clear();
sub_del_cache_.clear();
add_chunk_cache_.clear();
@@ -1214,6 +1224,7 @@ void SafeBrowsingDatabaseBloom::BuildBloomFilter() {
add_count_ = GetAddPrefixCount();
if (add_count_ == 0) {
+ AutoLock lock(lookup_lock_);
bloom_filter_ = NULL;
return;
}
@@ -1318,6 +1329,7 @@ void SafeBrowsingDatabaseBloom::GetCachedFullHashes(
std::vector<SBFullHashResult>* full_hits,
Time last_update) {
DCHECK(prefix_hits && full_hits);
+ lookup_lock_.AssertAcquired();
Time max_age = Time::Now() - TimeDelta::FromMinutes(kMaxStalenessMinutes);
diff --git a/chrome/browser/safe_browsing/safe_browsing_database_bloom.h b/chrome/browser/safe_browsing/safe_browsing_database_bloom.h
index c6a65b3..296e4e649 100644
--- a/chrome/browser/safe_browsing/safe_browsing_database_bloom.h
+++ b/chrome/browser/safe_browsing/safe_browsing_database_bloom.h
@@ -178,9 +178,6 @@ class SafeBrowsingDatabaseBloom : public SafeBrowsingDatabase {
// Cache of compiled statements for our database.
scoped_ptr<SqliteStatementCache> statement_cache_;
- // True iff the database has been opened successfully.
- bool init_;
-
// Called after an add/sub chunk is processed.
scoped_ptr<Callback0::Type> chunk_inserted_callback_;
@@ -202,9 +199,14 @@ class SafeBrowsingDatabaseBloom : public SafeBrowsingDatabase {
// Transaction for protecting database integrity during updates.
scoped_ptr<SQLTransaction> insert_transaction_;
- // Lock for protecting access to the bloom filter and hash cache.
+ // Lock for protecting access to variables that may be used on the IO thread.
+ // This includes |bloom_filter_|, |hash_cache_| and |prefix_miss_cache_|.
Lock lookup_lock_;
+ // True if we're in the middle of a reset. This is used to prevent possible
+ // infinite recursion.
+ bool performing_reset_;
+
// A store for GetHash results that have not yet been written to the database.
HashList pending_full_hashes_;
diff --git a/chrome/browser/safe_browsing/safe_browsing_service.cc b/chrome/browser/safe_browsing/safe_browsing_service.cc
index e59183b..cc01493 100644
--- a/chrome/browser/safe_browsing/safe_browsing_service.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_service.cc
@@ -39,7 +39,6 @@ SafeBrowsingService::SafeBrowsingService()
: database_(NULL),
protocol_manager_(NULL),
enabled_(false),
- resetting_(false),
update_in_progress_(false) {
}
@@ -66,7 +65,7 @@ bool SafeBrowsingService::CheckUrl(const GURL& url, Client* client) {
if (!enabled_)
return true;
- if (!database_ || resetting_) {
+ if (!database_) {
QueuedCheck check;
check.client = client;
check.url = url;
@@ -114,7 +113,7 @@ void SafeBrowsingService::CancelCheck(Client* client) {
}
// Scan the queued clients store. Clients may be here if they requested a URL
- // check before the database has finished loading or resetting.
+ // check before the database has finished loading.
for (std::deque<QueuedCheck>::iterator it(queued_checks_.begin());
it != queued_checks_.end(); ++it) {
if (it->client == client)
@@ -261,7 +260,6 @@ void SafeBrowsingService::RegisterPrefs(PrefService* prefs) {
void SafeBrowsingService::ResetDatabase() {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
- resetting_ = true;
safe_browsing_thread_->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
this, &SafeBrowsingService::OnResetDatabase));
}
@@ -317,7 +315,6 @@ void SafeBrowsingService::OnIOShutdown() {
return;
enabled_ = false;
- resetting_ = false;
// This cancels all in-flight GetHash requests.
delete protocol_manager_;
@@ -467,8 +464,7 @@ void SafeBrowsingService::DatabaseLoadComplete() {
return;
// If we have any queued requests, we can now check them.
- if (!resetting_)
- RunQueuedClients();
+ RunQueuedClients();
}
void SafeBrowsingService::HandleChunkForDatabase(
@@ -545,7 +541,6 @@ void SafeBrowsingService::Start() {
void SafeBrowsingService::OnResetDatabase() {
DCHECK(MessageLoop::current() == safe_browsing_thread_->message_loop());
GetDatabase()->ResetDatabase();
- resetting_ = false;
ChromeThread::PostTask(
ChromeThread::IO, FROM_HERE,
NewRunnableMethod(this, &SafeBrowsingService::DatabaseLoadComplete));
@@ -651,19 +646,22 @@ void SafeBrowsingService::ReportMalware(const GURL& malware_url,
const GURL& referrer_url) {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
- if (!enabled_ || !database_)
+ if (!enabled_)
return;
- // Check if 'page_url' is already blacklisted (exists in our cache). Only
- // report if it's not there.
- std::string list;
- std::vector<SBPrefix> prefix_hits;
- std::vector<SBFullHashResult> full_hits;
- database_->ContainsUrl(page_url, &list, &prefix_hits, &full_hits,
- protocol_manager_->last_update());
+ if (database_) {
+ // Check if 'page_url' is already blacklisted (exists in our cache). Only
+ // report if it's not there.
+ std::string list;
+ std::vector<SBPrefix> prefix_hits;
+ std::vector<SBFullHashResult> full_hits;
+ database_->ContainsUrl(page_url, &list, &prefix_hits, &full_hits,
+ protocol_manager_->last_update());
+ if (!full_hits.empty())
+ return;
+ }
- if (full_hits.empty())
- protocol_manager_->ReportMalware(malware_url, page_url, referrer_url);
+ protocol_manager_->ReportMalware(malware_url, page_url, referrer_url);
}
void SafeBrowsingService::RunQueuedClients() {
diff --git a/chrome/browser/safe_browsing/safe_browsing_service.h b/chrome/browser/safe_browsing/safe_browsing_service.h
index a2d5adb..9f138c8 100644
--- a/chrome/browser/safe_browsing/safe_browsing_service.h
+++ b/chrome/browser/safe_browsing/safe_browsing_service.h
@@ -274,9 +274,6 @@ class SafeBrowsingService
// The SafeBrowsing thread that runs database operations.
scoped_ptr<base::Thread> safe_browsing_thread_;
- // Indicates if we are in the process of resetting the database.
- bool resetting_;
-
// Indicates if we're currently in an update cycle.
bool update_in_progress_;