Home | History | Annotate | Download | only in search_engines
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/base_paths.h"
      6 #include "base/command_line.h"
      7 #include "base/strings/string_number_conversions.h"
      8 #include "base/strings/string_util.h"
      9 #include "base/strings/utf_string_conversions.h"
     10 #include "chrome/browser/search_engines/template_url.h"
     11 #include "chrome/common/chrome_switches.h"
     12 #include "components/metrics/proto/omnibox_event.pb.h"
     13 #include "components/metrics/proto/omnibox_input_type.pb.h"
     14 #include "components/search_engines/search_terms_data.h"
     15 #include "testing/gtest/include/gtest/gtest.h"
     16 
     17 using base::ASCIIToUTF16;
     18 
     19 // TestSearchTermsData --------------------------------------------------------
     20 
     21 // Simple implementation of SearchTermsData.
     22 class TestSearchTermsData : public SearchTermsData {
     23  public:
     24   explicit TestSearchTermsData(const std::string& google_base_url);
     25 
     26   virtual std::string GoogleBaseURLValue() const OVERRIDE;
     27   virtual base::string16 GetRlzParameterValue(
     28       bool from_app_list) const OVERRIDE;
     29   virtual std::string GetSearchClient() const OVERRIDE;
     30   virtual std::string GoogleImageSearchSource() const OVERRIDE;
     31 
     32   void set_google_base_url(const std::string& google_base_url) {
     33     google_base_url_ = google_base_url;
     34   }
     35   void set_search_client(const std::string& search_client) {
     36     search_client_ = search_client;
     37   }
     38 
     39  private:
     40   std::string google_base_url_;
     41   std::string search_client_;
     42 
     43   DISALLOW_COPY_AND_ASSIGN(TestSearchTermsData);
     44 };
     45 
     46 TestSearchTermsData::TestSearchTermsData(const std::string& google_base_url)
     47     : google_base_url_(google_base_url) {
     48 }
     49 
     50 std::string TestSearchTermsData::GoogleBaseURLValue() const {
     51   return google_base_url_;
     52 }
     53 
     54 base::string16 TestSearchTermsData::GetRlzParameterValue(
     55     bool from_app_list) const {
     56   return ASCIIToUTF16(
     57       from_app_list ? "rlz_parameter_from_app_list" : "rlz_parameter");
     58 }
     59 
     60 std::string TestSearchTermsData::GetSearchClient() const {
     61   return search_client_;
     62 }
     63 
     64 std::string TestSearchTermsData::GoogleImageSearchSource() const {
     65   return "google_image_search_source";
     66 }
     67 
     68 // TemplateURLTest ------------------------------------------------------------
     69 
     70 class TemplateURLTest : public testing::Test {
     71  public:
     72   TemplateURLTest() : search_terms_data_("http://www.google.com/") {}
     73   void CheckSuggestBaseURL(const std::string& base_url,
     74                            const std::string& base_suggest_url) const;
     75 
     76   TestSearchTermsData search_terms_data_;
     77 };
     78 
     79 void TemplateURLTest::CheckSuggestBaseURL(
     80     const std::string& base_url,
     81     const std::string& base_suggest_url) const {
     82   TestSearchTermsData search_terms_data(base_url);
     83   EXPECT_EQ(base_suggest_url, search_terms_data.GoogleBaseSuggestURLValue());
     84 }
     85 
     86 
     87 // Actual tests ---------------------------------------------------------------
     88 
     89 TEST_F(TemplateURLTest, Defaults) {
     90   TemplateURLData data;
     91   EXPECT_FALSE(data.show_in_default_list);
     92   EXPECT_FALSE(data.safe_for_autoreplace);
     93   EXPECT_EQ(0, data.prepopulate_id);
     94 }
     95 
     96 TEST_F(TemplateURLTest, TestValidWithComplete) {
     97   TemplateURLData data;
     98   data.SetURL("{searchTerms}");
     99   TemplateURL url(data);
    100   EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
    101 }
    102 
    103 TEST_F(TemplateURLTest, URLRefTestSearchTerms) {
    104   struct SearchTermsCase {
    105     const char* url;
    106     const base::string16 terms;
    107     const std::string output;
    108   } search_term_cases[] = {
    109     { "http://foo{searchTerms}", ASCIIToUTF16("sea rch/bar"),
    110       "http://foosea%20rch/bar" },
    111     { "http://foo{searchTerms}?boo=abc", ASCIIToUTF16("sea rch/bar"),
    112       "http://foosea%20rch/bar?boo=abc" },
    113     { "http://foo/?boo={searchTerms}", ASCIIToUTF16("sea rch/bar"),
    114       "http://foo/?boo=sea+rch%2Fbar" },
    115     { "http://en.wikipedia.org/{searchTerms}", ASCIIToUTF16("wiki/?"),
    116       "http://en.wikipedia.org/wiki/%3F" }
    117   };
    118   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(search_term_cases); ++i) {
    119     const SearchTermsCase& value = search_term_cases[i];
    120     TemplateURLData data;
    121     data.SetURL(value.url);
    122     TemplateURL url(data);
    123     EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
    124     ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
    125     GURL result(url.url_ref().ReplaceSearchTerms(
    126         TemplateURLRef::SearchTermsArgs(value.terms), search_terms_data_));
    127     ASSERT_TRUE(result.is_valid());
    128     EXPECT_EQ(value.output, result.spec());
    129   }
    130 }
    131 
    132 TEST_F(TemplateURLTest, URLRefTestCount) {
    133   TemplateURLData data;
    134   data.SetURL("http://foo{searchTerms}{count?}");
    135   TemplateURL url(data);
    136   EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
    137   ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
    138   GURL result(url.url_ref().ReplaceSearchTerms(
    139       TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("X")), search_terms_data_));
    140   ASSERT_TRUE(result.is_valid());
    141   EXPECT_EQ("http://foox/", result.spec());
    142 }
    143 
    144 TEST_F(TemplateURLTest, URLRefTestCount2) {
    145   TemplateURLData data;
    146   data.SetURL("http://foo{searchTerms}{count}");
    147   TemplateURL url(data);
    148   EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
    149   ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
    150   GURL result(url.url_ref().ReplaceSearchTerms(
    151       TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("X")), search_terms_data_));
    152   ASSERT_TRUE(result.is_valid());
    153   EXPECT_EQ("http://foox10/", result.spec());
    154 }
    155 
    156 TEST_F(TemplateURLTest, URLRefTestIndices) {
    157   TemplateURLData data;
    158   data.SetURL("http://foo{searchTerms}x{startIndex?}y{startPage?}");
    159   TemplateURL url(data);
    160   EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
    161   ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
    162   GURL result(url.url_ref().ReplaceSearchTerms(
    163       TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("X")), search_terms_data_));
    164   ASSERT_TRUE(result.is_valid());
    165   EXPECT_EQ("http://fooxxy/", result.spec());
    166 }
    167 
    168 TEST_F(TemplateURLTest, URLRefTestIndices2) {
    169   TemplateURLData data;
    170   data.SetURL("http://foo{searchTerms}x{startIndex}y{startPage}");
    171   TemplateURL url(data);
    172   EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
    173   ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
    174   GURL result(url.url_ref().ReplaceSearchTerms(
    175       TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("X")), search_terms_data_));
    176   ASSERT_TRUE(result.is_valid());
    177   EXPECT_EQ("http://fooxx1y1/", result.spec());
    178 }
    179 
    180 TEST_F(TemplateURLTest, URLRefTestEncoding) {
    181   TemplateURLData data;
    182   data.SetURL("http://foo{searchTerms}x{inputEncoding?}y{outputEncoding?}a");
    183   TemplateURL url(data);
    184   EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
    185   ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
    186   GURL result(url.url_ref().ReplaceSearchTerms(
    187       TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("X")), search_terms_data_));
    188   ASSERT_TRUE(result.is_valid());
    189   EXPECT_EQ("http://fooxxutf-8ya/", result.spec());
    190 }
    191 
    192 TEST_F(TemplateURLTest, URLRefTestImageURLWithPOST) {
    193   const char kInvalidPostParamsString[] =
    194       "unknown_template={UnknownTemplate},bad_value=bad{value},"
    195       "{google:sbiSource}";
    196   // List all accpectable parameter format in valid_post_params_string. it is
    197   // expected like: "name0=,name1=value1,name2={template1}"
    198   const char kValidPostParamsString[] =
    199       "image_content={google:imageThumbnail},image_url={google:imageURL},"
    200       "sbisrc={google:imageSearchSource},language={language},empty_param=,"
    201       "constant_param=constant,width={google:imageOriginalWidth}";
    202   const char KImageSearchURL[] = "http://foo.com/sbi";
    203 
    204   TemplateURLData data;
    205   data.image_url = KImageSearchURL;
    206 
    207   // Try to parse invalid post parameters.
    208   data.image_url_post_params = kInvalidPostParamsString;
    209   TemplateURL url_bad(data);
    210   ASSERT_FALSE(url_bad.image_url_ref().IsValid(search_terms_data_));
    211   const TemplateURLRef::PostParams& bad_post_params =
    212       url_bad.image_url_ref().post_params_;
    213   ASSERT_EQ(2U, bad_post_params.size());
    214   EXPECT_EQ("unknown_template", bad_post_params[0].first);
    215   EXPECT_EQ("{UnknownTemplate}", bad_post_params[0].second);
    216   EXPECT_EQ("bad_value", bad_post_params[1].first);
    217   EXPECT_EQ("bad{value}", bad_post_params[1].second);
    218 
    219   // Try to parse valid post parameters.
    220   data.image_url_post_params = kValidPostParamsString;
    221   TemplateURL url(data);
    222   ASSERT_TRUE(url.image_url_ref().IsValid(search_terms_data_));
    223   ASSERT_FALSE(url.image_url_ref().SupportsReplacement(search_terms_data_));
    224 
    225   // Check term replacement.
    226   TemplateURLRef::SearchTermsArgs search_args(ASCIIToUTF16("X"));
    227   search_args.image_thumbnail_content = "dummy-image-thumbnail";
    228   search_args.image_url = GURL("http://dummyimage.com/dummy.jpg");
    229   search_args.image_original_size = gfx::Size(10, 10);
    230   // Replacement operation with no post_data buffer should still return
    231   // the parsed URL.
    232   TestSearchTermsData search_terms_data("http://X");
    233   GURL result(url.image_url_ref().ReplaceSearchTerms(
    234       search_args, search_terms_data));
    235   ASSERT_TRUE(result.is_valid());
    236   EXPECT_EQ(KImageSearchURL, result.spec());
    237   TemplateURLRef::PostContent post_content;
    238   result = GURL(url.image_url_ref().ReplaceSearchTerms(
    239       search_args, search_terms_data, &post_content));
    240   ASSERT_TRUE(result.is_valid());
    241   EXPECT_EQ(KImageSearchURL, result.spec());
    242   ASSERT_FALSE(post_content.first.empty());
    243   ASSERT_FALSE(post_content.second.empty());
    244 
    245   // Check parsed result of post parameters.
    246   const TemplateURLRef::Replacements& replacements =
    247       url.image_url_ref().replacements_;
    248   const TemplateURLRef::PostParams& post_params =
    249       url.image_url_ref().post_params_;
    250   EXPECT_EQ(7U, post_params.size());
    251   for (TemplateURLRef::PostParams::const_iterator i = post_params.begin();
    252        i != post_params.end(); ++i) {
    253     TemplateURLRef::Replacements::const_iterator j = replacements.begin();
    254     for (; j != replacements.end(); ++j) {
    255       if (j->is_post_param && j->index ==
    256           static_cast<size_t>(i - post_params.begin())) {
    257         switch (j->type) {
    258           case TemplateURLRef::GOOGLE_IMAGE_ORIGINAL_WIDTH:
    259             EXPECT_EQ("width", i->first);
    260             EXPECT_EQ(
    261                 base::IntToString(search_args.image_original_size.width()),
    262                 i->second);
    263             break;
    264           case TemplateURLRef::GOOGLE_IMAGE_SEARCH_SOURCE:
    265             EXPECT_EQ("sbisrc", i->first);
    266             EXPECT_EQ(search_terms_data.GoogleImageSearchSource(), i->second);
    267             break;
    268           case TemplateURLRef::GOOGLE_IMAGE_THUMBNAIL:
    269             EXPECT_EQ("image_content", i->first);
    270             EXPECT_EQ(search_args.image_thumbnail_content, i->second);
    271             break;
    272           case TemplateURLRef::GOOGLE_IMAGE_URL:
    273             EXPECT_EQ("image_url", i->first);
    274             EXPECT_EQ(search_args.image_url.spec(), i->second);
    275             break;
    276           case TemplateURLRef::LANGUAGE:
    277             EXPECT_EQ("language", i->first);
    278             EXPECT_EQ("en", i->second);
    279             break;
    280           default:
    281             ADD_FAILURE();  // Should never go here.
    282         }
    283         break;
    284       }
    285     }
    286     if (j != replacements.end())
    287       continue;
    288     if (i->first == "empty_param") {
    289       EXPECT_TRUE(i->second.empty());
    290     } else if (i->first == "sbisrc") {
    291       EXPECT_FALSE(i->second.empty());
    292     } else {
    293       EXPECT_EQ("constant_param", i->first);
    294       EXPECT_EQ("constant", i->second);
    295     }
    296   }
    297 }
    298 
    299 // Test that setting the prepopulate ID from TemplateURL causes the stored
    300 // TemplateURLRef to handle parsing the URL parameters differently.
    301 TEST_F(TemplateURLTest, SetPrepopulatedAndParse) {
    302   TemplateURLData data;
    303   data.SetURL("http://foo{fhqwhgads}bar");
    304   TemplateURL url(data);
    305   TemplateURLRef::Replacements replacements;
    306   bool valid = false;
    307   EXPECT_EQ("http://foo{fhqwhgads}bar", url.url_ref().ParseURL(
    308       "http://foo{fhqwhgads}bar", &replacements, NULL, &valid));
    309   EXPECT_TRUE(replacements.empty());
    310   EXPECT_TRUE(valid);
    311 
    312   data.prepopulate_id = 123;
    313   TemplateURL url2(data);
    314   EXPECT_EQ("http://foobar", url2.url_ref().ParseURL("http://foo{fhqwhgads}bar",
    315                                                      &replacements, NULL,
    316                                                      &valid));
    317   EXPECT_TRUE(replacements.empty());
    318   EXPECT_TRUE(valid);
    319 }
    320 
    321 TEST_F(TemplateURLTest, InputEncodingBeforeSearchTerm) {
    322   TemplateURLData data;
    323   data.SetURL("http://foox{inputEncoding?}a{searchTerms}y{outputEncoding?}b");
    324   TemplateURL url(data);
    325   EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
    326   ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
    327   GURL result(url.url_ref().ReplaceSearchTerms(
    328       TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("X")), search_terms_data_));
    329   ASSERT_TRUE(result.is_valid());
    330   EXPECT_EQ("http://fooxutf-8axyb/", result.spec());
    331 }
    332 
    333 TEST_F(TemplateURLTest, URLRefTestEncoding2) {
    334   TemplateURLData data;
    335   data.SetURL("http://foo{searchTerms}x{inputEncoding}y{outputEncoding}a");
    336   TemplateURL url(data);
    337   EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
    338   ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
    339   GURL result(url.url_ref().ReplaceSearchTerms(
    340       TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("X")), search_terms_data_));
    341   ASSERT_TRUE(result.is_valid());
    342   EXPECT_EQ("http://fooxxutf-8yutf-8a/", result.spec());
    343 }
    344 
    345 TEST_F(TemplateURLTest, URLRefTestSearchTermsUsingTermsData) {
    346   struct SearchTermsCase {
    347     const char* url;
    348     const base::string16 terms;
    349     const char* output;
    350   } search_term_cases[] = {
    351     { "{google:baseURL}{language}{searchTerms}", base::string16(),
    352       "http://example.com/e/en" },
    353     { "{google:baseSuggestURL}{searchTerms}", base::string16(),
    354       "http://example.com/complete/" }
    355   };
    356 
    357   TestSearchTermsData search_terms_data("http://example.com/e/");
    358   TemplateURLData data;
    359   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(search_term_cases); ++i) {
    360     const SearchTermsCase& value = search_term_cases[i];
    361     data.SetURL(value.url);
    362     TemplateURL url(data);
    363     EXPECT_TRUE(url.url_ref().IsValid(search_terms_data));
    364     ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data));
    365     GURL result(url.url_ref().ReplaceSearchTerms(
    366         TemplateURLRef::SearchTermsArgs(value.terms), search_terms_data, NULL));
    367     ASSERT_TRUE(result.is_valid());
    368     EXPECT_EQ(value.output, result.spec());
    369   }
    370 }
    371 
    372 TEST_F(TemplateURLTest, URLRefTermToWide) {
    373   struct ToWideCase {
    374     const char* encoded_search_term;
    375     const base::string16 expected_decoded_term;
    376   } to_wide_cases[] = {
    377     {"hello+world", ASCIIToUTF16("hello world")},
    378     // Test some big-5 input.
    379     {"%a7A%A6%6e+to+you", base::WideToUTF16(L"\x4f60\x597d to you")},
    380     // Test some UTF-8 input. We should fall back to this when the encoding
    381     // doesn't look like big-5. We have a '5' in the middle, which is an invalid
    382     // Big-5 trailing byte.
    383     {"%e4%bd%a05%e5%a5%bd+to+you",
    384         base::WideToUTF16(L"\x4f60\x35\x597d to you")},
    385     // Undecodable input should stay escaped.
    386     {"%91%01+abcd", base::WideToUTF16(L"%91%01 abcd")},
    387     // Make sure we convert %2B to +.
    388     {"C%2B%2B", ASCIIToUTF16("C++")},
    389     // C%2B is escaped as C%252B, make sure we unescape it properly.
    390     {"C%252B", ASCIIToUTF16("C%2B")},
    391   };
    392 
    393   // Set one input encoding: big-5. This is so we can test fallback to UTF-8.
    394   TemplateURLData data;
    395   data.SetURL("http://foo?q={searchTerms}");
    396   data.input_encodings.push_back("big-5");
    397   TemplateURL url(data);
    398   EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
    399   ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
    400   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(to_wide_cases); i++) {
    401     EXPECT_EQ(to_wide_cases[i].expected_decoded_term,
    402               url.url_ref().SearchTermToString16(
    403                   to_wide_cases[i].encoded_search_term));
    404   }
    405 }
    406 
    407 TEST_F(TemplateURLTest, DisplayURLToURLRef) {
    408   struct TestData {
    409     const std::string url;
    410     const base::string16 expected_result;
    411   } test_data[] = {
    412     { "http://foo{searchTerms}x{inputEncoding}y{outputEncoding}a",
    413       ASCIIToUTF16("http://foo%sx{inputEncoding}y{outputEncoding}a") },
    414     { "http://X",
    415       ASCIIToUTF16("http://X") },
    416     { "http://foo{searchTerms",
    417       ASCIIToUTF16("http://foo{searchTerms") },
    418     { "http://foo{searchTerms}{language}",
    419       ASCIIToUTF16("http://foo%s{language}") },
    420   };
    421   TemplateURLData data;
    422   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
    423     data.SetURL(test_data[i].url);
    424     TemplateURL url(data);
    425     EXPECT_EQ(test_data[i].expected_result,
    426               url.url_ref().DisplayURL(search_terms_data_));
    427     EXPECT_EQ(test_data[i].url,
    428               TemplateURLRef::DisplayURLToURLRef(
    429                   url.url_ref().DisplayURL(search_terms_data_)));
    430   }
    431 }
    432 
    433 TEST_F(TemplateURLTest, ReplaceSearchTerms) {
    434   struct TestData {
    435     const std::string url;
    436     const std::string expected_result;
    437   } test_data[] = {
    438     { "http://foo/{language}{searchTerms}{inputEncoding}",
    439       "http://foo/{language}XUTF-8" },
    440     { "http://foo/{language}{inputEncoding}{searchTerms}",
    441       "http://foo/{language}UTF-8X" },
    442     { "http://foo/{searchTerms}{language}{inputEncoding}",
    443       "http://foo/X{language}UTF-8" },
    444     { "http://foo/{searchTerms}{inputEncoding}{language}",
    445       "http://foo/XUTF-8{language}" },
    446     { "http://foo/{inputEncoding}{searchTerms}{language}",
    447       "http://foo/UTF-8X{language}" },
    448     { "http://foo/{inputEncoding}{language}{searchTerms}",
    449       "http://foo/UTF-8{language}X" },
    450     { "http://foo/{language}a{searchTerms}a{inputEncoding}a",
    451       "http://foo/{language}aXaUTF-8a" },
    452     { "http://foo/{language}a{inputEncoding}a{searchTerms}a",
    453       "http://foo/{language}aUTF-8aXa" },
    454     { "http://foo/{searchTerms}a{language}a{inputEncoding}a",
    455       "http://foo/Xa{language}aUTF-8a" },
    456     { "http://foo/{searchTerms}a{inputEncoding}a{language}a",
    457       "http://foo/XaUTF-8a{language}a" },
    458     { "http://foo/{inputEncoding}a{searchTerms}a{language}a",
    459       "http://foo/UTF-8aXa{language}a" },
    460     { "http://foo/{inputEncoding}a{language}a{searchTerms}a",
    461       "http://foo/UTF-8a{language}aXa" },
    462   };
    463   TemplateURLData data;
    464   data.input_encodings.push_back("UTF-8");
    465   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
    466     data.SetURL(test_data[i].url);
    467     TemplateURL url(data);
    468     EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
    469     ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
    470     std::string expected_result = test_data[i].expected_result;
    471     ReplaceSubstringsAfterOffset(&expected_result, 0, "{language}",
    472                                  search_terms_data_.GetApplicationLocale());
    473     GURL result(url.url_ref().ReplaceSearchTerms(
    474         TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("X")),
    475         search_terms_data_));
    476     ASSERT_TRUE(result.is_valid());
    477     EXPECT_EQ(expected_result, result.spec());
    478   }
    479 }
    480 
    481 
    482 // Tests replacing search terms in various encodings and making sure the
    483 // generated URL matches the expected value.
    484 TEST_F(TemplateURLTest, ReplaceArbitrarySearchTerms) {
    485   struct TestData {
    486     const std::string encoding;
    487     const base::string16 search_term;
    488     const std::string url;
    489     const std::string expected_result;
    490   } test_data[] = {
    491     { "BIG5",  base::WideToUTF16(L"\x60BD"),
    492       "http://foo/?{searchTerms}{inputEncoding}",
    493       "http://foo/?%B1~BIG5" },
    494     { "UTF-8", ASCIIToUTF16("blah"),
    495       "http://foo/?{searchTerms}{inputEncoding}",
    496       "http://foo/?blahUTF-8" },
    497     { "Shift_JIS", base::UTF8ToUTF16("\xe3\x81\x82"),
    498       "http://foo/{searchTerms}/bar",
    499       "http://foo/%82%A0/bar"},
    500     { "Shift_JIS", base::UTF8ToUTF16("\xe3\x81\x82 \xe3\x81\x84"),
    501       "http://foo/{searchTerms}/bar",
    502       "http://foo/%82%A0%20%82%A2/bar"},
    503   };
    504   TemplateURLData data;
    505   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
    506     data.SetURL(test_data[i].url);
    507     data.input_encodings.clear();
    508     data.input_encodings.push_back(test_data[i].encoding);
    509     TemplateURL url(data);
    510     EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
    511     ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
    512     GURL result(url.url_ref().ReplaceSearchTerms(
    513         TemplateURLRef::SearchTermsArgs(test_data[i].search_term),
    514         search_terms_data_));
    515     ASSERT_TRUE(result.is_valid());
    516     EXPECT_EQ(test_data[i].expected_result, result.spec());
    517   }
    518 }
    519 
    520 // Tests replacing assisted query stats (AQS) in various scenarios.
    521 TEST_F(TemplateURLTest, ReplaceAssistedQueryStats) {
    522   struct TestData {
    523     const base::string16 search_term;
    524     const std::string aqs;
    525     const std::string base_url;
    526     const std::string url;
    527     const std::string expected_result;
    528   } test_data[] = {
    529     // No HTTPS, no AQS.
    530     { ASCIIToUTF16("foo"),
    531       "chrome.0.0l6",
    532       "http://foo/",
    533       "{google:baseURL}?{searchTerms}{google:assistedQueryStats}",
    534       "http://foo/?foo" },
    535     // HTTPS available, AQS should be replaced.
    536     { ASCIIToUTF16("foo"),
    537       "chrome.0.0l6",
    538       "https://foo/",
    539       "{google:baseURL}?{searchTerms}{google:assistedQueryStats}",
    540       "https://foo/?fooaqs=chrome.0.0l6&" },
    541     // HTTPS available, however AQS is empty.
    542     { ASCIIToUTF16("foo"),
    543       "",
    544       "https://foo/",
    545       "{google:baseURL}?{searchTerms}{google:assistedQueryStats}",
    546       "https://foo/?foo" },
    547     // No {google:baseURL} and protocol is HTTP, we must not substitute AQS.
    548     { ASCIIToUTF16("foo"),
    549       "chrome.0.0l6",
    550       "http://www.google.com",
    551       "http://foo?{searchTerms}{google:assistedQueryStats}",
    552       "http://foo/?foo" },
    553     // A non-Google search provider with HTTPS should allow AQS.
    554     { ASCIIToUTF16("foo"),
    555       "chrome.0.0l6",
    556       "https://www.google.com",
    557       "https://foo?{searchTerms}{google:assistedQueryStats}",
    558       "https://foo/?fooaqs=chrome.0.0l6&" },
    559   };
    560   TemplateURLData data;
    561   data.input_encodings.push_back("UTF-8");
    562   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
    563     data.SetURL(test_data[i].url);
    564     TemplateURL url(data);
    565     EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
    566     ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
    567     TemplateURLRef::SearchTermsArgs search_terms_args(test_data[i].search_term);
    568     search_terms_args.assisted_query_stats = test_data[i].aqs;
    569     search_terms_data_.set_google_base_url(test_data[i].base_url);
    570     GURL result(url.url_ref().ReplaceSearchTerms(search_terms_args,
    571                                                  search_terms_data_));
    572     ASSERT_TRUE(result.is_valid());
    573     EXPECT_EQ(test_data[i].expected_result, result.spec());
    574   }
    575 }
    576 
    577 // Tests replacing cursor position.
    578 TEST_F(TemplateURLTest, ReplaceCursorPosition) {
    579   struct TestData {
    580     const base::string16 search_term;
    581     size_t cursor_position;
    582     const std::string url;
    583     const std::string expected_result;
    584   } test_data[] = {
    585     { ASCIIToUTF16("foo"),
    586       base::string16::npos,
    587       "{google:baseURL}?{searchTerms}&{google:cursorPosition}",
    588       "http://www.google.com/?foo&" },
    589     { ASCIIToUTF16("foo"),
    590       2,
    591       "{google:baseURL}?{searchTerms}&{google:cursorPosition}",
    592       "http://www.google.com/?foo&cp=2&" },
    593     { ASCIIToUTF16("foo"),
    594       15,
    595       "{google:baseURL}?{searchTerms}&{google:cursorPosition}",
    596       "http://www.google.com/?foo&cp=15&" },
    597   };
    598   TemplateURLData data;
    599   data.input_encodings.push_back("UTF-8");
    600   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
    601     data.SetURL(test_data[i].url);
    602     TemplateURL url(data);
    603     EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
    604     ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
    605     TemplateURLRef::SearchTermsArgs search_terms_args(test_data[i].search_term);
    606     search_terms_args.cursor_position = test_data[i].cursor_position;
    607     GURL result(url.url_ref().ReplaceSearchTerms(search_terms_args,
    608                                                  search_terms_data_));
    609     ASSERT_TRUE(result.is_valid());
    610     EXPECT_EQ(test_data[i].expected_result, result.spec());
    611   }
    612 }
    613 
    614 // Tests replacing input type (&oit=).
    615 TEST_F(TemplateURLTest, ReplaceInputType) {
    616   struct TestData {
    617     const base::string16 search_term;
    618     metrics::OmniboxInputType::Type input_type;
    619     const std::string url;
    620     const std::string expected_result;
    621   } test_data[] = {
    622     { ASCIIToUTF16("foo"),
    623       metrics::OmniboxInputType::UNKNOWN,
    624       "{google:baseURL}?{searchTerms}&{google:inputType}",
    625       "http://www.google.com/?foo&oit=1&" },
    626     { ASCIIToUTF16("foo"),
    627       metrics::OmniboxInputType::URL,
    628       "{google:baseURL}?{searchTerms}&{google:inputType}",
    629       "http://www.google.com/?foo&oit=3&" },
    630     { ASCIIToUTF16("foo"),
    631       metrics::OmniboxInputType::FORCED_QUERY,
    632       "{google:baseURL}?{searchTerms}&{google:inputType}",
    633       "http://www.google.com/?foo&oit=5&" },
    634   };
    635   TemplateURLData data;
    636   data.input_encodings.push_back("UTF-8");
    637   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
    638     data.SetURL(test_data[i].url);
    639     TemplateURL url(data);
    640     EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
    641     ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
    642     TemplateURLRef::SearchTermsArgs search_terms_args(test_data[i].search_term);
    643     search_terms_args.input_type = test_data[i].input_type;
    644     GURL result(url.url_ref().ReplaceSearchTerms(search_terms_args,
    645                                                  search_terms_data_));
    646     ASSERT_TRUE(result.is_valid());
    647     EXPECT_EQ(test_data[i].expected_result, result.spec());
    648   }
    649 }
    650 
    651 // Tests replacing currentPageUrl.
    652 TEST_F(TemplateURLTest, ReplaceCurrentPageUrl) {
    653   struct TestData {
    654     const base::string16 search_term;
    655     const std::string current_page_url;
    656     const std::string url;
    657     const std::string expected_result;
    658   } test_data[] = {
    659     { ASCIIToUTF16("foo"),
    660       "http://www.google.com/",
    661       "{google:baseURL}?{searchTerms}&{google:currentPageUrl}",
    662       "http://www.google.com/?foo&url=http%3A%2F%2Fwww.google.com%2F&" },
    663     { ASCIIToUTF16("foo"),
    664       "",
    665       "{google:baseURL}?{searchTerms}&{google:currentPageUrl}",
    666       "http://www.google.com/?foo&" },
    667     { ASCIIToUTF16("foo"),
    668       "http://g.com/+-/*&=",
    669       "{google:baseURL}?{searchTerms}&{google:currentPageUrl}",
    670       "http://www.google.com/?foo&url=http%3A%2F%2Fg.com%2F%2B-%2F*%26%3D&" },
    671   };
    672   TemplateURLData data;
    673   data.input_encodings.push_back("UTF-8");
    674   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
    675     data.SetURL(test_data[i].url);
    676     TemplateURL url(data);
    677     EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
    678     ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
    679     TemplateURLRef::SearchTermsArgs search_terms_args(test_data[i].search_term);
    680     search_terms_args.current_page_url = test_data[i].current_page_url;
    681     GURL result(url.url_ref().ReplaceSearchTerms(search_terms_args,
    682                                                  search_terms_data_));
    683     ASSERT_TRUE(result.is_valid());
    684     EXPECT_EQ(test_data[i].expected_result, result.spec());
    685   }
    686 }
    687 
    688 TEST_F(TemplateURLTest, Suggestions) {
    689   struct TestData {
    690     const int accepted_suggestion;
    691     const base::string16 original_query_for_suggestion;
    692     const std::string expected_result;
    693   } test_data[] = {
    694     { TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, base::string16(),
    695       "http://bar/foo?q=foobar" },
    696     { TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, ASCIIToUTF16("foo"),
    697       "http://bar/foo?q=foobar" },
    698     { TemplateURLRef::NO_SUGGESTION_CHOSEN, base::string16(),
    699       "http://bar/foo?q=foobar" },
    700     { TemplateURLRef::NO_SUGGESTION_CHOSEN, ASCIIToUTF16("foo"),
    701       "http://bar/foo?q=foobar" },
    702     { 0, base::string16(), "http://bar/foo?oq=&q=foobar" },
    703     { 1, ASCIIToUTF16("foo"), "http://bar/foo?oq=foo&q=foobar" },
    704   };
    705   TemplateURLData data;
    706   data.SetURL("http://bar/foo?{google:originalQueryForSuggestion}"
    707               "q={searchTerms}");
    708   data.input_encodings.push_back("UTF-8");
    709   TemplateURL url(data);
    710   EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
    711   ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
    712   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
    713     TemplateURLRef::SearchTermsArgs search_terms_args(
    714         ASCIIToUTF16("foobar"));
    715     search_terms_args.accepted_suggestion = test_data[i].accepted_suggestion;
    716     search_terms_args.original_query =
    717         test_data[i].original_query_for_suggestion;
    718     GURL result(url.url_ref().ReplaceSearchTerms(search_terms_args,
    719                                                  search_terms_data_));
    720     ASSERT_TRUE(result.is_valid());
    721     EXPECT_EQ(test_data[i].expected_result, result.spec());
    722   }
    723 }
    724 
    725 TEST_F(TemplateURLTest, RLZ) {
    726   base::string16 rlz_string = search_terms_data_.GetRlzParameterValue(false);
    727 
    728   TemplateURLData data;
    729   data.SetURL("http://bar/?{google:RLZ}{searchTerms}");
    730   TemplateURL url(data);
    731   EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
    732   ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
    733   GURL result(url.url_ref().ReplaceSearchTerms(
    734       TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("x")), search_terms_data_));
    735   ASSERT_TRUE(result.is_valid());
    736   EXPECT_EQ("http://bar/?rlz=" + base::UTF16ToUTF8(rlz_string) + "&x",
    737             result.spec());
    738 }
    739 
    740 TEST_F(TemplateURLTest, RLZFromAppList) {
    741   base::string16 rlz_string = search_terms_data_.GetRlzParameterValue(true);
    742 
    743   TemplateURLData data;
    744   data.SetURL("http://bar/?{google:RLZ}{searchTerms}");
    745   TemplateURL url(data);
    746   EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
    747   ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
    748   TemplateURLRef::SearchTermsArgs args(ASCIIToUTF16("x"));
    749   args.from_app_list = true;
    750   GURL result(url.url_ref().ReplaceSearchTerms(args, search_terms_data_));
    751   ASSERT_TRUE(result.is_valid());
    752   EXPECT_EQ("http://bar/?rlz=" + base::UTF16ToUTF8(rlz_string) + "&x",
    753             result.spec());
    754 }
    755 
    756 TEST_F(TemplateURLTest, HostAndSearchTermKey) {
    757   struct TestData {
    758     const std::string url;
    759     const std::string host;
    760     const std::string path;
    761     const std::string search_term_key;
    762   } test_data[] = {
    763     { "http://blah/?foo=bar&q={searchTerms}&b=x", "blah", "/", "q"},
    764 
    765     // No query key should result in empty values.
    766     { "http://blah/{searchTerms}", "", "", ""},
    767 
    768     // No term should result in empty values.
    769     { "http://blah/", "", "", ""},
    770 
    771     // Multiple terms should result in empty values.
    772     { "http://blah/?q={searchTerms}&x={searchTerms}", "", "", ""},
    773 
    774     // Term in the host shouldn't match.
    775     { "http://{searchTerms}", "", "", ""},
    776 
    777     { "http://blah/?q={searchTerms}", "blah", "/", "q"},
    778     { "https://blah/?q={searchTerms}", "blah", "/", "q"},
    779 
    780     // Single term with extra chars in value should match.
    781     { "http://blah/?q=stock:{searchTerms}", "blah", "/", "q"},
    782   };
    783 
    784   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
    785     TemplateURLData data;
    786     data.SetURL(test_data[i].url);
    787     TemplateURL url(data);
    788     EXPECT_EQ(test_data[i].host, url.url_ref().GetHost(search_terms_data_));
    789     EXPECT_EQ(test_data[i].path, url.url_ref().GetPath(search_terms_data_));
    790     EXPECT_EQ(test_data[i].search_term_key,
    791               url.url_ref().GetSearchTermKey(search_terms_data_));
    792   }
    793 }
    794 
    795 TEST_F(TemplateURLTest, GoogleBaseSuggestURL) {
    796   static const struct {
    797     const char* const base_url;
    798     const char* const base_suggest_url;
    799   } data[] = {
    800     { "http://google.com/", "http://google.com/complete/", },
    801     { "http://www.google.com/", "http://www.google.com/complete/", },
    802     { "http://www.google.co.uk/", "http://www.google.co.uk/complete/", },
    803     { "http://www.google.com.by/", "http://www.google.com.by/complete/", },
    804     { "http://google.com/intl/xx/", "http://google.com/complete/", },
    805   };
    806 
    807   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i)
    808     CheckSuggestBaseURL(data[i].base_url, data[i].base_suggest_url);
    809 }
    810 
    811 TEST_F(TemplateURLTest, ParseParameterKnown) {
    812   std::string parsed_url("{searchTerms}");
    813   TemplateURLData data;
    814   data.SetURL(parsed_url);
    815   TemplateURL url(data);
    816   TemplateURLRef::Replacements replacements;
    817   EXPECT_TRUE(url.url_ref().ParseParameter(0, 12, &parsed_url, &replacements));
    818   EXPECT_EQ(std::string(), parsed_url);
    819   ASSERT_EQ(1U, replacements.size());
    820   EXPECT_EQ(0U, replacements[0].index);
    821   EXPECT_EQ(TemplateURLRef::SEARCH_TERMS, replacements[0].type);
    822 }
    823 
    824 TEST_F(TemplateURLTest, ParseParameterUnknown) {
    825   std::string parsed_url("{fhqwhgads}abc");
    826   TemplateURLData data;
    827   data.SetURL(parsed_url);
    828   TemplateURL url(data);
    829   TemplateURLRef::Replacements replacements;
    830 
    831   // By default, TemplateURLRef should not consider itself prepopulated.
    832   // Therefore we should not replace the unknown parameter.
    833   EXPECT_FALSE(url.url_ref().ParseParameter(0, 10, &parsed_url, &replacements));
    834   EXPECT_EQ("{fhqwhgads}abc", parsed_url);
    835   EXPECT_TRUE(replacements.empty());
    836 
    837   // If the TemplateURLRef is prepopulated, we should remove unknown parameters.
    838   parsed_url = "{fhqwhgads}abc";
    839   data.prepopulate_id = 1;
    840   TemplateURL url2(data);
    841   EXPECT_TRUE(url2.url_ref().ParseParameter(0, 10, &parsed_url, &replacements));
    842   EXPECT_EQ("abc", parsed_url);
    843   EXPECT_TRUE(replacements.empty());
    844 }
    845 
    846 TEST_F(TemplateURLTest, ParseURLEmpty) {
    847   TemplateURL url((TemplateURLData()));
    848   TemplateURLRef::Replacements replacements;
    849   bool valid = false;
    850   EXPECT_EQ(std::string(),
    851             url.url_ref().ParseURL(std::string(), &replacements, NULL, &valid));
    852   EXPECT_TRUE(replacements.empty());
    853   EXPECT_TRUE(valid);
    854 }
    855 
    856 TEST_F(TemplateURLTest, ParseURLNoTemplateEnd) {
    857   TemplateURLData data;
    858   data.SetURL("{");
    859   TemplateURL url(data);
    860   TemplateURLRef::Replacements replacements;
    861   bool valid = false;
    862   EXPECT_EQ(std::string(), url.url_ref().ParseURL("{", &replacements, NULL,
    863                                                   &valid));
    864   EXPECT_TRUE(replacements.empty());
    865   EXPECT_FALSE(valid);
    866 }
    867 
    868 TEST_F(TemplateURLTest, ParseURLNoKnownParameters) {
    869   TemplateURLData data;
    870   data.SetURL("{}");
    871   TemplateURL url(data);
    872   TemplateURLRef::Replacements replacements;
    873   bool valid = false;
    874   EXPECT_EQ("{}", url.url_ref().ParseURL("{}", &replacements, NULL, &valid));
    875   EXPECT_TRUE(replacements.empty());
    876   EXPECT_TRUE(valid);
    877 }
    878 
    879 TEST_F(TemplateURLTest, ParseURLTwoParameters) {
    880   TemplateURLData data;
    881   data.SetURL("{}{{%s}}");
    882   TemplateURL url(data);
    883   TemplateURLRef::Replacements replacements;
    884   bool valid = false;
    885   EXPECT_EQ("{}{}",
    886             url.url_ref().ParseURL("{}{{searchTerms}}", &replacements, NULL,
    887                                    &valid));
    888   ASSERT_EQ(1U, replacements.size());
    889   EXPECT_EQ(3U, replacements[0].index);
    890   EXPECT_EQ(TemplateURLRef::SEARCH_TERMS, replacements[0].type);
    891   EXPECT_TRUE(valid);
    892 }
    893 
    894 TEST_F(TemplateURLTest, ParseURLNestedParameter) {
    895   TemplateURLData data;
    896   data.SetURL("{%s");
    897   TemplateURL url(data);
    898   TemplateURLRef::Replacements replacements;
    899   bool valid = false;
    900   EXPECT_EQ("{",
    901             url.url_ref().ParseURL("{{searchTerms}", &replacements, NULL,
    902                                    &valid));
    903   ASSERT_EQ(1U, replacements.size());
    904   EXPECT_EQ(1U, replacements[0].index);
    905   EXPECT_EQ(TemplateURLRef::SEARCH_TERMS, replacements[0].type);
    906   EXPECT_TRUE(valid);
    907 }
    908 
    909 TEST_F(TemplateURLTest, SearchClient) {
    910   const std::string base_url_str("http://google.com/?");
    911   const std::string terms_str("{searchTerms}&{google:searchClient}");
    912   const std::string full_url_str = base_url_str + terms_str;
    913   const base::string16 terms(ASCIIToUTF16(terms_str));
    914   search_terms_data_.set_google_base_url(base_url_str);
    915 
    916   TemplateURLData data;
    917   data.SetURL(full_url_str);
    918   TemplateURL url(data);
    919   EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
    920   ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
    921   TemplateURLRef::SearchTermsArgs search_terms_args(ASCIIToUTF16("foobar"));
    922 
    923   // Check that the URL is correct when a client is not present.
    924   GURL result(url.url_ref().ReplaceSearchTerms(search_terms_args,
    925                                                search_terms_data_));
    926   ASSERT_TRUE(result.is_valid());
    927   EXPECT_EQ("http://google.com/?foobar&", result.spec());
    928 
    929   // Check that the URL is correct when a client is present.
    930   search_terms_data_.set_search_client("search_client");
    931   GURL result_2(url.url_ref().ReplaceSearchTerms(search_terms_args,
    932                                                  search_terms_data_));
    933   ASSERT_TRUE(result_2.is_valid());
    934   EXPECT_EQ("http://google.com/?foobar&client=search_client&", result_2.spec());
    935 }
    936 
    937 TEST_F(TemplateURLTest, GetURLNoInstantURL) {
    938   TemplateURLData data;
    939   data.SetURL("http://google.com/?q={searchTerms}");
    940   data.suggestions_url = "http://google.com/suggest?q={searchTerms}";
    941   data.alternate_urls.push_back("http://google.com/alt?q={searchTerms}");
    942   data.alternate_urls.push_back("{google:baseURL}/alt/#q={searchTerms}");
    943   TemplateURL url(data);
    944   ASSERT_EQ(3U, url.URLCount());
    945   EXPECT_EQ("http://google.com/alt?q={searchTerms}", url.GetURL(0));
    946   EXPECT_EQ("{google:baseURL}/alt/#q={searchTerms}", url.GetURL(1));
    947   EXPECT_EQ("http://google.com/?q={searchTerms}", url.GetURL(2));
    948 }
    949 
    950 TEST_F(TemplateURLTest, GetURLNoSuggestionsURL) {
    951   TemplateURLData data;
    952   data.SetURL("http://google.com/?q={searchTerms}");
    953   data.instant_url = "http://google.com/instant#q={searchTerms}";
    954   data.alternate_urls.push_back("http://google.com/alt?q={searchTerms}");
    955   data.alternate_urls.push_back("{google:baseURL}/alt/#q={searchTerms}");
    956   TemplateURL url(data);
    957   ASSERT_EQ(3U, url.URLCount());
    958   EXPECT_EQ("http://google.com/alt?q={searchTerms}", url.GetURL(0));
    959   EXPECT_EQ("{google:baseURL}/alt/#q={searchTerms}", url.GetURL(1));
    960   EXPECT_EQ("http://google.com/?q={searchTerms}", url.GetURL(2));
    961 }
    962 
    963 TEST_F(TemplateURLTest, GetURLOnlyOneURL) {
    964   TemplateURLData data;
    965   data.SetURL("http://www.google.co.uk/");
    966   TemplateURL url(data);
    967   ASSERT_EQ(1U, url.URLCount());
    968   EXPECT_EQ("http://www.google.co.uk/", url.GetURL(0));
    969 }
    970 
    971 TEST_F(TemplateURLTest, ExtractSearchTermsFromURL) {
    972   TemplateURLData data;
    973   data.SetURL("http://google.com/?q={searchTerms}");
    974   data.instant_url = "http://google.com/instant#q={searchTerms}";
    975   data.alternate_urls.push_back("http://google.com/alt/#q={searchTerms}");
    976   data.alternate_urls.push_back(
    977       "http://google.com/alt/?ext=foo&q={searchTerms}#ref=bar");
    978   TemplateURL url(data);
    979   base::string16 result;
    980 
    981   EXPECT_TRUE(url.ExtractSearchTermsFromURL(
    982       GURL("http://google.com/?q=something"), search_terms_data_, &result));
    983   EXPECT_EQ(ASCIIToUTF16("something"), result);
    984 
    985   EXPECT_TRUE(url.ExtractSearchTermsFromURL(
    986       GURL("http://google.com/?espv&q=something"),
    987       search_terms_data_, &result));
    988   EXPECT_EQ(ASCIIToUTF16("something"), result);
    989 
    990   EXPECT_TRUE(url.ExtractSearchTermsFromURL(
    991       GURL("http://google.com/?espv=1&q=something"),
    992       search_terms_data_, &result));
    993   EXPECT_EQ(ASCIIToUTF16("something"), result);
    994 
    995   EXPECT_TRUE(url.ExtractSearchTermsFromURL(
    996       GURL("http://google.com/?espv=0&q=something"),
    997       search_terms_data_, &result));
    998   EXPECT_EQ(ASCIIToUTF16("something"), result);
    999 
   1000   EXPECT_TRUE(url.ExtractSearchTermsFromURL(
   1001       GURL("http://google.com/alt/#q=something"),
   1002       search_terms_data_, &result));
   1003   EXPECT_EQ(ASCIIToUTF16("something"), result);
   1004 
   1005   EXPECT_TRUE(url.ExtractSearchTermsFromURL(
   1006       GURL("http://google.com/alt/#espv&q=something"),
   1007       search_terms_data_, &result));
   1008   EXPECT_EQ(ASCIIToUTF16("something"), result);
   1009 
   1010   EXPECT_TRUE(url.ExtractSearchTermsFromURL(
   1011       GURL("http://google.com/alt/#espv=1&q=something"),
   1012       search_terms_data_, &result));
   1013   EXPECT_EQ(ASCIIToUTF16("something"), result);
   1014 
   1015   EXPECT_TRUE(url.ExtractSearchTermsFromURL(
   1016       GURL("http://google.com/alt/#espv=0&q=something"),
   1017       search_terms_data_, &result));
   1018   EXPECT_EQ(ASCIIToUTF16("something"), result);
   1019 
   1020   EXPECT_FALSE(url.ExtractSearchTermsFromURL(
   1021       GURL("http://google.ca/?q=something"), search_terms_data_, &result));
   1022   EXPECT_EQ(base::string16(), result);
   1023 
   1024   EXPECT_FALSE(url.ExtractSearchTermsFromURL(
   1025       GURL("http://google.ca/?q=something&q=anything"),
   1026       search_terms_data_, &result));
   1027   EXPECT_EQ(base::string16(), result);
   1028 
   1029   EXPECT_FALSE(url.ExtractSearchTermsFromURL(
   1030       GURL("http://google.com/foo/?q=foo"), search_terms_data_, &result));
   1031   EXPECT_EQ(base::string16(), result);
   1032 
   1033   EXPECT_TRUE(url.ExtractSearchTermsFromURL(
   1034       GURL("https://google.com/?q=foo"), search_terms_data_, &result));
   1035   EXPECT_EQ(ASCIIToUTF16("foo"), result);
   1036 
   1037   EXPECT_FALSE(url.ExtractSearchTermsFromURL(
   1038       GURL("http://google.com:8080/?q=foo"), search_terms_data_, &result));
   1039   EXPECT_EQ(base::string16(), result);
   1040 
   1041   EXPECT_TRUE(url.ExtractSearchTermsFromURL(
   1042       GURL("http://google.com/?q=1+2+3&b=456"), search_terms_data_, &result));
   1043   EXPECT_EQ(ASCIIToUTF16("1 2 3"), result);
   1044 
   1045   EXPECT_TRUE(url.ExtractSearchTermsFromURL(
   1046       GURL("http://google.com/alt/?q=123#q=456"),
   1047       search_terms_data_, &result));
   1048   EXPECT_EQ(ASCIIToUTF16("456"), result);
   1049 
   1050   EXPECT_TRUE(url.ExtractSearchTermsFromURL(
   1051       GURL("http://google.com/alt/?a=012&q=123&b=456#f=789"),
   1052       search_terms_data_, &result));
   1053   EXPECT_EQ(ASCIIToUTF16("123"), result);
   1054 
   1055   EXPECT_TRUE(url.ExtractSearchTermsFromURL(GURL(
   1056       "http://google.com/alt/?a=012&q=123&b=456#j=abc&q=789&h=def9"),
   1057                                             search_terms_data_, &result));
   1058   EXPECT_EQ(ASCIIToUTF16("789"), result);
   1059 
   1060   EXPECT_FALSE(url.ExtractSearchTermsFromURL(
   1061       GURL("http://google.com/alt/?q="), search_terms_data_, &result));
   1062   EXPECT_EQ(base::string16(), result);
   1063 
   1064   EXPECT_FALSE(url.ExtractSearchTermsFromURL(
   1065       GURL("http://google.com/alt/?#q="), search_terms_data_, &result));
   1066   EXPECT_EQ(base::string16(), result);
   1067 
   1068   EXPECT_FALSE(url.ExtractSearchTermsFromURL(
   1069       GURL("http://google.com/alt/?q=#q="), search_terms_data_, &result));
   1070   EXPECT_EQ(base::string16(), result);
   1071 
   1072   EXPECT_FALSE(url.ExtractSearchTermsFromURL(
   1073       GURL("http://google.com/alt/?q=123#q="), search_terms_data_, &result));
   1074   EXPECT_EQ(base::string16(), result);
   1075 
   1076   EXPECT_TRUE(url.ExtractSearchTermsFromURL(
   1077       GURL("http://google.com/alt/?q=#q=123"), search_terms_data_, &result));
   1078   EXPECT_EQ(ASCIIToUTF16("123"), result);
   1079 }
   1080 
   1081 TEST_F(TemplateURLTest, HasSearchTermsReplacementKey) {
   1082   TemplateURLData data;
   1083   data.SetURL("http://google.com/?q={searchTerms}");
   1084   data.instant_url = "http://google.com/instant#q={searchTerms}";
   1085   data.alternate_urls.push_back("http://google.com/alt/#q={searchTerms}");
   1086   data.alternate_urls.push_back(
   1087       "http://google.com/alt/?ext=foo&q={searchTerms}#ref=bar");
   1088   data.search_terms_replacement_key = "espv";
   1089   TemplateURL url(data);
   1090 
   1091   // Test with instant enabled required.
   1092   EXPECT_FALSE(url.HasSearchTermsReplacementKey(
   1093       GURL("http://google.com/")));
   1094 
   1095   EXPECT_TRUE(url.HasSearchTermsReplacementKey(
   1096       GURL("http://google.com/?espv")));
   1097 
   1098   EXPECT_TRUE(url.HasSearchTermsReplacementKey(
   1099       GURL("http://google.com/#espv")));
   1100 
   1101   EXPECT_FALSE(url.HasSearchTermsReplacementKey(
   1102       GURL("http://google.com/?q=something")));
   1103 
   1104   EXPECT_TRUE(url.HasSearchTermsReplacementKey(
   1105       GURL("http://google.com/?q=something&espv")));
   1106 
   1107   EXPECT_TRUE(url.HasSearchTermsReplacementKey(
   1108       GURL("http://google.com/?q=something&espv=1")));
   1109 
   1110   EXPECT_TRUE(url.HasSearchTermsReplacementKey(
   1111       GURL("http://google.com/?q=something&espv=0")));
   1112 
   1113   EXPECT_TRUE(url.HasSearchTermsReplacementKey(
   1114       GURL("http://google.com/?espv&q=something")));
   1115 
   1116   EXPECT_TRUE(url.HasSearchTermsReplacementKey(
   1117       GURL("http://google.com/?espv=1&q=something")));
   1118 
   1119   EXPECT_TRUE(url.HasSearchTermsReplacementKey(
   1120       GURL("http://google.com/?espv=0&q=something")));
   1121 
   1122   EXPECT_FALSE(url.HasSearchTermsReplacementKey(
   1123       GURL("http://google.com/alt/#q=something")));
   1124 
   1125   EXPECT_TRUE(url.HasSearchTermsReplacementKey(
   1126       GURL("http://google.com/alt/#q=something&espv")));
   1127 
   1128   EXPECT_TRUE(url.HasSearchTermsReplacementKey(
   1129       GURL("http://google.com/alt/#q=something&espv=1")));
   1130 
   1131   EXPECT_TRUE(url.HasSearchTermsReplacementKey(
   1132       GURL("http://google.com/alt/#q=something&espv=0")));
   1133 
   1134   EXPECT_TRUE(url.HasSearchTermsReplacementKey(
   1135       GURL("http://google.com/alt/#espv&q=something")));
   1136 
   1137   EXPECT_TRUE(url.HasSearchTermsReplacementKey(
   1138       GURL("http://google.com/alt/#espv=1&q=something")));
   1139 
   1140   EXPECT_TRUE(url.HasSearchTermsReplacementKey(
   1141       GURL("http://google.com/alt/#espv=0&q=something")));
   1142 
   1143   EXPECT_TRUE(url.HasSearchTermsReplacementKey(
   1144       GURL("http://google.com/?espv#q=something")));
   1145 
   1146   EXPECT_TRUE(url.HasSearchTermsReplacementKey(
   1147       GURL("http://google.com/?espv=1#q=something")));
   1148 
   1149   EXPECT_TRUE(url.HasSearchTermsReplacementKey(
   1150       GURL("http://google.com/?q=something#espv")));
   1151 
   1152   EXPECT_TRUE(url.HasSearchTermsReplacementKey(
   1153       GURL("http://google.com/?q=something#espv=1")));
   1154 
   1155   // This does not ensure the domain matches.
   1156   EXPECT_TRUE(url.HasSearchTermsReplacementKey(
   1157       GURL("http://bing.com/?espv")));
   1158 
   1159   EXPECT_TRUE(url.HasSearchTermsReplacementKey(
   1160       GURL("http://bing.com/#espv")));
   1161 }
   1162 
   1163 TEST_F(TemplateURLTest, ReplaceSearchTermsInURL) {
   1164   TemplateURLData data;
   1165   data.SetURL("http://google.com/?q={searchTerms}");
   1166   data.instant_url = "http://google.com/instant#q={searchTerms}";
   1167   data.alternate_urls.push_back("http://google.com/alt/#q={searchTerms}");
   1168   data.alternate_urls.push_back(
   1169       "http://google.com/alt/?ext=foo&q={searchTerms}#ref=bar");
   1170   TemplateURL url(data);
   1171   TemplateURLRef::SearchTermsArgs search_terms(ASCIIToUTF16("Bob Morane"));
   1172   GURL result;
   1173 
   1174   EXPECT_TRUE(url.ReplaceSearchTermsInURL(
   1175       GURL("http://google.com/?q=something"), search_terms,
   1176       search_terms_data_, &result));
   1177   EXPECT_EQ(GURL("http://google.com/?q=Bob%20Morane"), result);
   1178 
   1179   result = GURL("http://should.not.change.com");
   1180   EXPECT_FALSE(url.ReplaceSearchTermsInURL(
   1181       GURL("http://google.ca/?q=something"), search_terms,
   1182       search_terms_data_, &result));
   1183   EXPECT_EQ(GURL("http://should.not.change.com"), result);
   1184 
   1185   EXPECT_FALSE(url.ReplaceSearchTermsInURL(
   1186       GURL("http://google.com/foo/?q=foo"), search_terms,
   1187       search_terms_data_, &result));
   1188 
   1189   EXPECT_TRUE(url.ReplaceSearchTermsInURL(
   1190       GURL("https://google.com/?q=foo"), search_terms,
   1191       search_terms_data_, &result));
   1192   EXPECT_EQ(GURL("https://google.com/?q=Bob%20Morane"), result);
   1193 
   1194   EXPECT_FALSE(url.ReplaceSearchTermsInURL(
   1195       GURL("http://google.com:8080/?q=foo"), search_terms,
   1196       search_terms_data_, &result));
   1197 
   1198   EXPECT_TRUE(url.ReplaceSearchTermsInURL(
   1199       GURL("http://google.com/?q=1+2+3&b=456"), search_terms,
   1200       search_terms_data_, &result));
   1201   EXPECT_EQ(GURL("http://google.com/?q=Bob%20Morane&b=456"), result);
   1202 
   1203   // Note: Spaces in REF parameters are not escaped. See TryEncoding() in
   1204   // template_url.cc for details.
   1205   EXPECT_TRUE(url.ReplaceSearchTermsInURL(
   1206       GURL("http://google.com/alt/?q=123#q=456"), search_terms,
   1207       search_terms_data_, &result));
   1208   EXPECT_EQ(GURL("http://google.com/alt/?q=123#q=Bob Morane"), result);
   1209 
   1210   EXPECT_TRUE(url.ReplaceSearchTermsInURL(
   1211       GURL("http://google.com/alt/?a=012&q=123&b=456#f=789"), search_terms,
   1212       search_terms_data_, &result));
   1213   EXPECT_EQ(GURL("http://google.com/alt/?a=012&q=Bob%20Morane&b=456#f=789"),
   1214             result);
   1215 
   1216   EXPECT_TRUE(url.ReplaceSearchTermsInURL(
   1217       GURL("http://google.com/alt/?a=012&q=123&b=456#j=abc&q=789&h=def9"),
   1218       search_terms, search_terms_data_, &result));
   1219   EXPECT_EQ(GURL("http://google.com/alt/?a=012&q=123&b=456"
   1220                  "#j=abc&q=Bob Morane&h=def9"), result);
   1221 
   1222   EXPECT_FALSE(url.ReplaceSearchTermsInURL(
   1223       GURL("http://google.com/alt/?q="), search_terms,
   1224       search_terms_data_, &result));
   1225 
   1226   EXPECT_FALSE(url.ReplaceSearchTermsInURL(
   1227       GURL("http://google.com/alt/?#q="), search_terms,
   1228       search_terms_data_, &result));
   1229 
   1230   EXPECT_FALSE(url.ReplaceSearchTermsInURL(
   1231       GURL("http://google.com/alt/?q=#q="), search_terms,
   1232       search_terms_data_, &result));
   1233 
   1234   EXPECT_FALSE(url.ReplaceSearchTermsInURL(
   1235       GURL("http://google.com/alt/?q=123#q="), search_terms,
   1236       search_terms_data_, &result));
   1237 
   1238   EXPECT_TRUE(url.ReplaceSearchTermsInURL(
   1239       GURL("http://google.com/alt/?q=#q=123"), search_terms,
   1240       search_terms_data_, &result));
   1241   EXPECT_EQ(GURL("http://google.com/alt/?q=#q=Bob Morane"), result);
   1242 }
   1243 
   1244 // Test the |suggest_query_params| field of SearchTermsArgs.
   1245 TEST_F(TemplateURLTest, SuggestQueryParams) {
   1246   TemplateURLData data;
   1247   // Pick a URL with replacements before, during, and after the query, to ensure
   1248   // we don't goof up any of them.
   1249   data.SetURL("{google:baseURL}search?q={searchTerms}"
   1250       "#{google:originalQueryForSuggestion}x");
   1251   TemplateURL url(data);
   1252 
   1253   // Baseline: no |suggest_query_params| field.
   1254   TemplateURLRef::SearchTermsArgs search_terms(ASCIIToUTF16("abc"));
   1255   search_terms.original_query = ASCIIToUTF16("def");
   1256   search_terms.accepted_suggestion = 0;
   1257   EXPECT_EQ("http://www.google.com/search?q=abc#oq=def&x",
   1258             url.url_ref().ReplaceSearchTerms(search_terms, search_terms_data_));
   1259 
   1260   // Set the suggest_query_params.
   1261   search_terms.suggest_query_params = "pq=xyz";
   1262   EXPECT_EQ("http://www.google.com/search?pq=xyz&q=abc#oq=def&x",
   1263             url.url_ref().ReplaceSearchTerms(search_terms, search_terms_data_));
   1264 
   1265   // Add extra_query_params in the mix, and ensure it works.
   1266   search_terms.append_extra_query_params = true;
   1267   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
   1268       switches::kExtraSearchQueryParams, "a=b");
   1269   EXPECT_EQ("http://www.google.com/search?a=b&pq=xyz&q=abc#oq=def&x",
   1270             url.url_ref().ReplaceSearchTerms(search_terms, search_terms_data_));
   1271 }
   1272 
   1273 // Test the |append_extra_query_params| field of SearchTermsArgs.
   1274 TEST_F(TemplateURLTest, ExtraQueryParams) {
   1275   TemplateURLData data;
   1276   // Pick a URL with replacements before, during, and after the query, to ensure
   1277   // we don't goof up any of them.
   1278   data.SetURL("{google:baseURL}search?q={searchTerms}"
   1279       "#{google:originalQueryForSuggestion}x");
   1280   TemplateURL url(data);
   1281 
   1282   // Baseline: no command-line args, no |append_extra_query_params| flag.
   1283   TemplateURLRef::SearchTermsArgs search_terms(ASCIIToUTF16("abc"));
   1284   search_terms.original_query = ASCIIToUTF16("def");
   1285   search_terms.accepted_suggestion = 0;
   1286   EXPECT_EQ("http://www.google.com/search?q=abc#oq=def&x",
   1287             url.url_ref().ReplaceSearchTerms(search_terms, search_terms_data_));
   1288 
   1289   // Set the flag.  Since there are no command-line args, this should have no
   1290   // effect.
   1291   search_terms.append_extra_query_params = true;
   1292   EXPECT_EQ("http://www.google.com/search?q=abc#oq=def&x",
   1293             url.url_ref().ReplaceSearchTerms(search_terms, search_terms_data_));
   1294 
   1295   // Now append the command-line arg.  This should be inserted into the query.
   1296   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
   1297       switches::kExtraSearchQueryParams, "a=b");
   1298   EXPECT_EQ("http://www.google.com/search?a=b&q=abc#oq=def&x",
   1299             url.url_ref().ReplaceSearchTerms(search_terms, search_terms_data_));
   1300 
   1301   // Turn off the flag.  Now the command-line arg should be ignored again.
   1302   search_terms.append_extra_query_params = false;
   1303   EXPECT_EQ("http://www.google.com/search?q=abc#oq=def&x",
   1304             url.url_ref().ReplaceSearchTerms(search_terms, search_terms_data_));
   1305 }
   1306 
   1307 // Tests replacing pageClassification.
   1308 TEST_F(TemplateURLTest, ReplacePageClassification) {
   1309   TemplateURLData data;
   1310   data.input_encodings.push_back("UTF-8");
   1311   data.SetURL("{google:baseURL}?{google:pageClassification}q={searchTerms}");
   1312   TemplateURL url(data);
   1313   EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
   1314   ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
   1315   TemplateURLRef::SearchTermsArgs search_terms_args(ASCIIToUTF16("foo"));
   1316 
   1317   std::string result = url.url_ref().ReplaceSearchTerms(search_terms_args,
   1318                                                         search_terms_data_);
   1319   EXPECT_EQ("http://www.google.com/?q=foo", result);
   1320 
   1321   search_terms_args.page_classification = metrics::OmniboxEventProto::NTP;
   1322   result = url.url_ref().ReplaceSearchTerms(search_terms_args,
   1323                                             search_terms_data_);
   1324   EXPECT_EQ("http://www.google.com/?pgcl=1&q=foo", result);
   1325 
   1326   search_terms_args.page_classification =
   1327       metrics::OmniboxEventProto::HOME_PAGE;
   1328   result = url.url_ref().ReplaceSearchTerms(search_terms_args,
   1329                                             search_terms_data_);
   1330   EXPECT_EQ("http://www.google.com/?pgcl=3&q=foo", result);
   1331 }
   1332 
   1333 // Test the IsSearchResults function.
   1334 TEST_F(TemplateURLTest, IsSearchResults) {
   1335   TemplateURLData data;
   1336   data.SetURL("http://bar/search?q={searchTerms}");
   1337   data.instant_url = "http://bar/instant#q={searchTerms}";
   1338   data.new_tab_url = "http://bar/newtab";
   1339   data.alternate_urls.push_back("http://bar/?q={searchTerms}");
   1340   data.alternate_urls.push_back("http://bar/#q={searchTerms}");
   1341   data.alternate_urls.push_back("http://bar/search#q{searchTerms}");
   1342   data.alternate_urls.push_back("http://bar/webhp#q={searchTerms}");
   1343   TemplateURL search_provider(data);
   1344 
   1345   const struct {
   1346     const char* const url;
   1347     bool result;
   1348   } url_data[] = {
   1349     { "http://bar/search?q=foo&oq=foo", true, },
   1350     { "http://bar/?q=foo&oq=foo", true, },
   1351     { "http://bar/#output=search&q=foo&oq=foo", true, },
   1352     { "http://bar/webhp#q=foo&oq=foo", true, },
   1353     { "http://bar/#q=foo&oq=foo", true, },
   1354     { "http://bar/?ext=foo&q=foo#ref=bar", true, },
   1355     { "http://bar/url?url=http://www.foo.com/&q=foo#ref=bar", false, },
   1356     { "http://bar/", false, },
   1357     { "http://foo/", false, },
   1358     { "http://bar/newtab", false, },
   1359   };
   1360 
   1361   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(url_data); ++i) {
   1362     EXPECT_EQ(url_data[i].result,
   1363               search_provider.IsSearchURL(GURL(url_data[i].url),
   1364                                           search_terms_data_));
   1365   }
   1366 }
   1367 
   1368 TEST_F(TemplateURLTest, ReflectsBookmarkBarPinned) {
   1369   TemplateURLData data;
   1370   data.input_encodings.push_back("UTF-8");
   1371   data.SetURL("{google:baseURL}?{google:bookmarkBarPinned}q={searchTerms}");
   1372   TemplateURL url(data);
   1373   EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
   1374   ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
   1375   TemplateURLRef::SearchTermsArgs search_terms_args(ASCIIToUTF16("foo"));
   1376 
   1377   // Do not add the param when InstantExtended is suppressed on SRPs.
   1378   url.url_ref_.showing_search_terms_ = false;
   1379   std::string result = url.url_ref().ReplaceSearchTerms(search_terms_args,
   1380                                                         search_terms_data_);
   1381   EXPECT_EQ("http://www.google.com/?q=foo", result);
   1382 
   1383   // Add the param when InstantExtended is not suppressed on SRPs.
   1384   url.url_ref_.showing_search_terms_ = true;
   1385   search_terms_args.bookmark_bar_pinned = false;
   1386   result = url.url_ref().ReplaceSearchTerms(search_terms_args,
   1387                                             search_terms_data_);
   1388   EXPECT_EQ("http://www.google.com/?bmbp=0&q=foo", result);
   1389 
   1390   url.url_ref_.showing_search_terms_ = true;
   1391   search_terms_args.bookmark_bar_pinned = true;
   1392   result = url.url_ref().ReplaceSearchTerms(search_terms_args,
   1393                                             search_terms_data_);
   1394   EXPECT_EQ("http://www.google.com/?bmbp=1&q=foo", result);
   1395 }
   1396 
   1397 TEST_F(TemplateURLTest, AnswersHasVersion) {
   1398   TemplateURLData data;
   1399   search_terms_data_.set_google_base_url("http://bar/");
   1400   data.SetURL("http://bar/search?q={searchTerms}&{google:searchVersion}xssi=t");
   1401 
   1402   TemplateURL url(data);
   1403   TemplateURLRef::SearchTermsArgs search_terms_args(ASCIIToUTF16("foo"));
   1404   std::string result = url.url_ref().ReplaceSearchTerms(search_terms_args,
   1405                                                         search_terms_data_);
   1406   EXPECT_EQ("http://bar/search?q=foo&xssi=t", result);
   1407 
   1408   CommandLine::ForCurrentProcess()->AppendSwitch(
   1409       switches::kEnableAnswersInSuggest);
   1410   TemplateURL url2(data);
   1411   result = url2.url_ref().ReplaceSearchTerms(search_terms_args,
   1412                                              search_terms_data_);
   1413   EXPECT_EQ("http://bar/search?q=foo&gs_rn=42&xssi=t", result);
   1414 }
   1415 
   1416 TEST_F(TemplateURLTest, SessionToken) {
   1417   TemplateURLData data;
   1418   search_terms_data_.set_google_base_url("http://bar/");
   1419   data.SetURL("http://bar/search?q={searchTerms}&{google:sessionToken}xssi=t");
   1420 
   1421   TemplateURL url(data);
   1422   TemplateURLRef::SearchTermsArgs search_terms_args(ASCIIToUTF16("foo"));
   1423   search_terms_args.session_token = "SESSIONTOKENGOESHERE";
   1424   std::string result = url.url_ref().ReplaceSearchTerms(search_terms_args,
   1425                                                         search_terms_data_);
   1426   EXPECT_EQ("http://bar/search?q=foo&psi=SESSIONTOKENGOESHERE&xssi=t", result);
   1427 
   1428   TemplateURL url2(data);
   1429   search_terms_args.session_token = "";
   1430   result = url.url_ref().ReplaceSearchTerms(search_terms_args,
   1431                                             search_terms_data_);
   1432   EXPECT_EQ("http://bar/search?q=foo&xssi=t", result);
   1433 }
   1434 
   1435 TEST_F(TemplateURLTest, ContextualSearchParameters) {
   1436   TemplateURLData data;
   1437   search_terms_data_.set_google_base_url("http://bar/");
   1438   data.SetURL("http://bar/_/contextualsearch?"
   1439               "{google:contextualSearchVersion}"
   1440               "{google:contextualSearchContextData}");
   1441 
   1442   TemplateURL url(data);
   1443   TemplateURLRef::SearchTermsArgs search_terms_args(ASCIIToUTF16("foo"));
   1444   std::string result = url.url_ref().ReplaceSearchTerms(search_terms_args,
   1445                                                         search_terms_data_);
   1446   EXPECT_EQ("http://bar/_/contextualsearch?", result);
   1447 
   1448   TemplateURLRef::SearchTermsArgs::ContextualSearchParams params(
   1449       1, 6, 11, "allen", "woody+allen+movies", "www.wikipedia.org",
   1450       "utf-8");
   1451   search_terms_args.contextual_search_params = params;
   1452   result = url.url_ref().ReplaceSearchTerms(search_terms_args,
   1453                                             search_terms_data_);
   1454   EXPECT_EQ("http://bar/_/contextualsearch?"
   1455                 "ctxs=1&"
   1456                 "ctxs_start=6&"
   1457                 "ctxs_end=11&"
   1458                 "q=allen&"
   1459                 "ctxs_content=woody+allen+movies&"
   1460                 "ctxs_url=www.wikipedia.org&"
   1461             "ctxs_encoding=utf-8&", result);
   1462 }
   1463 
   1464 TEST_F(TemplateURLTest, GenerateKeyword) {
   1465   ASSERT_EQ(ASCIIToUTF16("foo"),
   1466             TemplateURL::GenerateKeyword(GURL("http://foo")));
   1467   // www. should be stripped.
   1468   ASSERT_EQ(ASCIIToUTF16("foo"),
   1469             TemplateURL::GenerateKeyword(GURL("http://www.foo")));
   1470   // Make sure we don't get a trailing '/'.
   1471   ASSERT_EQ(ASCIIToUTF16("blah"),
   1472             TemplateURL::GenerateKeyword(GURL("http://blah/")));
   1473   // Don't generate the empty string.
   1474   ASSERT_EQ(ASCIIToUTF16("www"),
   1475             TemplateURL::GenerateKeyword(GURL("http://www.")));
   1476 }
   1477 
   1478 TEST_F(TemplateURLTest, GenerateSearchURL) {
   1479   struct GenerateSearchURLCase {
   1480     const char* test_name;
   1481     const char* url;
   1482     const char* expected;
   1483   } generate_url_cases[] = {
   1484     { "invalid URL", "foo{searchTerms}", "" },
   1485     { "URL with no replacements", "http://foo/", "http://foo/" },
   1486     { "basic functionality", "http://foo/{searchTerms}",
   1487       "http://foo/blah.blah.blah.blah.blah" }
   1488   };
   1489 
   1490   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(generate_url_cases); ++i) {
   1491     TemplateURLData data;
   1492     data.SetURL(generate_url_cases[i].url);
   1493     TemplateURL t_url(data);
   1494     EXPECT_EQ(t_url.GenerateSearchURL(search_terms_data_).spec(),
   1495               generate_url_cases[i].expected)
   1496         << generate_url_cases[i].test_name << " failed.";
   1497   }
   1498 }
   1499