summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgeorgey@chromium.org <georgey@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-17 00:44:51 +0000
committergeorgey@chromium.org <georgey@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-17 00:44:51 +0000
commit9c8242a77c7788a30112f6d840c12e481f312362 (patch)
tree0b1c4f96986206d413296113d632045d707c2d93
parent67c4e954ea58ea701c7500d622901ff3f7a03f60 (diff)
downloadchromium_src-9c8242a77c7788a30112f6d840c12e481f312362.zip
chromium_src-9c8242a77c7788a30112f6d840c12e481f312362.tar.gz
chromium_src-9c8242a77c7788a30112f6d840c12e481f312362.tar.bz2
Fixes and simplification to ShortcutsBackend including addition of "DeleteAll"
TEST=unit-tests BUG=none Review URL: http://codereview.chromium.org/7821011 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@101611 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/autocomplete/shortcuts_provider.cc67
-rw-r--r--chrome/browser/autocomplete/shortcuts_provider.h23
-rw-r--r--chrome/browser/autocomplete/shortcuts_provider_unittest.cc115
-rw-r--r--chrome/browser/history/shortcuts_backend.cc205
-rw-r--r--chrome/browser/history/shortcuts_backend.h75
-rw-r--r--chrome/browser/history/shortcuts_backend_unittest.cc58
-rw-r--r--chrome/browser/history/shortcuts_database.cc75
-rw-r--r--chrome/browser/history/shortcuts_database.h13
-rw-r--r--chrome/browser/history/shortcuts_database_unittest.cc16
9 files changed, 326 insertions, 321 deletions
diff --git a/chrome/browser/autocomplete/shortcuts_provider.cc b/chrome/browser/autocomplete/shortcuts_provider.cc
index 1b29dac..4ef6ae9 100644
--- a/chrome/browser/autocomplete/shortcuts_provider.cc
+++ b/chrome/browser/autocomplete/shortcuts_provider.cc
@@ -61,11 +61,12 @@ ShortcutsProvider::ShortcutsProvider(ACProviderListener* listener,
Profile* profile)
: AutocompleteProvider(listener, profile, "ShortcutsProvider"),
languages_(profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)),
+ initialized_(false),
shortcuts_backend_(profile->GetShortcutsBackend()) {
if (shortcuts_backend_.get()) {
shortcuts_backend_->AddObserver(this);
if (shortcuts_backend_->initialized())
- LoadShortcuts();
+ initialized_ = true;
}
}
@@ -81,6 +82,9 @@ void ShortcutsProvider::Start(const AutocompleteInput& input,
if (input.type() == AutocompleteInput::INVALID)
return;
+ if (!initialized_)
+ return;
+
base::TimeTicks start_time = base::TimeTicks::Now();
GetMatches(input);
if (input.text().length() < 6) {
@@ -114,29 +118,7 @@ void ShortcutsProvider::DeleteMatch(const AutocompleteMatch& match) {
}
void ShortcutsProvider::OnShortcutsLoaded() {
- LoadShortcuts();
-}
-
-void ShortcutsProvider::OnShortcutAddedOrUpdated(const Shortcut& shortcut) {
- shortcuts_provider::GuidToShortcutsIteratorMap::iterator it =
- guid_map_.find(shortcut.id);
- if (it != guid_map_.end()) {
- shortcuts_map_.erase(it->second);
- }
- guid_map_[shortcut.id] = shortcuts_map_.insert(
- std::make_pair(base::i18n::ToLower(shortcut.text), shortcut));
-}
-
-void ShortcutsProvider::OnShortcutsRemoved(
- const std::vector<std::string>& shortcuts_ids) {
- for (size_t i = 0; i < shortcuts_ids.size(); ++i) {
- shortcuts_provider::GuidToShortcutsIteratorMap::iterator it =
- guid_map_.find(shortcuts_ids[i]);
- if (it != guid_map_.end()) {
- shortcuts_map_.erase(it->second);
- guid_map_.erase(it);
- }
- }
+ initialized_ = true;
}
void ShortcutsProvider::DeleteMatchesWithURLs(const std::set<GURL>& urls) {
@@ -145,13 +127,6 @@ void ShortcutsProvider::DeleteMatchesWithURLs(const std::set<GURL>& urls) {
}
void ShortcutsProvider::DeleteShortcutsWithURLs(const std::set<GURL>& urls) {
- for (ShortcutMap::iterator it = shortcuts_map_.begin();
- it != shortcuts_map_.end();) {
- if (urls.find(it->second.url) != urls.end())
- shortcuts_map_.erase(it++);
- else
- ++it;
- }
if (!shortcuts_backend_.get())
return; // We are off the record.
for (std::set<GURL>::const_iterator url = urls.begin(); url != urls.end();
@@ -165,8 +140,8 @@ void ShortcutsProvider::GetMatches(const AutocompleteInput& input) {
string16 term_string(base::i18n::ToLower(input.text()));
DCHECK(!term_string.empty());
- for (ShortcutMap::iterator it = FindFirstMatch(term_string);
- it != shortcuts_map_.end() &&
+ for (ShortcutMap::const_iterator it = FindFirstMatch(term_string);
+ it != shortcuts_backend_->shortcuts_map().end() &&
StartsWith(it->first, term_string, true); ++it)
matches_.push_back(ShortcutToACMatch(input, term_string, it));
std::partial_sort(matches_.begin(),
@@ -182,7 +157,7 @@ void ShortcutsProvider::GetMatches(const AutocompleteInput& input) {
AutocompleteMatch ShortcutsProvider::ShortcutToACMatch(
const AutocompleteInput& input,
const string16& term_string,
- ShortcutMap::iterator it) {
+ ShortcutMap::const_iterator it) {
AutocompleteMatch match(this, CalculateScore(term_string, it->second),
true, AutocompleteMatch::HISTORY_TITLE);
match.destination_url = it->second.url;
@@ -280,13 +255,15 @@ ACMatchClassifications ShortcutsProvider::ClassifyAllMatchesInString(
return output;
}
-ShortcutMap::iterator ShortcutsProvider::FindFirstMatch(
+ShortcutMap::const_iterator ShortcutsProvider::FindFirstMatch(
const string16& keyword) {
- ShortcutMap::iterator it = shortcuts_map_.lower_bound(keyword);
+ ShortcutMap::const_iterator it =
+ shortcuts_backend_->shortcuts_map().lower_bound(keyword);
// Lower bound not necessarily matches the keyword, check for item pointed by
// the lower bound iterator to at least start with keyword.
- return ((it == shortcuts_map_.end()) ||
- StartsWith(it->first, keyword, true)) ? it : shortcuts_map_.end();
+ return ((it == shortcuts_backend_->shortcuts_map().end()) ||
+ StartsWith(it->first, keyword, true)) ? it :
+ shortcuts_backend_->shortcuts_map().end();
}
// static
@@ -320,11 +297,11 @@ int ShortcutsProvider::CalculateScore(const string16& terms,
0.5);
}
-void ShortcutsProvider::LoadShortcuts() {
- DCHECK(shortcuts_backend_.get());
- guid_map_.clear();
- CHECK(shortcuts_backend_->GetShortcuts(&shortcuts_map_));
- for (shortcuts_provider::ShortcutMap::iterator it = shortcuts_map_.begin();
- it != shortcuts_map_.end(); ++it)
- guid_map_[it->second.id] = it;
+void ShortcutsProvider::set_shortcuts_backend(
+ history::ShortcutsBackend* shortcuts_backend) {
+ DCHECK(shortcuts_backend);
+ shortcuts_backend_ = shortcuts_backend;
+ shortcuts_backend_->AddObserver(this);
+ if (shortcuts_backend_->initialized())
+ initialized_ = true;
}
diff --git a/chrome/browser/autocomplete/shortcuts_provider.h b/chrome/browser/autocomplete/shortcuts_provider.h
index 38161d4..d41a70b 100644
--- a/chrome/browser/autocomplete/shortcuts_provider.h
+++ b/chrome/browser/autocomplete/shortcuts_provider.h
@@ -51,10 +51,6 @@ class ShortcutsProvider
// ShortcutsBackendObserver:
virtual void OnShortcutsLoaded() OVERRIDE;
- virtual void OnShortcutAddedOrUpdated(
- const shortcuts_provider::Shortcut& shortcut) OVERRIDE;
- virtual void OnShortcutsRemoved(
- const std::vector<std::string>& shortcut_ids) OVERRIDE;
void DeleteMatchesWithURLs(const std::set<GURL>& urls);
void DeleteShortcutsWithURLs(const std::set<GURL>& urls);
@@ -65,7 +61,7 @@ class ShortcutsProvider
AutocompleteMatch ShortcutToACMatch(
const AutocompleteInput& input,
const string16& terms,
- shortcuts_provider::ShortcutMap::iterator it);
+ shortcuts_provider::ShortcutMap::const_iterator it);
// Given |text| and a corresponding base set of classifications
// |original_class|, adds ACMatchClassification::MATCH markers for all
@@ -85,25 +81,16 @@ class ShortcutsProvider
// Returns iterator to first item in |shortcuts_map_| matching |keyword|.
// Returns shortcuts_map_.end() if there are no matches.
- shortcuts_provider::ShortcutMap::iterator FindFirstMatch(
+ shortcuts_provider::ShortcutMap::const_iterator FindFirstMatch(
const string16& keyword);
static int CalculateScore(const string16& terms,
const shortcuts_provider::Shortcut& shortcut);
-
- // Loads shortcuts from the backend.
- void LoadShortcuts();
+ // For unit-test only.
+ void set_shortcuts_backend(history::ShortcutsBackend* shortcuts_backend);
std::string languages_;
-
- // The following two maps are duplicated from the ShortcutsBackend. If any
- // of the copies of ShortcutProvider makes a change and calls ShortcutBackend
- // the change will be committed to storage and to the back-end's copy on the
- // DB thread and propagated back to all copies of provider, so eventually they
- // all are going to be in sync.
- shortcuts_provider::ShortcutMap shortcuts_map_;
- // This is a helper map for quick access to a shortcut by guid.
- shortcuts_provider::GuidToShortcutsIteratorMap guid_map_;
+ bool initialized_;
scoped_refptr<history::ShortcutsBackend> shortcuts_backend_;
};
diff --git a/chrome/browser/autocomplete/shortcuts_provider_unittest.cc b/chrome/browser/autocomplete/shortcuts_provider_unittest.cc
index 534c53d..7b98206 100644
--- a/chrome/browser/autocomplete/shortcuts_provider_unittest.cc
+++ b/chrome/browser/autocomplete/shortcuts_provider_unittest.cc
@@ -18,6 +18,7 @@
#include "chrome/browser/autocomplete/autocomplete_match.h"
#include "chrome/browser/history/history.h"
#include "chrome/browser/history/in_memory_url_index.h"
+#include "chrome/browser/history/shortcuts_backend.h"
#include "chrome/browser/history/url_database.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/common/pref_names.h"
@@ -31,6 +32,7 @@ using base::TimeDelta;
namespace {
struct TestShortcutInfo {
+ std::string guid;
std::string url;
std::string title; // The text that orginally was searched for.
std::string contents;
@@ -40,62 +42,79 @@ struct TestShortcutInfo {
int typed_count;
int days_from_now;
} shortcut_test_db[] = {
- { "http://www.google.com/", "goog",
+ { "BD85DBA2-8C29-49F9-84AE-48E1E90880E0",
+ "http://www.google.com/", "goog",
"Google", "0,1,4,0", "Google", "0,3,4,1", 100, 1 },
- { "http://slashdot.org/", "slash",
+ { "BD85DBA2-8C29-49F9-84AE-48E1E90880E1",
+ "http://slashdot.org/", "slash",
"slashdot.org", "0,3,5,1",
"Slashdot - News for nerds, stuff that matters", "0,2,5,0", 100, 0},
- { "http://slashdot.org/", "news",
+ { "BD85DBA2-8C29-49F9-84AE-48E1E90880E2",
+ "http://slashdot.org/", "news",
"slashdot.org", "0,1",
"Slashdot - News for nerds, stuff that matters", "0,0,11,2,15,0", 5, 0},
- { "http://sports.yahoo.com/", "news",
+ { "BD85DBA2-8C29-49F9-84AE-48E1E90880E3",
+ "http://sports.yahoo.com/", "news",
"sports.yahoo.com", "0,1",
"Yahoo! Sports - Sports News, Scores, Rumors, Fantasy Games, and more",
"0,0,23,2,27,0", 5, 2},
- { "http://www.cnn.com/index.html", "news weather",
+ { "BD85DBA2-8C29-49F9-84AE-48E1E90880E4",
+ "http://www.cnn.com/index.html", "news weather",
"www.cnn.com/index.html", "0,1",
"CNN.com - Breaking News, U.S., World, Weather, Entertainment & Video",
"0,0,19,2,23,0,38,2,45,0", 10, 1},
- { "http://sports.yahoo.com/", "nhl scores",
+ { "BD85DBA2-8C29-49F9-84AE-48E1E90880E5",
+ "http://sports.yahoo.com/", "nhl scores",
"sports.yahoo.com", "0,1",
"Yahoo! Sports - Sports News, Scores, Rumors, Fantasy Games, and more",
"0,0,29,2,35,0", 10, 1},
- { "http://www.nhl.com/scores/index.html", "nhl scores",
+ { "BD85DBA2-8C29-49F9-84AE-48E1E90880E6",
+ "http://www.nhl.com/scores/index.html", "nhl scores",
"www.nhl.com/scores/index.html", "0,1,4,3,7,1",
"January 13, 2010 - NHL.com - Scores", "0,0,19,2,22,0,29,2,35,0", 1, 5},
- { "http://www.testsite.com/a.html", "just",
+ { "BD85DBA2-8C29-49F9-84AE-48E1E90880E7",
+ "http://www.testsite.com/a.html", "just",
"www.testsite.com/a.html", "0,1",
"Test - site - just a test", "0,0,14,2,18,0", 1, 5},
- { "http://www.testsite.com/b.html", "just",
+ { "BD85DBA2-8C29-49F9-84AE-48E1E90880E8",
+ "http://www.testsite.com/b.html", "just",
"www.testsite.com/b.html", "0,1",
"Test - site - just a test", "0,0,14,2,18,0", 2, 5},
- { "http://www.testsite.com/c.html", "just",
+ { "BD85DBA2-8C29-49F9-84AE-48E1E90880E9",
+ "http://www.testsite.com/c.html", "just",
"www.testsite.com/c.html", "0,1",
"Test - site - just a test", "0,0,14,2,18,0", 1, 8},
- { "http://www.testsite.com/d.html", "just a",
+ { "BD85DBA2-8C29-49F9-84AE-48E1E90880EA",
+ "http://www.testsite.com/d.html", "just a",
"www.testsite.com/d.html", "0,1",
"Test - site - just a test", "0,0,14,2,18,0", 1, 12},
- { "http://www.testsite.com/e.html", "just a t",
+ { "BD85DBA2-8C29-49F9-84AE-48E1E90880EB",
+ "http://www.testsite.com/e.html", "just a t",
"www.testsite.com/e.html", "0,1",
"Test - site - just a test", "0,0,14,2,18,0", 1, 12},
- { "http://www.testsite.com/f.html", "just a te",
+ { "BD85DBA2-8C29-49F9-84AE-48E1E90880EC",
+ "http://www.testsite.com/f.html", "just a te",
"www.testsite.com/f.html", "0,1",
"Test - site - just a test", "0,0,14,2,18,0", 1, 12},
- { "http://www.daysagotest.com/a.html", "ago",
+ { "BD85DBA2-8C29-49F9-84AE-48E1E90880ED",
+ "http://www.daysagotest.com/a.html", "ago",
"www.daysagotest.com/a.html", "0,1,8,3,11,1",
"Test - site", "0,0", 1, 1},
- { "http://www.daysagotest.com/b.html", "ago",
+ { "BD85DBA2-8C29-49F9-84AE-48E1E90880EE",
+ "http://www.daysagotest.com/b.html", "ago",
"www.daysagotest.com/b.html", "0,1,8,3,11,1",
"Test - site", "0,0", 1, 2},
- { "http://www.daysagotest.com/c.html", "ago",
+ { "BD85DBA2-8C29-49F9-84AE-48E1E90880EF",
+ "http://www.daysagotest.com/c.html", "ago",
"www.daysagotest.com/c.html", "0,1,8,3,11,1",
"Test - site", "0,0", 1, 3},
- { "http://www.daysagotest.com/d.html", "ago",
+ { "BD85DBA2-8C29-49F9-84AE-48E1E90880F0",
+ "http://www.daysagotest.com/d.html", "ago",
"www.daysagotest.com/d.html", "0,1,8,3,11,1",
"Test - site", "0,0", 1, 4},
};
-} // end namespace
+} // namespace
class ShortcutsProviderTest : public testing::Test,
public ACProviderListener {
@@ -139,6 +158,7 @@ class ShortcutsProviderTest : public testing::Test,
ACMatches ac_matches_; // The resulting matches after running RunTest.
+ scoped_refptr<history::ShortcutsBackend> mock_backend_;
scoped_refptr<ShortcutsProvider> provider_;
};
@@ -154,6 +174,9 @@ void ShortcutsProviderTest::SetUp() {
profile_.reset(new TestingProfile());
profile_->CreateHistoryService(true, false);
provider_ = new ShortcutsProvider(this, profile_.get());
+ mock_backend_ = new history::ShortcutsBackend(FilePath(), profile_.get());
+ mock_backend_->Init();
+ provider_->set_shortcuts_backend(mock_backend_.get());
FillData();
}
@@ -163,7 +186,7 @@ void ShortcutsProviderTest::TearDown() {
void ShortcutsProviderTest::FillData() {
DCHECK(provider_.get());
- provider_->shortcuts_map_.clear();
+ mock_backend_->DeleteAllShortcuts();
for (size_t i = 0; i < arraysize(shortcut_test_db); ++i) {
const TestShortcutInfo& cur = shortcut_test_db[i];
const GURL current_url(cur.url);
@@ -177,8 +200,8 @@ void ShortcutsProviderTest::FillData() {
shortcuts_provider::SpansFromString(
ASCIIToUTF16(cur.description_class)));
shortcut.last_access_time = visit_time;
- provider_->shortcuts_map_.insert(std::make_pair(ASCIIToUTF16(cur.title),
- shortcut));
+ shortcut.id = cur.guid;
+ mock_backend_->AddShortcut(shortcut);
}
}
@@ -536,18 +559,22 @@ TEST_F(ShortcutsProviderTest, CalculateScore) {
TEST_F(ShortcutsProviderTest, DeleteMatch) {
TestShortcutInfo shortcuts_to_test_delete[3] = {
- { "http://www.deletetest.com/1.html", "delete",
+ { "BD85DBA2-8C29-49F9-84AE-48E1E90880F1",
+ "http://www.deletetest.com/1.html", "delete",
"http://www.deletetest.com/1.html", "0,2",
"Erase this shortcut!", "0,0", 1, 1},
- { "http://www.deletetest.com/1.html", "erase",
+ { "BD85DBA2-8C29-49F9-84AE-48E1E90880F2",
+ "http://www.deletetest.com/1.html", "erase",
"http://www.deletetest.com/1.html", "0,2",
"Erase this shortcut!", "0,0", 1, 1},
- { "http://www.deletetest.com/2.html", "delete",
+ { "BD85DBA2-8C29-49F9-84AE-48E1E90880F3",
+ "http://www.deletetest.com/2.html", "delete",
"http://www.deletetest.com/2.html", "0,2",
"Erase this shortcut!", "0,0", 1, 1},
};
- size_t original_shortcuts_count = provider_->shortcuts_map_.size();
+ size_t original_shortcuts_count =
+ provider_->shortcuts_backend_->shortcuts_map().size();
for (size_t i = 0; i < arraysize(shortcuts_to_test_delete); ++i) {
const TestShortcutInfo& cur = shortcuts_to_test_delete[i];
@@ -562,15 +589,18 @@ TEST_F(ShortcutsProviderTest, DeleteMatch) {
shortcuts_provider::SpansFromString(
ASCIIToUTF16(cur.description_class)));
shortcut.last_access_time = visit_time;
- provider_->shortcuts_map_.insert(std::make_pair(ASCIIToUTF16(cur.title),
- shortcut));
+ shortcut.id = cur.guid;
+ mock_backend_->AddShortcut(shortcut);
}
- EXPECT_EQ(original_shortcuts_count + 3, provider_->shortcuts_map_.size());
- EXPECT_FALSE(provider_->shortcuts_map_.end() ==
- provider_->shortcuts_map_.find(ASCIIToUTF16("delete")));
- EXPECT_FALSE(provider_->shortcuts_map_.end() ==
- provider_->shortcuts_map_.find(ASCIIToUTF16("erase")));
+ EXPECT_EQ(original_shortcuts_count + 3,
+ provider_->shortcuts_backend_->shortcuts_map().size());
+ EXPECT_FALSE(provider_->shortcuts_backend_->shortcuts_map().end() ==
+ provider_->shortcuts_backend_->shortcuts_map().find(
+ ASCIIToUTF16("delete")));
+ EXPECT_FALSE(provider_->shortcuts_backend_->shortcuts_map().end() ==
+ provider_->shortcuts_backend_->shortcuts_map().find(
+ ASCIIToUTF16("erase")));
AutocompleteMatch match(provider_, 1200, true,
AutocompleteMatch::HISTORY_TITLE);
@@ -583,18 +613,23 @@ TEST_F(ShortcutsProviderTest, DeleteMatch) {
// |shortcuts_to_test_delete[0]| and |shortcuts_to_test_delete[1]| should be
// deleted, but not |shortcuts_to_test_delete[2]| as it has different url.
- EXPECT_EQ(original_shortcuts_count + 1, provider_->shortcuts_map_.size());
- EXPECT_FALSE(provider_->shortcuts_map_.end() ==
- provider_->shortcuts_map_.find(ASCIIToUTF16("delete")));
- EXPECT_TRUE(provider_->shortcuts_map_.end() ==
- provider_->shortcuts_map_.find(ASCIIToUTF16("erase")));
+ EXPECT_EQ(original_shortcuts_count + 1,
+ provider_->shortcuts_backend_->shortcuts_map().size());
+ EXPECT_FALSE(provider_->shortcuts_backend_->shortcuts_map().end() ==
+ provider_->shortcuts_backend_->shortcuts_map().find(
+ ASCIIToUTF16("delete")));
+ EXPECT_TRUE(provider_->shortcuts_backend_->shortcuts_map().end() ==
+ provider_->shortcuts_backend_->shortcuts_map().find(
+ ASCIIToUTF16("erase")));
match.destination_url = GURL(shortcuts_to_test_delete[2].url);
match.contents = ASCIIToUTF16(shortcuts_to_test_delete[2].contents);
match.description = ASCIIToUTF16(shortcuts_to_test_delete[2].description);
provider_->DeleteMatch(match);
- EXPECT_EQ(original_shortcuts_count, provider_->shortcuts_map_.size());
- EXPECT_TRUE(provider_->shortcuts_map_.end() ==
- provider_->shortcuts_map_.find(ASCIIToUTF16("delete")));
+ EXPECT_EQ(original_shortcuts_count,
+ provider_->shortcuts_backend_->shortcuts_map().size());
+ EXPECT_TRUE(provider_->shortcuts_backend_->shortcuts_map().end() ==
+ provider_->shortcuts_backend_->shortcuts_map().find(
+ ASCIIToUTF16("delete")));
}
diff --git a/chrome/browser/history/shortcuts_backend.cc b/chrome/browser/history/shortcuts_backend.cc
index 9c8d2ca..6505027 100644
--- a/chrome/browser/history/shortcuts_backend.cc
+++ b/chrome/browser/history/shortcuts_backend.cc
@@ -28,8 +28,8 @@ namespace history {
ShortcutsBackend::ShortcutsBackend(const FilePath& db_folder_path,
Profile *profile)
: current_state_(NOT_INITIALIZED),
- observer_list_(new ObserverListThreadSafe<ShortcutsBackendObserver>()),
- db_(db_folder_path) {
+ db_(new ShortcutsDatabase(db_folder_path)),
+ no_db_access_(db_folder_path.empty()) {
// |profile| can be NULL in tests.
if (profile) {
notification_registrar_.Add(this, chrome::NOTIFICATION_OMNIBOX_OPENED_URL,
@@ -42,146 +42,151 @@ ShortcutsBackend::ShortcutsBackend(const FilePath& db_folder_path,
ShortcutsBackend::~ShortcutsBackend() {}
bool ShortcutsBackend::Init() {
- if (base::subtle::NoBarrier_CompareAndSwap(&current_state_,
- NOT_INITIALIZED,
- INITIALIZING) == NOT_INITIALIZED) {
- return BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
- NewRunnableMethod(this, &ShortcutsBackend::InitInternal));
+ if (current_state_ == NOT_INITIALIZED) {
+ current_state_ = INITIALIZING;
+ if (no_db_access_) {
+ current_state_ = INITIALIZED;
+ return true;
+ } else {
+ return BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
+ NewRunnableMethod(this, &ShortcutsBackend::InitInternal));
+ }
} else {
return false;
}
}
-bool ShortcutsBackend::AddShortcut(shortcuts_provider::Shortcut shortcut) {
- // It is safe to add a shortcut while the backend is being initialized since
- // the addition will occur on the same thread as the initialization.
- DCHECK(current_state_ != NOT_INITIALIZED);
+bool ShortcutsBackend::AddShortcut(
+ const shortcuts_provider::Shortcut& shortcut) {
+ if (!initialized())
+ return false;
+ DCHECK(guid_map_.find(shortcut.id) == guid_map_.end());
+ guid_map_[shortcut.id] = shortcuts_map_.insert(
+ std::make_pair(base::i18n::ToLower(shortcut.text), shortcut));
+ FOR_EACH_OBSERVER(ShortcutsBackendObserver, observer_list_,
+ OnShortcutsChanged());
+ if (no_db_access_)
+ return true;
return BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
- NewRunnableMethod(this, &ShortcutsBackend::AddOrUpdateShortcutInternal,
- shortcut, true));
+ NewRunnableMethod(db_.get(), &ShortcutsDatabase::AddShortcut, shortcut));
}
-bool ShortcutsBackend::UpdateShortcut(shortcuts_provider::Shortcut shortcut) {
- DCHECK(initialized());
+bool ShortcutsBackend::UpdateShortcut(
+ const shortcuts_provider::Shortcut& shortcut) {
+ if (!initialized())
+ return false;
+ shortcuts_provider::GuidToShortcutsIteratorMap::iterator it =
+ guid_map_.find(shortcut.id);
+ if (it != guid_map_.end())
+ shortcuts_map_.erase(it->second);
+ guid_map_[shortcut.id] = shortcuts_map_.insert(
+ std::make_pair(base::i18n::ToLower(shortcut.text), shortcut));
+ FOR_EACH_OBSERVER(ShortcutsBackendObserver, observer_list_,
+ OnShortcutsChanged());
+ if (no_db_access_)
+ return true;
return BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
- NewRunnableMethod(this, &ShortcutsBackend::AddOrUpdateShortcutInternal,
- shortcut, false));
+ NewRunnableMethod(db_.get(), &ShortcutsDatabase::UpdateShortcut,
+ shortcut));
}
bool ShortcutsBackend::DeleteShortcutsWithIds(
const std::vector<std::string>& shortcut_ids) {
- DCHECK(initialized());
+ if (!initialized())
+ return false;
+ for (size_t i = 0; i < shortcut_ids.size(); ++i) {
+ shortcuts_provider::GuidToShortcutsIteratorMap::iterator it =
+ guid_map_.find(shortcut_ids[i]);
+ if (it != guid_map_.end()) {
+ shortcuts_map_.erase(it->second);
+ guid_map_.erase(it);
+ }
+ }
+ FOR_EACH_OBSERVER(ShortcutsBackendObserver, observer_list_,
+ OnShortcutsChanged());
+ if (no_db_access_)
+ return true;
return BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
- NewRunnableMethod(this, &ShortcutsBackend::DeleteShortcutsWithIdsInternal,
+ NewRunnableMethod(db_.get(), &ShortcutsDatabase::DeleteShortcutsWithIds,
shortcut_ids));
}
bool ShortcutsBackend::DeleteShortcutsWithUrl(const GURL& shortcut_url) {
- DCHECK(initialized());
+ if (!initialized())
+ return false;
+ std::vector<std::string> shortcut_ids;
+ for (shortcuts_provider::GuidToShortcutsIteratorMap::iterator
+ it = guid_map_.begin();
+ it != guid_map_.end();) {
+ if (it->second->second.url == shortcut_url) {
+ shortcut_ids.push_back(it->first);
+ shortcuts_map_.erase(it->second);
+ guid_map_.erase(it++);
+ } else {
+ ++it;
+ }
+ }
+ FOR_EACH_OBSERVER(ShortcutsBackendObserver, observer_list_,
+ OnShortcutsChanged());
+ if (no_db_access_)
+ return true;
return BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
- NewRunnableMethod(this, &ShortcutsBackend::DeleteShortcutsWithUrlInternal,
+ NewRunnableMethod(db_.get(), &ShortcutsDatabase::DeleteShortcutsWithUrl,
shortcut_url.spec()));
}
-bool ShortcutsBackend::GetShortcuts(
- shortcuts_provider::ShortcutMap* shortcuts) {
- DCHECK(initialized());
- DCHECK(shortcuts);
-
+bool ShortcutsBackend::DeleteAllShortcuts() {
if (!initialized())
return false;
- shortcuts->clear();
- base::AutoLock lock(data_access_lock_);
- shortcuts->insert(shortcuts_map_.begin(), shortcuts_map_.end());
- return true;
+ shortcuts_map_.clear();
+ guid_map_.clear();
+ FOR_EACH_OBSERVER(ShortcutsBackendObserver, observer_list_,
+ OnShortcutsChanged());
+ if (no_db_access_)
+ return true;
+ return BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
+ NewRunnableMethod(db_.get(), &ShortcutsDatabase::DeleteAllShortcuts));
}
void ShortcutsBackend::InitInternal() {
- db_.Init();
+ DCHECK(current_state_ == INITIALIZING);
+ db_->Init();
shortcuts_provider::GuidToShortcutMap shortcuts;
- db_.LoadShortcuts(&shortcuts);
+ db_->LoadShortcuts(&shortcuts);
+ temp_shortcuts_map_.reset(new shortcuts_provider::ShortcutMap);
+ temp_guid_map_.reset(new shortcuts_provider::GuidToShortcutsIteratorMap);
for (shortcuts_provider::GuidToShortcutMap::iterator it = shortcuts.begin();
it != shortcuts.end(); ++it) {
- guid_map_[it->first] = shortcuts_map_.insert(
+ (*temp_guid_map_)[it->first] = temp_shortcuts_map_->insert(
std::make_pair(base::i18n::ToLower(it->second.text), it->second));
}
- base::subtle::NoBarrier_CompareAndSwap(&current_state_, INITIALIZING,
- INITIALIZED);
- observer_list_->Notify(&ShortcutsBackendObserver::OnShortcutsLoaded);
-}
-
-void ShortcutsBackend::AddOrUpdateShortcutInternal(
- shortcuts_provider::Shortcut shortcut, bool add) {
- {
- // Update local copy.
- base::AutoLock lock(data_access_lock_);
- shortcuts_provider::GuidToShortcutsIteratorMap::iterator it =
- guid_map_.find(shortcut.id);
- if (it != guid_map_.end())
- shortcuts_map_.erase(it->second);
- guid_map_[shortcut.id] = shortcuts_map_.insert(
- std::make_pair(base::i18n::ToLower(shortcut.text), shortcut));
- }
- if (add)
- db_.AddShortcut(shortcut);
- else
- db_.UpdateShortcut(shortcut);
- observer_list_->Notify(&ShortcutsBackendObserver::OnShortcutAddedOrUpdated,
- shortcut);
-}
-
-void ShortcutsBackend::DeleteShortcutsWithIdsInternal(
- std::vector<std::string> shortcut_ids) {
- {
- // Update local copy.
- base::AutoLock lock(data_access_lock_);
- for (size_t i = 0; i < shortcut_ids.size(); ++i) {
- shortcuts_provider::GuidToShortcutsIteratorMap::iterator it =
- guid_map_.find(shortcut_ids[i]);
- if (it != guid_map_.end()) {
- shortcuts_map_.erase(it->second);
- guid_map_.erase(it);
- }
- }
- }
- db_.DeleteShortcutsWithIds(shortcut_ids);
- observer_list_->Notify(&ShortcutsBackendObserver::OnShortcutsRemoved,
- shortcut_ids);
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &ShortcutsBackend::InitCompleted));
}
-void ShortcutsBackend::DeleteShortcutsWithUrlInternal(
- std::string shortcut_url) {
- std::vector<std::string> shortcut_ids;
- {
- // Update local copy.
- base::AutoLock lock(data_access_lock_);
- for (shortcuts_provider::GuidToShortcutsIteratorMap::iterator
- it = guid_map_.begin();
- it != guid_map_.end();) {
- if (it->second->second.url.spec() == shortcut_url) {
- shortcut_ids.push_back(it->first);
- shortcuts_map_.erase(it->second);
- guid_map_.erase(it++);
- } else {
- ++it;
- }
- }
- }
- db_.DeleteShortcutsWithUrl(shortcut_url);
- observer_list_->Notify(&ShortcutsBackendObserver::OnShortcutsRemoved,
- shortcut_ids);
+void ShortcutsBackend::InitCompleted() {
+ temp_guid_map_->swap(guid_map_);
+ temp_shortcuts_map_->swap(shortcuts_map_);
+ temp_shortcuts_map_.reset(NULL);
+ temp_guid_map_.reset(NULL);
+ current_state_ = INITIALIZED;
+ FOR_EACH_OBSERVER(ShortcutsBackendObserver, observer_list_,
+ OnShortcutsLoaded());
}
// NotificationObserver:
void ShortcutsBackend::Observe(int type,
const NotificationSource& source,
const NotificationDetails& details) {
+ if (current_state_ != INITIALIZED)
+ return;
if (type == chrome::NOTIFICATION_HISTORY_URLS_DELETED) {
+ if (Details<const history::URLsDeletedDetails>(details)->all_history)
+ DeleteAllShortcuts();
const std::set<GURL>& urls =
Details<const history::URLsDeletedDetails>(details)->urls;
std::vector<std::string> shortcut_ids;
- base::AutoLock lock(data_access_lock_);
for (shortcuts_provider::GuidToShortcutsIteratorMap::iterator
it = guid_map_.begin();
it != guid_map_.end(); ++it) {
@@ -200,7 +205,6 @@ void ShortcutsBackend::Observe(int type,
int number_of_hits = 1;
std::string id;
const AutocompleteMatch& match(log->result.match_at(log->selected_index));
- base::AutoLock lock(data_access_lock_);
for (shortcuts_provider::ShortcutMap::iterator it =
shortcuts_map_.lower_bound(text_lowercase);
it != shortcuts_map_.end() &&
@@ -208,8 +212,6 @@ void ShortcutsBackend::Observe(int type,
if (match.destination_url == it->second.url) {
number_of_hits = it->second.number_of_hits + 1;
id = it->second.id;
- // guid_map_ will be updated further down on re-insertion.
- shortcuts_map_.erase(it);
break;
}
}
@@ -222,9 +224,6 @@ void ShortcutsBackend::Observe(int type,
else
shortcut.id = id;
- guid_map_[shortcut.id] = shortcuts_map_.insert(
- std::make_pair(text_lowercase, shortcut));
-
if (number_of_hits == 1)
AddShortcut(shortcut);
else
diff --git a/chrome/browser/history/shortcuts_backend.h b/chrome/browser/history/shortcuts_backend.h
index abaccd3..67bf64e 100644
--- a/chrome/browser/history/shortcuts_backend.h
+++ b/chrome/browser/history/shortcuts_backend.h
@@ -10,12 +10,11 @@
#include <string>
#include <vector>
-#include "base/atomicops.h"
#include "base/file_path.h"
#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
-#include "base/observer_list_threadsafe.h"
+#include "base/observer_list.h"
#include "base/string16.h"
#include "base/synchronization/lock.h"
#include "chrome/browser/autocomplete/shortcuts_provider_shortcut.h"
@@ -34,7 +33,8 @@ class ShortcutsBackend : public base::RefCountedThreadSafe<ShortcutsBackend>,
public NotificationObserver {
public:
// |profile| is necessary for profile notifications only and can be NULL in
- // unit-tests.
+ // unit-tests. |db_folder_path| could be an empty path only in unit-tests as
+ // well. It means there is no database created, all things are done in memory.
ShortcutsBackend(const FilePath& db_folder_path, Profile* profile);
virtual ~ShortcutsBackend();
@@ -44,13 +44,8 @@ class ShortcutsBackend : public base::RefCountedThreadSafe<ShortcutsBackend>,
public:
// Called after the database is loaded and Init() completed.
virtual void OnShortcutsLoaded() = 0;
- // This callback is called when addition or change was processed by the
- // database.
- virtual void OnShortcutAddedOrUpdated(
- const shortcuts_provider::Shortcut& shortcut) = 0;
- // Called when shortcuts are removed from the database.
- virtual void OnShortcutsRemoved(
- const std::vector<std::string>& shortcut_ids) = 0;
+ // Called when shortcuts changed (added/updated/removed) in the database.
+ virtual void OnShortcutsChanged() {}
protected:
virtual ~ShortcutsBackendObserver() {}
};
@@ -61,11 +56,13 @@ class ShortcutsBackend : public base::RefCountedThreadSafe<ShortcutsBackend>,
bool initialized() const { return current_state_ == INITIALIZED; }
+ // All of the public functions *must* be called on UI thread only!
+
// Adds the Shortcut to the database.
- bool AddShortcut(shortcuts_provider::Shortcut shortcut);
+ bool AddShortcut(const shortcuts_provider::Shortcut& shortcut);
// Updates timing and selection count for the Shortcut.
- bool UpdateShortcut(shortcuts_provider::Shortcut shortcut);
+ bool UpdateShortcut(const shortcuts_provider::Shortcut& shortcut);
// Deletes the Shortcuts with the id.
bool DeleteShortcutsWithIds(const std::vector<std::string>& shortcut_ids);
@@ -73,35 +70,32 @@ class ShortcutsBackend : public base::RefCountedThreadSafe<ShortcutsBackend>,
// Deletes the Shortcuts with the url.
bool DeleteShortcutsWithUrl(const GURL& shortcut_url);
- // Replaces the contents of |shortcuts| with the backend's from the database.
- bool GetShortcuts(shortcuts_provider::ShortcutMap* shortcuts);
+ // Deletes all of the shortcuts.
+ bool DeleteAllShortcuts();
+
+ const shortcuts_provider::ShortcutMap& shortcuts_map() const {
+ return shortcuts_map_;
+ }
+
+ const shortcuts_provider::GuidToShortcutsIteratorMap& guid_map() const {
+ return guid_map_;
+ }
void AddObserver(ShortcutsBackendObserver* obs) {
- observer_list_->AddObserver(obs);
+ observer_list_.AddObserver(obs);
}
void RemoveObserver(ShortcutsBackendObserver* obs) {
- observer_list_->RemoveObserver(obs);
+ observer_list_.RemoveObserver(obs);
}
private:
// Internal initialization of the back-end. Posted by Init() to the DB thread.
- // On completion notifies all back-end observers asyncronously on their own
- // thread.
+ // On completion posts InitCompleted() back to UI thread.
void InitInternal();
- // Internal addition or update of a shortcut. Posted by AddShortcut() or
- // UpdateShortcut() to the DB thread. On completion notifies all back-end
- // observers asyncronously on their own thread.
- void AddOrUpdateShortcutInternal(shortcuts_provider::Shortcut shortcut,
- bool add);
- // Internal deletion of shortcuts. Posted by DeleteShortcutsWithIds() to the
- // DB thread. On completion notifies all back-end observers asyncronously on
- // their own thread.
- void DeleteShortcutsWithIdsInternal(std::vector<std::string> shortcut_ids);
- // Internal deletion of shortcut with the url. Posted by
- // DeleteShortcutsWithUrl() to the DB thread. On completion notifies all
- // back-end observers asyncronously on their own thread.
- void DeleteShortcutsWithUrlInternal(std::string shortcut_url);
+
+ // Finishes initialization on UI thread, notifies all observers.
+ void InitCompleted();
// NotificationObserver:
virtual void Observe(int type,
@@ -114,20 +108,25 @@ class ShortcutsBackend : public base::RefCountedThreadSafe<ShortcutsBackend>,
INITIALIZED, // Initialization completed, all accessors can be safely
// called.
};
- // |current_state_| has values of CurrentState enum.
- volatile base::subtle::Atomic32 current_state_;
- scoped_refptr<ObserverListThreadSafe<ShortcutsBackendObserver> >
- observer_list_;
- ShortcutsDatabase db_;
+ CurrentState current_state_;
+ ObserverList<ShortcutsBackendObserver> observer_list_;
+ scoped_refptr<ShortcutsDatabase> db_;
+
+ // The |temp_shortcuts_map_| and |temp_guid_map_| used for temporary storage
+ // between InitInternal() and InitComplete() to avoid doing a potentially huge
+ // copy.
+ scoped_ptr<shortcuts_provider::ShortcutMap> temp_shortcuts_map_;
+ scoped_ptr<shortcuts_provider::GuidToShortcutsIteratorMap> temp_guid_map_;
shortcuts_provider::ShortcutMap shortcuts_map_;
// This is a helper map for quick access to a shortcut by guid.
shortcuts_provider::GuidToShortcutsIteratorMap guid_map_;
- base::Lock data_access_lock_;
-
NotificationRegistrar notification_registrar_;
+ // For some unit-test only.
+ bool no_db_access_;
+
DISALLOW_COPY_AND_ASSIGN(ShortcutsBackend);
};
diff --git a/chrome/browser/history/shortcuts_backend_unittest.cc b/chrome/browser/history/shortcuts_backend_unittest.cc
index 0bad07c..cc38425 100644
--- a/chrome/browser/history/shortcuts_backend_unittest.cc
+++ b/chrome/browser/history/shortcuts_backend_unittest.cc
@@ -36,9 +36,7 @@ class ShortcutsBackendTest : public testing::Test,
void TearDown();
virtual void OnShortcutsLoaded() OVERRIDE;
- virtual void OnShortcutAddedOrUpdated(const Shortcut& shortcut) OVERRIDE;
- virtual void OnShortcutsRemoved(
- const std::vector<std::string>& shortcut_ids) OVERRIDE;
+ virtual void OnShortcutsChanged() OVERRIDE;
void InitBackend();
@@ -49,8 +47,6 @@ class ShortcutsBackendTest : public testing::Test,
BrowserThread db_thread_;
bool load_notified_;
- Shortcut notified_shortcut_;
- std::vector<std::string> notified_shortcut_ids_;
};
void ShortcutsBackendTest::SetUp() {
@@ -70,15 +66,7 @@ void ShortcutsBackendTest::OnShortcutsLoaded() {
MessageLoop::current()->Quit();
}
-void ShortcutsBackendTest::OnShortcutAddedOrUpdated(const Shortcut& shortcut) {
- notified_shortcut_ = shortcut;
- MessageLoop::current()->Quit();
-}
-
-void ShortcutsBackendTest::OnShortcutsRemoved(
- const std::vector<std::string>& shortcut_ids) {
- notified_shortcut_ids_ = shortcut_ids;
- MessageLoop::current()->Quit();
+void ShortcutsBackendTest::OnShortcutsChanged() {
}
void ShortcutsBackendTest::InitBackend() {
@@ -90,7 +78,6 @@ void ShortcutsBackendTest::InitBackend() {
EXPECT_TRUE(backend_->initialized());
}
-
TEST_F(ShortcutsBackendTest, AddAndUpdateShortcut) {
InitBackend();
Shortcut shortcut("BD85DBA2-8C29-49F9-84AE-48E1E90880DF",
@@ -100,14 +87,15 @@ TEST_F(ShortcutsBackendTest, AddAndUpdateShortcut) {
base::Time::Now().ToInternalValue(),
100);
EXPECT_TRUE(backend_->AddShortcut(shortcut));
- MessageLoop::current()->Run();
- EXPECT_EQ(shortcut.id, notified_shortcut_.id);
- EXPECT_EQ(shortcut.contents, notified_shortcut_.contents);
+
+ const ShortcutMap& shortcuts = backend_->shortcuts_map();
+ ASSERT_TRUE(shortcuts.end() != shortcuts.find(shortcut.text));
+ EXPECT_EQ(shortcut.id, shortcuts.find(shortcut.text)->second.id);
+ EXPECT_EQ(shortcut.contents, shortcuts.find(shortcut.text)->second.contents);
shortcut.contents = ASCIIToUTF16("Google Web Search");
EXPECT_TRUE(backend_->UpdateShortcut(shortcut));
- MessageLoop::current()->Run();
- EXPECT_EQ(shortcut.id, notified_shortcut_.id);
- EXPECT_EQ(shortcut.contents, notified_shortcut_.contents);
+ EXPECT_EQ(shortcut.id, shortcuts.find(shortcut.text)->second.id);
+ EXPECT_EQ(shortcut.contents, shortcuts.find(shortcut.text)->second.contents);
}
TEST_F(ShortcutsBackendTest, DeleteShortcuts) {
@@ -120,7 +108,6 @@ TEST_F(ShortcutsBackendTest, DeleteShortcuts) {
base::Time::Now().ToInternalValue(),
100);
EXPECT_TRUE(backend_->AddShortcut(shortcut1));
- MessageLoop::current()->Run();
Shortcut shortcut2("BD85DBA2-8C29-49F9-84AE-48E1E90880E0",
ASCIIToUTF16("gle"), ASCIIToUTF16("http://www.google.com"),
@@ -129,7 +116,6 @@ TEST_F(ShortcutsBackendTest, DeleteShortcuts) {
base::Time::Now().ToInternalValue(),
100);
EXPECT_TRUE(backend_->AddShortcut(shortcut2));
- MessageLoop::current()->Run();
Shortcut shortcut3("BD85DBA2-8C29-49F9-84AE-48E1E90880E1",
ASCIIToUTF16("sp"), ASCIIToUTF16("http://www.sport.com"),
@@ -138,7 +124,6 @@ TEST_F(ShortcutsBackendTest, DeleteShortcuts) {
base::Time::Now().ToInternalValue(),
10);
EXPECT_TRUE(backend_->AddShortcut(shortcut3));
- MessageLoop::current()->Run();
Shortcut shortcut4("BD85DBA2-8C29-49F9-84AE-48E1E90880E2",
ASCIIToUTF16("mov"), ASCIIToUTF16("http://www.film.com"),
@@ -147,11 +132,8 @@ TEST_F(ShortcutsBackendTest, DeleteShortcuts) {
base::Time::Now().ToInternalValue(),
10);
EXPECT_TRUE(backend_->AddShortcut(shortcut4));
- MessageLoop::current()->Run();
-
- ShortcutMap shortcuts;
- EXPECT_TRUE(backend_->GetShortcuts(&shortcuts));
+ const ShortcutMap& shortcuts = backend_->shortcuts_map();
ASSERT_EQ(4U, shortcuts.size());
EXPECT_EQ(shortcut1.id, shortcuts.find(shortcut1.text)->second.id);
@@ -160,17 +142,12 @@ TEST_F(ShortcutsBackendTest, DeleteShortcuts) {
EXPECT_EQ(shortcut4.id, shortcuts.find(shortcut4.text)->second.id);
EXPECT_TRUE(backend_->DeleteShortcutsWithUrl(shortcut1.url));
- MessageLoop::current()->Run();
-
- ASSERT_EQ(2U, notified_shortcut_ids_.size());
- EXPECT_TRUE(notified_shortcut_ids_[0] == shortcut1.id ||
- notified_shortcut_ids_[1] == shortcut1.id);
- EXPECT_TRUE(notified_shortcut_ids_[0] == shortcut2.id ||
- notified_shortcut_ids_[1] == shortcut2.id);
-
- EXPECT_TRUE(backend_->GetShortcuts(&shortcuts));
ASSERT_EQ(2U, shortcuts.size());
+ EXPECT_TRUE(shortcuts.end() == shortcuts.find(shortcut1.text));
+ EXPECT_TRUE(shortcuts.end() == shortcuts.find(shortcut2.text));
+ ASSERT_TRUE(shortcuts.end() != shortcuts.find(shortcut3.text));
+ ASSERT_TRUE(shortcuts.end() != shortcuts.find(shortcut4.text));
EXPECT_EQ(shortcut3.id, shortcuts.find(shortcut3.text)->second.id);
EXPECT_EQ(shortcut4.id, shortcuts.find(shortcut4.text)->second.id);
@@ -179,13 +156,6 @@ TEST_F(ShortcutsBackendTest, DeleteShortcuts) {
deleted_ids.push_back(shortcut4.id);
EXPECT_TRUE(backend_->DeleteShortcutsWithIds(deleted_ids));
- MessageLoop::current()->Run();
-
- ASSERT_EQ(2U, notified_shortcut_ids_.size());
- EXPECT_EQ(notified_shortcut_ids_[0], deleted_ids[0]);
- EXPECT_EQ(notified_shortcut_ids_[1], deleted_ids[1]);
-
- EXPECT_TRUE(backend_->GetShortcuts(&shortcuts));
ASSERT_EQ(0U, shortcuts.size());
}
diff --git a/chrome/browser/history/shortcuts_database.cc b/chrome/browser/history/shortcuts_database.cc
index f400e5c..45e11a9 100644
--- a/chrome/browser/history/shortcuts_database.cc
+++ b/chrome/browser/history/shortcuts_database.cc
@@ -21,7 +21,8 @@ using base::Time;
namespace {
-const char *kShortcutsDBName = "omni_box_shortcuts";
+// Using define instead of const char, so I could use ## in the statements.
+#define kShortcutsDBName "omni_box_shortcuts"
// The maximum length allowed for form data.
const size_t kMaxDataLength = 2048; // 2K is a hard limit on URLs URI.
@@ -103,32 +104,18 @@ bool ShortcutsDatabase::Init() {
if (!db_.Open(database_path_))
return false;
- if (!db_.DoesTableExist(kShortcutsDBName)) {
- if (!db_.Execute(base::StringPrintf(
- "CREATE TABLE %s ( "
- "id VARCHAR PRIMARY KEY, "
- "text VARCHAR, "
- "url VARCHAR, "
- "contents VARCHAR, "
- "contents_class VARCHAR, "
- "description VARCHAR, "
- "description_class VARCHAR, "
- "last_access_time INTEGER, "
- "number_of_hits INTEGER)", kShortcutsDBName).c_str())) {
- NOTREACHED();
- return false;
- }
- }
+ if (!EnsureTable())
+ return false;
return true;
}
bool ShortcutsDatabase::AddShortcut(
- const shortcuts_provider::Shortcut &shortcut) {
- sql::Statement s(db_.GetUniqueStatement(base::StringPrintf(
- "INSERT INTO %s"
+ const shortcuts_provider::Shortcut& shortcut) {
+ sql::Statement s(db_.GetCachedStatement(SQL_FROM_HERE,
+ "INSERT INTO " kShortcutsDBName
" (id, text, url, contents, contents_class, description,"
" description_class, last_access_time, number_of_hits) "
- "VALUES (?,?,?,?,?,?,?,?,?)", kShortcutsDBName).c_str()));
+ "VALUES (?,?,?,?,?,?,?,?,?)"));
if (!s) {
NOTREACHED();
return false;
@@ -143,13 +130,13 @@ bool ShortcutsDatabase::AddShortcut(
}
bool ShortcutsDatabase::UpdateShortcut(
- const shortcuts_provider::Shortcut &shortcut) {
- sql::Statement s(db_.GetUniqueStatement(base::StringPrintf(
- "UPDATE %s "
+ const shortcuts_provider::Shortcut& shortcut) {
+ sql::Statement s(db_.GetCachedStatement(SQL_FROM_HERE,
+ "UPDATE " kShortcutsDBName " "
"SET id=?, text=?, url=?, contents=?, contents_class=?,"
" description=?, description_class=?, last_access_time=?,"
" number_of_hits=? "
- "WHERE id=?", kShortcutsDBName).c_str()));
+ "WHERE id=?"));
if (!s) {
NOTREACHED() << "Statement prepare failed";
return false;
@@ -180,15 +167,29 @@ bool ShortcutsDatabase::DeleteShortcutsWithUrl(
return DeleteShortcut("url", shortcut_url_spec, db_);
}
+bool ShortcutsDatabase::DeleteAllShortcuts() {
+ sql::Statement s(db_.GetCachedStatement(SQL_FROM_HERE,
+ "DROP TABLE " kShortcutsDBName));
+ if (!s) {
+ NOTREACHED() << "Statement prepare failed";
+ return false;
+ }
+
+ if (!s.Run())
+ return false;
+ EnsureTable();
+ db_.Execute("VACUUM");
+ return true;
+}
// Loads all of the shortcuts.
bool ShortcutsDatabase::LoadShortcuts(
std::map<std::string, shortcuts_provider::Shortcut>* shortcuts) {
DCHECK(shortcuts);
- sql::Statement s(db_.GetUniqueStatement(base::StringPrintf(
+ sql::Statement s(db_.GetCachedStatement(SQL_FROM_HERE,
"SELECT id, text, url, contents, contents_class, "
"description, description_class, last_access_time, number_of_hits "
- "FROM %s", kShortcutsDBName).c_str()));
+ "FROM " kShortcutsDBName));
if (!s) {
NOTREACHED() << "Statement prepare failed";
return false;
@@ -201,4 +202,24 @@ bool ShortcutsDatabase::LoadShortcuts(
return true;
}
+bool ShortcutsDatabase::EnsureTable() {
+ if (!db_.DoesTableExist(kShortcutsDBName)) {
+ if (!db_.Execute(base::StringPrintf(
+ "CREATE TABLE %s ( "
+ "id VARCHAR PRIMARY KEY, "
+ "text VARCHAR, "
+ "url VARCHAR, "
+ "contents VARCHAR, "
+ "contents_class VARCHAR, "
+ "description VARCHAR, "
+ "description_class VARCHAR, "
+ "last_access_time INTEGER, "
+ "number_of_hits INTEGER)", kShortcutsDBName).c_str())) {
+ NOTREACHED();
+ return false;
+ }
+ }
+ return true;
+}
+
} // namespace history
diff --git a/chrome/browser/history/shortcuts_database.h b/chrome/browser/history/shortcuts_database.h
index 3cbae58..4cd1fe5 100644
--- a/chrome/browser/history/shortcuts_database.h
+++ b/chrome/browser/history/shortcuts_database.h
@@ -12,6 +12,7 @@
#include "base/file_path.h"
#include "base/gtest_prod_util.h"
+#include "base/memory/ref_counted.h"
#include "base/string16.h"
#include "chrome/browser/autocomplete/shortcuts_provider_shortcut.h"
#include "googleurl/src/gurl.h"
@@ -37,7 +38,7 @@ namespace history {
// last_access_time Time the entry was accessed last, stored in seconds,
// UTC.
// number_of_hits Number of times that the entry has been selected.
-class ShortcutsDatabase {
+class ShortcutsDatabase : public base::RefCountedThreadSafe<ShortcutsDatabase> {
public:
explicit ShortcutsDatabase(const FilePath& folder_path);
virtual ~ShortcutsDatabase();
@@ -45,10 +46,10 @@ class ShortcutsDatabase {
bool Init();
// Adds the ShortcutsProvider::Shortcut to the database.
- bool AddShortcut(const shortcuts_provider::Shortcut &shortcut);
+ bool AddShortcut(const shortcuts_provider::Shortcut& shortcut);
// Updates timing and selection count for the ShortcutsProvider::Shortcut.
- bool UpdateShortcut(const shortcuts_provider::Shortcut &shortcut);
+ bool UpdateShortcut(const shortcuts_provider::Shortcut& shortcut);
// Deletes the ShortcutsProvider::Shortcuts with the id.
bool DeleteShortcutsWithIds(const std::vector<std::string>& shortcut_ids);
@@ -56,11 +57,17 @@ class ShortcutsDatabase {
// Deletes the ShortcutsProvider::Shortcuts with the url.
bool DeleteShortcutsWithUrl(const std::string& shortcut_url_spec);
+ // Deletes all of the ShortcutsProvider::Shortcuts.
+ bool DeleteAllShortcuts();
+
// Loads all of the shortcuts.
bool LoadShortcuts(
std::map<std::string, shortcuts_provider::Shortcut>* shortcuts);
private:
+ // Ensures that the table is present.
+ bool EnsureTable();
+
friend class ShortcutsDatabaseTest;
FRIEND_TEST_ALL_PREFIXES(ShortcutsDatabaseTest, AddShortcut);
FRIEND_TEST_ALL_PREFIXES(ShortcutsDatabaseTest, UpdateShortcut);
diff --git a/chrome/browser/history/shortcuts_database_unittest.cc b/chrome/browser/history/shortcuts_database_unittest.cc
index 88c802b..216df83 100644
--- a/chrome/browser/history/shortcuts_database_unittest.cc
+++ b/chrome/browser/history/shortcuts_database_unittest.cc
@@ -59,18 +59,18 @@ class ShortcutsDatabaseTest : public testing::Test {
void AddAll();
ScopedTempDir temp_dir_;
- scoped_ptr<ShortcutsDatabase> db_;
+ scoped_refptr<ShortcutsDatabase> db_;
};
void ShortcutsDatabaseTest::SetUp() {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- db_.reset(new ShortcutsDatabase(temp_dir_.path()));
+ db_ = new ShortcutsDatabase(temp_dir_.path());
ASSERT_TRUE(db_->Init());
ClearDB();
}
void ShortcutsDatabaseTest::TearDown() {
- db_.reset();
+ db_ = NULL;
}
void ShortcutsDatabaseTest::ClearDB() {
@@ -185,4 +185,14 @@ TEST_F(ShortcutsDatabaseTest, LoadShortcuts) {
}
}
+TEST_F(ShortcutsDatabaseTest, DeleteAllShortcuts) {
+ AddAll();
+ std::map<std::string, Shortcut> shortcuts;
+ EXPECT_TRUE(db_->LoadShortcuts(&shortcuts));
+ EXPECT_EQ(arraysize(shortcut_test_db), shortcuts.size());
+ EXPECT_TRUE(db_->DeleteAllShortcuts());
+ EXPECT_TRUE(db_->LoadShortcuts(&shortcuts));
+ EXPECT_EQ(0U, shortcuts.size());
+}
+
} // namespace history