diff options
author | vasilii@chromium.org <vasilii@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-03 22:59:43 +0000 |
---|---|---|
committer | vasilii@chromium.org <vasilii@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-03 22:59:43 +0000 |
commit | e937a970746f956283743e4df549369f0df64809 (patch) | |
tree | 05f8e6d132e5902d633bc8ff82a2b87daf32d8e7 | |
parent | 7192c12637f571a7f2e2e65cb60d6deb92759ff6 (diff) | |
download | chromium_src-e937a970746f956283743e4df549369f0df64809.zip chromium_src-e937a970746f956283743e4df549369f0df64809.tar.gz chromium_src-e937a970746f956283743e4df549369f0df64809.tar.bz2 |
Profile Reset: support "soft reset" of search engines, homepage and startup pages. The soft reset doesn't clear user-defined search engines, homepage URL and startup URLs.
BUG=235037
Review URL: https://codereview.chromium.org/23496004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@226880 0039d316-1c4b-4281-b951-d872f2087c98
13 files changed, 357 insertions, 346 deletions
diff --git a/chrome/browser/profile_resetter/profile_resetter.cc b/chrome/browser/profile_resetter/profile_resetter.cc index 3c797a7..0777632 100644 --- a/chrome/browser/profile_resetter/profile_resetter.cc +++ b/chrome/browser/profile_resetter/profile_resetter.cc @@ -14,6 +14,7 @@ #include "chrome/browser/google/google_url_tracker.h" #include "chrome/browser/profile_resetter/brandcoded_default_settings.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/search_engines/search_terms_data.h" #include "chrome/browser/search_engines/template_url_prepopulate_data.h" #include "chrome/browser/search_engines/template_url_service.h" #include "chrome/browser/search_engines/template_url_service_factory.h" @@ -47,14 +48,19 @@ void ProfileResetter::Reset( DCHECK(CalledOnValidThread()); DCHECK(master_settings); - master_settings_.swap(master_settings); - // We should never be called with unknown flags. CHECK_EQ(static_cast<ResettableFlags>(0), resettable_flags & ~ALL); // We should never be called when a previous reset has not finished. CHECK_EQ(static_cast<ResettableFlags>(0), pending_reset_flags_); + if (!resettable_flags) { + content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, + callback); + return; + } + + master_settings_.swap(master_settings); callback_ = callback; // These flags are set to false by the individual reset functions. @@ -63,7 +69,7 @@ void ProfileResetter::Reset( struct { Resettable flag; void (ProfileResetter::*method)(); - } flag2Method [] = { + } flagToMethod [] = { { DEFAULT_SEARCH_ENGINE, &ProfileResetter::ResetDefaultSearchEngine }, { HOMEPAGE, &ProfileResetter::ResetHomepage }, { CONTENT_SETTINGS, &ProfileResetter::ResetContentSettings }, @@ -74,10 +80,10 @@ void ProfileResetter::Reset( }; ResettableFlags reset_triggered_for_flags = 0; - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(flag2Method); ++i) { - if (resettable_flags & flag2Method[i].flag) { - reset_triggered_for_flags |= flag2Method[i].flag; - (this->*flag2Method[i].method)(); + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(flagToMethod); ++i) { + if (resettable_flags & flagToMethod[i].flag) { + reset_triggered_for_flags |= flagToMethod[i].flag; + (this->*flagToMethod[i].method)(); } } @@ -124,7 +130,7 @@ void ProfileResetter::ResetDefaultSearchEngine() { update->Swap(search_engines.get()); } - template_url_service_->ResetURLs(); + template_url_service_->RepairPrepopulatedSearchEngines(); // Reset Google search URL. prefs->ClearPref(prefs::kLastPromptedGoogleURL); @@ -149,8 +155,6 @@ void ProfileResetter::ResetHomepage() { if (master_settings_->GetHomepage(&homepage)) prefs->SetString(prefs::kHomePage, homepage); - else - prefs->ClearPref(prefs::kHomePage); if (master_settings_->GetHomepageIsNewTab(&homepage_is_ntp)) prefs->SetBoolean(prefs::kHomePageIsNewTabPage, homepage_is_ntp); @@ -217,8 +221,6 @@ void ProfileResetter::ResetStartupPages() { scoped_ptr<ListValue> url_list(master_settings_->GetUrlsToRestoreOnStartup()); if (url_list) ListPrefUpdate(prefs, prefs::kURLsToRestoreOnStartup)->Swap(url_list.get()); - else - prefs->ClearPref(prefs::kURLsToRestoreOnStartup); int restore_on_startup; if (master_settings_->GetRestoreOnStartup(&restore_on_startup)) diff --git a/chrome/browser/profile_resetter/profile_resetter_unittest.cc b/chrome/browser/profile_resetter/profile_resetter_unittest.cc index 3bac3e8..a1aaf6b 100644 --- a/chrome/browser/profile_resetter/profile_resetter_unittest.cc +++ b/chrome/browser/profile_resetter/profile_resetter_unittest.cc @@ -276,32 +276,9 @@ void ReplaceString(std::string* str, /********************* Tests *********************/ -TEST_F(ProfileResetterTest, ResetDefaultSearchEngine) { - // Search engine's logic is tested by - // TemplateURLServiceTest.ResetURLs. - PrefService* prefs = profile()->GetPrefs(); - DCHECK(prefs); - prefs->SetString(prefs::kLastPromptedGoogleURL, "http://www.foo.com/"); - - scoped_refptr<Extension> extension = CreateExtension( - ASCIIToUTF16("xxx"), - base::FilePath(FILE_PATH_LITERAL("//nonexistent")), - Manifest::COMPONENT, - extensions::Manifest::TYPE_EXTENSION, - false); - service_->AddExtension(extension.get()); - - ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE); - - // TemplateURLService should reset extension search engines. - TemplateURLService* model = - TemplateURLServiceFactory::GetForProfile(profile()); - TemplateURL* ext_url = model->GetTemplateURLForKeyword(ASCIIToUTF16("xxx")); - ASSERT_TRUE(ext_url); - EXPECT_TRUE(ext_url->IsExtensionKeyword()); - EXPECT_EQ(ASCIIToUTF16("xxx"), ext_url->keyword()); - EXPECT_EQ(ASCIIToUTF16("xxx"), ext_url->short_name()); - EXPECT_EQ("", prefs->GetString(prefs::kLastPromptedGoogleURL)); +TEST_F(ProfileResetterTest, ResetNothing) { + // The callback should be called even if there is nothing to reset. + ResetAndWait(0); } TEST_F(ProfileResetterTest, ResetDefaultSearchEngineNonOrganic) { @@ -313,7 +290,6 @@ TEST_F(ProfileResetterTest, ResetDefaultSearchEngineNonOrganic) { TemplateURLService* model = TemplateURLServiceFactory::GetForProfile(profile()); - EXPECT_EQ(1u, model->GetTemplateURLs().size()); TemplateURL* default_engine = model->GetDefaultSearchProvider(); ASSERT_NE(static_cast<TemplateURL*>(NULL), default_engine); EXPECT_EQ(ASCIIToUTF16("first"), default_engine->short_name()); @@ -323,18 +299,25 @@ TEST_F(ProfileResetterTest, ResetDefaultSearchEngineNonOrganic) { EXPECT_EQ("", prefs->GetString(prefs::kLastPromptedGoogleURL)); } -TEST_F(ProfileResetterTest, ResetHomepage) { +TEST_F(ProfileResetterTest, ResetDefaultSearchEnginePartially) { + // Search engine's logic is tested by + // TemplateURLServiceTest.RepairPrepopulatedSearchEngines. PrefService* prefs = profile()->GetPrefs(); DCHECK(prefs); - prefs->SetBoolean(prefs::kHomePageIsNewTabPage, false); - prefs->SetString(prefs::kHomePage, "http://google.com"); - prefs->SetBoolean(prefs::kShowHomeButton, true); + prefs->SetString(prefs::kLastPromptedGoogleURL, "http://www.foo.com/"); - ResetAndWait(ProfileResetter::HOMEPAGE); + // Make sure TemplateURLService has loaded. + ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE); - EXPECT_TRUE(prefs->GetBoolean(prefs::kHomePageIsNewTabPage)); - EXPECT_EQ(std::string(), prefs->GetString(prefs::kHomePage)); - EXPECT_FALSE(prefs->GetBoolean(prefs::kShowHomeButton)); + TemplateURLService* model = + TemplateURLServiceFactory::GetForProfile(profile()); + TemplateURLService::TemplateURLVector urls = model->GetTemplateURLs(); + + // The second call should produce no effect. + ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE); + + EXPECT_EQ(urls, model->GetTemplateURLs()); + EXPECT_EQ(std::string(), prefs->GetString(prefs::kLastPromptedGoogleURL)); } TEST_F(ProfileResetterTest, ResetHomepageNonOrganic) { @@ -351,6 +334,20 @@ TEST_F(ProfileResetterTest, ResetHomepageNonOrganic) { EXPECT_TRUE(prefs->GetBoolean(prefs::kShowHomeButton)); } +TEST_F(ProfileResetterTest, ResetHomepagePartially) { + PrefService* prefs = profile()->GetPrefs(); + DCHECK(prefs); + prefs->SetBoolean(prefs::kHomePageIsNewTabPage, false); + prefs->SetString(prefs::kHomePage, "http://www.foo.com"); + prefs->SetBoolean(prefs::kShowHomeButton, true); + + ResetAndWait(ProfileResetter::HOMEPAGE); + + EXPECT_TRUE(prefs->GetBoolean(prefs::kHomePageIsNewTabPage)); + EXPECT_EQ("http://www.foo.com", prefs->GetString(prefs::kHomePage)); + EXPECT_FALSE(prefs->GetBoolean(prefs::kShowHomeButton)); +} + TEST_F(ProfileResetterTest, ResetContentSettings) { HostContentSettingsMap* host_content_settings_map = profile()->GetHostContentSettingsMap(); @@ -572,34 +569,35 @@ TEST_F(ProfileResetterTest, ResetExtensionsAndDefaultApps) { EXPECT_TRUE(theme_service->UsingDefaultTheme()); } -TEST_F(ProfileResetterTest, ResetStartPage) { +TEST_F(ProfileResetterTest, ResetStartPageNonOrganic) { PrefService* prefs = profile()->GetPrefs(); DCHECK(prefs); - SessionStartupPref startup_pref(SessionStartupPref::URLS); - startup_pref.urls.push_back(GURL("http://foo")); - startup_pref.urls.push_back(GURL("http://bar")); + SessionStartupPref startup_pref(SessionStartupPref::LAST); SessionStartupPref::SetStartupPref(prefs, startup_pref); - ResetAndWait(ProfileResetter::STARTUP_PAGES); + ResetAndWait(ProfileResetter::STARTUP_PAGES, kDistributionConfig); startup_pref = SessionStartupPref::GetStartupPref(prefs); - EXPECT_EQ(SessionStartupPref::GetDefaultStartupType(), startup_pref.type); - EXPECT_EQ(std::vector<GURL>(), startup_pref.urls); + EXPECT_EQ(SessionStartupPref::URLS, startup_pref.type); + const GURL urls[] = {GURL("http://goo.gl"), GURL("http://foo.de")}; + EXPECT_EQ(std::vector<GURL>(urls, urls + arraysize(urls)), startup_pref.urls); } -TEST_F(ProfileResetterTest, ResetStartPageNonOrganic) { + +TEST_F(ProfileResetterTest, ResetStartPagePartially) { PrefService* prefs = profile()->GetPrefs(); DCHECK(prefs); - SessionStartupPref startup_pref(SessionStartupPref::LAST); + const GURL urls[] = {GURL("http://foo"), GURL("http://bar")}; + SessionStartupPref startup_pref(SessionStartupPref::URLS); + startup_pref.urls.assign(urls, urls + arraysize(urls)); SessionStartupPref::SetStartupPref(prefs, startup_pref); - ResetAndWait(ProfileResetter::STARTUP_PAGES, kDistributionConfig); + ResetAndWait(ProfileResetter::STARTUP_PAGES, std::string()); startup_pref = SessionStartupPref::GetStartupPref(prefs); - EXPECT_EQ(SessionStartupPref::URLS, startup_pref.type); - const GURL urls[] = {GURL("http://goo.gl"), GURL("http://foo.de")}; + EXPECT_EQ(SessionStartupPref::GetDefaultStartupType(), startup_pref.type); EXPECT_EQ(std::vector<GURL>(urls, urls + arraysize(urls)), startup_pref.urls); } @@ -715,7 +713,8 @@ TEST_F(ProfileResetterTest, CheckSnapshots) { // Reset to non organic defaults. ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE | ProfileResetter::HOMEPAGE | - ProfileResetter::STARTUP_PAGES, master_prefs); + ProfileResetter::STARTUP_PAGES, + master_prefs); ResettableSettingsSnapshot nonorganic_snap(profile()); EXPECT_EQ(ResettableSettingsSnapshot::ALL_FIELDS, @@ -756,7 +755,8 @@ TEST_F(ProfileResetterTest, FeedbackSerializtionTest) { // Reset to non organic defaults. ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE | ProfileResetter::HOMEPAGE | - ProfileResetter::STARTUP_PAGES, kDistributionConfig); + ProfileResetter::STARTUP_PAGES, + kDistributionConfig); scoped_refptr<Extension> ext = CreateExtension( ASCIIToUTF16("example"), @@ -769,7 +769,7 @@ TEST_F(ProfileResetterTest, FeedbackSerializtionTest) { const ResettableSettingsSnapshot nonorganic_snap(profile()); - COMPILE_ASSERT(ResettableSettingsSnapshot::ALL_FIELDS == 63, + COMPILE_ASSERT(ResettableSettingsSnapshot::ALL_FIELDS == 15, expand_this_test); for (int field_mask = 0; field_mask <= ResettableSettingsSnapshot::ALL_FIELDS; ++field_mask) { @@ -792,13 +792,13 @@ TEST_F(ProfileResetterTest, FeedbackSerializtionTest) { ListValue* extensions; int initiator = 0; - EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::STARTUP_URLS), + EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::STARTUP_MODE), dict->GetList("startup_urls", &startup_urls)); - EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::STARTUP_TYPE), + EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::STARTUP_MODE), dict->GetInteger("startup_type", &startup_type)); EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::HOMEPAGE), dict->GetString("homepage", &homepage)); - EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::HOMEPAGE_IS_NTP), + EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::HOMEPAGE), dict->GetBoolean("homepage_is_ntp", &homepage_is_ntp)); EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::DSE_URL), dict->GetString("default_search_engine", &default_search_engine)); diff --git a/chrome/browser/profile_resetter/resettable_settings_snapshot.cc b/chrome/browser/profile_resetter/resettable_settings_snapshot.cc index 095efcf..a5b8101 100644 --- a/chrome/browser/profile_resetter/resettable_settings_snapshot.cc +++ b/chrome/browser/profile_resetter/resettable_settings_snapshot.cc @@ -79,10 +79,6 @@ ResettableSettingsSnapshot::~ResettableSettingsSnapshot() {} void ResettableSettingsSnapshot::Subtract( const ResettableSettingsSnapshot& snapshot) { - std::vector<GURL> urls = base::STLSetDifference<std::vector<GURL> >( - startup_.urls, snapshot.startup_.urls); - startup_.urls.swap(urls); - ExtensionList extensions = base::STLSetDifference<ExtensionList>( enabled_extensions_, snapshot.enabled_extensions_); enabled_extensions_.swap(extensions); @@ -92,26 +88,21 @@ int ResettableSettingsSnapshot::FindDifferentFields( const ResettableSettingsSnapshot& snapshot) const { int bit_mask = 0; - if (startup_.urls != snapshot.startup_.urls) { - bit_mask |= STARTUP_URLS; - } - - if (startup_.type != snapshot.startup_.type) - bit_mask |= STARTUP_TYPE; + if (startup_.type != snapshot.startup_.type || + startup_.urls != snapshot.startup_.urls) + bit_mask |= STARTUP_MODE; - if (homepage_ != snapshot.homepage_) + if (homepage_is_ntp_ != snapshot.homepage_is_ntp_ || + homepage_ != snapshot.homepage_) bit_mask |= HOMEPAGE; - if (homepage_is_ntp_ != snapshot.homepage_is_ntp_) - bit_mask |= HOMEPAGE_IS_NTP; - if (dse_url_ != snapshot.dse_url_) bit_mask |= DSE_URL; if (enabled_extensions_ != snapshot.enabled_extensions_) bit_mask |= EXTENSIONS; - COMPILE_ASSERT(ResettableSettingsSnapshot::ALL_FIELDS == 63, + COMPILE_ASSERT(ResettableSettingsSnapshot::ALL_FIELDS == 15, add_new_field_here); return bit_mask; @@ -122,23 +113,20 @@ std::string SerializeSettingsReport(const ResettableSettingsSnapshot& snapshot, SnapshotCaller source) { DictionaryValue dict; - if (field_mask & ResettableSettingsSnapshot::STARTUP_URLS) { + if (field_mask & ResettableSettingsSnapshot::STARTUP_MODE) { ListValue* list = new ListValue; const std::vector<GURL>& urls = snapshot.startup_urls(); for (std::vector<GURL>::const_iterator i = urls.begin(); i != urls.end(); ++i) list->AppendString(i->spec()); dict.Set(kStartupURLPath, list); - } - - if (field_mask & ResettableSettingsSnapshot::STARTUP_TYPE) dict.SetInteger(kStartupTypePath, snapshot.startup_type()); + } - if (field_mask & ResettableSettingsSnapshot::HOMEPAGE) + if (field_mask & ResettableSettingsSnapshot::HOMEPAGE) { dict.SetString(kHomepagePath, snapshot.homepage()); - - if (field_mask & ResettableSettingsSnapshot::HOMEPAGE_IS_NTP) dict.SetBoolean(kHomepageIsNewTabPage, snapshot.homepage_is_ntp()); + } if (field_mask & ResettableSettingsSnapshot::DSE_URL) dict.SetString(kDefaultSearchEnginePath, snapshot.dse_url()); @@ -157,7 +145,7 @@ std::string SerializeSettingsReport(const ResettableSettingsSnapshot& snapshot, dict.Set(kEnabledExtensions, list); } - COMPILE_ASSERT(ResettableSettingsSnapshot::ALL_FIELDS == 63, + COMPILE_ASSERT(ResettableSettingsSnapshot::ALL_FIELDS == 15, serialize_new_field_here); dict.SetInteger(kFeedbackCaller, source); diff --git a/chrome/browser/profile_resetter/resettable_settings_snapshot.h b/chrome/browser/profile_resetter/resettable_settings_snapshot.h index 5abac6f..d3062a3 100644 --- a/chrome/browser/profile_resetter/resettable_settings_snapshot.h +++ b/chrome/browser/profile_resetter/resettable_settings_snapshot.h @@ -21,15 +21,12 @@ class ResettableSettingsSnapshot { typedef std::vector<std::pair<std::string, std::string> > ExtensionList; // All types of settings handled by this class. enum Field { - STARTUP_URLS = 1 << 0, - STARTUP_TYPE = 1 << 1, - HOMEPAGE = 1 << 2, - HOMEPAGE_IS_NTP = 1 << 3, - DSE_URL = 1 << 4, - EXTENSIONS = 1 << 5, - - ALL_FIELDS = STARTUP_URLS | STARTUP_TYPE | HOMEPAGE | - HOMEPAGE_IS_NTP | DSE_URL | EXTENSIONS, + STARTUP_MODE = 1 << 0, + HOMEPAGE = 1 << 1, + DSE_URL = 1 << 2, + EXTENSIONS = 1 << 3, + + ALL_FIELDS = STARTUP_MODE | HOMEPAGE | DSE_URL | EXTENSIONS, }; explicit ResettableSettingsSnapshot(Profile* profile); @@ -50,7 +47,6 @@ class ResettableSettingsSnapshot { return enabled_extensions_; } - // Substitutes |startup_.urls| with |startup_.urls|\|snapshot.startup_.urls|. // Substitutes |enabled_extensions_| with // |enabled_extensions_|\|snapshot.enabled_extensions_|. void Subtract(const ResettableSettingsSnapshot& snapshot); diff --git a/chrome/browser/search_engines/template_url_prepopulate_data.cc b/chrome/browser/search_engines/template_url_prepopulate_data.cc index 652ecf58..ba234ff 100644 --- a/chrome/browser/search_engines/template_url_prepopulate_data.cc +++ b/chrome/browser/search_engines/template_url_prepopulate_data.cc @@ -10,7 +10,6 @@ #include "base/command_line.h" #include "base/logging.h" -#include "base/memory/scoped_vector.h" #include "base/prefs/pref_service.h" #include "base/stl_util.h" #include "base/strings/string16.h" @@ -1118,15 +1117,15 @@ TemplateURL* MakePrepopulatedTemplateURL( return new TemplateURL(profile, data); } -void GetPrepopulatedTemplateFromPrefs(Profile* profile, - std::vector<TemplateURL*>* t_urls) { +ScopedVector<TemplateURL> GetPrepopulatedTemplateFromPrefs(Profile* profile) { + ScopedVector<TemplateURL> t_urls; if (!profile) - return; + return t_urls.Pass(); const ListValue* list = profile->GetPrefs()->GetList(prefs::kSearchProviderOverrides); if (!list) - return; + return t_urls.Pass(); size_t num_engines = list->GetSize(); for (size_t i = 0; i != num_engines; ++i) { @@ -1169,7 +1168,7 @@ void GetPrepopulatedTemplateFromPrefs(Profile* profile, engine->GetList("alternate_urls", &alternate_urls); engine->GetString("search_terms_replacement_key", &search_terms_replacement_key); - t_urls->push_back(MakePrepopulatedTemplateURL(profile, name, keyword, + t_urls.push_back(MakePrepopulatedTemplateURL(profile, name, keyword, search_url, suggest_url, instant_url, image_url, new_tab_url, search_url_post_params, suggest_url_post_params, instant_url_post_params, image_url_post_params, @@ -1177,6 +1176,7 @@ void GetPrepopulatedTemplateFromPrefs(Profile* profile, id)); } } + return t_urls.Pass(); } // The caller owns the returned TemplateURL. @@ -1248,24 +1248,24 @@ int GetDataVersion(PrefService* prefs) { kCurrentDataVersion; } -void GetPrepopulatedEngines(Profile* profile, - std::vector<TemplateURL*>* t_urls, - size_t* default_search_provider_index) { +ScopedVector<TemplateURL> GetPrepopulatedEngines( + Profile* profile, size_t* default_search_provider_index) { // If there is a set of search engines in the preferences file, it overrides // the built-in set. *default_search_provider_index = 0; - GetPrepopulatedTemplateFromPrefs(profile, t_urls); - if (!t_urls->empty()) - return; + ScopedVector<TemplateURL> t_urls = GetPrepopulatedTemplateFromPrefs(profile); + if (!t_urls.empty()) + return t_urls.Pass(); const PrepopulatedEngine** engines; size_t num_engines; GetPrepopulationSetFromCountryID(profile ? profile->GetPrefs() : NULL, &engines, &num_engines); for (size_t i = 0; i != num_engines; ++i) { - t_urls->push_back( + t_urls.push_back( MakePrepopulatedTemplateURLFromPrepopulateEngine(profile, *engines[i])); } + return t_urls.Pass(); } void ClearPrepopulatedEnginesInPrefs(Profile* profile) { @@ -1280,11 +1280,11 @@ void ClearPrepopulatedEnginesInPrefs(Profile* profile) { TemplateURL* GetPrepopulatedDefaultSearch(Profile* profile) { TemplateURL* default_search_provider = NULL; - ScopedVector<TemplateURL> loaded_urls; size_t default_search_index; // This could be more efficient. We are loading all the URLs to only keep // the first one. - GetPrepopulatedEngines(profile, &loaded_urls.get(), &default_search_index); + ScopedVector<TemplateURL> loaded_urls = GetPrepopulatedEngines( + profile, &default_search_index); if (default_search_index < loaded_urls.size()) { default_search_provider = loaded_urls[default_search_index]; loaded_urls.weak_erase(loaded_urls.begin() + default_search_index); diff --git a/chrome/browser/search_engines/template_url_prepopulate_data.h b/chrome/browser/search_engines/template_url_prepopulate_data.h index 40f6cd7..2d644982 100644 --- a/chrome/browser/search_engines/template_url_prepopulate_data.h +++ b/chrome/browser/search_engines/template_url_prepopulate_data.h @@ -9,6 +9,7 @@ #include <string> #include <vector> +#include "base/memory/scoped_vector.h" #include "base/strings/string16.h" #include "chrome/browser/search_engines/search_engine_type.h" @@ -44,13 +45,11 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); // file then it returns the version specified there. int GetDataVersion(PrefService* prefs); -// Loads the set of TemplateURLs from the prepopulate data. Ownership of the -// TemplateURLs is passed to the caller. On return, +// Loads the set of TemplateURLs from the prepopulate data. On return, // |default_search_provider_index| is set to the index of the default search // provider. -void GetPrepopulatedEngines(Profile* profile, - std::vector<TemplateURL*>* t_urls, - size_t* default_search_provider_index); +ScopedVector<TemplateURL> GetPrepopulatedEngines( + Profile* profile, size_t* default_search_provider_index); // Removes prepopulated engines and their version stored in user prefs. void ClearPrepopulatedEnginesInPrefs(Profile* profile); diff --git a/chrome/browser/search_engines/template_url_prepopulate_data_unittest.cc b/chrome/browser/search_engines/template_url_prepopulate_data_unittest.cc index d2e4db4..4e33b43 100644 --- a/chrome/browser/search_engines/template_url_prepopulate_data_unittest.cc +++ b/chrome/browser/search_engines/template_url_prepopulate_data_unittest.cc @@ -86,10 +86,10 @@ TEST(TemplateURLPrepopulateDataTest, UniqueIDs) { TestingProfile profile; for (size_t i = 0; i < arraysize(kCountryIds); ++i) { profile.GetPrefs()->SetInteger(prefs::kCountryIDAtInstall, kCountryIds[i]); - ScopedVector<TemplateURL> urls; size_t default_index; - TemplateURLPrepopulateData::GetPrepopulatedEngines(&profile, &urls.get(), - &default_index); + ScopedVector<TemplateURL> urls = + TemplateURLPrepopulateData::GetPrepopulatedEngines(&profile, + &default_index); std::set<int> unique_ids; for (size_t turl_i = 0; turl_i < urls.size(); ++turl_i) { ASSERT_TRUE(unique_ids.find(urls[turl_i]->prepopulate_id()) == @@ -121,10 +121,10 @@ TEST(TemplateURLPrepopulateDataTest, ProvidersFromPrefs) { int version = TemplateURLPrepopulateData::GetDataVersion(prefs); EXPECT_EQ(1, version); - ScopedVector<TemplateURL> t_urls; size_t default_index; - TemplateURLPrepopulateData::GetPrepopulatedEngines(&profile, &t_urls.get(), - &default_index); + ScopedVector<TemplateURL> t_urls = + TemplateURLPrepopulateData::GetPrepopulatedEngines(&profile, + &default_index); ASSERT_EQ(1u, t_urls.size()); EXPECT_EQ(ASCIIToUTF16("foo"), t_urls[0]->short_name()); @@ -149,9 +149,8 @@ TEST(TemplateURLPrepopulateDataTest, ProvidersFromPrefs) { overrides->Append(entry->DeepCopy()); prefs->SetUserPref(prefs::kSearchProviderOverrides, overrides); - t_urls.clear(); - TemplateURLPrepopulateData::GetPrepopulatedEngines(&profile, &t_urls.get(), - &default_index); + t_urls = TemplateURLPrepopulateData::GetPrepopulatedEngines(&profile, + &default_index); ASSERT_EQ(1u, t_urls.size()); EXPECT_EQ(ASCIIToUTF16("foo"), t_urls[0]->short_name()); EXPECT_EQ(ASCIIToUTF16("fook"), t_urls[0]->keyword()); @@ -184,9 +183,8 @@ TEST(TemplateURLPrepopulateDataTest, ProvidersFromPrefs) { overrides->Append(entry->DeepCopy()); prefs->SetUserPref(prefs::kSearchProviderOverrides, overrides); - t_urls.clear(); - TemplateURLPrepopulateData::GetPrepopulatedEngines(&profile, &t_urls.get(), - &default_index); + t_urls = TemplateURLPrepopulateData::GetPrepopulatedEngines(&profile, + &default_index); EXPECT_EQ(2u, t_urls.size()); } @@ -216,10 +214,10 @@ TEST(TemplateURLPrepopulateDataTest, ClearProvidersFromPrefs) { version = TemplateURLPrepopulateData::GetDataVersion(prefs); EXPECT_EQ(TemplateURLPrepopulateData::kCurrentDataVersion, version); - ScopedVector<TemplateURL> t_urls; size_t default_index; - TemplateURLPrepopulateData::GetPrepopulatedEngines(&profile, &t_urls.get(), - &default_index); + ScopedVector<TemplateURL> t_urls = + TemplateURLPrepopulateData::GetPrepopulatedEngines(&profile, + &default_index); ASSERT_FALSE(t_urls.empty()); for (size_t i = 0; i < t_urls.size(); ++i) { EXPECT_NE(ASCIIToUTF16("foo"), t_urls[i]->short_name()); @@ -245,10 +243,10 @@ TEST(TemplateURLPrepopulateDataTest, ProvidersFromPrepopulated) { CommandLine::ForCurrentProcess()->AppendSwitchASCII( switches::kCountry, "US"); TestingProfile profile; - ScopedVector<TemplateURL> t_urls; size_t default_index; - TemplateURLPrepopulateData::GetPrepopulatedEngines(&profile, &t_urls.get(), - &default_index); + ScopedVector<TemplateURL> t_urls = + TemplateURLPrepopulateData::GetPrepopulatedEngines(&profile, + &default_index); // Ensure all the URLs have the required fields populated. ASSERT_FALSE(t_urls.empty()); diff --git a/chrome/browser/search_engines/template_url_service.cc b/chrome/browser/search_engines/template_url_service.cc index 02f1551..cca1a36 100644 --- a/chrome/browser/search_engines/template_url_service.cc +++ b/chrome/browser/search_engines/template_url_service.cc @@ -708,53 +708,47 @@ TemplateURL* TemplateURLService::FindNewDefaultSearchProvider() { return FirstPotentialDefaultEngine(template_urls_); } -void TemplateURLService::ResetURLs() { +void TemplateURLService::RepairPrepopulatedSearchEngines() { // Can't clean DB if it hasn't been loaded. DCHECK(loaded()); - DCHECK(service_); - ClearDefaultProviderFromPrefs(); - - TemplateURLVector entries_to_process = template_urls_; - // Clear default provider to be able to delete it. - default_search_provider_ = NULL; - for (TemplateURLVector::const_iterator i = entries_to_process.begin(); - i != entries_to_process.end(); ++i) - RemoveNoNotify(*i); - entries_to_process.clear(); - provider_map_.reset(new SearchHostToURLsMap); - UIThreadSearchTermsData search_terms_data(profile_); - provider_map_->Init(TemplateURLVector(), search_terms_data); + size_t default_search_provider_index = 0; + ScopedVector<TemplateURL> prepopulated_urls = + TemplateURLPrepopulateData::GetPrepopulatedEngines( + profile_, &default_search_provider_index); + DCHECK(!prepopulated_urls.empty()); + int default_search_engine_id = + prepopulated_urls[default_search_provider_index]->prepopulate_id(); + TemplateURL* current_dse = default_search_provider_; + ActionsFromPrepopulateData actions(CreateActionsFromCurrentPrepopulateData( + &prepopulated_urls, template_urls_, current_dse)); + // Remove items. + for (std::vector<TemplateURL*>::iterator i = actions.removed_engines.begin(); + i < actions.removed_engines.end(); ++i) + RemoveNoNotify(*i); - TemplateURL* default_search_provider = NULL; - // Force GetSearchProvidersUsingLoadedEngines() to include the prepopulated - // engines in the list by claiming we are currently on version 0, ensuring - // that the prepopulate data version will be newer. - int new_resource_keyword_version = 0; - GetSearchProvidersUsingLoadedEngines(service_.get(), profile_, - &entries_to_process, - &default_search_provider, - &new_resource_keyword_version, - &pre_sync_deletes_); - // Setup search engines and a default one. - base::AutoReset<DefaultSearchChangeOrigin> change_origin( - &dsp_change_origin_, DSP_CHANGE_PROFILE_RESET); - AddTemplateURLsAndSetupDefaultEngine(&entries_to_process, - default_search_provider); - - // Repopulate extension keywords. - std::vector<ExtensionKeyword> extension_keywords = - GetExtensionKeywords(profile()); - for (size_t i = 0; i < extension_keywords.size(); ++i) { - TemplateURL* extension_url = - CreateTemplateURLForExtension(extension_keywords[i]); - AddNoNotify(extension_url, true); + // Edit items. + for (EditedEngines::iterator i(actions.edited_engines.begin()); + i < actions.edited_engines.end(); ++i) { + UIThreadSearchTermsData search_terms_data(profile()); + TemplateURL new_values(profile(), i->second); + UpdateNoNotify(i->first, new_values, search_terms_data); } - if (new_resource_keyword_version) - service_->SetBuiltinKeywordVersion(new_resource_keyword_version); + // Add items. + for (std::vector<TemplateURL*>::iterator i = actions.added_engines.begin(); + i < actions.added_engines.end(); ++i) + AddNoNotify(*i, true); - EnsureDefaultSearchProviderExists(); + // Change the DSE. + TemplateURL* new_dse = FindURLByPrepopulateID(template_urls_, + default_search_engine_id); + DCHECK(new_dse); + if (CanMakeDefault(new_dse)) { + base::AutoReset<DefaultSearchChangeOrigin> change_origin( + &dsp_change_origin_, DSP_CHANGE_PROFILE_RESET); + SetDefaultSearchProviderNoNotify(new_dse); + } NotifyObservers(); } @@ -1880,10 +1874,10 @@ void TemplateURLService::UpdateTemplateURLIfPrepopulated( if (template_url->prepopulate_id() == 0) return; - ScopedVector<TemplateURL> prepopulated_urls; size_t default_search_index; - TemplateURLPrepopulateData::GetPrepopulatedEngines(profile, - &prepopulated_urls.get(), &default_search_index); + ScopedVector<TemplateURL> prepopulated_urls = + TemplateURLPrepopulateData::GetPrepopulatedEngines(profile, + &default_search_index); for (size_t i = 0; i < prepopulated_urls.size(); ++i) { if (prepopulated_urls[i]->prepopulate_id() == prepopulate_id) { diff --git a/chrome/browser/search_engines/template_url_service.h b/chrome/browser/search_engines/template_url_service.h index 019552f6..c47c85e 100644 --- a/chrome/browser/search_engines/template_url_service.h +++ b/chrome/browser/search_engines/template_url_service.h @@ -241,12 +241,16 @@ class TemplateURLService : public WebDataServiceConsumer, // destroyed at any time so should be used right after the call. TemplateURL* FindNewDefaultSearchProvider(); - // Resets the search providers to the prepopulated engines plus any keywords - // from currently-installed extensions. The user will lose all auto-added - // keywords from webpages, all edits to both normal and extension keywords, - // and any keywords belonging to no-longer-installed extensions. - // Modifications will be synced later. - void ResetURLs(); + // Performs the same actions that happen when the prepopulate data version is + // revved: all existing prepopulated entries are checked against the current + // prepopulate data, any now-extraneous safe_for_autoreplace() entries are + // removed, any existing engines are reset to the provided data (except for + // user-edited names or keywords), and any new prepopulated anegines are + // added. + // + // After this, the default search engine is reset to the default entry in the + // prepopulate data. + void RepairPrepopulatedSearchEngines(); // Observers used to listen for changes to the model. // TemplateURLService does NOT delete the observers when deleted. diff --git a/chrome/browser/search_engines/template_url_service_sync_unittest.cc b/chrome/browser/search_engines/template_url_service_sync_unittest.cc index e41aeda..c4c9cfd 100644 --- a/chrome/browser/search_engines/template_url_service_sync_unittest.cc +++ b/chrome/browser/search_engines/template_url_service_sync_unittest.cc @@ -1885,10 +1885,10 @@ TEST_F(TemplateURLServiceSyncTest, PreSyncDeletes) { TEST_F(TemplateURLServiceSyncTest, PreSyncUpdates) { const char* kNewKeyword = "somethingnew"; // Fetch the prepopulate search engines so we know what they are. - ScopedVector<TemplateURL> prepop_turls; size_t default_search_provider_index = 0; - TemplateURLPrepopulateData::GetPrepopulatedEngines( - profile_a(), &prepop_turls.get(), &default_search_provider_index); + ScopedVector<TemplateURL> prepop_turls = + TemplateURLPrepopulateData::GetPrepopulatedEngines( + profile_a(), &default_search_provider_index); // We have to prematurely exit this test if for some reason this machine does // not have any prepopulate TemplateURLs. diff --git a/chrome/browser/search_engines/template_url_service_unittest.cc b/chrome/browser/search_engines/template_url_service_unittest.cc index 41c117e..252c58e 100644 --- a/chrome/browser/search_engines/template_url_service_unittest.cc +++ b/chrome/browser/search_engines/template_url_service_unittest.cc @@ -138,54 +138,6 @@ void ExpectSimilar(const TemplateURL* expected, const TemplateURL* actual) { } // namespace -// TemplateURLServiceExtensionTest -------------------------------------------- - -class TemplateURLServiceExtensionTest : public ExtensionServiceTestBase, - public TemplateURLServiceTestUtilBase { - public: - TemplateURLServiceExtensionTest(); - virtual ~TemplateURLServiceExtensionTest(); - - // ExtensionServiceTestBase: - virtual void SetUp() OVERRIDE; - - // TemplateURLServiceTestUtilBase: - virtual TestingProfile* profile() const OVERRIDE; - - void CheckExtensionKeyword(const string16& keyword, const string16& name); - - private: - DISALLOW_COPY_AND_ASSIGN(TemplateURLServiceExtensionTest); -}; - -TemplateURLServiceExtensionTest::TemplateURLServiceExtensionTest() {} - -TemplateURLServiceExtensionTest::~TemplateURLServiceExtensionTest() {} - -void TemplateURLServiceExtensionTest::SetUp() { - ExtensionServiceTestBase::SetUp(); - ExtensionServiceInitParams params; - InitializeExtensionService(params); - TemplateURLServiceTestUtilBase::CreateTemplateUrlService(); -} - - -TestingProfile* TemplateURLServiceExtensionTest::profile() const { - return profile_.get(); -} - -void TemplateURLServiceExtensionTest::CheckExtensionKeyword( - const string16& keyword, const string16& name) { -#if !defined(OS_ANDROID) - TemplateURL* ext_url = - model()->GetTemplateURLForKeyword(keyword); - ASSERT_TRUE(ext_url); - EXPECT_EQ(keyword, ext_url->keyword()); - EXPECT_EQ(name, ext_url->short_name()); -#endif -} - - // TemplateURLServiceTest ----------------------------------------------------- class TemplateURLServiceTest : public testing::Test { @@ -338,10 +290,10 @@ TemplateURL* TemplateURLServiceTest::CreateReplaceablePreloadedTemplateURL( bool safe_for_autoreplace, size_t index_offset_from_default, string16* prepopulated_display_url) { - ScopedVector<TemplateURL> prepopulated_urls; size_t default_search_provider_index = 0; - TemplateURLPrepopulateData::GetPrepopulatedEngines(test_util_.profile(), - &prepopulated_urls.get(), &default_search_provider_index); + ScopedVector<TemplateURL> prepopulated_urls = + TemplateURLPrepopulateData::GetPrepopulatedEngines( + test_util_.profile(), &default_search_provider_index); EXPECT_LT(index_offset_from_default, prepopulated_urls.size()); size_t prepopulated_index = (default_search_provider_index + index_offset_from_default) % prepopulated_urls.size(); @@ -932,68 +884,57 @@ TEST_F(TemplateURLServiceTest, DefaultSearchProviderLoadedFromPrefs) { AssertEquals(*cloned_url, *model()->GetDefaultSearchProvider()); } -TEST_F(TemplateURLServiceExtensionTest, ResetURLs) { - VerifyLoad(); +TEST_F(TemplateURLServiceTest, RepairPrepopulatedSearchEngines) { + test_util_.VerifyLoad(); - TemplateURL* new_provider = AddKeywordWithDate( - model(), "short_name", "keyword", "http://test.com/search?t={searchTerms}", + // Edit Google search engine. + TemplateURL* google = model()->GetTemplateURLForKeyword( + ASCIIToUTF16("google.com")); + ASSERT_TRUE(google); + model()->ResetTemplateURL(google, ASCIIToUTF16("trash"), ASCIIToUTF16("xxx"), + "http://www.foo.com/s?q={searchTerms}"); + EXPECT_EQ(ASCIIToUTF16("trash"), google->short_name()); + EXPECT_EQ(ASCIIToUTF16("xxx"), google->keyword()); + + // Add third-party default search engine. + TemplateURL* user_dse = AddKeywordWithDate( + "malware", "google.com", "http://www.goo.com/s?q={searchTerms}", std::string(), std::string(), std::string(), true, "UTF-8", Time(), Time()); - model()->SetDefaultSearchProvider(new_provider); - AddKeywordWithDate( - model(), "extension1", "ext_keyword", - std::string(extensions::kExtensionScheme) + "://test1", std::string(), - std::string(), std::string(), false, "UTF-8", Time(), Time()); - AddKeywordWithDate( - model(), "extension2", "ext_keyword2", - std::string(extensions::kExtensionScheme) + "://test2", std::string(), - std::string(), std::string(), false, "UTF-8", Time(), Time()); - TemplateURL* default_provider = model()->GetDefaultSearchProvider(); - EXPECT_NE(SEARCH_ENGINE_GOOGLE, - TemplateURLPrepopulateData::GetEngineType(*default_provider)); - - DictionaryValue manifest; - manifest.SetString(extensions::manifest_keys::kVersion, "1.0.0.0"); - manifest.SetString(extensions::manifest_keys::kName, "ext1"); - manifest.SetString("app.launch.web_url", "http://www.google.com"); - manifest.SetString(extensions::manifest_keys::kOmniboxKeyword, "ext_keyword"); - std::string error; - scoped_refptr<extensions::Extension> extension = - extensions::Extension::Create( - base::FilePath(FILE_PATH_LITERAL("//nonexistent")), - extensions::Manifest::COMPONENT, - manifest, - extensions::Extension::NO_FLAGS, - &error); - EXPECT_TRUE(extension.get() != NULL) << error; - ExtensionService* extension_service = profile()->GetExtensionService(); - ASSERT_TRUE(extension_service); - extension_service->AddExtension(extension.get()); - // All URLs except |extension_keywords| should go away. Default search engine - // is Google again. - model()->ResetURLs(); - - default_provider = model()->GetDefaultSearchProvider(); - ASSERT_TRUE(default_provider); - EXPECT_EQ(SEARCH_ENGINE_GOOGLE, - TemplateURLPrepopulateData::GetEngineType(*default_provider)); - CheckExtensionKeyword(ASCIIToUTF16("ext_keyword"), ASCIIToUTF16("ext1")); - EXPECT_FALSE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("ext_keyword2"))); - EXPECT_FALSE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword"))); - - // Reload URLs. Result should be the same, as extension keywords are now - // persisted. - ResetModel(true); - default_provider = model()->GetDefaultSearchProvider(); - ASSERT_TRUE(default_provider); - EXPECT_EQ(SEARCH_ENGINE_GOOGLE, - TemplateURLPrepopulateData::GetEngineType(*default_provider)); - CheckExtensionKeyword(ASCIIToUTF16("ext_keyword"), ASCIIToUTF16("ext1")); - EXPECT_FALSE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("ext_keyword2"))); - EXPECT_FALSE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword"))); + model()->SetDefaultSearchProvider(user_dse); + EXPECT_EQ(user_dse, model()->GetDefaultSearchProvider()); + + // Remove bing. + TemplateURL* bing = model()->GetTemplateURLForKeyword( + ASCIIToUTF16("bing.com")); + ASSERT_TRUE(bing); + model()->Remove(bing); + EXPECT_FALSE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("bing.com"))); + + // Register an extension with bing keyword. + model()->RegisterExtensionKeyword("abcdefg", "extension_name", "bing.com"); + EXPECT_TRUE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("bing.com"))); + + model()->RepairPrepopulatedSearchEngines(); + + // Google is default. + ASSERT_EQ(google, model()->GetDefaultSearchProvider()); + // The keyword wasn't reverted. + EXPECT_EQ(ASCIIToUTF16("trash"), google->short_name()); + EXPECT_EQ("www.google.com", + TemplateURLService::GenerateSearchURL(google).host()); + + // Bing was repaired. + bing = model()->GetTemplateURLForKeyword(ASCIIToUTF16("bing.com")); + ASSERT_TRUE(bing); + EXPECT_FALSE(bing->IsExtensionKeyword()); + + // User search engine is preserved. + EXPECT_EQ(user_dse, model()->GetTemplateURLForHost("www.goo.com")); + EXPECT_EQ(ASCIIToUTF16("google.com"), user_dse->keyword()); } -TEST_F(TemplateURLServiceExtensionTest, ResetURLsWithManagedDefault) { +TEST_F(TemplateURLServiceTest, RepairSearchEnginesWithManagedDefault) { // Set a managed preference that establishes a default search provider. const char kName[] = "test1"; const char kKeyword[] = "test.com"; @@ -1002,12 +943,12 @@ TEST_F(TemplateURLServiceExtensionTest, ResetURLsWithManagedDefault) { const char kEncodings[] = "UTF-16;UTF-32"; const char kAlternateURL[] = "http://test.com/search#t={searchTerms}"; const char kSearchTermsReplacementKey[] = "espv"; - SetManagedDefaultSearchPreferences(true, kName, kKeyword, - kSearchURL, std::string(), - kIconURL, kEncodings, - kAlternateURL, - kSearchTermsReplacementKey); - VerifyLoad(); + test_util_.SetManagedDefaultSearchPreferences(true, kName, kKeyword, + kSearchURL, std::string(), + kIconURL, kEncodings, + kAlternateURL, + kSearchTermsReplacementKey); + test_util_.VerifyLoad(); // Verify that the default manager we are getting is the managed one. TemplateURLData data; data.short_name = ASCIIToUTF16(kName); @@ -1018,15 +959,15 @@ TEST_F(TemplateURLServiceExtensionTest, ResetURLsWithManagedDefault) { base::SplitString(kEncodings, ';', &data.input_encodings); data.alternate_urls.push_back(kAlternateURL); data.search_terms_replacement_key = kSearchTermsReplacementKey; - scoped_ptr<TemplateURL> expected_managed_default(new TemplateURL(profile(), - data)); + scoped_ptr<TemplateURL> expected_managed_default(new TemplateURL( + test_util_.profile(), data)); EXPECT_TRUE(model()->is_default_search_managed()); const TemplateURL* actual_managed_default = model()->GetDefaultSearchProvider(); ExpectSimilar(expected_managed_default.get(), actual_managed_default); // The following call has no effect on the managed search engine. - model()->ResetURLs(); + model()->RepairPrepopulatedSearchEngines(); EXPECT_TRUE(model()->is_default_search_managed()); actual_managed_default = model()->GetDefaultSearchProvider(); diff --git a/chrome/browser/search_engines/util.cc b/chrome/browser/search_engines/util.cc index 6aa478e..0ccf57f 100644 --- a/chrome/browser/search_engines/util.cc +++ b/chrome/browser/search_engines/util.cc @@ -150,6 +150,17 @@ TemplateURL* GetTemplateURLByID( return NULL; } +TemplateURL* FindURLByPrepopulateID( + const TemplateURLService::TemplateURLVector& template_urls, + int prepopulate_id) { + for (std::vector<TemplateURL*>::const_iterator i = template_urls.begin(); + i < template_urls.end(); ++i) { + if ((*i)->prepopulate_id() == prepopulate_id) + return *i; + } + return NULL; +} + void MergeIntoPrepopulatedEngineData(TemplateURLData* prepopulated_url, const TemplateURL* original_turl) { DCHECK_EQ(original_turl->prepopulate_id(), prepopulated_url->prepopulate_id); @@ -164,7 +175,10 @@ void MergeIntoPrepopulatedEngineData(TemplateURLData* prepopulated_url, prepopulated_url->last_modified = original_turl->last_modified(); } -// Merges the provided prepopulated engines with the provided existing engines. +ActionsFromPrepopulateData::ActionsFromPrepopulateData() {} + +ActionsFromPrepopulateData::~ActionsFromPrepopulateData() {} + // This is invoked when the version of the prepopulate data changes. // If |removed_keyword_guids| is not NULL, the Sync GUID of each item removed // from the DB will be added to it. Note that this function will take @@ -178,15 +192,69 @@ void MergeEnginesFromPrepopulateData( TemplateURL** default_search_provider, std::set<std::string>* removed_keyword_guids) { DCHECK(service == NULL || BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK(prepopulated_urls); DCHECK(template_urls); DCHECK(default_search_provider); + int default_prepopulated_id = + (*prepopulated_urls)[default_search_index]->prepopulate_id(); + ActionsFromPrepopulateData actions(CreateActionsFromCurrentPrepopulateData( + prepopulated_urls, *template_urls, *default_search_provider)); + + // Remove items. + for (std::vector<TemplateURL*>::iterator i = actions.removed_engines.begin(); + i < actions.removed_engines.end(); ++i) { + scoped_ptr<TemplateURL> template_url(*i); + TemplateURLService::TemplateURLVector::iterator j = + std::find(template_urls->begin(), template_urls->end(), template_url); + DCHECK(j != template_urls->end()); + DCHECK(*j != *default_search_provider); + template_urls->erase(j); + if (service) { + service->RemoveKeyword(template_url->id()); + if (removed_keyword_guids) + removed_keyword_guids->insert(template_url->sync_guid()); + } + } + + // Edit items. + for (EditedEngines::iterator i(actions.edited_engines.begin()); + i < actions.edited_engines.end(); ++i) { + TemplateURLData& data = i->second; + scoped_ptr<TemplateURL> existing_url(i->first); + if (service) + service->UpdateKeyword(data); + + // Replace the entry in |template_urls| with the updated one. + TemplateURLService::TemplateURLVector::iterator j = std::find( + template_urls->begin(), template_urls->end(), existing_url.get()); + *j = new TemplateURL(profile, data); + if (*default_search_provider == existing_url.get()) + *default_search_provider = *j; + } + + // Add items. + template_urls->insert(template_urls->end(), actions.added_engines.begin(), + actions.added_engines.end()); + + if (!*default_search_provider) { + // The user had no existing default search provider, so set the + // default to the default prepopulated engine. + *default_search_provider = FindURLByPrepopulateID(*template_urls, + default_prepopulated_id); + } +} + +ActionsFromPrepopulateData CreateActionsFromCurrentPrepopulateData( + ScopedVector<TemplateURL>* prepopulated_urls, + const TemplateURLService::TemplateURLVector& existing_urls, + const TemplateURL* default_search_provider) { // Create a map to hold all provided |template_urls| that originally came from // prepopulate data (i.e. have a non-zero prepopulate_id()). typedef std::map<int, TemplateURL*> IDMap; IDMap id_to_turl; - for (TemplateURLService::TemplateURLVector::iterator i( - template_urls->begin()); i != template_urls->end(); ++i) { + for (TemplateURLService::TemplateURLVector::const_iterator i( + existing_urls.begin()); i != existing_urls.end(); ++i) { int prepopulate_id = (*i)->prepopulate_id(); if (prepopulate_id > 0) id_to_turl[prepopulate_id] = *i; @@ -195,45 +263,30 @@ void MergeEnginesFromPrepopulateData( // For each current prepopulated URL, check whether |template_urls| contained // a matching prepopulated URL. If so, update the passed-in URL to match the // current data. (If the passed-in URL was user-edited, we persist the user's - // name and keyword.) If not, add the prepopulated URL to |template_urls|. - // Along the way, point |default_search_provider| at the default prepopulated - // URL, if the user hasn't already set another URL as default. + // name and keyword.) If not, add the prepopulated URL. + ActionsFromPrepopulateData actions; for (size_t i = 0; i < prepopulated_urls->size(); ++i) { // We take ownership of |prepopulated_urls[i]|. scoped_ptr<TemplateURL> prepopulated_url((*prepopulated_urls)[i]); const int prepopulated_id = prepopulated_url->prepopulate_id(); DCHECK_NE(0, prepopulated_id); - TemplateURL* url_in_vector = NULL; IDMap::iterator existing_url_iter(id_to_turl.find(prepopulated_id)); if (existing_url_iter != id_to_turl.end()) { - // Update the data store with the new prepopulated data. Preserve user + // Update the data store with the new prepopulated data. Preserve user // edits to the name and keyword. TemplateURLData data(prepopulated_url->data()); - scoped_ptr<TemplateURL> existing_url(existing_url_iter->second); + TemplateURL* existing_url(existing_url_iter->second); id_to_turl.erase(existing_url_iter); - MergeIntoPrepopulatedEngineData(&data, existing_url.get()); + MergeIntoPrepopulatedEngineData(&data, existing_url); // Update last_modified to ensure that if this entry is later merged with // entries from Sync, the conflict resolution logic knows that this was // updated and propagates the new values to the server. data.last_modified = base::Time::Now(); - if (service) - service->UpdateKeyword(data); - - // Replace the entry in |template_urls| with the updated one. - TemplateURLService::TemplateURLVector::iterator j = std::find( - template_urls->begin(), template_urls->end(), existing_url.get()); - *j = new TemplateURL(profile, data); - url_in_vector = *j; - if (*default_search_provider == existing_url.get()) - *default_search_provider = url_in_vector; + actions.edited_engines.push_back(std::make_pair(existing_url, data)); } else { - template_urls->push_back(prepopulated_url.release()); - url_in_vector = template_urls->back(); + actions.added_engines.push_back(prepopulated_url.release()); } - DCHECK(url_in_vector); - if (i == default_search_index && !*default_search_provider) - *default_search_provider = url_in_vector; } // The above loop takes ownership of all the contents of prepopulated_urls. // Clear the pointers. @@ -244,21 +297,13 @@ void MergeEnginesFromPrepopulateData( // found in the prepopulate data. Any remaining URLs that haven't been // user-edited or made default can be removed from the data store. for (IDMap::iterator i(id_to_turl.begin()); i != id_to_turl.end(); ++i) { - const TemplateURL* template_url = i->second; + TemplateURL* template_url = i->second; if ((template_url->safe_for_autoreplace()) && - (template_url != *default_search_provider)) { - TemplateURLService::TemplateURLVector::iterator j = - std::find(template_urls->begin(), template_urls->end(), template_url); - DCHECK(j != template_urls->end()); - template_urls->erase(j); - if (service) { - service->RemoveKeyword(template_url->id()); - if (removed_keyword_guids) - removed_keyword_guids->insert(template_url->sync_guid()); - } - delete template_url; - } + (template_url != default_search_provider)) + actions.removed_engines.push_back(template_url); } + + return actions; } void GetSearchProvidersUsingKeywordResult( @@ -321,10 +366,10 @@ void GetSearchProvidersUsingLoadedEngines( DCHECK(default_search_provider); DCHECK(resource_keyword_version); - ScopedVector<TemplateURL> prepopulated_urls; size_t default_search_index; - TemplateURLPrepopulateData::GetPrepopulatedEngines(profile, - &prepopulated_urls.get(), &default_search_index); + ScopedVector<TemplateURL> prepopulated_urls = + TemplateURLPrepopulateData::GetPrepopulatedEngines(profile, + &default_search_index); RemoveDuplicatePrepopulateIDs(service, prepopulated_urls, *default_search_provider, template_urls, removed_keyword_guids); diff --git a/chrome/browser/search_engines/util.h b/chrome/browser/search_engines/util.h index b496e2a..56553de 100644 --- a/chrome/browser/search_engines/util.h +++ b/chrome/browser/search_engines/util.h @@ -27,11 +27,55 @@ string16 GetDefaultSearchEngineName(Profile* profile); // |profile|. GURL GetDefaultSearchURLForSearchTerms(Profile* profile, const string16& terms); +// Returns matching URL from |template_urls| or NULL. +TemplateURL* FindURLByPrepopulateID( + const TemplateURLService::TemplateURLVector& template_urls, + int prepopulate_id); + // Modifies |prepopulated_url| so that it contains user-modified fields from // |original_turl|. Both URLs must have the same prepopulate_id. void MergeIntoPrepopulatedEngineData(TemplateURLData* prepopulated_url, const TemplateURL* original_turl); +// CreateActionsFromCurrentPrepopulateData() (see below) takes in the current +// prepopulated URLs as well as the user's current URLs, and returns an instance +// of the following struct representing the changes necessary to bring the +// user's URLs in line with the prepopulated URLs. +// +// There are three types of changes: +// (1) Previous prepopulated engines that no longer exist in the current set of +// prepopulated engines and thus should be removed from the user's current +// URLs. +// (2) Previous prepopulated engines whose data has changed. The existing +// entries for these engines should be updated to reflect the new data, +// except for any user-set names and keywords, which can be preserved. +// (3) New prepopulated engines not in the user's engine list, which should be +// added. + +// The pair of current search engine and its new value. +typedef std::pair<TemplateURL*, TemplateURLData> EditedSearchEngine; +typedef std::vector<EditedSearchEngine> EditedEngines; + +struct ActionsFromPrepopulateData { + ActionsFromPrepopulateData(); + ~ActionsFromPrepopulateData(); + + TemplateURLService::TemplateURLVector removed_engines; + EditedEngines edited_engines; + TemplateURLService::TemplateURLVector added_engines; +}; + +// Given the user's current URLs and the current set of prepopulated URLs, +// produces the set of actions (see above) required to make the user's URLs +// reflect the prepopulate data. |default_search_provider| is used to avoid +// placing the current default provider on the "to be removed" list. +// +// NOTE: Takes ownership of, and clears, |prepopulated_urls|. +ActionsFromPrepopulateData CreateActionsFromCurrentPrepopulateData( + ScopedVector<TemplateURL>* prepopulated_urls, + const TemplateURLService::TemplateURLVector& existing_urls, + const TemplateURL* default_search_provider); + // Processes the results of WebDataService::GetKeywords, combining it with // prepopulated search providers to result in: // * a set of template_urls (search providers). The caller owns the |