summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorstevet@chromium.org <stevet@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-28 14:29:06 +0000
committerstevet@chromium.org <stevet@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-28 14:29:06 +0000
commitc4996f76eb3298229264f2402aeb62f56f8f4790 (patch)
tree79fae951e6c178d5b8edcad89a7a2c5bf015cdce /chrome/browser
parentf9f39163edfe72a91cdeb3c62d5c209914696a96 (diff)
downloadchromium_src-c4996f76eb3298229264f2402aeb62f56f8f4790.zip
chromium_src-c4996f76eb3298229264f2402aeb62f56f8f4790.tar.gz
chromium_src-c4996f76eb3298229264f2402aeb62f56f8f4790.tar.bz2
Added last_modified field to TemplateURL and database. Updated unit tests, including refactoring MockTimeProvider out of media/.
BUG=None TEST=No visible changes. Ensure that changed unittests all pass. Review URL: http://codereview.chromium.org/7232023 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@90764 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/importer/profile_import_process_messages.h4
-rw-r--r--chrome/browser/search_engines/template_url.cc1
-rw-r--r--chrome/browser/search_engines/template_url.h8
-rw-r--r--chrome/browser/search_engines/template_url_prepopulate_data.cc1
-rw-r--r--chrome/browser/search_engines/template_url_service.cc7
-rw-r--r--chrome/browser/search_engines/template_url_service.h13
-rw-r--r--chrome/browser/search_engines/template_url_service_unittest.cc76
-rw-r--r--chrome/browser/webdata/keyword_table.cc22
-rw-r--r--chrome/browser/webdata/keyword_table.h3
-rw-r--r--chrome/browser/webdata/keyword_table_unittest.cc6
-rw-r--r--chrome/browser/webdata/web_database.cc11
-rw-r--r--chrome/browser/webdata/web_database_migration_unittest.cc64
12 files changed, 173 insertions, 43 deletions
diff --git a/chrome/browser/importer/profile_import_process_messages.h b/chrome/browser/importer/profile_import_process_messages.h
index d7d9048..8e6d848 100644
--- a/chrome/browser/importer/profile_import_process_messages.h
+++ b/chrome/browser/importer/profile_import_process_messages.h
@@ -274,6 +274,7 @@ struct ParamTraits<TemplateURL> {
WriteParam(m, p.languages());
WriteParam(m, p.input_encodings());
WriteParam(m, p.date_created());
+ WriteParam(m, p.last_modified());
WriteParam(m, p.usage_count());
WriteParam(m, p.prepopulate_id());
}
@@ -291,6 +292,7 @@ struct ParamTraits<TemplateURL> {
std::vector<string16> languages;
std::vector<std::string> input_encodings;
base::Time date_created;
+ base::Time last_modified;
int usage_count;
int prepopulate_id;
@@ -332,6 +334,7 @@ struct ParamTraits<TemplateURL> {
if (!ReadParam(m, iter, &languages) ||
!ReadParam(m, iter, &input_encodings) ||
!ReadParam(m, iter, &date_created) ||
+ !ReadParam(m, iter, &last_modified) ||
!ReadParam(m, iter, &usage_count) ||
!ReadParam(m, iter, &prepopulate_id))
return false;
@@ -355,6 +358,7 @@ struct ParamTraits<TemplateURL> {
}
p->set_input_encodings(input_encodings);
p->set_date_created(date_created);
+ p->set_last_modified(last_modified);
p->set_usage_count(usage_count);
p->set_prepopulate_id(prepopulate_id);
return true;
diff --git a/chrome/browser/search_engines/template_url.cc b/chrome/browser/search_engines/template_url.cc
index 6a5808b..56db39c 100644
--- a/chrome/browser/search_engines/template_url.cc
+++ b/chrome/browser/search_engines/template_url.cc
@@ -594,6 +594,7 @@ TemplateURL::TemplateURL()
safe_for_autoreplace_(false),
id_(0),
date_created_(base::Time::Now()),
+ last_modified_(base::Time::Now()),
created_by_policy_(false),
usage_count_(0),
search_engine_type_(SEARCH_ENGINE_OTHER),
diff --git a/chrome/browser/search_engines/template_url.h b/chrome/browser/search_engines/template_url.h
index 5fe6a96..fc60674 100644
--- a/chrome/browser/search_engines/template_url.h
+++ b/chrome/browser/search_engines/template_url.h
@@ -142,6 +142,7 @@ class TemplateURLRef {
friend class TemplateURLTest;
FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseParameterKnown);
FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseParameterUnknown);
+ FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseParameterReallyUnknown);
FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseURLEmpty);
FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseURLNoTemplateEnd);
FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseURLNoKnownParameters);
@@ -425,6 +426,12 @@ class TemplateURL {
void set_date_created(base::Time time) { date_created_ = time; }
base::Time date_created() const { return date_created_; }
+ // The last time this keyword was modified by a user, since creation.
+ //
+ // NOTE: Like date_created above, this may be 0.
+ void set_last_modified(base::Time time) { last_modified_ = time; }
+ base::Time last_modified() const { return last_modified_; }
+
// True if this TemplateURL was automatically created by the administrator via
// group policy.
void set_created_by_policy(bool created_by_policy) {
@@ -510,6 +517,7 @@ class TemplateURL {
std::vector<std::string> input_encodings_;
TemplateURLID id_;
base::Time date_created_;
+ base::Time last_modified_;
bool created_by_policy_;
int usage_count_;
SearchEngineType search_engine_type_;
diff --git a/chrome/browser/search_engines/template_url_prepopulate_data.cc b/chrome/browser/search_engines/template_url_prepopulate_data.cc
index 0a8aa90..587d10e 100644
--- a/chrome/browser/search_engines/template_url_prepopulate_data.cc
+++ b/chrome/browser/search_engines/template_url_prepopulate_data.cc
@@ -3394,6 +3394,7 @@ TemplateURL* MakePrepopulatedTemplateURL(const wchar_t* name,
new_turl->set_show_in_default_list(true);
new_turl->set_safe_for_autoreplace(true);
new_turl->set_date_created(Time());
+ new_turl->set_last_modified(Time());
std::vector<std::string> turl_encodings;
turl_encodings.push_back(encoding);
new_turl->set_input_encodings(turl_encodings);
diff --git a/chrome/browser/search_engines/template_url_service.cc b/chrome/browser/search_engines/template_url_service.cc
index 3e99e85..b98278c 100644
--- a/chrome/browser/search_engines/template_url_service.cc
+++ b/chrome/browser/search_engines/template_url_service.cc
@@ -102,7 +102,8 @@ TemplateURLService::TemplateURLService(Profile* profile)
load_handle_(0),
default_search_provider_(NULL),
is_default_search_managed_(false),
- next_id_(1) {
+ next_id_(1),
+ time_provider_(&base::Time::Now) {
DCHECK(profile_);
Init(NULL, 0);
}
@@ -116,7 +117,8 @@ TemplateURLService::TemplateURLService(const Initializer* initializers,
service_(NULL),
default_search_provider_(NULL),
is_default_search_managed_(false),
- next_id_(1) {
+ next_id_(1),
+ time_provider_(&base::Time::Now) {
Init(initializers, count);
}
@@ -399,6 +401,7 @@ void TemplateURLService::ResetTemplateURL(const TemplateURL* url,
new_url.SetURL(search_url, 0, 0);
}
new_url.set_safe_for_autoreplace(false);
+ new_url.set_last_modified(time_provider_());
UpdateNoNotify(url, new_url);
NotifyObservers();
}
diff --git a/chrome/browser/search_engines/template_url_service.h b/chrome/browser/search_engines/template_url_service.h
index f5c6264..d029d86 100644
--- a/chrome/browser/search_engines/template_url_service.h
+++ b/chrome/browser/search_engines/template_url_service.h
@@ -62,6 +62,8 @@ class TemplateURLService : public WebDataServiceConsumer,
public:
typedef std::map<std::string, std::string> QueryTerms;
typedef std::vector<const TemplateURL*> TemplateURLVector;
+ // Type for a static function pointer that acts as a time source.
+ typedef base::Time(TimeProvider)();
// Struct used for initializing the data store with fake data.
// Each initializer is mapped to a TemplateURL.
@@ -240,6 +242,14 @@ class TemplateURLService : public WebDataServiceConsumer,
// Registers the preferences used to save a TemplateURL to prefs.
static void RegisterUserPrefs(PrefService* prefs);
+#if defined(UNIT_TEST)
+ // Set a different time provider function, such as
+ // base::MockTimeProvider::StaticNow, when testing calls to base::Time::Now.
+ void set_time_provider(TimeProvider* time_provider) {
+ time_provider_ = time_provider;
+ }
+#endif
+
protected:
// Cover method for the method of the same name on the HistoryService.
// url is the one that was visited with the given search terms.
@@ -440,6 +450,9 @@ class TemplateURLService : public WebDataServiceConsumer,
// List of extension IDs waiting for Load to have keywords registered.
std::vector<std::string> pending_extension_ids_;
+ // Function returning current time in base::Time units.
+ TimeProvider* time_provider_;
+
DISALLOW_COPY_AND_ASSIGN(TemplateURLService);
};
diff --git a/chrome/browser/search_engines/template_url_service_unittest.cc b/chrome/browser/search_engines/template_url_service_unittest.cc
index d62bb5d..16936e8 100644
--- a/chrome/browser/search_engines/template_url_service_unittest.cc
+++ b/chrome/browser/search_engines/template_url_service_unittest.cc
@@ -5,6 +5,7 @@
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_vector.h"
+#include "base/test/mock_time_provider.h"
#include "base/string_split.h"
#include "base/string_util.h"
#include "base/threading/thread.h"
@@ -28,6 +29,8 @@
using base::Time;
using base::TimeDelta;
+using ::testing::Return;
+using ::testing::StrictMock;
// Test the GenerateSearchURL on a thread or the main thread.
class TestGenerateSearchURL
@@ -93,6 +96,7 @@ static TemplateURL* CreatePreloadedTemplateURL() {
GURL favicon_url("http://favicon.url");
t_url->SetFaviconURL(favicon_url);
t_url->set_date_created(Time::FromTimeT(100));
+ t_url->set_last_modified(Time::FromTimeT(100));
t_url->set_prepopulate_id(999999);
return t_url;
}
@@ -117,7 +121,8 @@ class TemplateURLServiceTest : public testing::Test {
const std::string& encodings,
const std::string& short_name,
bool safe_for_autoreplace,
- Time created_date) {
+ Time created_date,
+ Time last_modified) {
TemplateURL* template_url = new TemplateURL();
template_url->SetURL(url, 0, 0);
template_url->SetSuggestionsURL(suggest_url, 0, 0);
@@ -129,6 +134,7 @@ class TemplateURLServiceTest : public testing::Test {
base::SplitString(encodings, ';', &encodings_vector);
template_url->set_input_encodings(encodings_vector);
template_url->set_date_created(created_date);
+ template_url->set_last_modified(last_modified);
template_url->set_safe_for_autoreplace(safe_for_autoreplace);
model()->Add(template_url);
EXPECT_NE(0, template_url->id());
@@ -158,10 +164,11 @@ class TemplateURLServiceTest : public testing::Test {
ASSERT_EQ(expected.safe_for_autoreplace(), actual.safe_for_autoreplace());
ASSERT_EQ(expected.show_in_default_list(), actual.show_in_default_list());
ASSERT_TRUE(expected.date_created() == actual.date_created());
+ ASSERT_TRUE(expected.last_modified() == actual.last_modified());
}
- // Checks that the two TemplateURLs are similar. It does not check the id
- // and the date_created. Neither pointer should be NULL.
+ // Checks that the two TemplateURLs are similar. It does not check the id, the
+ // date_created or the last_modified time. Neither pointer should be NULL.
void ExpectSimilar(const TemplateURL* expected, const TemplateURL* actual) {
ASSERT_TRUE(expected != NULL);
ASSERT_TRUE(actual != NULL);
@@ -387,6 +394,7 @@ TEST_F(TemplateURLServiceTest, AddUpdateRemove) {
GURL favicon_url("http://favicon.url");
t_url->SetFaviconURL(favicon_url);
t_url->set_date_created(Time::FromTimeT(100));
+ t_url->set_last_modified(Time::FromTimeT(100));
t_url->set_safe_for_autoreplace(true);
model()->Add(t_url);
ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("keyword"),
@@ -410,6 +418,14 @@ TEST_F(TemplateURLServiceTest, AddUpdateRemove) {
ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("keyword"),
GURL(), NULL));
+ // We expect the last_modified time to be updated to the present time on an
+ // explicit reset. We have to set up the expectation here because ResetModel
+ // resets the TimeProvider in the TemplateURLService.
+ StrictMock<base::MockTimeProvider> mock_time;
+ model()->set_time_provider(&base::MockTimeProvider::StaticNow);
+ EXPECT_CALL(mock_time, Now())
+ .WillOnce(Return(base::Time::FromDoubleT(1337)));
+
// Mutate an element and verify it succeeded.
model()->ResetTemplateURL(loaded_url, ASCIIToUTF16("a"),
ASCIIToUTF16("b"), "c");
@@ -427,6 +443,9 @@ TEST_F(TemplateURLServiceTest, AddUpdateRemove) {
loaded_url = model()->GetTemplateURLForKeyword(ASCIIToUTF16("b"));
ASSERT_TRUE(loaded_url != NULL);
AssertEquals(cloned_url, *loaded_url);
+ // We changed a TemplateURL in the service, so ensure that the time was
+ // updated.
+ ASSERT_EQ(loaded_url->last_modified(), base::Time::FromDoubleT(1337));
// Remove an element and verify it succeeded.
model()->Remove(loaded_url);
@@ -492,21 +511,23 @@ TEST_F(TemplateURLServiceTest, ClearBrowsingData_Keywords) {
// Create one with a 0 time.
AddKeywordWithDate("key1", false, "http://foo1", "http://suggest1",
- "http://icon1", "UTF-8;UTF-16", "name1", true, Time());
+ "http://icon1", "UTF-8;UTF-16", "name1", true, Time(),
+ Time());
// Create one for now and +/- 1 day.
AddKeywordWithDate("key2", false, "http://foo2", "http://suggest2",
"http://icon2", "UTF-8;UTF-16", "name2", true,
- now - one_day);
+ now - one_day, Time());
AddKeywordWithDate("key3", false, "http://foo3", "", "", "", "name3",
- true, now);
+ true, now, Time());
AddKeywordWithDate("key4", false, "http://foo4", "", "", "", "name4",
- true, now + one_day);
+ true, now + one_day, Time());
// Try the other three states.
AddKeywordWithDate("key5", false, "http://foo5", "http://suggest5",
- "http://icon5", "UTF-8;UTF-16", "name5", false, now);
+ "http://icon5", "UTF-8;UTF-16", "name5", false, now,
+ Time());
AddKeywordWithDate("key6", false, "http://foo6", "http://suggest6",
"http://icon6", "UTF-8;UTF-16", "name6", false,
- month_ago);
+ month_ago, Time());
// We just added a few items, validate them.
EXPECT_EQ(6U, model()->GetTemplateURLs().size());
@@ -553,11 +574,17 @@ TEST_F(TemplateURLServiceTest, Reset) {
GURL favicon_url("http://favicon.url");
t_url->SetFaviconURL(favicon_url);
t_url->set_date_created(Time::FromTimeT(100));
+ t_url->set_last_modified(Time::FromTimeT(100));
model()->Add(t_url);
VerifyObserverCount(1);
BlockTillServiceProcessesRequests();
+ StrictMock<base::MockTimeProvider> mock_time;
+ model()->set_time_provider(&base::MockTimeProvider::StaticNow);
+ EXPECT_CALL(mock_time, Now())
+ .WillOnce(Return(base::Time::FromDoubleT(1337)));
+
// Reset the short name, keyword, url and make sure it takes.
const string16 new_short_name(ASCIIToUTF16("a"));
const string16 new_keyword(ASCIIToUTF16("b"));
@@ -581,6 +608,7 @@ TEST_F(TemplateURLServiceTest, Reset) {
const TemplateURL* read_url = model()->GetTemplateURLForKeyword(new_keyword);
ASSERT_TRUE(read_url);
AssertEquals(last_url, *read_url);
+ ASSERT_EQ(read_url->last_modified(), base::Time::FromDoubleT(1337));
}
TEST_F(TemplateURLServiceTest, DefaultSearchProvider) {
@@ -588,7 +616,8 @@ TEST_F(TemplateURLServiceTest, DefaultSearchProvider) {
VerifyLoad();
const size_t initial_count = model()->GetTemplateURLs().size();
TemplateURL* t_url = AddKeywordWithDate("key1", false, "http://foo1",
- "http://sugg1", "http://icon1", "UTF-8;UTF-16", "name1", true, Time());
+ "http://sugg1", "http://icon1", "UTF-8;UTF-16", "name1", true, Time(),
+ Time());
test_util_.ResetObserverCount();
model()->SetDefaultSearchProvider(t_url);
@@ -620,7 +649,7 @@ TEST_F(TemplateURLServiceTest, TemplateURLWithNoKeyword) {
const size_t initial_count = model()->GetTemplateURLs().size();
AddKeywordWithDate("", false, "http://foo1", "http://sugg1",
- "http://icon1", "UTF-8;UTF-16", "name1", true, Time());
+ "http://icon1", "UTF-8;UTF-16", "name1", true, Time(), Time());
// We just added a few items, validate them.
ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
@@ -644,7 +673,8 @@ TEST_F(TemplateURLServiceTest, CantReplaceWithSameKeyword) {
ChangeModelToLoadState();
ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"), GURL(), NULL));
TemplateURL* t_url = AddKeywordWithDate("foo", false, "http://foo1",
- "http://sugg1", "http://icon1", "UTF-8;UTF-16", "name1", true, Time());
+ "http://sugg1", "http://icon1", "UTF-8;UTF-16", "name1", true, Time(),
+ Time());
// Can still replace, newly added template url is marked safe to replace.
ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"),
@@ -653,7 +683,7 @@ TEST_F(TemplateURLServiceTest, CantReplaceWithSameKeyword) {
// ResetTemplateURL marks the TemplateURL as unsafe to replace, so it should
// no longer be replaceable.
model()->ResetTemplateURL(t_url, t_url->short_name(), t_url->keyword(),
- t_url->url()->url());
+ t_url->url()->url());
ASSERT_FALSE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"),
GURL("http://foo2"), NULL));
@@ -664,7 +694,8 @@ TEST_F(TemplateURLServiceTest, CantReplaceWithSameHosts) {
ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"),
GURL("http://foo.com"), NULL));
TemplateURL* t_url = AddKeywordWithDate("foo", false, "http://foo.com",
- "http://sugg1", "http://icon1", "UTF-8;UTF-16", "name1", true, Time());
+ "http://sugg1", "http://icon1", "UTF-8;UTF-16", "name1", true, Time(),
+ Time());
// Can still replace, newly added template url is marked safe to replace.
ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("bar"),
@@ -673,7 +704,7 @@ TEST_F(TemplateURLServiceTest, CantReplaceWithSameHosts) {
// ResetTemplateURL marks the TemplateURL as unsafe to replace, so it should
// no longer be replaceable.
model()->ResetTemplateURL(t_url, t_url->short_name(), t_url->keyword(),
- t_url->url()->url());
+ t_url->url()->url());
ASSERT_FALSE(model()->CanReplaceKeyword(ASCIIToUTF16("bar"),
GURL("http://foo.com"), NULL));
@@ -699,6 +730,7 @@ TEST_F(TemplateURLServiceTest, DefaultSearchProviderLoadedFromPrefs) {
template_url->set_short_name(ASCIIToUTF16("a"));
template_url->set_safe_for_autoreplace(true);
template_url->set_date_created(Time::FromTimeT(100));
+ template_url->set_last_modified(Time::FromTimeT(100));
model()->Add(template_url);
@@ -799,7 +831,8 @@ TEST_F(TemplateURLServiceTest, UpdateKeywordSearchTermsForURL) {
ChangeModelToLoadState();
AddKeywordWithDate("x", false, "http://x/foo?q={searchTerms}",
- "http://sugg1", "http://icon1", "UTF-8;UTF-16", "name", false, Time());
+ "http://sugg1", "http://icon1", "UTF-8;UTF-16", "name", false, Time(),
+ Time());
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
history::URLVisitedDetails details;
@@ -821,7 +854,7 @@ TEST_F(TemplateURLServiceTest, DontUpdateKeywordSearchForNonReplaceable) {
ChangeModelToLoadState();
AddKeywordWithDate("x", false, "http://x/foo", "http://sugg1",
- "http://icon1", "UTF-8;UTF-16", "name", false, Time());
+ "http://icon1", "UTF-8;UTF-16", "name", false, Time(), Time());
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
history::URLVisitedDetails details;
@@ -840,7 +873,7 @@ TEST_F(TemplateURLServiceTest, ChangeGoogleBaseValue) {
SetGoogleBaseURL("http://google.com/");
const TemplateURL* t_url = AddKeywordWithDate("", true,
"{google:baseURL}?q={searchTerms}", "http://sugg1", "http://icon1",
- "UTF-8;UTF-16", "name", false, Time());
+ "UTF-8;UTF-16", "name", false, Time(), Time());
ASSERT_EQ(t_url, model()->GetTemplateURLForHost("google.com"));
EXPECT_EQ("google.com", t_url->url()->GetHost());
EXPECT_EQ(ASCIIToUTF16("google.com"), t_url->keyword());
@@ -887,7 +920,7 @@ TEST_F(TemplateURLServiceTest, GenerateVisitOnKeyword) {
TemplateURL* t_url = AddKeywordWithDate(
"keyword", false, "http://foo.com/foo?query={searchTerms}",
"http://sugg1", "http://icon1", "UTF-8;UTF-16", "keyword",
- true, base::Time::Now());
+ true, base::Time::Now(), base::Time::Now());
// Add a visit that matches the url of the keyword.
HistoryService* history =
@@ -1102,7 +1135,7 @@ TEST_F(TemplateURLServiceTest, TestManagedDefaultSearch) {
// Set a regular default search provider.
TemplateURL* regular_default = AddKeywordWithDate("key1", false,
"http://foo1", "http://sugg1", "http://icon1", "UTF-8;UTF-16", "name1",
- true, Time());
+ true, Time(), Time());
VerifyObserverCount(1);
model()->SetDefaultSearchProvider(regular_default);
// Adding the URL and setting the default search provider should have caused
@@ -1196,7 +1229,8 @@ TEST_F(TemplateURLServiceTest, TestManagedDefaultSearch) {
RemoveManagedDefaultSearchPreferences();
ResetModel(true);
TemplateURL* t_url = AddKeywordWithDate("key1", false, "http://foo1",
- "http://sugg1", "http://icon1", "UTF-8;UTF-16", "name1", true, Time());
+ "http://sugg1", "http://icon1", "UTF-8;UTF-16", "name1", true, Time(),
+ Time());
model()->SetDefaultSearchProvider(t_url);
EXPECT_EQ(t_url, model()->GetDefaultSearchProvider());
diff --git a/chrome/browser/webdata/keyword_table.cc b/chrome/browser/webdata/keyword_table.cc
index 2e31a8a..5d93869 100644
--- a/chrome/browser/webdata/keyword_table.cc
+++ b/chrome/browser/webdata/keyword_table.cc
@@ -18,7 +18,7 @@ using base::Time;
namespace {
// ID of the url column in keywords.
-const int kUrlIdPosition = 16;
+const int kUrlIdPosition = 17;
// Keys used in the meta table.
const char* kDefaultSearchProviderKey = "Default Search Provider ID";
@@ -54,6 +54,7 @@ void BindURLToStatement(const TemplateURL& url, sql::Statement* s) {
s->BindBool(14, url.created_by_policy());
s->BindString(15, url.instant_url() ? url.instant_url()->url() :
std::string());
+ s->BindInt64(16, url.last_modified().ToTimeT());
}
} // anonymous namespace
@@ -78,7 +79,8 @@ bool KeywordTable::Init() {
"autogenerate_keyword INTEGER DEFAULT 0,"
"logo_id INTEGER DEFAULT 0,"
"created_by_policy INTEGER DEFAULT 0,"
- "instant_url VARCHAR)")) {
+ "instant_url VARCHAR,"
+ "last_modified INTEGER DEFAULT 0)")) {
NOTREACHED();
return false;
}
@@ -99,8 +101,8 @@ bool KeywordTable::AddKeyword(const TemplateURL& url) {
"originating_url, date_created, usage_count, input_encodings, "
"show_in_default_list, suggest_url, prepopulate_id, "
"autogenerate_keyword, logo_id, created_by_policy, instant_url, "
- "id) VALUES "
- "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
+ "last_modified, id) VALUES "
+ "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
if (!s) {
NOTREACHED() << "Statement prepare failed";
return false;
@@ -132,7 +134,7 @@ bool KeywordTable::GetKeywords(std::vector<TemplateURL*>* urls) {
"safe_for_autoreplace, originating_url, date_created, "
"usage_count, input_encodings, show_in_default_list, "
"suggest_url, prepopulate_id, autogenerate_keyword, logo_id, "
- "created_by_policy, instant_url "
+ "created_by_policy, instant_url, last_modified "
"FROM keywords ORDER BY id ASC"));
if (!s) {
NOTREACHED() << "Statement prepare failed";
@@ -183,6 +185,8 @@ bool KeywordTable::GetKeywords(std::vector<TemplateURL*>* urls) {
template_url->SetInstantURL(s.ColumnString(16), 0, 0);
+ template_url->set_last_modified(Time::FromTimeT(s.ColumnInt64(17)));
+
urls->push_back(template_url);
}
return s.Succeeded();
@@ -197,7 +201,8 @@ bool KeywordTable::UpdateKeyword(const TemplateURL& url) {
"safe_for_autoreplace=?, originating_url=?, date_created=?, "
"usage_count=?, input_encodings=?, show_in_default_list=?, "
"suggest_url=?, prepopulate_id=?, autogenerate_keyword=?, "
- "logo_id=?, created_by_policy=?, instant_url=? WHERE id=?"));
+ "logo_id=?, created_by_policy=?, instant_url=?, last_modified=? "
+ "WHERE id=?"));
if (!s) {
NOTREACHED() << "Statement prepare failed";
return false;
@@ -291,3 +296,8 @@ bool KeywordTable::MigrateToVersion29InstantUrlToSupportsInstant() {
return true;
}
+
+bool KeywordTable::MigrateToVersion38AddLastModifiedColumn() {
+ return db_->Execute(
+ "ALTER TABLE keywords ADD COLUMN last_modified INTEGER DEFAULT 0");
+}
diff --git a/chrome/browser/webdata/keyword_table.h b/chrome/browser/webdata/keyword_table.h
index fc31433..dda570d 100644
--- a/chrome/browser/webdata/keyword_table.h
+++ b/chrome/browser/webdata/keyword_table.h
@@ -47,6 +47,8 @@ class Time;
// in version 26.
// instant_url See TemplateURL::instant_url. This was added
// in version 29.
+// last_modified See TemplateURL::last_modified. This was added in
+// version 38.
//
class KeywordTable : public WebDatabaseTable {
public:
@@ -87,6 +89,7 @@ class KeywordTable : public WebDatabaseTable {
bool MigrateToVersion26AddCreatedByPolicyColumn();
bool MigrateToVersion28SupportsInstantColumn();
bool MigrateToVersion29InstantUrlToSupportsInstant();
+ bool MigrateToVersion38AddLastModifiedColumn();
private:
DISALLOW_COPY_AND_ASSIGN(KeywordTable);
diff --git a/chrome/browser/webdata/keyword_table_unittest.cc b/chrome/browser/webdata/keyword_table_unittest.cc
index e2ae690..a668ae1 100644
--- a/chrome/browser/webdata/keyword_table_unittest.cc
+++ b/chrome/browser/webdata/keyword_table_unittest.cc
@@ -13,6 +13,7 @@
#include "testing/gtest/include/gtest/gtest.h"
using base::Time;
+using base::TimeDelta;
class KeywordTableTest : public testing::Test {
public:
@@ -71,6 +72,8 @@ TEST_F(KeywordTableTest, Keywords) {
template_url.set_safe_for_autoreplace(true);
Time created_time = Time::Now();
template_url.set_date_created(created_time);
+ Time last_modified_time = created_time + TimeDelta::FromSeconds(10);
+ template_url.set_last_modified(last_modified_time);
template_url.set_show_in_default_list(true);
template_url.set_originating_url(originating_url);
template_url.set_usage_count(32);
@@ -103,6 +106,9 @@ TEST_F(KeywordTableTest, Keywords) {
// The database stores time only at the resolution of a second.
EXPECT_EQ(created_time.ToTimeT(), restored_url->date_created().ToTimeT());
+ EXPECT_EQ(last_modified_time.ToTimeT(),
+ restored_url->last_modified().ToTimeT());
+
EXPECT_TRUE(restored_url->show_in_default_list());
EXPECT_EQ(GetID(&template_url), GetID(restored_url));
diff --git a/chrome/browser/webdata/web_database.cc b/chrome/browser/webdata/web_database.cc
index 45a06a8..9ad3613 100644
--- a/chrome/browser/webdata/web_database.cc
+++ b/chrome/browser/webdata/web_database.cc
@@ -16,8 +16,8 @@ namespace {
// Current version number. Note: when changing the current version number,
// corresponding changes must happen in the unit tests, and new migration test
// added. See |WebDatabaseMigrationTest::kCurrentTestedVersionNumber|.
-const int kCurrentVersionNumber = 37;
-const int kCompatibleVersionNumber = 37;
+const int kCurrentVersionNumber = 38;
+const int kCompatibleVersionNumber = 38;
// Change the version number and possibly the compatibility version of
// |meta_table_|.
@@ -279,6 +279,13 @@ sql::InitStatus WebDatabase::MigrateOldVersionsAsNeeded() {
ChangeVersion(&meta_table_, 37, true);
// FALL THROUGH
+ case 37:
+ if (!keyword_table_->MigrateToVersion38AddLastModifiedColumn())
+ return FailedMigrationTo(38);
+
+ ChangeVersion(&meta_table_, 38, true);
+ // FALL THROUGH
+
// Add successive versions here. Each should set the version number and
// compatible version number as appropriate, then fall through to the next
// case.
diff --git a/chrome/browser/webdata/web_database_migration_unittest.cc b/chrome/browser/webdata/web_database_migration_unittest.cc
index 19613d4..bb6dad0 100644
--- a/chrome/browser/webdata/web_database_migration_unittest.cc
+++ b/chrome/browser/webdata/web_database_migration_unittest.cc
@@ -41,7 +41,7 @@ void AutofillProfile31FromStatement(const sql::Statement& s,
*unique_id = s.ColumnInt(1);
profile->SetInfo(NAME_FIRST, s.ColumnString16(2));
profile->SetInfo(NAME_MIDDLE, s.ColumnString16(3));
- profile->SetInfo(NAME_LAST,s.ColumnString16(4));
+ profile->SetInfo(NAME_LAST, s.ColumnString16(4));
profile->SetInfo(EMAIL_ADDRESS, s.ColumnString16(5));
profile->SetInfo(COMPANY_NAME, s.ColumnString16(6));
profile->SetInfo(ADDRESS_HOME_LINE1, s.ColumnString16(7));
@@ -186,7 +186,7 @@ class WebDatabaseMigrationTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(WebDatabaseMigrationTest);
};
-const int WebDatabaseMigrationTest::kCurrentTestedVersionNumber = 37;
+const int WebDatabaseMigrationTest::kCurrentTestedVersionNumber = 38;
void WebDatabaseMigrationTest::LoadDatabase(const FilePath::StringType& file) {
std::string contents;
@@ -454,7 +454,7 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion25ToCurrent) {
// Check version.
EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection));
- // |keywords| |logo_id| column should have been added.
+ // |keywords| |created_by_policy| column should have been added.
EXPECT_TRUE(connection.DoesColumnExist("keywords", "id"));
EXPECT_TRUE(connection.DoesColumnExist("keywords", "created_by_policy"));
}
@@ -587,7 +587,7 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion26ToCurrentStringIDs) {
// Check version.
EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection));
- // |keywords| |logo_id| column should have been added.
+ // |keywords| |created_by_policy| column should have been added.
EXPECT_TRUE(connection.DoesColumnExist("keywords", "id"));
EXPECT_TRUE(connection.DoesColumnExist("keywords", "created_by_policy"));
EXPECT_FALSE(connection.DoesColumnExist("credit_cards", "billing_address"));
@@ -601,7 +601,7 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion26ToCurrentStringIDs) {
EXPECT_EQ("Jack", s.ColumnString(1));
EXPECT_EQ(2, s.ColumnInt(2));
EXPECT_EQ(2012, s.ColumnInt(3));
- // Column 5 is encrypted credit card number blob.
+ // Column 5 is encrypted credit card number blo b.
// Column 6 is date_modified.
}
}
@@ -1169,7 +1169,7 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion32ToCurrent) {
// John Doe fax.
ASSERT_TRUE(s4.Step());
EXPECT_EQ("00580526-FF81-EE2A-0546-1AC593A32E2F", s4.ColumnString(0));
- EXPECT_EQ(1, s4.ColumnInt(1)); // 1 means phone.
+ EXPECT_EQ(1, s4.ColumnInt(1)); // 1 means phone.
EXPECT_EQ(ASCIIToUTF16("4153334444"), s4.ColumnString16(2));
// John P. Doe phone.
@@ -1183,25 +1183,25 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion32ToCurrent) {
// 2 Main Street phone.
ASSERT_TRUE(s4.Step());
EXPECT_EQ("4C74A9D8-7EEE-423E-F9C2-E7FA70ED1396", s4.ColumnString(0));
- EXPECT_EQ(0, s4.ColumnInt(1)); // 0 means phone.
+ EXPECT_EQ(0, s4.ColumnInt(1)); // 0 means phone.
EXPECT_EQ(ASCIIToUTF16(""), s4.ColumnString16(2));
// 2 Main Street fax.
ASSERT_TRUE(s4.Step());
EXPECT_EQ("4C74A9D8-7EEE-423E-F9C2-E7FA70ED1396", s4.ColumnString(0));
- EXPECT_EQ(1, s4.ColumnInt(1)); // 1 means fax.
+ EXPECT_EQ(1, s4.ColumnInt(1)); // 1 means fax.
EXPECT_EQ(ASCIIToUTF16(""), s4.ColumnString16(2));
// 2 Main St phone.
ASSERT_TRUE(s4.Step());
EXPECT_EQ("722DF5C4-F74A-294A-46F0-31FFDED0D635", s4.ColumnString(0));
- EXPECT_EQ(0, s4.ColumnInt(1)); // 0 means phone.
+ EXPECT_EQ(0, s4.ColumnInt(1)); // 0 means phone.
EXPECT_EQ(ASCIIToUTF16(""), s4.ColumnString16(2));
// 2 Main St fax.
ASSERT_TRUE(s4.Step());
EXPECT_EQ("722DF5C4-F74A-294A-46F0-31FFDED0D635", s4.ColumnString(0));
- EXPECT_EQ(1, s4.ColumnInt(1)); // 1 means fax.
+ EXPECT_EQ(1, s4.ColumnInt(1)); // 1 means fax.
EXPECT_EQ(ASCIIToUTF16(""), s4.ColumnString16(2));
// Note no phone or fax for Alfred E Newman.
@@ -1209,13 +1209,13 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion32ToCurrent) {
// 3 Main St phone.
ASSERT_TRUE(s4.Step());
EXPECT_EQ("9E5FE298-62C7-83DF-6293-381BC589183F", s4.ColumnString(0));
- EXPECT_EQ(0, s4.ColumnInt(1)); // 0 means phone.
+ EXPECT_EQ(0, s4.ColumnInt(1)); // 0 means phone.
EXPECT_EQ(ASCIIToUTF16(""), s4.ColumnString16(2));
// 2 Main St fax.
ASSERT_TRUE(s4.Step());
EXPECT_EQ("9E5FE298-62C7-83DF-6293-381BC589183F", s4.ColumnString(0));
- EXPECT_EQ(1, s4.ColumnInt(1)); // 1 means fax.
+ EXPECT_EQ(1, s4.ColumnInt(1)); // 1 means fax.
EXPECT_EQ(ASCIIToUTF16(""), s4.ColumnString16(2));
// Should be all.
@@ -1424,3 +1424,43 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion35ToCurrent) {
ASSERT_FALSE(s2.Step());
}
}
+
+// Tests that the |keywords| |last_modified| column gets added to the schema for
+// a version 37 database.
+TEST_F(WebDatabaseMigrationTest, MigrateVersion37ToCurrent) {
+ // This schema is taken from a build prior to the addition of the |keywords|
+ // |last_modified| column.
+ ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_37.sql")));
+
+ // Verify pre-conditions. These are expectations for version 37 of the
+ // database.
+ {
+ sql::Connection connection;
+ ASSERT_TRUE(connection.Open(GetDatabasePath()));
+
+ // Columns existing and not existing before current version.
+ ASSERT_TRUE(connection.DoesColumnExist("keywords", "id"));
+ ASSERT_FALSE(connection.DoesColumnExist("keywords", "last_modified"));
+ }
+
+ // Load the database via the WebDatabase class and migrate the database to
+ // the current version.
+ {
+ WebDatabase db;
+ ASSERT_EQ(sql::INIT_OK, db.Init(GetDatabasePath()));
+ }
+
+ // Verify post-conditions. These are expectations for current version of the
+ // database.
+ {
+ sql::Connection connection;
+ ASSERT_TRUE(connection.Open(GetDatabasePath()));
+
+ // Check version.
+ EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection));
+
+ // |keywords| |last_modified| column should have been added.
+ EXPECT_TRUE(connection.DoesColumnExist("keywords", "id"));
+ EXPECT_TRUE(connection.DoesColumnExist("keywords", "last_modified"));
+ }
+}