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