diff options
author | hashimoto@chromium.org <hashimoto@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-11 03:14:16 +0000 |
---|---|---|
committer | hashimoto@chromium.org <hashimoto@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-11 03:14:16 +0000 |
commit | 63f021880e7b818d51f0c1dfc99f47633c764644 (patch) | |
tree | 7f1ee11d854e139c0950bdef3b94bd90e02f15e7 /components/search_engines | |
parent | c8850e6df0cad15cd7c763f1cd4933f3c8d3eaef (diff) | |
download | chromium_src-63f021880e7b818d51f0c1dfc99f47633c764644.zip chromium_src-63f021880e7b818d51f0c1dfc99f47633c764644.tar.gz chromium_src-63f021880e7b818d51f0c1dfc99f47633c764644.tar.bz2 |
Componentize tests under search_engines
BUG=387985
TEST=components_unittests
Review URL: https://codereview.chromium.org/382663004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@282523 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'components/search_engines')
6 files changed, 2908 insertions, 0 deletions
diff --git a/components/search_engines/default_search_manager_unittest.cc b/components/search_engines/default_search_manager_unittest.cc new file mode 100644 index 0000000..847be02 --- /dev/null +++ b/components/search_engines/default_search_manager_unittest.cc @@ -0,0 +1,324 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/files/scoped_temp_dir.h" +#include "base/memory/scoped_ptr.h" +#include "base/strings/string_split.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" +#include "base/time/time.h" +#include "components/pref_registry/pref_registry_syncable.h" +#include "components/pref_registry/testing_pref_service_syncable.h" +#include "components/search_engines/default_search_manager.h" +#include "components/search_engines/search_engines_pref_names.h" +#include "components/search_engines/template_url_data.h" +#include "components/search_engines/template_url_prepopulate_data.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { +// A dictionary to hold all data related to the Default Search Engine. +// Eventually, this should replace all the data stored in the +// default_search_provider.* prefs. +const char kDefaultSearchProviderData[] = + "default_search_provider_data.template_url_data"; + +// Checks that the two TemplateURLs are similar. Does not check the id, the +// date_created or the last_modified time. Neither pointer should be NULL. +void ExpectSimilar(const TemplateURLData* expected, + const TemplateURLData* actual) { + ASSERT_TRUE(expected != NULL); + ASSERT_TRUE(actual != NULL); + + EXPECT_EQ(expected->short_name, actual->short_name); + EXPECT_EQ(expected->keyword(), actual->keyword()); + EXPECT_EQ(expected->url(), actual->url()); + EXPECT_EQ(expected->suggestions_url, actual->suggestions_url); + EXPECT_EQ(expected->favicon_url, actual->favicon_url); + EXPECT_EQ(expected->alternate_urls, actual->alternate_urls); + EXPECT_EQ(expected->show_in_default_list, actual->show_in_default_list); + EXPECT_EQ(expected->safe_for_autoreplace, actual->safe_for_autoreplace); + EXPECT_EQ(expected->input_encodings, actual->input_encodings); + EXPECT_EQ(expected->search_terms_replacement_key, + actual->search_terms_replacement_key); +} + +// TODO(caitkp): TemplateURLData-ify this. +void SetOverrides(user_prefs::TestingPrefServiceSyncable* prefs, bool update) { + prefs->SetUserPref(prefs::kSearchProviderOverridesVersion, + base::Value::CreateIntegerValue(1)); + base::ListValue* overrides = new base::ListValue; + scoped_ptr<base::DictionaryValue> entry(new base::DictionaryValue); + + entry->SetString("name", update ? "new_foo" : "foo"); + entry->SetString("keyword", update ? "new_fook" : "fook"); + entry->SetString("search_url", "http://foo.com/s?q={searchTerms}"); + entry->SetString("favicon_url", "http://foi.com/favicon.ico"); + entry->SetString("encoding", "UTF-8"); + entry->SetInteger("id", 1001); + entry->SetString("suggest_url", "http://foo.com/suggest?q={searchTerms}"); + entry->SetString("instant_url", "http://foo.com/instant?q={searchTerms}"); + base::ListValue* alternate_urls = new base::ListValue; + alternate_urls->AppendString("http://foo.com/alternate?q={searchTerms}"); + entry->Set("alternate_urls", alternate_urls); + entry->SetString("search_terms_replacement_key", "espv"); + overrides->Append(entry->DeepCopy()); + + entry.reset(new base::DictionaryValue); + entry->SetInteger("id", 1002); + entry->SetString("name", update ? "new_bar" : "bar"); + entry->SetString("keyword", update ? "new_bark" : "bark"); + entry->SetString("encoding", std::string()); + overrides->Append(entry->DeepCopy()); + entry->SetInteger("id", 1003); + entry->SetString("name", "baz"); + entry->SetString("keyword", "bazk"); + entry->SetString("encoding", "UTF-8"); + overrides->Append(entry->DeepCopy()); + prefs->SetUserPref(prefs::kSearchProviderOverrides, overrides); +} + +void SetPolicy(user_prefs::TestingPrefServiceSyncable* prefs, + bool enabled, + TemplateURLData* data) { + if (enabled) { + EXPECT_FALSE(data->keyword().empty()); + EXPECT_FALSE(data->url().empty()); + } + scoped_ptr<base::DictionaryValue> entry(new base::DictionaryValue); + entry->SetString(DefaultSearchManager::kShortName, data->short_name); + entry->SetString(DefaultSearchManager::kKeyword, data->keyword()); + entry->SetString(DefaultSearchManager::kURL, data->url()); + entry->SetString(DefaultSearchManager::kFaviconURL, data->favicon_url.spec()); + entry->SetString(DefaultSearchManager::kSuggestionsURL, + data->suggestions_url); + entry->SetBoolean(DefaultSearchManager::kSafeForAutoReplace, + data->safe_for_autoreplace); + scoped_ptr<base::ListValue> alternate_urls(new base::ListValue); + for (std::vector<std::string>::const_iterator it = + data->alternate_urls.begin(); + it != data->alternate_urls.end(); + ++it) { + alternate_urls->AppendString(*it); + } + entry->Set(DefaultSearchManager::kAlternateURLs, alternate_urls.release()); + + scoped_ptr<base::ListValue> encodings(new base::ListValue); + for (std::vector<std::string>::const_iterator it = + data->input_encodings.begin(); + it != data->input_encodings.end(); + ++it) { + encodings->AppendString(*it); + } + entry->Set(DefaultSearchManager::kInputEncodings, encodings.release()); + + entry->SetString(DefaultSearchManager::kSearchTermsReplacementKey, + data->search_terms_replacement_key); + entry->SetBoolean(DefaultSearchManager::kDisabledByPolicy, !enabled); + prefs->SetManagedPref(kDefaultSearchProviderData, entry.release()); +} + +scoped_ptr<TemplateURLData> GenerateDummyTemplateURLData(std::string type) { + scoped_ptr<TemplateURLData> data(new TemplateURLData()); + data->short_name = base::UTF8ToUTF16(std::string(type).append("name")); + data->SetKeyword(base::UTF8ToUTF16(std::string(type).append("key"))); + data->SetURL(std::string("http://").append(type).append("foo/{searchTerms}")); + data->suggestions_url = std::string("http://").append(type).append("sugg"); + data->alternate_urls.push_back( + std::string("http://").append(type).append("foo/alt")); + data->favicon_url = GURL("http://icon1"); + data->safe_for_autoreplace = true; + data->show_in_default_list = true; + base::SplitString("UTF-8;UTF-16", ';', &data->input_encodings); + data->date_created = base::Time(); + data->last_modified = base::Time(); + return data.Pass(); +} + +} // namespace + +class DefaultSearchManagerTest : public testing::Test { + public: + DefaultSearchManagerTest() {}; + + virtual void SetUp() OVERRIDE { + pref_service_.reset(new user_prefs::TestingPrefServiceSyncable); + DefaultSearchManager::RegisterProfilePrefs(pref_service_->registry()); + TemplateURLPrepopulateData::RegisterProfilePrefs(pref_service_->registry()); + } + + user_prefs::TestingPrefServiceSyncable* pref_service() { + return pref_service_.get(); + } + + private: + scoped_ptr<user_prefs::TestingPrefServiceSyncable> pref_service_; + + DISALLOW_COPY_AND_ASSIGN(DefaultSearchManagerTest); +}; + +// Test that a TemplateURLData object is properly written and read from Prefs. +TEST_F(DefaultSearchManagerTest, ReadAndWritePref) { + DefaultSearchManager manager(pref_service(), + DefaultSearchManager::ObserverCallback()); + TemplateURLData data; + data.short_name = base::UTF8ToUTF16("name1"); + data.SetKeyword(base::UTF8ToUTF16("key1")); + data.SetURL("http://foo1/{searchTerms}"); + data.suggestions_url = "http://sugg1"; + data.alternate_urls.push_back("http://foo1/alt"); + data.favicon_url = GURL("http://icon1"); + data.safe_for_autoreplace = true; + data.show_in_default_list = true; + base::SplitString("UTF-8;UTF-16", ';', &data.input_encodings); + data.date_created = base::Time(); + data.last_modified = base::Time(); + + manager.SetUserSelectedDefaultSearchEngine(data); + TemplateURLData* read_data = manager.GetDefaultSearchEngine(NULL); + ExpectSimilar(&data, read_data); +} + +// Test DefaultSearchmanager handles user-selected DSEs correctly. +TEST_F(DefaultSearchManagerTest, DefaultSearchSetByUserPref) { + size_t default_search_index = 0; + DefaultSearchManager manager(pref_service(), + DefaultSearchManager::ObserverCallback()); + ScopedVector<TemplateURLData> prepopulated_urls = + TemplateURLPrepopulateData::GetPrepopulatedEngines(pref_service(), + &default_search_index); + DefaultSearchManager::Source source = DefaultSearchManager::FROM_POLICY; + // If no user pref is set, we should use the pre-populated values. + ExpectSimilar(prepopulated_urls[default_search_index], + manager.GetDefaultSearchEngine(&source)); + EXPECT_EQ(DefaultSearchManager::FROM_FALLBACK, source); + + // Setting a user pref overrides the pre-populated values. + scoped_ptr<TemplateURLData> data = GenerateDummyTemplateURLData("user"); + manager.SetUserSelectedDefaultSearchEngine(*data.get()); + + ExpectSimilar(data.get(), manager.GetDefaultSearchEngine(&source)); + EXPECT_EQ(DefaultSearchManager::FROM_USER, source); + + // Updating the user pref (externally to this instance of + // DefaultSearchManager) triggers an update. + scoped_ptr<TemplateURLData> new_data = GenerateDummyTemplateURLData("user2"); + DefaultSearchManager other_manager(pref_service(), + DefaultSearchManager::ObserverCallback()); + other_manager.SetUserSelectedDefaultSearchEngine(*new_data.get()); + + ExpectSimilar(new_data.get(), manager.GetDefaultSearchEngine(&source)); + EXPECT_EQ(DefaultSearchManager::FROM_USER, source); + + // Clearing the user pref should cause the default search to revert to the + // prepopulated vlaues. + manager.ClearUserSelectedDefaultSearchEngine(); + ExpectSimilar(prepopulated_urls[default_search_index], + manager.GetDefaultSearchEngine(&source)); + EXPECT_EQ(DefaultSearchManager::FROM_FALLBACK, source); +} + +// Test that DefaultSearch manager detects changes to kSearchProviderOverrides. +TEST_F(DefaultSearchManagerTest, DefaultSearchSetByOverrides) { + SetOverrides(pref_service(), false); + size_t default_search_index = 0; + DefaultSearchManager manager(pref_service(), + DefaultSearchManager::ObserverCallback()); + ScopedVector<TemplateURLData> prepopulated_urls = + TemplateURLPrepopulateData::GetPrepopulatedEngines(pref_service(), + &default_search_index); + + DefaultSearchManager::Source source = DefaultSearchManager::FROM_POLICY; + TemplateURLData first_default(*manager.GetDefaultSearchEngine(&source)); + ExpectSimilar(prepopulated_urls[default_search_index], &first_default); + EXPECT_EQ(DefaultSearchManager::FROM_FALLBACK, source); + + // Update the overrides: + SetOverrides(pref_service(), true); + prepopulated_urls = TemplateURLPrepopulateData::GetPrepopulatedEngines( + pref_service(), &default_search_index); + + // Make sure DefaultSearchManager updated: + ExpectSimilar(prepopulated_urls[default_search_index], + manager.GetDefaultSearchEngine(&source)); + EXPECT_EQ(DefaultSearchManager::FROM_FALLBACK, source); + EXPECT_NE(manager.GetDefaultSearchEngine(NULL)->short_name, + first_default.short_name); + EXPECT_NE(manager.GetDefaultSearchEngine(NULL)->keyword(), + first_default.keyword()); +} + +// Test DefaultSearchManager handles policy-enforced DSEs correctly. +TEST_F(DefaultSearchManagerTest, DefaultSearchSetByPolicy) { + DefaultSearchManager manager(pref_service(), + DefaultSearchManager::ObserverCallback()); + scoped_ptr<TemplateURLData> data = GenerateDummyTemplateURLData("user"); + manager.SetUserSelectedDefaultSearchEngine(*data.get()); + + DefaultSearchManager::Source source = DefaultSearchManager::FROM_FALLBACK; + ExpectSimilar(data.get(), manager.GetDefaultSearchEngine(&source)); + EXPECT_EQ(DefaultSearchManager::FROM_USER, source); + + scoped_ptr<TemplateURLData> policy_data = + GenerateDummyTemplateURLData("policy"); + SetPolicy(pref_service(), true, policy_data.get()); + + ExpectSimilar(policy_data.get(), manager.GetDefaultSearchEngine(&source)); + EXPECT_EQ(DefaultSearchManager::FROM_POLICY, source); + + TemplateURLData null_policy_data; + SetPolicy(pref_service(), false, &null_policy_data); + EXPECT_EQ(NULL, manager.GetDefaultSearchEngine(&source)); + EXPECT_EQ(DefaultSearchManager::FROM_POLICY, source); + + pref_service()->RemoveManagedPref(kDefaultSearchProviderData); + ExpectSimilar(data.get(), manager.GetDefaultSearchEngine(&source)); + EXPECT_EQ(DefaultSearchManager::FROM_USER, source); +} + +// Test DefaultSearchManager handles extension-controlled DSEs correctly. +TEST_F(DefaultSearchManagerTest, DefaultSearchSetByExtension) { + DefaultSearchManager manager(pref_service(), + DefaultSearchManager::ObserverCallback()); + scoped_ptr<TemplateURLData> data = GenerateDummyTemplateURLData("user"); + manager.SetUserSelectedDefaultSearchEngine(*data); + + DefaultSearchManager::Source source = DefaultSearchManager::FROM_FALLBACK; + ExpectSimilar(data.get(), manager.GetDefaultSearchEngine(&source)); + EXPECT_EQ(DefaultSearchManager::FROM_USER, source); + + // Extension trumps prefs: + scoped_ptr<TemplateURLData> extension_data_1 = + GenerateDummyTemplateURLData("ext1"); + manager.SetExtensionControlledDefaultSearchEngine(*extension_data_1); + + ExpectSimilar(extension_data_1.get(), + manager.GetDefaultSearchEngine(&source)); + EXPECT_EQ(DefaultSearchManager::FROM_EXTENSION, source); + + // Policy trumps extension: + scoped_ptr<TemplateURLData> policy_data = + GenerateDummyTemplateURLData("policy"); + SetPolicy(pref_service(), true, policy_data.get()); + + ExpectSimilar(policy_data.get(), manager.GetDefaultSearchEngine(&source)); + EXPECT_EQ(DefaultSearchManager::FROM_POLICY, source); + pref_service()->RemoveManagedPref(kDefaultSearchProviderData); + + // Extensions trump each other: + scoped_ptr<TemplateURLData> extension_data_2 = + GenerateDummyTemplateURLData("ext2"); + scoped_ptr<TemplateURLData> extension_data_3 = + GenerateDummyTemplateURLData("ext3"); + manager.SetExtensionControlledDefaultSearchEngine(*extension_data_2); + manager.SetExtensionControlledDefaultSearchEngine(*extension_data_3); + + ExpectSimilar(extension_data_3.get(), + manager.GetDefaultSearchEngine(&source)); + EXPECT_EQ(DefaultSearchManager::FROM_EXTENSION, source); + + manager.ClearExtensionControlledDefaultSearchEngine(); + + ExpectSimilar(data.get(), manager.GetDefaultSearchEngine(&source)); + EXPECT_EQ(DefaultSearchManager::FROM_USER, source); +} diff --git a/components/search_engines/default_search_policy_handler_unittest.cc b/components/search_engines/default_search_policy_handler_unittest.cc new file mode 100644 index 0000000..a79b5a6 --- /dev/null +++ b/components/search_engines/default_search_policy_handler_unittest.cc @@ -0,0 +1,488 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/memory/scoped_ptr.h" +#include "components/policy/core/browser/configuration_policy_pref_store.h" +#include "components/policy/core/browser/configuration_policy_pref_store_test.h" +#include "components/search_engines/default_search_manager.h" +#include "components/search_engines/default_search_policy_handler.h" +#include "components/search_engines/search_engines_pref_names.h" +#include "policy/policy_constants.h" + +namespace { +// TODO(caitkp): Should we find a way to route this through DefaultSearchManager +// to avoid hardcoding this here? +const char kDefaultSearchProviderData[] = + "default_search_provider_data.template_url_data"; +} // namespace + +namespace policy { + +class DefaultSearchPolicyHandlerTest + : public ConfigurationPolicyPrefStoreTest { + public: + DefaultSearchPolicyHandlerTest() { + default_alternate_urls_.AppendString( + "http://www.google.com/#q={searchTerms}"); + default_alternate_urls_.AppendString( + "http://www.google.com/search#q={searchTerms}"); + } + + virtual void SetUp() OVERRIDE { + handler_list_.AddHandler(make_scoped_ptr<ConfigurationPolicyHandler>( + new DefaultSearchPolicyHandler)); + } + + protected: + static const char kSearchURL[]; + static const char kSuggestURL[]; + static const char kIconURL[]; + static const char kName[]; + static const char kKeyword[]; + static const char kReplacementKey[]; + static const char kImageURL[]; + static const char kImageParams[]; + static const char kNewTabURL[]; + static const char kFileSearchURL[]; + static const char kHostName[]; + + // Build a default search policy by setting search-related keys in |policy| to + // reasonable values. You can update any of the keys after calling this + // method. + void BuildDefaultSearchPolicy(PolicyMap* policy); + + base::ListValue default_alternate_urls_; +}; + +const char DefaultSearchPolicyHandlerTest::kSearchURL[] = + "http://test.com/search?t={searchTerms}"; +const char DefaultSearchPolicyHandlerTest::kSuggestURL[] = + "http://test.com/sugg?={searchTerms}"; +const char DefaultSearchPolicyHandlerTest::kIconURL[] = + "http://test.com/icon.jpg"; +const char DefaultSearchPolicyHandlerTest::kName[] = + "MyName"; +const char DefaultSearchPolicyHandlerTest::kKeyword[] = + "MyKeyword"; +const char DefaultSearchPolicyHandlerTest::kReplacementKey[] = + "espv"; +const char DefaultSearchPolicyHandlerTest::kImageURL[] = + "http://test.com/searchbyimage/upload"; +const char DefaultSearchPolicyHandlerTest::kImageParams[] = + "image_content=content,image_url=http://test.com/test.png"; +const char DefaultSearchPolicyHandlerTest::kNewTabURL[] = + "http://test.com/newtab"; +const char DefaultSearchPolicyHandlerTest::kFileSearchURL[] = + "file:///c:/path/to/search?t={searchTerms}"; +const char DefaultSearchPolicyHandlerTest::kHostName[] = "test.com"; + +void DefaultSearchPolicyHandlerTest:: + BuildDefaultSearchPolicy(PolicyMap* policy) { + base::ListValue* encodings = new base::ListValue(); + encodings->AppendString("UTF-16"); + encodings->AppendString("UTF-8"); + policy->Set(key::kDefaultSearchProviderEnabled, POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, base::Value::CreateBooleanValue(true), NULL); + policy->Set(key::kDefaultSearchProviderSearchURL, POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, base::Value::CreateStringValue(kSearchURL), + NULL); + policy->Set(key::kDefaultSearchProviderName, POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, base::Value::CreateStringValue(kName), NULL); + policy->Set(key::kDefaultSearchProviderKeyword, POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, base::Value::CreateStringValue(kKeyword), + NULL); + policy->Set(key::kDefaultSearchProviderSuggestURL, POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, base::Value::CreateStringValue(kSuggestURL), + NULL); + policy->Set(key::kDefaultSearchProviderIconURL, POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, base::Value::CreateStringValue(kIconURL), + NULL); + policy->Set(key::kDefaultSearchProviderEncodings, POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, encodings, NULL); + policy->Set(key::kDefaultSearchProviderAlternateURLs, POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, default_alternate_urls_.DeepCopy(), NULL); + policy->Set(key::kDefaultSearchProviderSearchTermsReplacementKey, + POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + base::Value::CreateStringValue(kReplacementKey), NULL); + policy->Set(key::kDefaultSearchProviderImageURL, + POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + base::Value::CreateStringValue(kImageURL), NULL); + policy->Set(key::kDefaultSearchProviderImageURLPostParams, + POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + base::Value::CreateStringValue(kImageParams), NULL); + policy->Set(key::kDefaultSearchProviderNewTabURL, + POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + base::Value::CreateStringValue(kNewTabURL), NULL); +} + +// Checks that if the policy for default search is valid, i.e. there's a +// search URL, that all the elements have been given proper defaults. +TEST_F(DefaultSearchPolicyHandlerTest, MinimallyDefined) { + PolicyMap policy; + policy.Set(key::kDefaultSearchProviderEnabled, POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, base::Value::CreateBooleanValue(true), NULL); + policy.Set(key::kDefaultSearchProviderSearchURL, POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, base::Value::CreateStringValue(kSearchURL), + NULL); + UpdateProviderPolicy(policy); + + const base::Value* value = NULL; + EXPECT_TRUE(store_->GetValue(prefs::kDefaultSearchProviderSearchURL, &value)); + EXPECT_TRUE(base::StringValue(kSearchURL).Equals(value)); + + EXPECT_TRUE(store_->GetValue(prefs::kDefaultSearchProviderName, &value)); + EXPECT_TRUE(base::StringValue(kHostName).Equals(value)); + + EXPECT_TRUE(store_->GetValue(prefs::kDefaultSearchProviderKeyword, &value)); + EXPECT_TRUE(base::StringValue(kHostName).Equals(value)); + + EXPECT_TRUE(store_->GetValue(prefs::kDefaultSearchProviderSuggestURL, + &value)); + EXPECT_TRUE(base::StringValue(std::string()).Equals(value)); + + EXPECT_TRUE(store_->GetValue(prefs::kDefaultSearchProviderIconURL, &value)); + EXPECT_TRUE(base::StringValue(std::string()).Equals(value)); + + EXPECT_TRUE(store_->GetValue(prefs::kDefaultSearchProviderEncodings, &value)); + EXPECT_TRUE(base::StringValue(std::string()).Equals(value)); + + EXPECT_TRUE(store_->GetValue(prefs::kDefaultSearchProviderInstantURL, + &value)); + EXPECT_TRUE(base::StringValue(std::string()).Equals(value)); + + EXPECT_TRUE(store_->GetValue(prefs::kDefaultSearchProviderAlternateURLs, + &value)); + EXPECT_TRUE(base::ListValue().Equals(value)); + + EXPECT_TRUE( + store_->GetValue(prefs::kDefaultSearchProviderSearchTermsReplacementKey, + &value)); + EXPECT_TRUE(base::StringValue(std::string()).Equals(value)); + + EXPECT_TRUE(store_->GetValue(prefs::kDefaultSearchProviderImageURL, &value)); + EXPECT_TRUE(base::StringValue(std::string()).Equals(value)); + + EXPECT_TRUE(store_->GetValue( + prefs::kDefaultSearchProviderSearchURLPostParams, &value)); + EXPECT_TRUE(base::StringValue(std::string()).Equals(value)); + + EXPECT_TRUE(store_->GetValue( + prefs::kDefaultSearchProviderSuggestURLPostParams, &value)); + EXPECT_TRUE(base::StringValue(std::string()).Equals(value)); + + EXPECT_TRUE(store_->GetValue( + prefs::kDefaultSearchProviderInstantURLPostParams, &value)); + EXPECT_TRUE(base::StringValue(std::string()).Equals(value)); + + EXPECT_TRUE(store_->GetValue( + prefs::kDefaultSearchProviderImageURLPostParams, &value)); + EXPECT_TRUE(base::StringValue(std::string()).Equals(value)); + + EXPECT_TRUE(store_->GetValue( + prefs::kDefaultSearchProviderNewTabURL, &value)); + EXPECT_TRUE(base::StringValue(std::string()).Equals(value)); +} + +// Checks that for a fully defined search policy, all elements have been +// read properly. +TEST_F(DefaultSearchPolicyHandlerTest, FullyDefined) { + PolicyMap policy; + BuildDefaultSearchPolicy(&policy); + UpdateProviderPolicy(policy); + + const base::Value* value = NULL; + EXPECT_TRUE(store_->GetValue(prefs::kDefaultSearchProviderSearchURL, &value)); + EXPECT_TRUE(base::StringValue(kSearchURL).Equals(value)); + + EXPECT_TRUE(store_->GetValue(prefs::kDefaultSearchProviderName, &value)); + EXPECT_TRUE(base::StringValue(kName).Equals(value)); + + EXPECT_TRUE(store_->GetValue(prefs::kDefaultSearchProviderKeyword, &value)); + EXPECT_TRUE(base::StringValue(kKeyword).Equals(value)); + + EXPECT_TRUE(store_->GetValue(prefs::kDefaultSearchProviderSuggestURL, + &value)); + EXPECT_TRUE(base::StringValue(kSuggestURL).Equals(value)); + + EXPECT_TRUE(store_->GetValue(prefs::kDefaultSearchProviderIconURL, &value)); + EXPECT_TRUE(base::StringValue(kIconURL).Equals(value)); + + EXPECT_TRUE(store_->GetValue(prefs::kDefaultSearchProviderEncodings, &value)); + EXPECT_TRUE(base::StringValue("UTF-16;UTF-8").Equals(value)); + + EXPECT_TRUE(store_->GetValue( + prefs::kDefaultSearchProviderAlternateURLs, &value)); + EXPECT_TRUE(default_alternate_urls_.Equals(value)); + + EXPECT_TRUE( + store_->GetValue(prefs::kDefaultSearchProviderSearchTermsReplacementKey, + &value)); + EXPECT_TRUE(base::StringValue(kReplacementKey).Equals(value)); + + EXPECT_TRUE(store_->GetValue(prefs::kDefaultSearchProviderImageURL, &value)); + EXPECT_TRUE(base::StringValue(std::string(kImageURL)).Equals(value)); + + EXPECT_TRUE(store_->GetValue(prefs::kDefaultSearchProviderImageURLPostParams, + &value)); + EXPECT_TRUE(base::StringValue(std::string(kImageParams)).Equals(value)); + + EXPECT_TRUE(store_->GetValue( + prefs::kDefaultSearchProviderSearchURLPostParams, &value)); + EXPECT_TRUE(base::StringValue(std::string()).Equals(value)); + + EXPECT_TRUE(store_->GetValue( + prefs::kDefaultSearchProviderSuggestURLPostParams, &value)); + EXPECT_TRUE(base::StringValue(std::string()).Equals(value)); + + EXPECT_TRUE(store_->GetValue( + prefs::kDefaultSearchProviderInstantURLPostParams, &value)); + EXPECT_TRUE(base::StringValue(std::string()).Equals(value)); +} + +// Checks that if the default search policy is missing, that no elements of the +// default search policy will be present. +TEST_F(DefaultSearchPolicyHandlerTest, MissingUrl) { + PolicyMap policy; + BuildDefaultSearchPolicy(&policy); + policy.Erase(key::kDefaultSearchProviderSearchURL); + UpdateProviderPolicy(policy); + + EXPECT_FALSE(store_->GetValue(prefs::kDefaultSearchProviderSearchURL, NULL)); + EXPECT_FALSE(store_->GetValue(prefs::kDefaultSearchProviderName, NULL)); + EXPECT_FALSE(store_->GetValue(prefs::kDefaultSearchProviderKeyword, NULL)); + EXPECT_FALSE(store_->GetValue(prefs::kDefaultSearchProviderSuggestURL, NULL)); + EXPECT_FALSE(store_->GetValue(prefs::kDefaultSearchProviderIconURL, NULL)); + EXPECT_FALSE(store_->GetValue(prefs::kDefaultSearchProviderEncodings, NULL)); + EXPECT_FALSE(store_->GetValue(prefs::kDefaultSearchProviderAlternateURLs, + NULL)); + EXPECT_FALSE(store_->GetValue( + prefs::kDefaultSearchProviderSearchTermsReplacementKey, NULL)); + EXPECT_FALSE(store_->GetValue(prefs::kDefaultSearchProviderImageURL, NULL)); + EXPECT_FALSE(store_->GetValue( + prefs::kDefaultSearchProviderImageURLPostParams, NULL)); + EXPECT_FALSE(store_->GetValue(prefs::kDefaultSearchProviderInstantURL, NULL)); + EXPECT_FALSE(store_->GetValue(prefs::kDefaultSearchProviderNewTabURL, NULL)); +} + +// Checks that if the default search policy is invalid, that no elements of the +// default search policy will be present. +TEST_F(DefaultSearchPolicyHandlerTest, Invalid) { + PolicyMap policy; + BuildDefaultSearchPolicy(&policy); + const char bad_search_url[] = "http://test.com/noSearchTerms"; + policy.Set(key::kDefaultSearchProviderSearchURL, POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, + base::Value::CreateStringValue(bad_search_url), NULL); + UpdateProviderPolicy(policy); + + EXPECT_FALSE(store_->GetValue(prefs::kDefaultSearchProviderSearchURL, NULL)); + EXPECT_FALSE(store_->GetValue(prefs::kDefaultSearchProviderName, NULL)); + EXPECT_FALSE(store_->GetValue(prefs::kDefaultSearchProviderKeyword, NULL)); + EXPECT_FALSE(store_->GetValue(prefs::kDefaultSearchProviderSuggestURL, NULL)); + EXPECT_FALSE(store_->GetValue(prefs::kDefaultSearchProviderIconURL, NULL)); + EXPECT_FALSE(store_->GetValue(prefs::kDefaultSearchProviderEncodings, NULL)); + EXPECT_FALSE(store_->GetValue(prefs::kDefaultSearchProviderAlternateURLs, + NULL)); + EXPECT_FALSE(store_->GetValue( + prefs::kDefaultSearchProviderSearchTermsReplacementKey, NULL)); + EXPECT_FALSE(store_->GetValue(prefs::kDefaultSearchProviderImageURL, NULL)); + EXPECT_FALSE(store_->GetValue( + prefs::kDefaultSearchProviderImageURLPostParams, NULL)); + EXPECT_FALSE(store_->GetValue(prefs::kDefaultSearchProviderInstantURL, NULL)); + EXPECT_FALSE(store_->GetValue(prefs::kDefaultSearchProviderNewTabURL, NULL)); +} + +// Checks that if the default search policy is invalid, that no elements of the +// default search policy will be present. +TEST_F(DefaultSearchPolicyHandlerTest, Disabled) { + PolicyMap policy; + policy.Set(key::kDefaultSearchProviderEnabled, POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, base::Value::CreateBooleanValue(false), NULL); + UpdateProviderPolicy(policy); + + const base::Value* value = NULL; + EXPECT_TRUE(store_->GetValue(prefs::kDefaultSearchProviderEnabled, &value)); + base::FundamentalValue expected_enabled(false); + EXPECT_TRUE(base::Value::Equals(&expected_enabled, value)); + EXPECT_TRUE(store_->GetValue(prefs::kDefaultSearchProviderSearchURL, &value)); + base::StringValue expected_search_url((std::string())); + EXPECT_TRUE(base::Value::Equals(&expected_search_url, value)); +} + +// Checks that for a fully defined search policy, all elements have been +// read properly into the dictionary pref. +TEST_F(DefaultSearchPolicyHandlerTest, DictionaryPref) { + PolicyMap policy; + BuildDefaultSearchPolicy(&policy); + UpdateProviderPolicy(policy); + + const base::Value* temp = NULL; + const base::DictionaryValue* dictionary; + std::string value; + const base::ListValue* list_value; + EXPECT_TRUE(store_->GetValue(kDefaultSearchProviderData, &temp)); + temp->GetAsDictionary(&dictionary); + + EXPECT_TRUE(dictionary->GetString(DefaultSearchManager::kURL, &value)); + EXPECT_EQ(kSearchURL, value); + EXPECT_TRUE(dictionary->GetString(DefaultSearchManager::kShortName, &value)); + EXPECT_EQ(kName, value); + EXPECT_TRUE(dictionary->GetString(DefaultSearchManager::kKeyword, &value)); + EXPECT_EQ(kKeyword, value); + + EXPECT_TRUE( + dictionary->GetString(DefaultSearchManager::kSuggestionsURL, &value)); + EXPECT_EQ(kSuggestURL, value); + EXPECT_TRUE(dictionary->GetString(DefaultSearchManager::kFaviconURL, &value)); + EXPECT_EQ(kIconURL, value); + + base::ListValue encodings; + encodings.AppendString("UTF-16"); + encodings.AppendString("UTF-8"); + + EXPECT_TRUE( + dictionary->GetList(DefaultSearchManager::kInputEncodings, &list_value)); + EXPECT_TRUE(encodings.Equals(list_value)); + + EXPECT_TRUE( + dictionary->GetList(DefaultSearchManager::kAlternateURLs, &list_value)); + EXPECT_TRUE(default_alternate_urls_.Equals(list_value)); + + EXPECT_TRUE(dictionary->GetString( + DefaultSearchManager::kSearchTermsReplacementKey, &value)); + EXPECT_EQ(kReplacementKey, value); + + EXPECT_TRUE(dictionary->GetString(DefaultSearchManager::kImageURL, &value)); + EXPECT_EQ(kImageURL, value); + + EXPECT_TRUE( + dictionary->GetString(DefaultSearchManager::kImageURLPostParams, &value)); + EXPECT_EQ(kImageParams, value); + + EXPECT_TRUE(dictionary->GetString(DefaultSearchManager::kSearchURLPostParams, + &value)); + EXPECT_EQ(std::string(), value); + + EXPECT_TRUE(dictionary->GetString( + DefaultSearchManager::kSuggestionsURLPostParams, &value)); + EXPECT_EQ(std::string(), value); + + EXPECT_TRUE(dictionary->GetString(DefaultSearchManager::kInstantURLPostParams, + &value)); + EXPECT_EQ(std::string(), value); +} + +// Checks that disabling default search is properly reflected the dictionary +// pref. +TEST_F(DefaultSearchPolicyHandlerTest, DictionaryPrefDSEDisabled) { + PolicyMap policy; + policy.Set(key::kDefaultSearchProviderEnabled, + POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, + base::Value::CreateBooleanValue(false), + NULL); + UpdateProviderPolicy(policy); + const base::Value* temp = NULL; + const base::DictionaryValue* dictionary; + EXPECT_TRUE(store_->GetValue(kDefaultSearchProviderData, &temp)); + temp->GetAsDictionary(&dictionary); + bool disabled = false; + EXPECT_TRUE(dictionary->GetBoolean(DefaultSearchManager::kDisabledByPolicy, + &disabled)); + EXPECT_TRUE(disabled); +} + +// Checks that if the policy for default search is valid, i.e. there's a +// search URL, that all the elements have been given proper defaults. +TEST_F(DefaultSearchPolicyHandlerTest, DictionaryPrefMinimallyDefined) { + PolicyMap policy; + policy.Set(key::kDefaultSearchProviderEnabled, + POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, + base::Value::CreateBooleanValue(true), + NULL); + policy.Set(key::kDefaultSearchProviderSearchURL, + POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, + base::Value::CreateStringValue(kSearchURL), + NULL); + UpdateProviderPolicy(policy); + + const base::Value* temp = NULL; + const base::DictionaryValue* dictionary; + std::string value; + const base::ListValue* list_value; + EXPECT_TRUE(store_->GetValue(kDefaultSearchProviderData, &temp)); + temp->GetAsDictionary(&dictionary); + + // Name and keyword should be derived from host. + EXPECT_TRUE(dictionary->GetString(DefaultSearchManager::kURL, &value)); + EXPECT_EQ(kSearchURL, value); + EXPECT_TRUE(dictionary->GetString(DefaultSearchManager::kShortName, &value)); + EXPECT_EQ(kHostName, value); + EXPECT_TRUE(dictionary->GetString(DefaultSearchManager::kKeyword, &value)); + EXPECT_EQ(kHostName, value); + + // Everything else should be set to the default value. + EXPECT_TRUE( + dictionary->GetString(DefaultSearchManager::kSuggestionsURL, &value)); + EXPECT_EQ(std::string(), value); + EXPECT_TRUE(dictionary->GetString(DefaultSearchManager::kFaviconURL, &value)); + EXPECT_EQ(std::string(), value); + EXPECT_TRUE( + dictionary->GetList(DefaultSearchManager::kInputEncodings, &list_value)); + EXPECT_TRUE(base::ListValue().Equals(list_value)); + EXPECT_TRUE( + dictionary->GetList(DefaultSearchManager::kAlternateURLs, &list_value)); + EXPECT_TRUE(base::ListValue().Equals(list_value)); + EXPECT_TRUE(dictionary->GetString( + DefaultSearchManager::kSearchTermsReplacementKey, &value)); + EXPECT_EQ(std::string(), value); + EXPECT_TRUE(dictionary->GetString(DefaultSearchManager::kImageURL, &value)); + EXPECT_EQ(std::string(), value); + EXPECT_TRUE( + dictionary->GetString(DefaultSearchManager::kImageURLPostParams, &value)); + EXPECT_EQ(std::string(), value); + EXPECT_TRUE(dictionary->GetString(DefaultSearchManager::kSearchURLPostParams, + &value)); + EXPECT_EQ(std::string(), value); + EXPECT_TRUE(dictionary->GetString( + DefaultSearchManager::kSuggestionsURLPostParams, &value)); + EXPECT_EQ(std::string(), value); + EXPECT_TRUE(dictionary->GetString(DefaultSearchManager::kInstantURLPostParams, + &value)); + EXPECT_EQ(std::string(), value); +} + +// Checks that setting a file URL as the default search is reflected properly in +// the dictionary pref. +TEST_F(DefaultSearchPolicyHandlerTest, DictionaryPrefFileURL) { + PolicyMap policy; + policy.Set(key::kDefaultSearchProviderEnabled, + POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, + base::Value::CreateBooleanValue(true), + NULL); + policy.Set(key::kDefaultSearchProviderSearchURL, + POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, + base::Value::CreateStringValue(kFileSearchURL), + NULL); + UpdateProviderPolicy(policy); + + const base::Value* temp = NULL; + const base::DictionaryValue* dictionary; + std::string value; + + EXPECT_TRUE(store_->GetValue(kDefaultSearchProviderData, &temp)); + temp->GetAsDictionary(&dictionary); + + EXPECT_TRUE(dictionary->GetString(DefaultSearchManager::kURL, &value)); + EXPECT_EQ(kFileSearchURL, value); + EXPECT_TRUE(dictionary->GetString(DefaultSearchManager::kShortName, &value)); + EXPECT_EQ("_", value); + EXPECT_TRUE(dictionary->GetString(DefaultSearchManager::kKeyword, &value)); + EXPECT_EQ("_", value); +} +} // namespace policy diff --git a/components/search_engines/search_host_to_urls_map_unittest.cc b/components/search_engines/search_host_to_urls_map_unittest.cc new file mode 100644 index 0000000..f87db78 --- /dev/null +++ b/components/search_engines/search_host_to_urls_map_unittest.cc @@ -0,0 +1,107 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "components/search_engines/search_host_to_urls_map.h" +#include "components/search_engines/search_terms_data.h" +#include "components/search_engines/template_url.h" +#include "testing/gtest/include/gtest/gtest.h" + +typedef SearchHostToURLsMap::TemplateURLSet TemplateURLSet; + +// Basic functionality for the SearchHostToURLsMap tests. +class SearchHostToURLsMapTest : public testing::Test { + public: + SearchHostToURLsMapTest() {} + + virtual void SetUp(); + + protected: + scoped_ptr<SearchHostToURLsMap> provider_map_; + scoped_ptr<TemplateURL> t_urls_[2]; + std::string host_; + + DISALLOW_COPY_AND_ASSIGN(SearchHostToURLsMapTest); +}; + +void SearchHostToURLsMapTest::SetUp() { + // Add some entries to the search host map. + host_ = "www.unittest.com"; + TemplateURLData data; + data.SetURL("http://" + host_ + "/path1"); + t_urls_[0].reset(new TemplateURL(data)); + data.SetURL("http://" + host_ + "/path2"); + t_urls_[1].reset(new TemplateURL(data)); + std::vector<TemplateURL*> template_urls; + template_urls.push_back(t_urls_[0].get()); + template_urls.push_back(t_urls_[1].get()); + + provider_map_.reset(new SearchHostToURLsMap); + provider_map_->Init(template_urls, SearchTermsData()); +} + +TEST_F(SearchHostToURLsMapTest, Add) { + std::string new_host = "example.com"; + TemplateURLData data; + data.SetURL("http://" + new_host + "/"); + TemplateURL new_t_url(data); + provider_map_->Add(&new_t_url, SearchTermsData()); + + ASSERT_EQ(&new_t_url, provider_map_->GetTemplateURLForHost(new_host)); +} + +TEST_F(SearchHostToURLsMapTest, Remove) { + provider_map_->Remove(t_urls_[0].get()); + + const TemplateURL* found_url = provider_map_->GetTemplateURLForHost(host_); + ASSERT_EQ(t_urls_[1].get(), found_url); + + const TemplateURLSet* urls = provider_map_->GetURLsForHost(host_); + ASSERT_TRUE(urls != NULL); + + int url_count = 0; + for (TemplateURLSet::const_iterator i(urls->begin()); i != urls->end(); ++i) { + url_count++; + ASSERT_EQ(t_urls_[1].get(), *i); + } + ASSERT_EQ(1, url_count); +} + +TEST_F(SearchHostToURLsMapTest, GetTemplateURLForKnownHost) { + const TemplateURL* found_url = provider_map_->GetTemplateURLForHost(host_); + ASSERT_TRUE(found_url == t_urls_[0].get() || found_url == t_urls_[1].get()); +} + +TEST_F(SearchHostToURLsMapTest, GetTemplateURLForUnknownHost) { + const TemplateURL* found_url = + provider_map_->GetTemplateURLForHost("a" + host_); + ASSERT_TRUE(found_url == NULL); +} + +TEST_F(SearchHostToURLsMapTest, GetURLsForKnownHost) { + const TemplateURLSet* urls = provider_map_->GetURLsForHost(host_); + ASSERT_TRUE(urls != NULL); + + bool found_urls[arraysize(t_urls_)] = { false }; + + for (TemplateURLSet::const_iterator i(urls->begin()); i != urls->end(); ++i) { + const TemplateURL* url = *i; + for (size_t i = 0; i < arraysize(found_urls); ++i) { + if (url == t_urls_[i].get()) { + found_urls[i] = true; + break; + } + } + } + + for (size_t i = 0; i < arraysize(found_urls); ++i) + ASSERT_TRUE(found_urls[i]); +} + +TEST_F(SearchHostToURLsMapTest, GetURLsForUnknownHost) { + const SearchHostToURLsMap::TemplateURLSet* urls = + provider_map_->GetURLsForHost("a" + host_); + ASSERT_TRUE(urls == NULL); +} diff --git a/components/search_engines/template_url_prepopulate_data_unittest.cc b/components/search_engines/template_url_prepopulate_data_unittest.cc new file mode 100644 index 0000000..b1906c3 --- /dev/null +++ b/components/search_engines/template_url_prepopulate_data_unittest.cc @@ -0,0 +1,349 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/command_line.h" +#include "base/files/scoped_temp_dir.h" +#include "base/memory/scoped_vector.h" +#include "base/strings/utf_string_conversions.h" +#include "components/google/core/browser/google_switches.h" +#include "components/pref_registry/testing_pref_service_syncable.h" +#include "components/search_engines/prepopulated_engines.h" +#include "components/search_engines/search_engines_pref_names.h" +#include "components/search_engines/search_terms_data.h" +#include "components/search_engines/template_url.h" +#include "components/search_engines/template_url_prepopulate_data.h" +#include "components/search_engines/template_url_service.h" +#include "testing/gtest/include/gtest/gtest.h" + +using base::ASCIIToUTF16; + +namespace { + +SearchEngineType GetEngineType(const std::string& url) { + TemplateURLData data; + data.SetURL(url); + return TemplateURLPrepopulateData::GetEngineType(TemplateURL(data), + SearchTermsData()); +} + +std::string GetHostFromTemplateURLData(const TemplateURLData& data) { + return TemplateURL(data).url_ref().GetHost(SearchTermsData()); +} + +} // namespace + +class TemplateURLPrepopulateDataTest : public testing::Test { + public: + virtual void SetUp() OVERRIDE { + TemplateURLPrepopulateData::RegisterProfilePrefs(prefs_.registry()); + } + + protected: + user_prefs::TestingPrefServiceSyncable prefs_; +}; + +// Verifies the set of prepopulate data doesn't contain entries with duplicate +// ids. +TEST_F(TemplateURLPrepopulateDataTest, UniqueIDs) { + const int kCountryIds[] = { + 'A'<<8|'D', 'A'<<8|'E', 'A'<<8|'F', 'A'<<8|'G', 'A'<<8|'I', + 'A'<<8|'L', 'A'<<8|'M', 'A'<<8|'N', 'A'<<8|'O', 'A'<<8|'Q', + 'A'<<8|'R', 'A'<<8|'S', 'A'<<8|'T', 'A'<<8|'U', 'A'<<8|'W', + 'A'<<8|'X', 'A'<<8|'Z', 'B'<<8|'A', 'B'<<8|'B', 'B'<<8|'D', + 'B'<<8|'E', 'B'<<8|'F', 'B'<<8|'G', 'B'<<8|'H', 'B'<<8|'I', + 'B'<<8|'J', 'B'<<8|'M', 'B'<<8|'N', 'B'<<8|'O', 'B'<<8|'R', + 'B'<<8|'S', 'B'<<8|'T', 'B'<<8|'V', 'B'<<8|'W', 'B'<<8|'Y', + 'B'<<8|'Z', 'C'<<8|'A', 'C'<<8|'C', 'C'<<8|'D', 'C'<<8|'F', + 'C'<<8|'G', 'C'<<8|'H', 'C'<<8|'I', 'C'<<8|'K', 'C'<<8|'L', + 'C'<<8|'M', 'C'<<8|'N', 'C'<<8|'O', 'C'<<8|'R', 'C'<<8|'U', + 'C'<<8|'V', 'C'<<8|'X', 'C'<<8|'Y', 'C'<<8|'Z', 'D'<<8|'E', + 'D'<<8|'J', 'D'<<8|'K', 'D'<<8|'M', 'D'<<8|'O', 'D'<<8|'Z', + 'E'<<8|'C', 'E'<<8|'E', 'E'<<8|'G', 'E'<<8|'R', 'E'<<8|'S', + 'E'<<8|'T', 'F'<<8|'I', 'F'<<8|'J', 'F'<<8|'K', 'F'<<8|'M', + 'F'<<8|'O', 'F'<<8|'R', 'G'<<8|'A', 'G'<<8|'B', 'G'<<8|'D', + 'G'<<8|'E', 'G'<<8|'F', 'G'<<8|'G', 'G'<<8|'H', 'G'<<8|'I', + 'G'<<8|'L', 'G'<<8|'M', 'G'<<8|'N', 'G'<<8|'P', 'G'<<8|'Q', + 'G'<<8|'R', 'G'<<8|'S', 'G'<<8|'T', 'G'<<8|'U', 'G'<<8|'W', + 'G'<<8|'Y', 'H'<<8|'K', 'H'<<8|'M', 'H'<<8|'N', 'H'<<8|'R', + 'H'<<8|'T', 'H'<<8|'U', 'I'<<8|'D', 'I'<<8|'E', 'I'<<8|'L', + 'I'<<8|'M', 'I'<<8|'N', 'I'<<8|'O', 'I'<<8|'P', 'I'<<8|'Q', + 'I'<<8|'R', 'I'<<8|'S', 'I'<<8|'T', 'J'<<8|'E', 'J'<<8|'M', + 'J'<<8|'O', 'J'<<8|'P', 'K'<<8|'E', 'K'<<8|'G', 'K'<<8|'H', + 'K'<<8|'I', 'K'<<8|'M', 'K'<<8|'N', 'K'<<8|'P', 'K'<<8|'R', + 'K'<<8|'W', 'K'<<8|'Y', 'K'<<8|'Z', 'L'<<8|'A', 'L'<<8|'B', + 'L'<<8|'C', 'L'<<8|'I', 'L'<<8|'K', 'L'<<8|'R', 'L'<<8|'S', + 'L'<<8|'T', 'L'<<8|'U', 'L'<<8|'V', 'L'<<8|'Y', 'M'<<8|'A', + 'M'<<8|'C', 'M'<<8|'D', 'M'<<8|'E', 'M'<<8|'G', 'M'<<8|'H', + 'M'<<8|'K', 'M'<<8|'L', 'M'<<8|'M', 'M'<<8|'N', 'M'<<8|'O', + 'M'<<8|'P', 'M'<<8|'Q', 'M'<<8|'R', 'M'<<8|'S', 'M'<<8|'T', + 'M'<<8|'U', 'M'<<8|'V', 'M'<<8|'W', 'M'<<8|'X', 'M'<<8|'Y', + 'M'<<8|'Z', 'N'<<8|'A', 'N'<<8|'C', 'N'<<8|'E', 'N'<<8|'F', + 'N'<<8|'G', 'N'<<8|'I', 'N'<<8|'L', 'N'<<8|'O', 'N'<<8|'P', + 'N'<<8|'R', 'N'<<8|'U', 'N'<<8|'Z', 'O'<<8|'M', 'P'<<8|'A', + 'P'<<8|'E', 'P'<<8|'F', 'P'<<8|'G', 'P'<<8|'H', 'P'<<8|'K', + 'P'<<8|'L', 'P'<<8|'M', 'P'<<8|'N', 'P'<<8|'R', 'P'<<8|'S', + 'P'<<8|'T', 'P'<<8|'W', 'P'<<8|'Y', 'Q'<<8|'A', 'R'<<8|'E', + 'R'<<8|'O', 'R'<<8|'S', 'R'<<8|'U', 'R'<<8|'W', 'S'<<8|'A', + 'S'<<8|'B', 'S'<<8|'C', 'S'<<8|'D', 'S'<<8|'E', 'S'<<8|'G', + 'S'<<8|'H', 'S'<<8|'I', 'S'<<8|'J', 'S'<<8|'K', 'S'<<8|'L', + 'S'<<8|'M', 'S'<<8|'N', 'S'<<8|'O', 'S'<<8|'R', 'S'<<8|'T', + 'S'<<8|'V', 'S'<<8|'Y', 'S'<<8|'Z', 'T'<<8|'C', 'T'<<8|'D', + 'T'<<8|'F', 'T'<<8|'G', 'T'<<8|'H', 'T'<<8|'J', 'T'<<8|'K', + 'T'<<8|'L', 'T'<<8|'M', 'T'<<8|'N', 'T'<<8|'O', 'T'<<8|'R', + 'T'<<8|'T', 'T'<<8|'V', 'T'<<8|'W', 'T'<<8|'Z', 'U'<<8|'A', + 'U'<<8|'G', 'U'<<8|'M', 'U'<<8|'S', 'U'<<8|'Y', 'U'<<8|'Z', + 'V'<<8|'A', 'V'<<8|'C', 'V'<<8|'E', 'V'<<8|'G', 'V'<<8|'I', + 'V'<<8|'N', 'V'<<8|'U', 'W'<<8|'F', 'W'<<8|'S', 'Y'<<8|'E', + 'Y'<<8|'T', 'Z'<<8|'A', 'Z'<<8|'M', 'Z'<<8|'W', -1 }; + + for (size_t i = 0; i < arraysize(kCountryIds); ++i) { + prefs_.SetInteger(prefs::kCountryIDAtInstall, kCountryIds[i]); + size_t default_index; + ScopedVector<TemplateURLData> urls = + TemplateURLPrepopulateData::GetPrepopulatedEngines(&prefs_, + &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) == + unique_ids.end()); + unique_ids.insert(urls[turl_i]->prepopulate_id); + } + } +} + +// Verifies that default search providers from the preferences file +// override the built-in ones. +TEST_F(TemplateURLPrepopulateDataTest, ProvidersFromPrefs) { + prefs_.SetUserPref(prefs::kSearchProviderOverridesVersion, + base::Value::CreateIntegerValue(1)); + base::ListValue* overrides = new base::ListValue; + scoped_ptr<base::DictionaryValue> entry(new base::DictionaryValue); + // Set only the minimal required settings for a search provider configuration. + entry->SetString("name", "foo"); + entry->SetString("keyword", "fook"); + entry->SetString("search_url", "http://foo.com/s?q={searchTerms}"); + entry->SetString("favicon_url", "http://foi.com/favicon.ico"); + entry->SetString("encoding", "UTF-8"); + entry->SetInteger("id", 1001); + overrides->Append(entry->DeepCopy()); + prefs_.SetUserPref(prefs::kSearchProviderOverrides, overrides); + + int version = TemplateURLPrepopulateData::GetDataVersion(&prefs_); + EXPECT_EQ(1, version); + + size_t default_index; + ScopedVector<TemplateURLData> t_urls = + TemplateURLPrepopulateData::GetPrepopulatedEngines(&prefs_, + &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()); + EXPECT_EQ("foo.com", GetHostFromTemplateURLData(*t_urls[0])); + EXPECT_EQ("foi.com", t_urls[0]->favicon_url.host()); + EXPECT_EQ(1u, t_urls[0]->input_encodings.size()); + EXPECT_EQ(1001, t_urls[0]->prepopulate_id); + EXPECT_TRUE(t_urls[0]->suggestions_url.empty()); + EXPECT_TRUE(t_urls[0]->instant_url.empty()); + EXPECT_EQ(0u, t_urls[0]->alternate_urls.size()); + EXPECT_TRUE(t_urls[0]->search_terms_replacement_key.empty()); + + // Test the optional settings too. + entry->SetString("suggest_url", "http://foo.com/suggest?q={searchTerms}"); + entry->SetString("instant_url", "http://foo.com/instant?q={searchTerms}"); + base::ListValue* alternate_urls = new base::ListValue; + alternate_urls->AppendString("http://foo.com/alternate?q={searchTerms}"); + entry->Set("alternate_urls", alternate_urls); + entry->SetString("search_terms_replacement_key", "espv"); + overrides = new base::ListValue; + overrides->Append(entry->DeepCopy()); + prefs_.SetUserPref(prefs::kSearchProviderOverrides, overrides); + + t_urls = TemplateURLPrepopulateData::GetPrepopulatedEngines( + &prefs_, &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()); + EXPECT_EQ("foo.com", GetHostFromTemplateURLData(*t_urls[0])); + EXPECT_EQ("foi.com", t_urls[0]->favicon_url.host()); + EXPECT_EQ(1u, t_urls[0]->input_encodings.size()); + EXPECT_EQ(1001, t_urls[0]->prepopulate_id); + EXPECT_EQ("http://foo.com/suggest?q={searchTerms}", + t_urls[0]->suggestions_url); + EXPECT_EQ("http://foo.com/instant?q={searchTerms}", + t_urls[0]->instant_url); + ASSERT_EQ(1u, t_urls[0]->alternate_urls.size()); + EXPECT_EQ("http://foo.com/alternate?q={searchTerms}", + t_urls[0]->alternate_urls[0]); + EXPECT_EQ("espv", t_urls[0]->search_terms_replacement_key); + + // Test that subsequent providers are loaded even if an intermediate + // provider has an incomplete configuration. + overrides = new base::ListValue; + overrides->Append(entry->DeepCopy()); + entry->SetInteger("id", 1002); + entry->SetString("name", "bar"); + entry->SetString("keyword", "bark"); + entry->SetString("encoding", std::string()); + overrides->Append(entry->DeepCopy()); + entry->SetInteger("id", 1003); + entry->SetString("name", "baz"); + entry->SetString("keyword", "bazk"); + entry->SetString("encoding", "UTF-8"); + overrides->Append(entry->DeepCopy()); + prefs_.SetUserPref(prefs::kSearchProviderOverrides, overrides); + + t_urls = + TemplateURLPrepopulateData::GetPrepopulatedEngines(&prefs_, + &default_index); + EXPECT_EQ(2u, t_urls.size()); +} + +TEST_F(TemplateURLPrepopulateDataTest, ClearProvidersFromPrefs) { + prefs_.SetUserPref(prefs::kSearchProviderOverridesVersion, + base::Value::CreateIntegerValue(1)); + base::ListValue* overrides = new base::ListValue; + base::DictionaryValue* entry(new base::DictionaryValue); + // Set only the minimal required settings for a search provider configuration. + entry->SetString("name", "foo"); + entry->SetString("keyword", "fook"); + entry->SetString("search_url", "http://foo.com/s?q={searchTerms}"); + entry->SetString("favicon_url", "http://foi.com/favicon.ico"); + entry->SetString("encoding", "UTF-8"); + entry->SetInteger("id", 1001); + overrides->Append(entry); + prefs_.SetUserPref(prefs::kSearchProviderOverrides, overrides); + + int version = TemplateURLPrepopulateData::GetDataVersion(&prefs_); + EXPECT_EQ(1, version); + + // This call removes the above search engine. + TemplateURLPrepopulateData::ClearPrepopulatedEnginesInPrefs(&prefs_); + + version = TemplateURLPrepopulateData::GetDataVersion(&prefs_); + EXPECT_EQ(TemplateURLPrepopulateData::kCurrentDataVersion, version); + + size_t default_index; + ScopedVector<TemplateURLData> t_urls = + TemplateURLPrepopulateData::GetPrepopulatedEngines(&prefs_, + &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); + EXPECT_NE(ASCIIToUTF16("fook"), t_urls[i]->keyword()); + EXPECT_NE("foi.com", t_urls[i]->favicon_url.host()); + EXPECT_NE("foo.com", GetHostFromTemplateURLData(*t_urls[i])); + EXPECT_NE(1001, t_urls[i]->prepopulate_id); + } + // Ensures the default URL is Google and has the optional fields filled. + EXPECT_EQ(ASCIIToUTF16("Google"), t_urls[default_index]->short_name); + EXPECT_FALSE(t_urls[default_index]->suggestions_url.empty()); + EXPECT_FALSE(t_urls[default_index]->instant_url.empty()); + EXPECT_FALSE(t_urls[default_index]->image_url.empty()); + EXPECT_FALSE(t_urls[default_index]->new_tab_url.empty()); + EXPECT_FALSE(t_urls[default_index]->contextual_search_url.empty()); + EXPECT_FALSE(t_urls[default_index]->image_url_post_params.empty()); + EXPECT_EQ(SEARCH_ENGINE_GOOGLE, + TemplateURLPrepopulateData::GetEngineType( + TemplateURL(*t_urls[default_index]), + SearchTermsData())); +} + +// Verifies that built-in search providers are processed correctly. +TEST_F(TemplateURLPrepopulateDataTest, ProvidersFromPrepopulated) { + // Use United States. + prefs_.SetInteger(prefs::kCountryIDAtInstall, 'U'<<8|'S'); + size_t default_index; + ScopedVector<TemplateURLData> t_urls = + TemplateURLPrepopulateData::GetPrepopulatedEngines(&prefs_, + &default_index); + + // Ensure all the URLs have the required fields populated. + ASSERT_FALSE(t_urls.empty()); + for (size_t i = 0; i < t_urls.size(); ++i) { + ASSERT_FALSE(t_urls[i]->short_name.empty()); + ASSERT_FALSE(t_urls[i]->keyword().empty()); + ASSERT_FALSE(t_urls[i]->favicon_url.host().empty()); + ASSERT_FALSE(GetHostFromTemplateURLData(*t_urls[i]).empty()); + ASSERT_FALSE(t_urls[i]->input_encodings.empty()); + EXPECT_GT(t_urls[i]->prepopulate_id, 0); + } + + // Ensures the default URL is Google and has the optional fields filled. + EXPECT_EQ(ASCIIToUTF16("Google"), t_urls[default_index]->short_name); + EXPECT_FALSE(t_urls[default_index]->suggestions_url.empty()); + EXPECT_FALSE(t_urls[default_index]->instant_url.empty()); + EXPECT_FALSE(t_urls[default_index]->image_url.empty()); + EXPECT_FALSE(t_urls[default_index]->new_tab_url.empty()); + EXPECT_FALSE(t_urls[default_index]->contextual_search_url.empty()); + EXPECT_FALSE(t_urls[default_index]->image_url_post_params.empty()); + // Expect at least 2 alternate_urls. + // This caught a bug with static initialization of arrays, so leave this in. + EXPECT_GT(t_urls[default_index]->alternate_urls.size(), 1u); + for (size_t i = 0; i < t_urls[default_index]->alternate_urls.size(); ++i) + EXPECT_FALSE(t_urls[default_index]->alternate_urls[i].empty()); + EXPECT_EQ(SEARCH_ENGINE_GOOGLE, + TemplateURLPrepopulateData::GetEngineType( + TemplateURL(*t_urls[default_index]), + SearchTermsData())); + EXPECT_FALSE(t_urls[default_index]->search_terms_replacement_key.empty()); +} + +TEST_F(TemplateURLPrepopulateDataTest, GetEngineTypeBasic) { + EXPECT_EQ(SEARCH_ENGINE_OTHER, GetEngineType("http://example.com/")); + EXPECT_EQ(SEARCH_ENGINE_ASK, GetEngineType("http://www.ask.com/")); + EXPECT_EQ(SEARCH_ENGINE_OTHER, GetEngineType("http://search.atlas.cz/")); + EXPECT_EQ(SEARCH_ENGINE_GOOGLE, GetEngineType("http://www.google.com/")); +} + +TEST_F(TemplateURLPrepopulateDataTest, GetEngineTypeAdvanced) { + // Google URLs in different forms. + const char* kGoogleURLs[] = { + // Original with google:baseURL: + "{google:baseURL}search?q={searchTerms}&{google:RLZ}" + "{google:originalQueryForSuggestion}{google:searchFieldtrialParameter}" + "sourceid=chrome&ie={inputEncoding}", + // Custom with google.com and reordered query params: + "http://google.com/search?{google:RLZ}{google:originalQueryForSuggestion}" + "{google:searchFieldtrialParameter}" + "sourceid=chrome&ie={inputEncoding}&q={searchTerms}", + // Custom with a country TLD and almost no query params: + "http://www.google.ru/search?q={searchTerms}" + }; + for (size_t i = 0; i < arraysize(kGoogleURLs); ++i) { + EXPECT_EQ(SEARCH_ENGINE_GOOGLE, GetEngineType(kGoogleURLs[i])); + } + + // Non-Google URLs. + const char* kYahooURLs[] = { + "http://search.yahoo.com/search?" + "ei={inputEncoding}&fr=crmas&p={searchTerms}", + "http://search.yahoo.com/search?p={searchTerms}", + // Aggressively match types by checking just TLD+1. + "http://someothersite.yahoo.com/", + }; + for (size_t i = 0; i < arraysize(kYahooURLs); ++i) { + EXPECT_EQ(SEARCH_ENGINE_YAHOO, GetEngineType(kYahooURLs[i])); + } + + // URLs for engines not present in country-specific lists. + EXPECT_EQ(SEARCH_ENGINE_NIGMA, + GetEngineType("http://nigma.ru/?s={searchTerms}&arg1=value1")); + // Also test matching against alternate URLs (and TLD+1 matching). + EXPECT_EQ(SEARCH_ENGINE_SOFTONIC, + GetEngineType("http://test.softonic.com.br/?{searchTerms}")); + + // Search URL for which no prepopulated search provider exists. + EXPECT_EQ(SEARCH_ENGINE_OTHER, + GetEngineType("http://example.net/search?q={searchTerms}")); + EXPECT_EQ(SEARCH_ENGINE_OTHER, GetEngineType("invalid:search:url")); + + // URL that doesn't look Google-related, but matches a Google base URL + // specified on the command line. + const std::string foo_url("http://www.foo.com/search?q={searchTerms}"); + EXPECT_EQ(SEARCH_ENGINE_OTHER, GetEngineType(foo_url)); + CommandLine::ForCurrentProcess()->AppendSwitchASCII(switches::kGoogleBaseURL, + "http://www.foo.com/"); + EXPECT_EQ(SEARCH_ENGINE_GOOGLE, GetEngineType(foo_url)); +} diff --git a/components/search_engines/template_url_service_util_unittest.cc b/components/search_engines/template_url_service_util_unittest.cc new file mode 100644 index 0000000..65b992a --- /dev/null +++ b/components/search_engines/template_url_service_util_unittest.cc @@ -0,0 +1,101 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/memory/scoped_vector.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" +#include "components/search_engines/search_terms_data.h" +#include "components/search_engines/template_url.h" +#include "components/search_engines/template_url_service.h" +#include "components/search_engines/util.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +scoped_ptr<TemplateURLData> CreatePrepopulateTemplateURLData( + int prepopulate_id, + const std::string& keyword, + TemplateURLID id) { + scoped_ptr<TemplateURLData> data(new TemplateURLData); + data->prepopulate_id = prepopulate_id; + data->SetKeyword(base::ASCIIToUTF16(keyword)); + data->id = id; + return data.Pass(); +} + +// Creates a TemplateURL with default values except for the prepopulate ID, +// keyword and TemplateURLID. Only use this in tests if your tests do not +// care about other fields. +scoped_ptr<TemplateURL> CreatePrepopulateTemplateURL(int prepopulate_id, + const std::string& keyword, + TemplateURLID id) { + return make_scoped_ptr(new TemplateURL( + *CreatePrepopulateTemplateURLData(prepopulate_id, keyword, id))); +} + +}; // namespace + +TEST(TemplateURLServiceUtilTest, RemoveDuplicatePrepopulateIDs) { + ScopedVector<TemplateURLData> prepopulated_turls; + TemplateURLService::TemplateURLVector local_turls; + STLElementDeleter<TemplateURLService::TemplateURLVector> local_turls_deleter( + &local_turls); + + prepopulated_turls.push_back( + CreatePrepopulateTemplateURLData(1, "winner4", 1).release()); + prepopulated_turls.push_back( + CreatePrepopulateTemplateURLData(2, "xxx", 2).release()); + prepopulated_turls.push_back( + CreatePrepopulateTemplateURLData(3, "yyy", 3).release()); + + // Create a sets of different TURLs grouped by prepopulate ID. Each group + // will test a different heuristic of RemoveDuplicatePrepopulateIDs. + // Ignored set - These should be left alone as they do not have valid + // prepopulate IDs. + local_turls.push_back( + CreatePrepopulateTemplateURL(0, "winner1", 4).release()); + local_turls.push_back( + CreatePrepopulateTemplateURL(0, "winner2", 5).release()); + local_turls.push_back( + CreatePrepopulateTemplateURL(0, "winner3", 6).release()); + size_t num_non_prepopulated_urls = local_turls.size(); + + // Keyword match set - Prefer the one that matches the keyword of the + // prepopulate ID. + local_turls.push_back(CreatePrepopulateTemplateURL(1, "loser1", 7).release()); + local_turls.push_back(CreatePrepopulateTemplateURL(1, "loser2", 8).release()); + local_turls.push_back( + CreatePrepopulateTemplateURL(1, "winner4", 9).release()); + + // Default set - Prefer the default search engine over all other criteria. + // The last one is the default. It will be passed as the + // default_search_provider parameter to RemoveDuplicatePrepopulateIDs. + local_turls.push_back( + CreatePrepopulateTemplateURL(2, "loser3", 10).release()); + local_turls.push_back(CreatePrepopulateTemplateURL(2, "xxx", 11).release()); + TemplateURL* default_turl = + CreatePrepopulateTemplateURL(2, "winner5", 12).release(); + local_turls.push_back(default_turl); + + // ID set - Prefer the lowest TemplateURLID if the keywords don't match and if + // none are the default. + local_turls.push_back( + CreatePrepopulateTemplateURL(3, "winner6", 13).release()); + local_turls.push_back( + CreatePrepopulateTemplateURL(3, "loser5", 14).release()); + local_turls.push_back( + CreatePrepopulateTemplateURL(3, "loser6", 15).release()); + + RemoveDuplicatePrepopulateIDs(NULL, prepopulated_turls, default_turl, + &local_turls, SearchTermsData(), NULL); + + // Verify that the expected local TURLs survived the process. + EXPECT_EQ(local_turls.size(), + prepopulated_turls.size() + num_non_prepopulated_urls); + for (TemplateURLService::TemplateURLVector::const_iterator itr = + local_turls.begin(); itr != local_turls.end(); ++itr) { + EXPECT_TRUE( + StartsWith((*itr)->keyword(), base::ASCIIToUTF16("winner"), true)); + } +} diff --git a/components/search_engines/template_url_unittest.cc b/components/search_engines/template_url_unittest.cc new file mode 100644 index 0000000..f591afc --- /dev/null +++ b/components/search_engines/template_url_unittest.cc @@ -0,0 +1,1539 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/base_paths.h" +#include "base/command_line.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" +#include "components/metrics/proto/omnibox_event.pb.h" +#include "components/metrics/proto/omnibox_input_type.pb.h" +#include "components/search_engines/search_engines_switches.h" +#include "components/search_engines/search_terms_data.h" +#include "components/search_engines/template_url.h" +#include "testing/gtest/include/gtest/gtest.h" + +using base::ASCIIToUTF16; + +// TestSearchTermsData -------------------------------------------------------- + +// Simple implementation of SearchTermsData. +class TestSearchTermsData : public SearchTermsData { + public: + explicit TestSearchTermsData(const std::string& google_base_url); + + virtual std::string GoogleBaseURLValue() const OVERRIDE; + virtual base::string16 GetRlzParameterValue( + bool from_app_list) const OVERRIDE; + virtual std::string GetSearchClient() const OVERRIDE; + virtual std::string GoogleImageSearchSource() const OVERRIDE; + virtual bool EnableAnswersInSuggest() const OVERRIDE; + virtual bool IsShowingSearchTermsOnSearchResultsPages() const OVERRIDE; + + void set_google_base_url(const std::string& google_base_url) { + google_base_url_ = google_base_url; + } + void set_search_client(const std::string& search_client) { + search_client_ = search_client; + } + void set_enable_answers_in_suggest(bool enable_answers_in_suggest) { + enable_answers_in_suggest_ = enable_answers_in_suggest; + } + void set_is_showing_search_terms_on_search_results_pages(bool value) { + is_showing_search_terms_on_search_results_pages_ = value; + } + + private: + std::string google_base_url_; + std::string search_client_; + bool enable_answers_in_suggest_; + bool is_showing_search_terms_on_search_results_pages_; + + DISALLOW_COPY_AND_ASSIGN(TestSearchTermsData); +}; + +TestSearchTermsData::TestSearchTermsData(const std::string& google_base_url) + : google_base_url_(google_base_url), + enable_answers_in_suggest_(false), + is_showing_search_terms_on_search_results_pages_(false) { +} + +std::string TestSearchTermsData::GoogleBaseURLValue() const { + return google_base_url_; +} + +base::string16 TestSearchTermsData::GetRlzParameterValue( + bool from_app_list) const { + return ASCIIToUTF16( + from_app_list ? "rlz_parameter_from_app_list" : "rlz_parameter"); +} + +std::string TestSearchTermsData::GetSearchClient() const { + return search_client_; +} + +std::string TestSearchTermsData::GoogleImageSearchSource() const { + return "google_image_search_source"; +} + +bool TestSearchTermsData::EnableAnswersInSuggest() const { + return enable_answers_in_suggest_; +} + +bool TestSearchTermsData::IsShowingSearchTermsOnSearchResultsPages() const { + return is_showing_search_terms_on_search_results_pages_; +} + +// TemplateURLTest ------------------------------------------------------------ + +class TemplateURLTest : public testing::Test { + public: + TemplateURLTest() : search_terms_data_("http://www.google.com/") {} + void CheckSuggestBaseURL(const std::string& base_url, + const std::string& base_suggest_url) const; + + TestSearchTermsData search_terms_data_; +}; + +void TemplateURLTest::CheckSuggestBaseURL( + const std::string& base_url, + const std::string& base_suggest_url) const { + TestSearchTermsData search_terms_data(base_url); + EXPECT_EQ(base_suggest_url, search_terms_data.GoogleBaseSuggestURLValue()); +} + + +// Actual tests --------------------------------------------------------------- + +TEST_F(TemplateURLTest, Defaults) { + TemplateURLData data; + EXPECT_FALSE(data.show_in_default_list); + EXPECT_FALSE(data.safe_for_autoreplace); + EXPECT_EQ(0, data.prepopulate_id); +} + +TEST_F(TemplateURLTest, TestValidWithComplete) { + TemplateURLData data; + data.SetURL("{searchTerms}"); + TemplateURL url(data); + EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_)); +} + +TEST_F(TemplateURLTest, URLRefTestSearchTerms) { + struct SearchTermsCase { + const char* url; + const base::string16 terms; + const std::string output; + } search_term_cases[] = { + { "http://foo{searchTerms}", ASCIIToUTF16("sea rch/bar"), + "http://foosea%20rch/bar" }, + { "http://foo{searchTerms}?boo=abc", ASCIIToUTF16("sea rch/bar"), + "http://foosea%20rch/bar?boo=abc" }, + { "http://foo/?boo={searchTerms}", ASCIIToUTF16("sea rch/bar"), + "http://foo/?boo=sea+rch%2Fbar" }, + { "http://en.wikipedia.org/{searchTerms}", ASCIIToUTF16("wiki/?"), + "http://en.wikipedia.org/wiki/%3F" } + }; + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(search_term_cases); ++i) { + const SearchTermsCase& value = search_term_cases[i]; + TemplateURLData data; + data.SetURL(value.url); + TemplateURL url(data); + EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_)); + ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_)); + GURL result(url.url_ref().ReplaceSearchTerms( + TemplateURLRef::SearchTermsArgs(value.terms), search_terms_data_)); + ASSERT_TRUE(result.is_valid()); + EXPECT_EQ(value.output, result.spec()); + } +} + +TEST_F(TemplateURLTest, URLRefTestCount) { + TemplateURLData data; + data.SetURL("http://foo{searchTerms}{count?}"); + TemplateURL url(data); + EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_)); + ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_)); + GURL result(url.url_ref().ReplaceSearchTerms( + TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("X")), search_terms_data_)); + ASSERT_TRUE(result.is_valid()); + EXPECT_EQ("http://foox/", result.spec()); +} + +TEST_F(TemplateURLTest, URLRefTestCount2) { + TemplateURLData data; + data.SetURL("http://foo{searchTerms}{count}"); + TemplateURL url(data); + EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_)); + ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_)); + GURL result(url.url_ref().ReplaceSearchTerms( + TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("X")), search_terms_data_)); + ASSERT_TRUE(result.is_valid()); + EXPECT_EQ("http://foox10/", result.spec()); +} + +TEST_F(TemplateURLTest, URLRefTestIndices) { + TemplateURLData data; + data.SetURL("http://foo{searchTerms}x{startIndex?}y{startPage?}"); + TemplateURL url(data); + EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_)); + ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_)); + GURL result(url.url_ref().ReplaceSearchTerms( + TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("X")), search_terms_data_)); + ASSERT_TRUE(result.is_valid()); + EXPECT_EQ("http://fooxxy/", result.spec()); +} + +TEST_F(TemplateURLTest, URLRefTestIndices2) { + TemplateURLData data; + data.SetURL("http://foo{searchTerms}x{startIndex}y{startPage}"); + TemplateURL url(data); + EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_)); + ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_)); + GURL result(url.url_ref().ReplaceSearchTerms( + TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("X")), search_terms_data_)); + ASSERT_TRUE(result.is_valid()); + EXPECT_EQ("http://fooxx1y1/", result.spec()); +} + +TEST_F(TemplateURLTest, URLRefTestEncoding) { + TemplateURLData data; + data.SetURL("http://foo{searchTerms}x{inputEncoding?}y{outputEncoding?}a"); + TemplateURL url(data); + EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_)); + ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_)); + GURL result(url.url_ref().ReplaceSearchTerms( + TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("X")), search_terms_data_)); + ASSERT_TRUE(result.is_valid()); + EXPECT_EQ("http://fooxxutf-8ya/", result.spec()); +} + +TEST_F(TemplateURLTest, URLRefTestImageURLWithPOST) { + const char kInvalidPostParamsString[] = + "unknown_template={UnknownTemplate},bad_value=bad{value}," + "{google:sbiSource}"; + // List all accpectable parameter format in valid_post_params_string. it is + // expected like: "name0=,name1=value1,name2={template1}" + const char kValidPostParamsString[] = + "image_content={google:imageThumbnail},image_url={google:imageURL}," + "sbisrc={google:imageSearchSource},language={language},empty_param=," + "constant_param=constant,width={google:imageOriginalWidth}"; + const char KImageSearchURL[] = "http://foo.com/sbi"; + + TemplateURLData data; + data.image_url = KImageSearchURL; + + // Try to parse invalid post parameters. + data.image_url_post_params = kInvalidPostParamsString; + TemplateURL url_bad(data); + ASSERT_FALSE(url_bad.image_url_ref().IsValid(search_terms_data_)); + const TemplateURLRef::PostParams& bad_post_params = + url_bad.image_url_ref().post_params_; + ASSERT_EQ(2U, bad_post_params.size()); + EXPECT_EQ("unknown_template", bad_post_params[0].first); + EXPECT_EQ("{UnknownTemplate}", bad_post_params[0].second); + EXPECT_EQ("bad_value", bad_post_params[1].first); + EXPECT_EQ("bad{value}", bad_post_params[1].second); + + // Try to parse valid post parameters. + data.image_url_post_params = kValidPostParamsString; + TemplateURL url(data); + ASSERT_TRUE(url.image_url_ref().IsValid(search_terms_data_)); + ASSERT_FALSE(url.image_url_ref().SupportsReplacement(search_terms_data_)); + + // Check term replacement. + TemplateURLRef::SearchTermsArgs search_args(ASCIIToUTF16("X")); + search_args.image_thumbnail_content = "dummy-image-thumbnail"; + search_args.image_url = GURL("http://dummyimage.com/dummy.jpg"); + search_args.image_original_size = gfx::Size(10, 10); + // Replacement operation with no post_data buffer should still return + // the parsed URL. + TestSearchTermsData search_terms_data("http://X"); + GURL result(url.image_url_ref().ReplaceSearchTerms( + search_args, search_terms_data)); + ASSERT_TRUE(result.is_valid()); + EXPECT_EQ(KImageSearchURL, result.spec()); + TemplateURLRef::PostContent post_content; + result = GURL(url.image_url_ref().ReplaceSearchTerms( + search_args, search_terms_data, &post_content)); + ASSERT_TRUE(result.is_valid()); + EXPECT_EQ(KImageSearchURL, result.spec()); + ASSERT_FALSE(post_content.first.empty()); + ASSERT_FALSE(post_content.second.empty()); + + // Check parsed result of post parameters. + const TemplateURLRef::Replacements& replacements = + url.image_url_ref().replacements_; + const TemplateURLRef::PostParams& post_params = + url.image_url_ref().post_params_; + EXPECT_EQ(7U, post_params.size()); + for (TemplateURLRef::PostParams::const_iterator i = post_params.begin(); + i != post_params.end(); ++i) { + TemplateURLRef::Replacements::const_iterator j = replacements.begin(); + for (; j != replacements.end(); ++j) { + if (j->is_post_param && j->index == + static_cast<size_t>(i - post_params.begin())) { + switch (j->type) { + case TemplateURLRef::GOOGLE_IMAGE_ORIGINAL_WIDTH: + EXPECT_EQ("width", i->first); + EXPECT_EQ( + base::IntToString(search_args.image_original_size.width()), + i->second); + break; + case TemplateURLRef::GOOGLE_IMAGE_SEARCH_SOURCE: + EXPECT_EQ("sbisrc", i->first); + EXPECT_EQ(search_terms_data.GoogleImageSearchSource(), i->second); + break; + case TemplateURLRef::GOOGLE_IMAGE_THUMBNAIL: + EXPECT_EQ("image_content", i->first); + EXPECT_EQ(search_args.image_thumbnail_content, i->second); + break; + case TemplateURLRef::GOOGLE_IMAGE_URL: + EXPECT_EQ("image_url", i->first); + EXPECT_EQ(search_args.image_url.spec(), i->second); + break; + case TemplateURLRef::LANGUAGE: + EXPECT_EQ("language", i->first); + EXPECT_EQ("en", i->second); + break; + default: + ADD_FAILURE(); // Should never go here. + } + break; + } + } + if (j != replacements.end()) + continue; + if (i->first == "empty_param") { + EXPECT_TRUE(i->second.empty()); + } else if (i->first == "sbisrc") { + EXPECT_FALSE(i->second.empty()); + } else { + EXPECT_EQ("constant_param", i->first); + EXPECT_EQ("constant", i->second); + } + } +} + +// Test that setting the prepopulate ID from TemplateURL causes the stored +// TemplateURLRef to handle parsing the URL parameters differently. +TEST_F(TemplateURLTest, SetPrepopulatedAndParse) { + TemplateURLData data; + data.SetURL("http://foo{fhqwhgads}bar"); + TemplateURL url(data); + TemplateURLRef::Replacements replacements; + bool valid = false; + EXPECT_EQ("http://foo{fhqwhgads}bar", url.url_ref().ParseURL( + "http://foo{fhqwhgads}bar", &replacements, NULL, &valid)); + EXPECT_TRUE(replacements.empty()); + EXPECT_TRUE(valid); + + data.prepopulate_id = 123; + TemplateURL url2(data); + EXPECT_EQ("http://foobar", url2.url_ref().ParseURL("http://foo{fhqwhgads}bar", + &replacements, NULL, + &valid)); + EXPECT_TRUE(replacements.empty()); + EXPECT_TRUE(valid); +} + +TEST_F(TemplateURLTest, InputEncodingBeforeSearchTerm) { + TemplateURLData data; + data.SetURL("http://foox{inputEncoding?}a{searchTerms}y{outputEncoding?}b"); + TemplateURL url(data); + EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_)); + ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_)); + GURL result(url.url_ref().ReplaceSearchTerms( + TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("X")), search_terms_data_)); + ASSERT_TRUE(result.is_valid()); + EXPECT_EQ("http://fooxutf-8axyb/", result.spec()); +} + +TEST_F(TemplateURLTest, URLRefTestEncoding2) { + TemplateURLData data; + data.SetURL("http://foo{searchTerms}x{inputEncoding}y{outputEncoding}a"); + TemplateURL url(data); + EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_)); + ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_)); + GURL result(url.url_ref().ReplaceSearchTerms( + TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("X")), search_terms_data_)); + ASSERT_TRUE(result.is_valid()); + EXPECT_EQ("http://fooxxutf-8yutf-8a/", result.spec()); +} + +TEST_F(TemplateURLTest, URLRefTestSearchTermsUsingTermsData) { + struct SearchTermsCase { + const char* url; + const base::string16 terms; + const char* output; + } search_term_cases[] = { + { "{google:baseURL}{language}{searchTerms}", base::string16(), + "http://example.com/e/en" }, + { "{google:baseSuggestURL}{searchTerms}", base::string16(), + "http://example.com/complete/" } + }; + + TestSearchTermsData search_terms_data("http://example.com/e/"); + TemplateURLData data; + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(search_term_cases); ++i) { + const SearchTermsCase& value = search_term_cases[i]; + data.SetURL(value.url); + TemplateURL url(data); + EXPECT_TRUE(url.url_ref().IsValid(search_terms_data)); + ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data)); + GURL result(url.url_ref().ReplaceSearchTerms( + TemplateURLRef::SearchTermsArgs(value.terms), search_terms_data, NULL)); + ASSERT_TRUE(result.is_valid()); + EXPECT_EQ(value.output, result.spec()); + } +} + +TEST_F(TemplateURLTest, URLRefTermToWide) { + struct ToWideCase { + const char* encoded_search_term; + const base::string16 expected_decoded_term; + } to_wide_cases[] = { + {"hello+world", ASCIIToUTF16("hello world")}, + // Test some big-5 input. + {"%a7A%A6%6e+to+you", base::WideToUTF16(L"\x4f60\x597d to you")}, + // Test some UTF-8 input. We should fall back to this when the encoding + // doesn't look like big-5. We have a '5' in the middle, which is an invalid + // Big-5 trailing byte. + {"%e4%bd%a05%e5%a5%bd+to+you", + base::WideToUTF16(L"\x4f60\x35\x597d to you")}, + // Undecodable input should stay escaped. + {"%91%01+abcd", base::WideToUTF16(L"%91%01 abcd")}, + // Make sure we convert %2B to +. + {"C%2B%2B", ASCIIToUTF16("C++")}, + // C%2B is escaped as C%252B, make sure we unescape it properly. + {"C%252B", ASCIIToUTF16("C%2B")}, + }; + + // Set one input encoding: big-5. This is so we can test fallback to UTF-8. + TemplateURLData data; + data.SetURL("http://foo?q={searchTerms}"); + data.input_encodings.push_back("big-5"); + TemplateURL url(data); + EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_)); + ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_)); + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(to_wide_cases); i++) { + EXPECT_EQ(to_wide_cases[i].expected_decoded_term, + url.url_ref().SearchTermToString16( + to_wide_cases[i].encoded_search_term)); + } +} + +TEST_F(TemplateURLTest, DisplayURLToURLRef) { + struct TestData { + const std::string url; + const base::string16 expected_result; + } test_data[] = { + { "http://foo{searchTerms}x{inputEncoding}y{outputEncoding}a", + ASCIIToUTF16("http://foo%sx{inputEncoding}y{outputEncoding}a") }, + { "http://X", + ASCIIToUTF16("http://X") }, + { "http://foo{searchTerms", + ASCIIToUTF16("http://foo{searchTerms") }, + { "http://foo{searchTerms}{language}", + ASCIIToUTF16("http://foo%s{language}") }, + }; + TemplateURLData data; + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { + data.SetURL(test_data[i].url); + TemplateURL url(data); + EXPECT_EQ(test_data[i].expected_result, + url.url_ref().DisplayURL(search_terms_data_)); + EXPECT_EQ(test_data[i].url, + TemplateURLRef::DisplayURLToURLRef( + url.url_ref().DisplayURL(search_terms_data_))); + } +} + +TEST_F(TemplateURLTest, ReplaceSearchTerms) { + struct TestData { + const std::string url; + const std::string expected_result; + } test_data[] = { + { "http://foo/{language}{searchTerms}{inputEncoding}", + "http://foo/{language}XUTF-8" }, + { "http://foo/{language}{inputEncoding}{searchTerms}", + "http://foo/{language}UTF-8X" }, + { "http://foo/{searchTerms}{language}{inputEncoding}", + "http://foo/X{language}UTF-8" }, + { "http://foo/{searchTerms}{inputEncoding}{language}", + "http://foo/XUTF-8{language}" }, + { "http://foo/{inputEncoding}{searchTerms}{language}", + "http://foo/UTF-8X{language}" }, + { "http://foo/{inputEncoding}{language}{searchTerms}", + "http://foo/UTF-8{language}X" }, + { "http://foo/{language}a{searchTerms}a{inputEncoding}a", + "http://foo/{language}aXaUTF-8a" }, + { "http://foo/{language}a{inputEncoding}a{searchTerms}a", + "http://foo/{language}aUTF-8aXa" }, + { "http://foo/{searchTerms}a{language}a{inputEncoding}a", + "http://foo/Xa{language}aUTF-8a" }, + { "http://foo/{searchTerms}a{inputEncoding}a{language}a", + "http://foo/XaUTF-8a{language}a" }, + { "http://foo/{inputEncoding}a{searchTerms}a{language}a", + "http://foo/UTF-8aXa{language}a" }, + { "http://foo/{inputEncoding}a{language}a{searchTerms}a", + "http://foo/UTF-8a{language}aXa" }, + }; + TemplateURLData data; + data.input_encodings.push_back("UTF-8"); + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { + data.SetURL(test_data[i].url); + TemplateURL url(data); + EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_)); + ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_)); + std::string expected_result = test_data[i].expected_result; + ReplaceSubstringsAfterOffset(&expected_result, 0, "{language}", + search_terms_data_.GetApplicationLocale()); + GURL result(url.url_ref().ReplaceSearchTerms( + TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("X")), + search_terms_data_)); + ASSERT_TRUE(result.is_valid()); + EXPECT_EQ(expected_result, result.spec()); + } +} + + +// Tests replacing search terms in various encodings and making sure the +// generated URL matches the expected value. +TEST_F(TemplateURLTest, ReplaceArbitrarySearchTerms) { + struct TestData { + const std::string encoding; + const base::string16 search_term; + const std::string url; + const std::string expected_result; + } test_data[] = { + { "BIG5", base::WideToUTF16(L"\x60BD"), + "http://foo/?{searchTerms}{inputEncoding}", + "http://foo/?%B1~BIG5" }, + { "UTF-8", ASCIIToUTF16("blah"), + "http://foo/?{searchTerms}{inputEncoding}", + "http://foo/?blahUTF-8" }, + { "Shift_JIS", base::UTF8ToUTF16("\xe3\x81\x82"), + "http://foo/{searchTerms}/bar", + "http://foo/%82%A0/bar"}, + { "Shift_JIS", base::UTF8ToUTF16("\xe3\x81\x82 \xe3\x81\x84"), + "http://foo/{searchTerms}/bar", + "http://foo/%82%A0%20%82%A2/bar"}, + }; + TemplateURLData data; + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { + data.SetURL(test_data[i].url); + data.input_encodings.clear(); + data.input_encodings.push_back(test_data[i].encoding); + TemplateURL url(data); + EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_)); + ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_)); + GURL result(url.url_ref().ReplaceSearchTerms( + TemplateURLRef::SearchTermsArgs(test_data[i].search_term), + search_terms_data_)); + ASSERT_TRUE(result.is_valid()); + EXPECT_EQ(test_data[i].expected_result, result.spec()); + } +} + +// Tests replacing assisted query stats (AQS) in various scenarios. +TEST_F(TemplateURLTest, ReplaceAssistedQueryStats) { + struct TestData { + const base::string16 search_term; + const std::string aqs; + const std::string base_url; + const std::string url; + const std::string expected_result; + } test_data[] = { + // No HTTPS, no AQS. + { ASCIIToUTF16("foo"), + "chrome.0.0l6", + "http://foo/", + "{google:baseURL}?{searchTerms}{google:assistedQueryStats}", + "http://foo/?foo" }, + // HTTPS available, AQS should be replaced. + { ASCIIToUTF16("foo"), + "chrome.0.0l6", + "https://foo/", + "{google:baseURL}?{searchTerms}{google:assistedQueryStats}", + "https://foo/?fooaqs=chrome.0.0l6&" }, + // HTTPS available, however AQS is empty. + { ASCIIToUTF16("foo"), + "", + "https://foo/", + "{google:baseURL}?{searchTerms}{google:assistedQueryStats}", + "https://foo/?foo" }, + // No {google:baseURL} and protocol is HTTP, we must not substitute AQS. + { ASCIIToUTF16("foo"), + "chrome.0.0l6", + "http://www.google.com", + "http://foo?{searchTerms}{google:assistedQueryStats}", + "http://foo/?foo" }, + // A non-Google search provider with HTTPS should allow AQS. + { ASCIIToUTF16("foo"), + "chrome.0.0l6", + "https://www.google.com", + "https://foo?{searchTerms}{google:assistedQueryStats}", + "https://foo/?fooaqs=chrome.0.0l6&" }, + }; + TemplateURLData data; + data.input_encodings.push_back("UTF-8"); + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { + data.SetURL(test_data[i].url); + TemplateURL url(data); + EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_)); + ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_)); + TemplateURLRef::SearchTermsArgs search_terms_args(test_data[i].search_term); + search_terms_args.assisted_query_stats = test_data[i].aqs; + search_terms_data_.set_google_base_url(test_data[i].base_url); + GURL result(url.url_ref().ReplaceSearchTerms(search_terms_args, + search_terms_data_)); + ASSERT_TRUE(result.is_valid()); + EXPECT_EQ(test_data[i].expected_result, result.spec()); + } +} + +// Tests replacing cursor position. +TEST_F(TemplateURLTest, ReplaceCursorPosition) { + struct TestData { + const base::string16 search_term; + size_t cursor_position; + const std::string url; + const std::string expected_result; + } test_data[] = { + { ASCIIToUTF16("foo"), + base::string16::npos, + "{google:baseURL}?{searchTerms}&{google:cursorPosition}", + "http://www.google.com/?foo&" }, + { ASCIIToUTF16("foo"), + 2, + "{google:baseURL}?{searchTerms}&{google:cursorPosition}", + "http://www.google.com/?foo&cp=2&" }, + { ASCIIToUTF16("foo"), + 15, + "{google:baseURL}?{searchTerms}&{google:cursorPosition}", + "http://www.google.com/?foo&cp=15&" }, + }; + TemplateURLData data; + data.input_encodings.push_back("UTF-8"); + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { + data.SetURL(test_data[i].url); + TemplateURL url(data); + EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_)); + ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_)); + TemplateURLRef::SearchTermsArgs search_terms_args(test_data[i].search_term); + search_terms_args.cursor_position = test_data[i].cursor_position; + GURL result(url.url_ref().ReplaceSearchTerms(search_terms_args, + search_terms_data_)); + ASSERT_TRUE(result.is_valid()); + EXPECT_EQ(test_data[i].expected_result, result.spec()); + } +} + +// Tests replacing input type (&oit=). +TEST_F(TemplateURLTest, ReplaceInputType) { + struct TestData { + const base::string16 search_term; + metrics::OmniboxInputType::Type input_type; + const std::string url; + const std::string expected_result; + } test_data[] = { + { ASCIIToUTF16("foo"), + metrics::OmniboxInputType::UNKNOWN, + "{google:baseURL}?{searchTerms}&{google:inputType}", + "http://www.google.com/?foo&oit=1&" }, + { ASCIIToUTF16("foo"), + metrics::OmniboxInputType::URL, + "{google:baseURL}?{searchTerms}&{google:inputType}", + "http://www.google.com/?foo&oit=3&" }, + { ASCIIToUTF16("foo"), + metrics::OmniboxInputType::FORCED_QUERY, + "{google:baseURL}?{searchTerms}&{google:inputType}", + "http://www.google.com/?foo&oit=5&" }, + }; + TemplateURLData data; + data.input_encodings.push_back("UTF-8"); + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { + data.SetURL(test_data[i].url); + TemplateURL url(data); + EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_)); + ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_)); + TemplateURLRef::SearchTermsArgs search_terms_args(test_data[i].search_term); + search_terms_args.input_type = test_data[i].input_type; + GURL result(url.url_ref().ReplaceSearchTerms(search_terms_args, + search_terms_data_)); + ASSERT_TRUE(result.is_valid()); + EXPECT_EQ(test_data[i].expected_result, result.spec()); + } +} + +// Tests replacing currentPageUrl. +TEST_F(TemplateURLTest, ReplaceCurrentPageUrl) { + struct TestData { + const base::string16 search_term; + const std::string current_page_url; + const std::string url; + const std::string expected_result; + } test_data[] = { + { ASCIIToUTF16("foo"), + "http://www.google.com/", + "{google:baseURL}?{searchTerms}&{google:currentPageUrl}", + "http://www.google.com/?foo&url=http%3A%2F%2Fwww.google.com%2F&" }, + { ASCIIToUTF16("foo"), + "", + "{google:baseURL}?{searchTerms}&{google:currentPageUrl}", + "http://www.google.com/?foo&" }, + { ASCIIToUTF16("foo"), + "http://g.com/+-/*&=", + "{google:baseURL}?{searchTerms}&{google:currentPageUrl}", + "http://www.google.com/?foo&url=http%3A%2F%2Fg.com%2F%2B-%2F*%26%3D&" }, + }; + TemplateURLData data; + data.input_encodings.push_back("UTF-8"); + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { + data.SetURL(test_data[i].url); + TemplateURL url(data); + EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_)); + ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_)); + TemplateURLRef::SearchTermsArgs search_terms_args(test_data[i].search_term); + search_terms_args.current_page_url = test_data[i].current_page_url; + GURL result(url.url_ref().ReplaceSearchTerms(search_terms_args, + search_terms_data_)); + ASSERT_TRUE(result.is_valid()); + EXPECT_EQ(test_data[i].expected_result, result.spec()); + } +} + +TEST_F(TemplateURLTest, Suggestions) { + struct TestData { + const int accepted_suggestion; + const base::string16 original_query_for_suggestion; + const std::string expected_result; + } test_data[] = { + { TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, base::string16(), + "http://bar/foo?q=foobar" }, + { TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, ASCIIToUTF16("foo"), + "http://bar/foo?q=foobar" }, + { TemplateURLRef::NO_SUGGESTION_CHOSEN, base::string16(), + "http://bar/foo?q=foobar" }, + { TemplateURLRef::NO_SUGGESTION_CHOSEN, ASCIIToUTF16("foo"), + "http://bar/foo?q=foobar" }, + { 0, base::string16(), "http://bar/foo?oq=&q=foobar" }, + { 1, ASCIIToUTF16("foo"), "http://bar/foo?oq=foo&q=foobar" }, + }; + TemplateURLData data; + data.SetURL("http://bar/foo?{google:originalQueryForSuggestion}" + "q={searchTerms}"); + data.input_encodings.push_back("UTF-8"); + TemplateURL url(data); + EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_)); + ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_)); + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { + TemplateURLRef::SearchTermsArgs search_terms_args( + ASCIIToUTF16("foobar")); + search_terms_args.accepted_suggestion = test_data[i].accepted_suggestion; + search_terms_args.original_query = + test_data[i].original_query_for_suggestion; + GURL result(url.url_ref().ReplaceSearchTerms(search_terms_args, + search_terms_data_)); + ASSERT_TRUE(result.is_valid()); + EXPECT_EQ(test_data[i].expected_result, result.spec()); + } +} + +TEST_F(TemplateURLTest, RLZ) { + base::string16 rlz_string = search_terms_data_.GetRlzParameterValue(false); + + TemplateURLData data; + data.SetURL("http://bar/?{google:RLZ}{searchTerms}"); + TemplateURL url(data); + EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_)); + ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_)); + GURL result(url.url_ref().ReplaceSearchTerms( + TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("x")), search_terms_data_)); + ASSERT_TRUE(result.is_valid()); + EXPECT_EQ("http://bar/?rlz=" + base::UTF16ToUTF8(rlz_string) + "&x", + result.spec()); +} + +TEST_F(TemplateURLTest, RLZFromAppList) { + base::string16 rlz_string = search_terms_data_.GetRlzParameterValue(true); + + TemplateURLData data; + data.SetURL("http://bar/?{google:RLZ}{searchTerms}"); + TemplateURL url(data); + EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_)); + ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_)); + TemplateURLRef::SearchTermsArgs args(ASCIIToUTF16("x")); + args.from_app_list = true; + GURL result(url.url_ref().ReplaceSearchTerms(args, search_terms_data_)); + ASSERT_TRUE(result.is_valid()); + EXPECT_EQ("http://bar/?rlz=" + base::UTF16ToUTF8(rlz_string) + "&x", + result.spec()); +} + +TEST_F(TemplateURLTest, HostAndSearchTermKey) { + struct TestData { + const std::string url; + const std::string host; + const std::string path; + const std::string search_term_key; + } test_data[] = { + { "http://blah/?foo=bar&q={searchTerms}&b=x", "blah", "/", "q"}, + + // No query key should result in empty values. + { "http://blah/{searchTerms}", "", "", ""}, + + // No term should result in empty values. + { "http://blah/", "", "", ""}, + + // Multiple terms should result in empty values. + { "http://blah/?q={searchTerms}&x={searchTerms}", "", "", ""}, + + // Term in the host shouldn't match. + { "http://{searchTerms}", "", "", ""}, + + { "http://blah/?q={searchTerms}", "blah", "/", "q"}, + { "https://blah/?q={searchTerms}", "blah", "/", "q"}, + + // Single term with extra chars in value should match. + { "http://blah/?q=stock:{searchTerms}", "blah", "/", "q"}, + }; + + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { + TemplateURLData data; + data.SetURL(test_data[i].url); + TemplateURL url(data); + EXPECT_EQ(test_data[i].host, url.url_ref().GetHost(search_terms_data_)); + EXPECT_EQ(test_data[i].path, url.url_ref().GetPath(search_terms_data_)); + EXPECT_EQ(test_data[i].search_term_key, + url.url_ref().GetSearchTermKey(search_terms_data_)); + } +} + +TEST_F(TemplateURLTest, GoogleBaseSuggestURL) { + static const struct { + const char* const base_url; + const char* const base_suggest_url; + } data[] = { + { "http://google.com/", "http://google.com/complete/", }, + { "http://www.google.com/", "http://www.google.com/complete/", }, + { "http://www.google.co.uk/", "http://www.google.co.uk/complete/", }, + { "http://www.google.com.by/", "http://www.google.com.by/complete/", }, + { "http://google.com/intl/xx/", "http://google.com/complete/", }, + }; + + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) + CheckSuggestBaseURL(data[i].base_url, data[i].base_suggest_url); +} + +TEST_F(TemplateURLTest, ParseParameterKnown) { + std::string parsed_url("{searchTerms}"); + TemplateURLData data; + data.SetURL(parsed_url); + TemplateURL url(data); + TemplateURLRef::Replacements replacements; + EXPECT_TRUE(url.url_ref().ParseParameter(0, 12, &parsed_url, &replacements)); + EXPECT_EQ(std::string(), parsed_url); + ASSERT_EQ(1U, replacements.size()); + EXPECT_EQ(0U, replacements[0].index); + EXPECT_EQ(TemplateURLRef::SEARCH_TERMS, replacements[0].type); +} + +TEST_F(TemplateURLTest, ParseParameterUnknown) { + std::string parsed_url("{fhqwhgads}abc"); + TemplateURLData data; + data.SetURL(parsed_url); + TemplateURL url(data); + TemplateURLRef::Replacements replacements; + + // By default, TemplateURLRef should not consider itself prepopulated. + // Therefore we should not replace the unknown parameter. + EXPECT_FALSE(url.url_ref().ParseParameter(0, 10, &parsed_url, &replacements)); + EXPECT_EQ("{fhqwhgads}abc", parsed_url); + EXPECT_TRUE(replacements.empty()); + + // If the TemplateURLRef is prepopulated, we should remove unknown parameters. + parsed_url = "{fhqwhgads}abc"; + data.prepopulate_id = 1; + TemplateURL url2(data); + EXPECT_TRUE(url2.url_ref().ParseParameter(0, 10, &parsed_url, &replacements)); + EXPECT_EQ("abc", parsed_url); + EXPECT_TRUE(replacements.empty()); +} + +TEST_F(TemplateURLTest, ParseURLEmpty) { + TemplateURL url((TemplateURLData())); + TemplateURLRef::Replacements replacements; + bool valid = false; + EXPECT_EQ(std::string(), + url.url_ref().ParseURL(std::string(), &replacements, NULL, &valid)); + EXPECT_TRUE(replacements.empty()); + EXPECT_TRUE(valid); +} + +TEST_F(TemplateURLTest, ParseURLNoTemplateEnd) { + TemplateURLData data; + data.SetURL("{"); + TemplateURL url(data); + TemplateURLRef::Replacements replacements; + bool valid = false; + EXPECT_EQ(std::string(), url.url_ref().ParseURL("{", &replacements, NULL, + &valid)); + EXPECT_TRUE(replacements.empty()); + EXPECT_FALSE(valid); +} + +TEST_F(TemplateURLTest, ParseURLNoKnownParameters) { + TemplateURLData data; + data.SetURL("{}"); + TemplateURL url(data); + TemplateURLRef::Replacements replacements; + bool valid = false; + EXPECT_EQ("{}", url.url_ref().ParseURL("{}", &replacements, NULL, &valid)); + EXPECT_TRUE(replacements.empty()); + EXPECT_TRUE(valid); +} + +TEST_F(TemplateURLTest, ParseURLTwoParameters) { + TemplateURLData data; + data.SetURL("{}{{%s}}"); + TemplateURL url(data); + TemplateURLRef::Replacements replacements; + bool valid = false; + EXPECT_EQ("{}{}", + url.url_ref().ParseURL("{}{{searchTerms}}", &replacements, NULL, + &valid)); + ASSERT_EQ(1U, replacements.size()); + EXPECT_EQ(3U, replacements[0].index); + EXPECT_EQ(TemplateURLRef::SEARCH_TERMS, replacements[0].type); + EXPECT_TRUE(valid); +} + +TEST_F(TemplateURLTest, ParseURLNestedParameter) { + TemplateURLData data; + data.SetURL("{%s"); + TemplateURL url(data); + TemplateURLRef::Replacements replacements; + bool valid = false; + EXPECT_EQ("{", + url.url_ref().ParseURL("{{searchTerms}", &replacements, NULL, + &valid)); + ASSERT_EQ(1U, replacements.size()); + EXPECT_EQ(1U, replacements[0].index); + EXPECT_EQ(TemplateURLRef::SEARCH_TERMS, replacements[0].type); + EXPECT_TRUE(valid); +} + +TEST_F(TemplateURLTest, SearchClient) { + const std::string base_url_str("http://google.com/?"); + const std::string terms_str("{searchTerms}&{google:searchClient}"); + const std::string full_url_str = base_url_str + terms_str; + const base::string16 terms(ASCIIToUTF16(terms_str)); + search_terms_data_.set_google_base_url(base_url_str); + + TemplateURLData data; + data.SetURL(full_url_str); + TemplateURL url(data); + EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_)); + ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_)); + TemplateURLRef::SearchTermsArgs search_terms_args(ASCIIToUTF16("foobar")); + + // Check that the URL is correct when a client is not present. + GURL result(url.url_ref().ReplaceSearchTerms(search_terms_args, + search_terms_data_)); + ASSERT_TRUE(result.is_valid()); + EXPECT_EQ("http://google.com/?foobar&", result.spec()); + + // Check that the URL is correct when a client is present. + search_terms_data_.set_search_client("search_client"); + GURL result_2(url.url_ref().ReplaceSearchTerms(search_terms_args, + search_terms_data_)); + ASSERT_TRUE(result_2.is_valid()); + EXPECT_EQ("http://google.com/?foobar&client=search_client&", result_2.spec()); +} + +TEST_F(TemplateURLTest, GetURLNoInstantURL) { + TemplateURLData data; + data.SetURL("http://google.com/?q={searchTerms}"); + data.suggestions_url = "http://google.com/suggest?q={searchTerms}"; + data.alternate_urls.push_back("http://google.com/alt?q={searchTerms}"); + data.alternate_urls.push_back("{google:baseURL}/alt/#q={searchTerms}"); + TemplateURL url(data); + ASSERT_EQ(3U, url.URLCount()); + EXPECT_EQ("http://google.com/alt?q={searchTerms}", url.GetURL(0)); + EXPECT_EQ("{google:baseURL}/alt/#q={searchTerms}", url.GetURL(1)); + EXPECT_EQ("http://google.com/?q={searchTerms}", url.GetURL(2)); +} + +TEST_F(TemplateURLTest, GetURLNoSuggestionsURL) { + TemplateURLData data; + data.SetURL("http://google.com/?q={searchTerms}"); + data.instant_url = "http://google.com/instant#q={searchTerms}"; + data.alternate_urls.push_back("http://google.com/alt?q={searchTerms}"); + data.alternate_urls.push_back("{google:baseURL}/alt/#q={searchTerms}"); + TemplateURL url(data); + ASSERT_EQ(3U, url.URLCount()); + EXPECT_EQ("http://google.com/alt?q={searchTerms}", url.GetURL(0)); + EXPECT_EQ("{google:baseURL}/alt/#q={searchTerms}", url.GetURL(1)); + EXPECT_EQ("http://google.com/?q={searchTerms}", url.GetURL(2)); +} + +TEST_F(TemplateURLTest, GetURLOnlyOneURL) { + TemplateURLData data; + data.SetURL("http://www.google.co.uk/"); + TemplateURL url(data); + ASSERT_EQ(1U, url.URLCount()); + EXPECT_EQ("http://www.google.co.uk/", url.GetURL(0)); +} + +TEST_F(TemplateURLTest, ExtractSearchTermsFromURL) { + TemplateURLData data; + data.SetURL("http://google.com/?q={searchTerms}"); + data.instant_url = "http://google.com/instant#q={searchTerms}"; + data.alternate_urls.push_back("http://google.com/alt/#q={searchTerms}"); + data.alternate_urls.push_back( + "http://google.com/alt/?ext=foo&q={searchTerms}#ref=bar"); + TemplateURL url(data); + base::string16 result; + + EXPECT_TRUE(url.ExtractSearchTermsFromURL( + GURL("http://google.com/?q=something"), search_terms_data_, &result)); + EXPECT_EQ(ASCIIToUTF16("something"), result); + + EXPECT_TRUE(url.ExtractSearchTermsFromURL( + GURL("http://google.com/?espv&q=something"), + search_terms_data_, &result)); + EXPECT_EQ(ASCIIToUTF16("something"), result); + + EXPECT_TRUE(url.ExtractSearchTermsFromURL( + GURL("http://google.com/?espv=1&q=something"), + search_terms_data_, &result)); + EXPECT_EQ(ASCIIToUTF16("something"), result); + + EXPECT_TRUE(url.ExtractSearchTermsFromURL( + GURL("http://google.com/?espv=0&q=something"), + search_terms_data_, &result)); + EXPECT_EQ(ASCIIToUTF16("something"), result); + + EXPECT_TRUE(url.ExtractSearchTermsFromURL( + GURL("http://google.com/alt/#q=something"), + search_terms_data_, &result)); + EXPECT_EQ(ASCIIToUTF16("something"), result); + + EXPECT_TRUE(url.ExtractSearchTermsFromURL( + GURL("http://google.com/alt/#espv&q=something"), + search_terms_data_, &result)); + EXPECT_EQ(ASCIIToUTF16("something"), result); + + EXPECT_TRUE(url.ExtractSearchTermsFromURL( + GURL("http://google.com/alt/#espv=1&q=something"), + search_terms_data_, &result)); + EXPECT_EQ(ASCIIToUTF16("something"), result); + + EXPECT_TRUE(url.ExtractSearchTermsFromURL( + GURL("http://google.com/alt/#espv=0&q=something"), + search_terms_data_, &result)); + EXPECT_EQ(ASCIIToUTF16("something"), result); + + EXPECT_FALSE(url.ExtractSearchTermsFromURL( + GURL("http://google.ca/?q=something"), search_terms_data_, &result)); + EXPECT_EQ(base::string16(), result); + + EXPECT_FALSE(url.ExtractSearchTermsFromURL( + GURL("http://google.ca/?q=something&q=anything"), + search_terms_data_, &result)); + EXPECT_EQ(base::string16(), result); + + EXPECT_FALSE(url.ExtractSearchTermsFromURL( + GURL("http://google.com/foo/?q=foo"), search_terms_data_, &result)); + EXPECT_EQ(base::string16(), result); + + EXPECT_TRUE(url.ExtractSearchTermsFromURL( + GURL("https://google.com/?q=foo"), search_terms_data_, &result)); + EXPECT_EQ(ASCIIToUTF16("foo"), result); + + EXPECT_FALSE(url.ExtractSearchTermsFromURL( + GURL("http://google.com:8080/?q=foo"), search_terms_data_, &result)); + EXPECT_EQ(base::string16(), result); + + EXPECT_TRUE(url.ExtractSearchTermsFromURL( + GURL("http://google.com/?q=1+2+3&b=456"), search_terms_data_, &result)); + EXPECT_EQ(ASCIIToUTF16("1 2 3"), result); + + EXPECT_TRUE(url.ExtractSearchTermsFromURL( + GURL("http://google.com/alt/?q=123#q=456"), + search_terms_data_, &result)); + EXPECT_EQ(ASCIIToUTF16("456"), result); + + EXPECT_TRUE(url.ExtractSearchTermsFromURL( + GURL("http://google.com/alt/?a=012&q=123&b=456#f=789"), + search_terms_data_, &result)); + EXPECT_EQ(ASCIIToUTF16("123"), result); + + EXPECT_TRUE(url.ExtractSearchTermsFromURL(GURL( + "http://google.com/alt/?a=012&q=123&b=456#j=abc&q=789&h=def9"), + search_terms_data_, &result)); + EXPECT_EQ(ASCIIToUTF16("789"), result); + + EXPECT_FALSE(url.ExtractSearchTermsFromURL( + GURL("http://google.com/alt/?q="), search_terms_data_, &result)); + EXPECT_EQ(base::string16(), result); + + EXPECT_FALSE(url.ExtractSearchTermsFromURL( + GURL("http://google.com/alt/?#q="), search_terms_data_, &result)); + EXPECT_EQ(base::string16(), result); + + EXPECT_FALSE(url.ExtractSearchTermsFromURL( + GURL("http://google.com/alt/?q=#q="), search_terms_data_, &result)); + EXPECT_EQ(base::string16(), result); + + EXPECT_FALSE(url.ExtractSearchTermsFromURL( + GURL("http://google.com/alt/?q=123#q="), search_terms_data_, &result)); + EXPECT_EQ(base::string16(), result); + + EXPECT_TRUE(url.ExtractSearchTermsFromURL( + GURL("http://google.com/alt/?q=#q=123"), search_terms_data_, &result)); + EXPECT_EQ(ASCIIToUTF16("123"), result); +} + +TEST_F(TemplateURLTest, HasSearchTermsReplacementKey) { + TemplateURLData data; + data.SetURL("http://google.com/?q={searchTerms}"); + data.instant_url = "http://google.com/instant#q={searchTerms}"; + data.alternate_urls.push_back("http://google.com/alt/#q={searchTerms}"); + data.alternate_urls.push_back( + "http://google.com/alt/?ext=foo&q={searchTerms}#ref=bar"); + data.search_terms_replacement_key = "espv"; + TemplateURL url(data); + + // Test with instant enabled required. + EXPECT_FALSE(url.HasSearchTermsReplacementKey( + GURL("http://google.com/"))); + + EXPECT_TRUE(url.HasSearchTermsReplacementKey( + GURL("http://google.com/?espv"))); + + EXPECT_TRUE(url.HasSearchTermsReplacementKey( + GURL("http://google.com/#espv"))); + + EXPECT_FALSE(url.HasSearchTermsReplacementKey( + GURL("http://google.com/?q=something"))); + + EXPECT_TRUE(url.HasSearchTermsReplacementKey( + GURL("http://google.com/?q=something&espv"))); + + EXPECT_TRUE(url.HasSearchTermsReplacementKey( + GURL("http://google.com/?q=something&espv=1"))); + + EXPECT_TRUE(url.HasSearchTermsReplacementKey( + GURL("http://google.com/?q=something&espv=0"))); + + EXPECT_TRUE(url.HasSearchTermsReplacementKey( + GURL("http://google.com/?espv&q=something"))); + + EXPECT_TRUE(url.HasSearchTermsReplacementKey( + GURL("http://google.com/?espv=1&q=something"))); + + EXPECT_TRUE(url.HasSearchTermsReplacementKey( + GURL("http://google.com/?espv=0&q=something"))); + + EXPECT_FALSE(url.HasSearchTermsReplacementKey( + GURL("http://google.com/alt/#q=something"))); + + EXPECT_TRUE(url.HasSearchTermsReplacementKey( + GURL("http://google.com/alt/#q=something&espv"))); + + EXPECT_TRUE(url.HasSearchTermsReplacementKey( + GURL("http://google.com/alt/#q=something&espv=1"))); + + EXPECT_TRUE(url.HasSearchTermsReplacementKey( + GURL("http://google.com/alt/#q=something&espv=0"))); + + EXPECT_TRUE(url.HasSearchTermsReplacementKey( + GURL("http://google.com/alt/#espv&q=something"))); + + EXPECT_TRUE(url.HasSearchTermsReplacementKey( + GURL("http://google.com/alt/#espv=1&q=something"))); + + EXPECT_TRUE(url.HasSearchTermsReplacementKey( + GURL("http://google.com/alt/#espv=0&q=something"))); + + EXPECT_TRUE(url.HasSearchTermsReplacementKey( + GURL("http://google.com/?espv#q=something"))); + + EXPECT_TRUE(url.HasSearchTermsReplacementKey( + GURL("http://google.com/?espv=1#q=something"))); + + EXPECT_TRUE(url.HasSearchTermsReplacementKey( + GURL("http://google.com/?q=something#espv"))); + + EXPECT_TRUE(url.HasSearchTermsReplacementKey( + GURL("http://google.com/?q=something#espv=1"))); + + // This does not ensure the domain matches. + EXPECT_TRUE(url.HasSearchTermsReplacementKey( + GURL("http://bing.com/?espv"))); + + EXPECT_TRUE(url.HasSearchTermsReplacementKey( + GURL("http://bing.com/#espv"))); +} + +TEST_F(TemplateURLTest, ReplaceSearchTermsInURL) { + TemplateURLData data; + data.SetURL("http://google.com/?q={searchTerms}"); + data.instant_url = "http://google.com/instant#q={searchTerms}"; + data.alternate_urls.push_back("http://google.com/alt/#q={searchTerms}"); + data.alternate_urls.push_back( + "http://google.com/alt/?ext=foo&q={searchTerms}#ref=bar"); + TemplateURL url(data); + TemplateURLRef::SearchTermsArgs search_terms(ASCIIToUTF16("Bob Morane")); + GURL result; + + EXPECT_TRUE(url.ReplaceSearchTermsInURL( + GURL("http://google.com/?q=something"), search_terms, + search_terms_data_, &result)); + EXPECT_EQ(GURL("http://google.com/?q=Bob%20Morane"), result); + + result = GURL("http://should.not.change.com"); + EXPECT_FALSE(url.ReplaceSearchTermsInURL( + GURL("http://google.ca/?q=something"), search_terms, + search_terms_data_, &result)); + EXPECT_EQ(GURL("http://should.not.change.com"), result); + + EXPECT_FALSE(url.ReplaceSearchTermsInURL( + GURL("http://google.com/foo/?q=foo"), search_terms, + search_terms_data_, &result)); + + EXPECT_TRUE(url.ReplaceSearchTermsInURL( + GURL("https://google.com/?q=foo"), search_terms, + search_terms_data_, &result)); + EXPECT_EQ(GURL("https://google.com/?q=Bob%20Morane"), result); + + EXPECT_FALSE(url.ReplaceSearchTermsInURL( + GURL("http://google.com:8080/?q=foo"), search_terms, + search_terms_data_, &result)); + + EXPECT_TRUE(url.ReplaceSearchTermsInURL( + GURL("http://google.com/?q=1+2+3&b=456"), search_terms, + search_terms_data_, &result)); + EXPECT_EQ(GURL("http://google.com/?q=Bob%20Morane&b=456"), result); + + // Note: Spaces in REF parameters are not escaped. See TryEncoding() in + // template_url.cc for details. + EXPECT_TRUE(url.ReplaceSearchTermsInURL( + GURL("http://google.com/alt/?q=123#q=456"), search_terms, + search_terms_data_, &result)); + EXPECT_EQ(GURL("http://google.com/alt/?q=123#q=Bob Morane"), result); + + EXPECT_TRUE(url.ReplaceSearchTermsInURL( + GURL("http://google.com/alt/?a=012&q=123&b=456#f=789"), search_terms, + search_terms_data_, &result)); + EXPECT_EQ(GURL("http://google.com/alt/?a=012&q=Bob%20Morane&b=456#f=789"), + result); + + EXPECT_TRUE(url.ReplaceSearchTermsInURL( + GURL("http://google.com/alt/?a=012&q=123&b=456#j=abc&q=789&h=def9"), + search_terms, search_terms_data_, &result)); + EXPECT_EQ(GURL("http://google.com/alt/?a=012&q=123&b=456" + "#j=abc&q=Bob Morane&h=def9"), result); + + EXPECT_FALSE(url.ReplaceSearchTermsInURL( + GURL("http://google.com/alt/?q="), search_terms, + search_terms_data_, &result)); + + EXPECT_FALSE(url.ReplaceSearchTermsInURL( + GURL("http://google.com/alt/?#q="), search_terms, + search_terms_data_, &result)); + + EXPECT_FALSE(url.ReplaceSearchTermsInURL( + GURL("http://google.com/alt/?q=#q="), search_terms, + search_terms_data_, &result)); + + EXPECT_FALSE(url.ReplaceSearchTermsInURL( + GURL("http://google.com/alt/?q=123#q="), search_terms, + search_terms_data_, &result)); + + EXPECT_TRUE(url.ReplaceSearchTermsInURL( + GURL("http://google.com/alt/?q=#q=123"), search_terms, + search_terms_data_, &result)); + EXPECT_EQ(GURL("http://google.com/alt/?q=#q=Bob Morane"), result); +} + +// Test the |suggest_query_params| field of SearchTermsArgs. +TEST_F(TemplateURLTest, SuggestQueryParams) { + TemplateURLData data; + // Pick a URL with replacements before, during, and after the query, to ensure + // we don't goof up any of them. + data.SetURL("{google:baseURL}search?q={searchTerms}" + "#{google:originalQueryForSuggestion}x"); + TemplateURL url(data); + + // Baseline: no |suggest_query_params| field. + TemplateURLRef::SearchTermsArgs search_terms(ASCIIToUTF16("abc")); + search_terms.original_query = ASCIIToUTF16("def"); + search_terms.accepted_suggestion = 0; + EXPECT_EQ("http://www.google.com/search?q=abc#oq=def&x", + url.url_ref().ReplaceSearchTerms(search_terms, search_terms_data_)); + + // Set the suggest_query_params. + search_terms.suggest_query_params = "pq=xyz"; + EXPECT_EQ("http://www.google.com/search?pq=xyz&q=abc#oq=def&x", + url.url_ref().ReplaceSearchTerms(search_terms, search_terms_data_)); + + // Add extra_query_params in the mix, and ensure it works. + search_terms.append_extra_query_params = true; + CommandLine::ForCurrentProcess()->AppendSwitchASCII( + switches::kExtraSearchQueryParams, "a=b"); + EXPECT_EQ("http://www.google.com/search?a=b&pq=xyz&q=abc#oq=def&x", + url.url_ref().ReplaceSearchTerms(search_terms, search_terms_data_)); +} + +// Test the |append_extra_query_params| field of SearchTermsArgs. +TEST_F(TemplateURLTest, ExtraQueryParams) { + TemplateURLData data; + // Pick a URL with replacements before, during, and after the query, to ensure + // we don't goof up any of them. + data.SetURL("{google:baseURL}search?q={searchTerms}" + "#{google:originalQueryForSuggestion}x"); + TemplateURL url(data); + + // Baseline: no command-line args, no |append_extra_query_params| flag. + TemplateURLRef::SearchTermsArgs search_terms(ASCIIToUTF16("abc")); + search_terms.original_query = ASCIIToUTF16("def"); + search_terms.accepted_suggestion = 0; + EXPECT_EQ("http://www.google.com/search?q=abc#oq=def&x", + url.url_ref().ReplaceSearchTerms(search_terms, search_terms_data_)); + + // Set the flag. Since there are no command-line args, this should have no + // effect. + search_terms.append_extra_query_params = true; + EXPECT_EQ("http://www.google.com/search?q=abc#oq=def&x", + url.url_ref().ReplaceSearchTerms(search_terms, search_terms_data_)); + + // Now append the command-line arg. This should be inserted into the query. + CommandLine::ForCurrentProcess()->AppendSwitchASCII( + switches::kExtraSearchQueryParams, "a=b"); + EXPECT_EQ("http://www.google.com/search?a=b&q=abc#oq=def&x", + url.url_ref().ReplaceSearchTerms(search_terms, search_terms_data_)); + + // Turn off the flag. Now the command-line arg should be ignored again. + search_terms.append_extra_query_params = false; + EXPECT_EQ("http://www.google.com/search?q=abc#oq=def&x", + url.url_ref().ReplaceSearchTerms(search_terms, search_terms_data_)); +} + +// Tests replacing pageClassification. +TEST_F(TemplateURLTest, ReplacePageClassification) { + TemplateURLData data; + data.input_encodings.push_back("UTF-8"); + data.SetURL("{google:baseURL}?{google:pageClassification}q={searchTerms}"); + TemplateURL url(data); + EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_)); + ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_)); + TemplateURLRef::SearchTermsArgs search_terms_args(ASCIIToUTF16("foo")); + + std::string result = url.url_ref().ReplaceSearchTerms(search_terms_args, + search_terms_data_); + EXPECT_EQ("http://www.google.com/?q=foo", result); + + search_terms_args.page_classification = metrics::OmniboxEventProto::NTP; + result = url.url_ref().ReplaceSearchTerms(search_terms_args, + search_terms_data_); + EXPECT_EQ("http://www.google.com/?pgcl=1&q=foo", result); + + search_terms_args.page_classification = + metrics::OmniboxEventProto::HOME_PAGE; + result = url.url_ref().ReplaceSearchTerms(search_terms_args, + search_terms_data_); + EXPECT_EQ("http://www.google.com/?pgcl=3&q=foo", result); +} + +// Test the IsSearchResults function. +TEST_F(TemplateURLTest, IsSearchResults) { + TemplateURLData data; + data.SetURL("http://bar/search?q={searchTerms}"); + data.instant_url = "http://bar/instant#q={searchTerms}"; + data.new_tab_url = "http://bar/newtab"; + data.alternate_urls.push_back("http://bar/?q={searchTerms}"); + data.alternate_urls.push_back("http://bar/#q={searchTerms}"); + data.alternate_urls.push_back("http://bar/search#q{searchTerms}"); + data.alternate_urls.push_back("http://bar/webhp#q={searchTerms}"); + TemplateURL search_provider(data); + + const struct { + const char* const url; + bool result; + } url_data[] = { + { "http://bar/search?q=foo&oq=foo", true, }, + { "http://bar/?q=foo&oq=foo", true, }, + { "http://bar/#output=search&q=foo&oq=foo", true, }, + { "http://bar/webhp#q=foo&oq=foo", true, }, + { "http://bar/#q=foo&oq=foo", true, }, + { "http://bar/?ext=foo&q=foo#ref=bar", true, }, + { "http://bar/url?url=http://www.foo.com/&q=foo#ref=bar", false, }, + { "http://bar/", false, }, + { "http://foo/", false, }, + { "http://bar/newtab", false, }, + }; + + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(url_data); ++i) { + EXPECT_EQ(url_data[i].result, + search_provider.IsSearchURL(GURL(url_data[i].url), + search_terms_data_)); + } +} + +TEST_F(TemplateURLTest, ReflectsBookmarkBarPinned) { + TemplateURLData data; + data.input_encodings.push_back("UTF-8"); + data.SetURL("{google:baseURL}?{google:bookmarkBarPinned}q={searchTerms}"); + TemplateURL url(data); + EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_)); + ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_)); + TemplateURLRef::SearchTermsArgs search_terms_args(ASCIIToUTF16("foo")); + + // Do not add the param when InstantExtended is suppressed on SRPs. + search_terms_data_.set_is_showing_search_terms_on_search_results_pages(false); + std::string result = url.url_ref().ReplaceSearchTerms(search_terms_args, + search_terms_data_); + EXPECT_EQ("http://www.google.com/?q=foo", result); + + // Add the param when InstantExtended is not suppressed on SRPs. + search_terms_data_.set_is_showing_search_terms_on_search_results_pages(true); + search_terms_args.bookmark_bar_pinned = false; + result = url.url_ref().ReplaceSearchTerms(search_terms_args, + search_terms_data_); + EXPECT_EQ("http://www.google.com/?bmbp=0&q=foo", result); + + search_terms_data_.set_is_showing_search_terms_on_search_results_pages(true); + search_terms_args.bookmark_bar_pinned = true; + result = url.url_ref().ReplaceSearchTerms(search_terms_args, + search_terms_data_); + EXPECT_EQ("http://www.google.com/?bmbp=1&q=foo", result); +} + +TEST_F(TemplateURLTest, AnswersHasVersion) { + TemplateURLData data; + search_terms_data_.set_google_base_url("http://bar/"); + data.SetURL("http://bar/search?q={searchTerms}&{google:searchVersion}xssi=t"); + + TemplateURL url(data); + TemplateURLRef::SearchTermsArgs search_terms_args(ASCIIToUTF16("foo")); + std::string result = url.url_ref().ReplaceSearchTerms(search_terms_args, + search_terms_data_); + EXPECT_EQ("http://bar/search?q=foo&xssi=t", result); + + search_terms_data_.set_enable_answers_in_suggest(true); + TemplateURL url2(data); + result = url2.url_ref().ReplaceSearchTerms(search_terms_args, + search_terms_data_); + EXPECT_EQ("http://bar/search?q=foo&gs_rn=42&xssi=t", result); +} + +TEST_F(TemplateURLTest, SessionToken) { + TemplateURLData data; + search_terms_data_.set_google_base_url("http://bar/"); + data.SetURL("http://bar/search?q={searchTerms}&{google:sessionToken}xssi=t"); + + TemplateURL url(data); + TemplateURLRef::SearchTermsArgs search_terms_args(ASCIIToUTF16("foo")); + search_terms_args.session_token = "SESSIONTOKENGOESHERE"; + std::string result = url.url_ref().ReplaceSearchTerms(search_terms_args, + search_terms_data_); + EXPECT_EQ("http://bar/search?q=foo&psi=SESSIONTOKENGOESHERE&xssi=t", result); + + TemplateURL url2(data); + search_terms_args.session_token = ""; + result = url.url_ref().ReplaceSearchTerms(search_terms_args, + search_terms_data_); + EXPECT_EQ("http://bar/search?q=foo&xssi=t", result); +} + +TEST_F(TemplateURLTest, ContextualSearchParameters) { + TemplateURLData data; + search_terms_data_.set_google_base_url("http://bar/"); + data.SetURL("http://bar/_/contextualsearch?" + "{google:contextualSearchVersion}" + "{google:contextualSearchContextData}"); + + TemplateURL url(data); + TemplateURLRef::SearchTermsArgs search_terms_args(ASCIIToUTF16("foo")); + std::string result = url.url_ref().ReplaceSearchTerms(search_terms_args, + search_terms_data_); + EXPECT_EQ("http://bar/_/contextualsearch?", result); + + TemplateURLRef::SearchTermsArgs::ContextualSearchParams params( + 1, 6, 11, "allen", "woody+allen+movies", "www.wikipedia.org", + "utf-8"); + search_terms_args.contextual_search_params = params; + result = url.url_ref().ReplaceSearchTerms(search_terms_args, + search_terms_data_); + EXPECT_EQ("http://bar/_/contextualsearch?" + "ctxs=1&" + "ctxs_start=6&" + "ctxs_end=11&" + "q=allen&" + "ctxs_content=woody+allen+movies&" + "ctxs_url=www.wikipedia.org&" + "ctxs_encoding=utf-8&", result); +} + +TEST_F(TemplateURLTest, GenerateKeyword) { + ASSERT_EQ(ASCIIToUTF16("foo"), + TemplateURL::GenerateKeyword(GURL("http://foo"))); + // www. should be stripped. + ASSERT_EQ(ASCIIToUTF16("foo"), + TemplateURL::GenerateKeyword(GURL("http://www.foo"))); + // Make sure we don't get a trailing '/'. + ASSERT_EQ(ASCIIToUTF16("blah"), + TemplateURL::GenerateKeyword(GURL("http://blah/"))); + // Don't generate the empty string. + ASSERT_EQ(ASCIIToUTF16("www"), + TemplateURL::GenerateKeyword(GURL("http://www."))); +} + +TEST_F(TemplateURLTest, GenerateSearchURL) { + struct GenerateSearchURLCase { + const char* test_name; + const char* url; + const char* expected; + } generate_url_cases[] = { + { "invalid URL", "foo{searchTerms}", "" }, + { "URL with no replacements", "http://foo/", "http://foo/" }, + { "basic functionality", "http://foo/{searchTerms}", + "http://foo/blah.blah.blah.blah.blah" } + }; + + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(generate_url_cases); ++i) { + TemplateURLData data; + data.SetURL(generate_url_cases[i].url); + TemplateURL t_url(data); + EXPECT_EQ(t_url.GenerateSearchURL(search_terms_data_).spec(), + generate_url_cases[i].expected) + << generate_url_cases[i].test_name << " failed."; + } +} + +TEST_F(TemplateURLTest, PrefetchQueryParameters) { + TemplateURLData data; + search_terms_data_.set_google_base_url("http://bar/"); + data.SetURL("http://bar/search?q={searchTerms}&{google:prefetchQuery}xssi=t"); + + TemplateURL url(data); + TemplateURLRef::SearchTermsArgs search_terms_args(ASCIIToUTF16("foo")); + search_terms_args.prefetch_query = "full query text"; + search_terms_args.prefetch_query_type = "2338"; + std::string result = + url.url_ref().ReplaceSearchTerms(search_terms_args, search_terms_data_); + EXPECT_EQ("http://bar/search?q=foo&pfq=full%20query%20text&qha=2338&xssi=t", + result); + + TemplateURL url2(data); + search_terms_args.prefetch_query.clear(); + search_terms_args.prefetch_query_type.clear(); + result = + url2.url_ref().ReplaceSearchTerms(search_terms_args, search_terms_data_); + EXPECT_EQ("http://bar/search?q=foo&xssi=t", result); +} |