1 // Copyright 2014 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/search_engines/template_url.h"
10 #include "base/base64.h"
11 #include "base/base_paths.h"
12 #include "base/command_line.h"
13 #include "base/feature_list.h"
14 #include "base/i18n/case_conversion.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/string_util.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "base/test/metrics/histogram_tester.h"
19 #include "base/test/scoped_feature_list.h"
20 #include "components/google/core/common/google_util.h"
21 #include "components/omnibox/common/omnibox_features.h"
22 #include "components/search_engines/search_engines_switches.h"
23 #include "components/search_engines/search_terms_data.h"
24 #include "components/search_engines/testing_search_terms_data.h"
25 #include "net/base/url_util.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27 #include "third_party/metrics_proto/omnibox_event.pb.h"
28 #include "third_party/metrics_proto/omnibox_input_type.pb.h"
29 #include "third_party/omnibox_proto/chrome_searchbox_stats.pb.h"
31 using base::ASCIIToUTF16;
32 using RequestSource = SearchTermsData::RequestSource;
35 bool IsLowerCase(const std::u16string& str) {
36 return str == base::i18n::ToLower(str);
40 class TemplateURLTest : public testing::Test {
42 TemplateURLTest() : search_terms_data_("http://www.google.com/") {}
43 void CheckSuggestBaseURL(const std::string& base_url,
44 const std::string& base_suggest_url) const;
46 static void ExpectPostParamIs(
47 const TemplateURLRef::PostParam& param,
48 const std::string& name,
49 const std::string& value,
50 const std::string& content_type = std::string());
52 static void ExpectContainsPostParam(
53 const TemplateURLRef::PostParams& params,
54 const std::string& name,
55 const std::string& value,
56 const std::string& content_type = std::string());
58 TestingSearchTermsData search_terms_data_;
61 void TemplateURLTest::CheckSuggestBaseURL(
62 const std::string& base_url,
63 const std::string& base_suggest_url) const {
64 TestingSearchTermsData search_terms_data(base_url);
65 EXPECT_EQ(base_suggest_url, search_terms_data.GoogleBaseSuggestURLValue());
69 void TemplateURLTest::ExpectPostParamIs(const TemplateURLRef::PostParam& param,
70 const std::string& name,
71 const std::string& value,
72 const std::string& content_type) {
73 EXPECT_EQ(name, param.name);
74 EXPECT_EQ(value, param.value);
75 EXPECT_EQ(content_type, param.content_type);
79 void TemplateURLTest::ExpectContainsPostParam(
80 const TemplateURLRef::PostParams& params,
81 const std::string& name,
82 const std::string& value,
83 const std::string& content_type) {
84 for (const auto& param : params) {
85 if (param.name == name && param.value == value &&
86 param.content_type == content_type) {
90 FAIL() << "Expected post param not found.";
93 TEST_F(TemplateURLTest, Defaults) {
95 EXPECT_FALSE(data.safe_for_autoreplace);
96 EXPECT_EQ(0, data.prepopulate_id);
99 TEST_F(TemplateURLTest, TestValidWithComplete) {
100 TemplateURLData data;
101 data.SetURL("{searchTerms}");
102 TemplateURL url(data);
103 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
106 TEST_F(TemplateURLTest, URLRefTestSearchTerms) {
107 struct SearchTermsCase {
109 const std::u16string terms;
110 const std::string output;
111 } search_term_cases[] = {
112 {"http://foo{searchTerms}", u"sea rch/bar", "http://foosea%20rch/bar"},
113 {"http://foo{searchTerms}?boo=abc", u"sea rch/bar",
114 "http://foosea%20rch/bar?boo=abc"},
115 {"http://foo/?boo={searchTerms}", u"sea rch/bar",
116 "http://foo/?boo=sea+rch%2Fbar"},
117 {"http://en.wikipedia.org/{searchTerms}", u"wiki/?",
118 "http://en.wikipedia.org/wiki/%3F"}};
119 for (size_t i = 0; i < std::size(search_term_cases); ++i) {
120 const SearchTermsCase& value = search_term_cases[i];
121 TemplateURLData data;
122 data.SetURL(value.url);
123 TemplateURL url(data);
124 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
125 ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
126 GURL result(url.url_ref().ReplaceSearchTerms(
127 TemplateURLRef::SearchTermsArgs(value.terms), search_terms_data_));
128 ASSERT_TRUE(result.is_valid());
129 EXPECT_EQ(value.output, result.spec());
133 TEST_F(TemplateURLTest, URLRefTestCount) {
134 TemplateURLData data;
135 data.SetURL("http://foo{searchTerms}{count?}");
136 TemplateURL url(data);
137 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
138 ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
139 GURL result(url.url_ref().ReplaceSearchTerms(
140 TemplateURLRef::SearchTermsArgs(u"X"), search_terms_data_));
141 ASSERT_TRUE(result.is_valid());
142 EXPECT_EQ("http://foox/", result.spec());
145 TEST_F(TemplateURLTest, URLRefTestCount2) {
146 TemplateURLData data;
147 data.SetURL("http://foo{searchTerms}{count}");
148 TemplateURL url(data);
149 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
150 ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
151 GURL result(url.url_ref().ReplaceSearchTerms(
152 TemplateURLRef::SearchTermsArgs(u"X"), search_terms_data_));
153 ASSERT_TRUE(result.is_valid());
154 EXPECT_EQ("http://foox10/", result.spec());
157 TEST_F(TemplateURLTest, URLRefTestIndices) {
158 TemplateURLData data;
159 data.SetURL("http://foo{searchTerms}x{startIndex?}y{startPage?}");
160 TemplateURL url(data);
161 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
162 ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
163 GURL result(url.url_ref().ReplaceSearchTerms(
164 TemplateURLRef::SearchTermsArgs(u"X"), search_terms_data_));
165 ASSERT_TRUE(result.is_valid());
166 EXPECT_EQ("http://fooxxy/", result.spec());
169 TEST_F(TemplateURLTest, URLRefTestIndices2) {
170 TemplateURLData data;
171 data.SetURL("http://foo{searchTerms}x{startIndex}y{startPage}");
172 TemplateURL url(data);
173 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
174 ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
175 GURL result(url.url_ref().ReplaceSearchTerms(
176 TemplateURLRef::SearchTermsArgs(u"X"), search_terms_data_));
177 ASSERT_TRUE(result.is_valid());
178 EXPECT_EQ("http://fooxx1y1/", result.spec());
181 TEST_F(TemplateURLTest, URLRefTestEncoding) {
182 TemplateURLData data;
183 data.SetURL("http://foo{searchTerms}x{inputEncoding?}y{outputEncoding?}a");
184 TemplateURL url(data);
185 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
186 ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
187 GURL result(url.url_ref().ReplaceSearchTerms(
188 TemplateURLRef::SearchTermsArgs(u"X"), search_terms_data_));
189 ASSERT_TRUE(result.is_valid());
190 EXPECT_EQ("http://fooxxutf-8ya/", result.spec());
193 TEST_F(TemplateURLTest, URLRefTestImageURLWithPOST) {
194 const char kInvalidPostParamsString[] =
195 "unknown_template={UnknownTemplate},bad_value=bad{value},"
196 "{google:sbiSource}";
197 // List all accpectable parameter format in valid_post_params_string. it is
198 // expected like: "name0=,name1=value1,name2={template1}"
199 const char kValidPostParamsString[] =
200 "image_content={google:imageThumbnail},image_url={google:imageURL},"
201 "sbisrc={google:imageSearchSource},language={language},empty_param=,"
202 "constant_param=constant,width={google:imageOriginalWidth},"
203 "base64_image_content={google:imageThumbnailBase64}";
204 const char KImageSearchURL[] = "http://foo.com/sbi";
206 TemplateURLData data;
207 data.image_url = KImageSearchURL;
209 // Try to parse invalid post parameters.
210 data.image_url_post_params = kInvalidPostParamsString;
211 TemplateURL url_bad(data);
212 ASSERT_FALSE(url_bad.image_url_ref().IsValid(search_terms_data_));
213 const TemplateURLRef::PostParams& bad_post_params =
214 url_bad.image_url_ref().post_params_;
215 ASSERT_EQ(2U, bad_post_params.size());
216 ExpectPostParamIs(bad_post_params[0], "unknown_template",
217 "{UnknownTemplate}");
218 ExpectPostParamIs(bad_post_params[1], "bad_value", "bad{value}");
220 // Try to parse valid post parameters.
221 data.image_url_post_params = kValidPostParamsString;
222 TemplateURL url(data);
223 ASSERT_TRUE(url.image_url_ref().IsValid(search_terms_data_));
224 ASSERT_FALSE(url.image_url_ref().SupportsReplacement(search_terms_data_));
226 // Check term replacement.
227 TemplateURLRef::SearchTermsArgs search_args(u"X");
228 search_args.image_thumbnail_content = "dummy-image-thumbnail";
229 search_args.image_url = GURL("http://dummyimage.com/dummy.jpg");
230 search_args.image_original_size = gfx::Size(10, 10);
231 // Replacement operation with no post_data buffer should still return
233 TestingSearchTermsData search_terms_data("http://X");
234 GURL result(url.image_url_ref().ReplaceSearchTerms(
235 search_args, search_terms_data));
236 ASSERT_TRUE(result.is_valid());
237 EXPECT_EQ(KImageSearchURL, result.spec());
238 TemplateURLRef::PostContent post_content;
239 result = GURL(url.image_url_ref().ReplaceSearchTerms(
240 search_args, search_terms_data, &post_content));
241 ASSERT_TRUE(result.is_valid());
242 EXPECT_EQ(KImageSearchURL, result.spec());
243 ASSERT_FALSE(post_content.first.empty());
244 ASSERT_FALSE(post_content.second.empty());
246 // Check parsed result of post parameters.
247 const TemplateURLRef::Replacements& replacements =
248 url.image_url_ref().replacements_;
249 const TemplateURLRef::PostParams& post_params =
250 url.image_url_ref().post_params_;
251 EXPECT_EQ(8U, post_params.size());
252 for (auto i = post_params.begin(); i != post_params.end(); ++i) {
253 auto 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())) {
258 case TemplateURLRef::GOOGLE_IMAGE_ORIGINAL_WIDTH:
261 base::NumberToString(search_args.image_original_size.width()));
263 case TemplateURLRef::GOOGLE_IMAGE_SEARCH_SOURCE:
264 ExpectPostParamIs(*i, "sbisrc",
265 search_terms_data.GoogleImageSearchSource());
267 case TemplateURLRef::GOOGLE_IMAGE_THUMBNAIL:
268 ExpectPostParamIs(*i, "image_content",
269 search_args.image_thumbnail_content,
272 case TemplateURLRef::GOOGLE_IMAGE_THUMBNAIL_BASE64: {
273 std::string base64_image_content;
274 base::Base64Encode(search_args.image_thumbnail_content,
275 &base64_image_content);
276 ExpectPostParamIs(*i, "base64_image_content", base64_image_content,
280 case TemplateURLRef::GOOGLE_IMAGE_URL:
281 ExpectPostParamIs(*i, "image_url", search_args.image_url.spec());
283 case TemplateURLRef::LANGUAGE:
284 ExpectPostParamIs(*i, "language", "en");
287 ADD_FAILURE(); // Should never go here.
292 if (j != replacements.end())
294 if (i->name == "empty_param")
295 ExpectPostParamIs(*i, "empty_param", std::string());
297 ExpectPostParamIs(*i, "constant_param", "constant");
301 TEST_F(TemplateURLTest, ImageThumbnailContentTypePostParams) {
302 TemplateURLData data;
303 data.image_url = "http://foo.com/sbi";
304 data.image_url_post_params =
305 "image_content={google:imageThumbnail},"
306 "base64_image_content={google:imageThumbnailBase64}";
307 TemplateURL url(data);
308 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
310 TemplateURLRef::SearchTermsArgs search_args(u"X");
311 search_args.image_thumbnail_content = "dummy-image-thumbnail";
312 search_args.image_thumbnail_content_type = "image/tiff";
313 TestingSearchTermsData search_terms_data("http://X");
315 url.image_url_ref().ReplaceSearchTerms(search_args, search_terms_data));
316 ASSERT_TRUE(result.is_valid());
318 const TemplateURLRef::PostParams& post_params =
319 url.image_url_ref().post_params_;
320 ExpectContainsPostParam(post_params, "image_content",
321 search_args.image_thumbnail_content, "image/tiff");
322 std::string base64_image_content;
323 base::Base64Encode(search_args.image_thumbnail_content,
324 &base64_image_content);
325 ExpectContainsPostParam(post_params, "base64_image_content",
326 base64_image_content, "image/tiff");
329 TEST_F(TemplateURLTest, ImageURLWithGetShouldNotCrash) {
330 TemplateURLData data;
331 data.SetURL("http://foo/?q={searchTerms}&t={google:imageThumbnail}");
332 TemplateURL url(data);
333 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
334 ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
336 TemplateURLRef::SearchTermsArgs search_args(u"X");
337 search_args.image_thumbnail_content = "dummy-image-thumbnail";
339 url.url_ref().ReplaceSearchTerms(search_args, search_terms_data_));
340 ASSERT_TRUE(result.is_valid());
341 EXPECT_EQ("http://foo/?q=X&t=dummy-image-thumbnail", result.spec());
344 // Test that setting the prepopulate ID from TemplateURL causes the stored
345 // TemplateURLRef to handle parsing the URL parameters differently.
346 TEST_F(TemplateURLTest, SetPrepopulatedAndParse) {
347 TemplateURLData data;
348 data.SetURL("http://foo{fhqwhgads}bar");
349 TemplateURL url(data);
350 TemplateURLRef::Replacements replacements;
352 EXPECT_EQ("http://foo{fhqwhgads}bar",
353 url.url_ref().ParseURL("http://foo{fhqwhgads}bar", &replacements,
355 EXPECT_TRUE(replacements.empty());
358 data.prepopulate_id = 123;
359 TemplateURL url2(data);
360 EXPECT_EQ("http://foobar",
361 url2.url_ref().ParseURL("http://foo{fhqwhgads}bar", &replacements,
363 EXPECT_TRUE(replacements.empty());
367 // Test that setting the prepopulate ID from TemplateURL causes the stored
368 // TemplateURLRef to handle parsing the URL parameters differently.
369 TEST_F(TemplateURLTest, SetPrepopulatedAndReplace) {
370 TemplateURLData data;
371 data.SetURL("http://foo{fhqwhgads}search/?q={searchTerms}");
372 data.suggestions_url = "http://foo{fhqwhgads}suggest/?q={searchTerms}";
373 data.image_url = "http://foo{fhqwhgads}image/";
374 data.image_translate_url = "http://foo{fhqwhgads}image/?translate";
375 data.new_tab_url = "http://foo{fhqwhgads}newtab/";
376 data.contextual_search_url = "http://foo{fhqwhgads}context/";
377 data.alternate_urls.push_back(
378 "http://foo{fhqwhgads}alternate/?q={searchTerms}");
380 TemplateURLRef::SearchTermsArgs args(u"X");
381 const SearchTermsData& stdata = search_terms_data_;
383 TemplateURL url(data);
384 EXPECT_EQ("http://foo%7Bfhqwhgads%7Dsearch/?q=X",
385 url.url_ref().ReplaceSearchTerms(args, stdata));
386 EXPECT_EQ("http://foo%7Bfhqwhgads%7Dalternate/?q=X",
387 url.url_refs()[0].ReplaceSearchTerms(args, stdata));
388 EXPECT_EQ("http://foo%7Bfhqwhgads%7Dsearch/?q=X",
389 url.url_refs()[1].ReplaceSearchTerms(args, stdata));
390 EXPECT_EQ("http://foo%7Bfhqwhgads%7Dsuggest/?q=X",
391 url.suggestions_url_ref().ReplaceSearchTerms(args, stdata));
392 EXPECT_EQ("http://foo{fhqwhgads}image/",
393 url.image_url_ref().ReplaceSearchTerms(args, stdata));
394 EXPECT_EQ("http://foo%7Bfhqwhgads%7Dimage/?translate",
395 url.image_translate_url_ref().ReplaceSearchTerms(args, stdata));
396 EXPECT_EQ("http://foo{fhqwhgads}newtab/",
397 url.new_tab_url_ref().ReplaceSearchTerms(args, stdata));
398 EXPECT_EQ("http://foo{fhqwhgads}context/",
399 url.contextual_search_url_ref().ReplaceSearchTerms(args, stdata));
401 data.prepopulate_id = 123;
402 TemplateURL url2(data);
403 EXPECT_EQ("http://foosearch/?q=X",
404 url2.url_ref().ReplaceSearchTerms(args, stdata));
405 EXPECT_EQ("http://fooalternate/?q=X",
406 url2.url_refs()[0].ReplaceSearchTerms(args, stdata));
407 EXPECT_EQ("http://foosearch/?q=X",
408 url2.url_refs()[1].ReplaceSearchTerms(args, stdata));
409 EXPECT_EQ("http://foosuggest/?q=X",
410 url2.suggestions_url_ref().ReplaceSearchTerms(args, stdata));
411 EXPECT_EQ("http://fooimage/",
412 url2.image_url_ref().ReplaceSearchTerms(args, stdata));
413 EXPECT_EQ("http://fooimage/?translate",
414 url2.image_translate_url_ref().ReplaceSearchTerms(args, stdata));
415 EXPECT_EQ("http://foonewtab/",
416 url2.new_tab_url_ref().ReplaceSearchTerms(args, stdata));
417 EXPECT_EQ("http://foocontext/",
418 url2.contextual_search_url_ref().ReplaceSearchTerms(args, stdata));
421 TEST_F(TemplateURLTest, InputEncodingBeforeSearchTerm) {
422 TemplateURLData data;
423 data.SetURL("http://foox{inputEncoding?}a{searchTerms}y{outputEncoding?}b");
424 TemplateURL url(data);
425 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
426 ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
427 GURL result(url.url_ref().ReplaceSearchTerms(
428 TemplateURLRef::SearchTermsArgs(u"X"), search_terms_data_));
429 ASSERT_TRUE(result.is_valid());
430 EXPECT_EQ("http://fooxutf-8axyb/", result.spec());
433 TEST_F(TemplateURLTest, URLRefTestEncoding2) {
434 TemplateURLData data;
435 data.SetURL("http://foo{searchTerms}x{inputEncoding}y{outputEncoding}a");
436 TemplateURL url(data);
437 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
438 ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
439 GURL result(url.url_ref().ReplaceSearchTerms(
440 TemplateURLRef::SearchTermsArgs(u"X"), search_terms_data_));
441 ASSERT_TRUE(result.is_valid());
442 EXPECT_EQ("http://fooxxutf-8yutf-8a/", result.spec());
445 TEST_F(TemplateURLTest, URLRefTestSearchTermsUsingTermsData) {
446 struct SearchTermsCase {
448 const std::u16string terms;
450 } search_term_cases[] = {{"{google:baseURL}{language}{searchTerms}",
451 std::u16string(), "http://example.com/e/en"},
452 {"{google:baseSuggestURL}{searchTerms}",
453 std::u16string(), "http://example.com/complete/"}};
455 TestingSearchTermsData search_terms_data("http://example.com/e/");
456 TemplateURLData data;
457 for (size_t i = 0; i < std::size(search_term_cases); ++i) {
458 const SearchTermsCase& value = search_term_cases[i];
459 data.SetURL(value.url);
460 TemplateURL url(data);
461 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data));
462 ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data));
463 GURL result(url.url_ref().ReplaceSearchTerms(
464 TemplateURLRef::SearchTermsArgs(value.terms), search_terms_data,
466 ASSERT_TRUE(result.is_valid());
467 EXPECT_EQ(value.output, result.spec());
471 TEST_F(TemplateURLTest, URLRefTermToWide) {
473 const char* encoded_search_term;
474 const std::u16string expected_decoded_term;
475 } to_wide_cases[] = {
476 {"hello+world", u"hello world"},
477 // Test some big-5 input.
478 {"%a7A%A6%6e+to+you", u"\x4f60\x597d to you"},
479 // Test some UTF-8 input. We should fall back to this when the encoding
480 // doesn't look like big-5. We have a '5' in the middle, which is an
481 // invalid Big-5 trailing byte.
482 {"%e4%bd%a05%e5%a5%bd+to+you", u"\x4f60\x35\x597d to you"},
483 // Undecodable input should stay escaped.
484 {"%91%01+abcd", u"%91%01 abcd"},
485 // Make sure we convert %2B to +.
487 // C%2B is escaped as C%252B, make sure we unescape it properly.
491 // Set one input encoding: big-5. This is so we can test fallback to UTF-8.
492 TemplateURLData data;
493 data.SetURL("http://foo?q={searchTerms}");
494 data.input_encodings.push_back("big-5");
495 TemplateURL url(data);
496 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
497 ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
498 for (size_t i = 0; i < std::size(to_wide_cases); i++) {
499 EXPECT_EQ(to_wide_cases[i].expected_decoded_term,
500 url.url_ref().SearchTermToString16(
501 to_wide_cases[i].encoded_search_term));
505 TEST_F(TemplateURLTest, DisplayURLToURLRef) {
507 const std::string url;
508 const std::u16string expected_result;
510 {"http://foo{searchTerms}x{inputEncoding}y{outputEncoding}a",
511 u"http://foo%sx{inputEncoding}y{outputEncoding}a"},
512 {"http://X", u"http://X"},
513 {"http://foo{searchTerms", u"http://foo{searchTerms"},
514 {"http://foo{searchTerms}{language}", u"http://foo%s{language}"},
516 TemplateURLData data;
517 for (const auto& entry : test_data) {
518 data.SetURL(entry.url);
519 TemplateURL url(data);
520 EXPECT_EQ(entry.expected_result,
521 url.url_ref().DisplayURL(search_terms_data_));
522 EXPECT_EQ(entry.url, TemplateURLRef::DisplayURLToURLRef(
523 url.url_ref().DisplayURL(search_terms_data_)));
527 TEST_F(TemplateURLTest, ReplaceSearchTerms) {
529 const std::string url;
530 const std::string expected_result;
532 { "http://foo/{language}{searchTerms}{inputEncoding}",
533 "http://foo/{language}XUTF-8" },
534 { "http://foo/{language}{inputEncoding}{searchTerms}",
535 "http://foo/{language}UTF-8X" },
536 { "http://foo/{searchTerms}{language}{inputEncoding}",
537 "http://foo/X{language}UTF-8" },
538 { "http://foo/{searchTerms}{inputEncoding}{language}",
539 "http://foo/XUTF-8{language}" },
540 { "http://foo/{inputEncoding}{searchTerms}{language}",
541 "http://foo/UTF-8X{language}" },
542 { "http://foo/{inputEncoding}{language}{searchTerms}",
543 "http://foo/UTF-8{language}X" },
544 { "http://foo/{language}a{searchTerms}a{inputEncoding}a",
545 "http://foo/{language}aXaUTF-8a" },
546 { "http://foo/{language}a{inputEncoding}a{searchTerms}a",
547 "http://foo/{language}aUTF-8aXa" },
548 { "http://foo/{searchTerms}a{language}a{inputEncoding}a",
549 "http://foo/Xa{language}aUTF-8a" },
550 { "http://foo/{searchTerms}a{inputEncoding}a{language}a",
551 "http://foo/XaUTF-8a{language}a" },
552 { "http://foo/{inputEncoding}a{searchTerms}a{language}a",
553 "http://foo/UTF-8aXa{language}a" },
554 { "http://foo/{inputEncoding}a{language}a{searchTerms}a",
555 "http://foo/UTF-8a{language}aXa" },
557 TemplateURLData data;
558 data.input_encodings.push_back("UTF-8");
559 for (const auto& entry : test_data) {
560 data.SetURL(entry.url);
561 TemplateURL url(data);
562 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
563 ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
564 std::string expected_result = entry.expected_result;
565 base::ReplaceSubstringsAfterOffset(
566 &expected_result, 0, "{language}",
567 search_terms_data_.GetApplicationLocale());
568 GURL result(url.url_ref().ReplaceSearchTerms(
569 TemplateURLRef::SearchTermsArgs(u"X"), search_terms_data_));
570 ASSERT_TRUE(result.is_valid());
571 EXPECT_EQ(expected_result, result.spec());
576 // Tests replacing search terms in various encodings and making sure the
577 // generated URL matches the expected value.
578 TEST_F(TemplateURLTest, ReplaceArbitrarySearchTerms) {
580 const std::string encoding;
581 const std::u16string search_term;
582 const std::string url;
583 const std::string expected_result;
585 {"BIG5", u"悽", "http://foo/?{searchTerms}{inputEncoding}",
586 "http://foo/?%B1~BIG5"},
587 {"UTF-8", u"blah", "http://foo/?{searchTerms}{inputEncoding}",
588 "http://foo/?blahUTF-8"},
589 {"Shift_JIS", u"あ", "http://foo/{searchTerms}/bar",
590 "http://foo/%82%A0/bar"},
591 {"Shift_JIS", u"あ い", "http://foo/{searchTerms}/bar",
592 "http://foo/%82%A0%20%82%A2/bar"},
594 TemplateURLData data;
595 for (const auto& entry : test_data) {
596 data.SetURL(entry.url);
597 data.input_encodings.clear();
598 data.input_encodings.push_back(entry.encoding);
599 TemplateURL url(data);
600 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
601 ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
602 GURL result(url.url_ref().ReplaceSearchTerms(
603 TemplateURLRef::SearchTermsArgs(entry.search_term),
604 search_terms_data_));
605 ASSERT_TRUE(result.is_valid());
606 EXPECT_EQ(entry.expected_result, result.spec());
610 // Test that encoding with several optional codepages works as intended.
611 // Codepages are tried in order, fallback is UTF-8.
612 TEST_F(TemplateURLTest, ReplaceSearchTermsMultipleEncodings) {
614 const std::vector<std::string> encodings;
615 const std::u16string search_term;
616 const std::string url;
617 const std::string expected_result;
619 // First and third encodings are valid. First is used.
620 {{"windows-1251", "cp-866", "UTF-8"},
622 "http://foo/?{searchTerms}{inputEncoding}",
623 "http://foo/?%FFwindows-1251"},
624 // Second and third encodings are valid, second is used.
625 {{"cp-866", "GB2312", "UTF-8"},
627 "http://foo/?{searchTerms}{inputEncoding}",
628 "http://foo/?%B9%B7GB2312"},
629 // Second and third encodings are valid in another order, second is used.
630 {{"cp-866", "UTF-8", "GB2312"},
632 "http://foo/?{searchTerms}{inputEncoding}",
633 "http://foo/?%E7%8B%97UTF-8"},
634 // Both encodings are invalid, fallback to UTF-8.
635 {{"cp-866", "windows-1251"},
637 "http://foo/?{searchTerms}{inputEncoding}",
638 "http://foo/?%E7%8B%97UTF-8"},
639 // No encodings are given, fallback to UTF-8.
642 "http://foo/?{searchTerms}{inputEncoding}",
643 "http://foo/?%E7%8B%97UTF-8"},
646 TemplateURLData data;
647 for (const auto& entry : test_data) {
648 data.SetURL(entry.url);
649 data.input_encodings = entry.encodings;
650 TemplateURL url(data);
651 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
652 ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
653 GURL result(url.url_ref().ReplaceSearchTerms(
654 TemplateURLRef::SearchTermsArgs(entry.search_term),
655 search_terms_data_));
656 ASSERT_TRUE(result.is_valid());
657 EXPECT_EQ(entry.expected_result, result.spec());
661 // Tests replacing assisted query stats (AQS) in various scenarios.
662 TEST_F(TemplateURLTest, ReplaceAssistedQueryStats) {
663 base::HistogramTester histogram_tester;
664 base::test::ScopedFeatureList feature_list;
665 feature_list.InitWithFeatures({omnibox::kReportAssistedQueryStats},
666 {omnibox::kReportSearchboxStats});
668 omnibox::metrics::ChromeSearchboxStats searchbox_stats;
669 searchbox_stats.set_client_name("chrome");
670 searchbox_stats.set_zero_prefix_enabled(true);
673 const std::u16string search_term;
674 const std::string aqs;
675 const omnibox::metrics::ChromeSearchboxStats searchbox_stats;
676 const std::string base_url;
677 const std::string url;
678 const std::string expected_result;
680 // HTTPS and non-empty gs_lcrp and non-empty AQS: Success.
681 {u"foo", "chrome.0.0l6", searchbox_stats, "https://foo/",
682 "{google:baseURL}?q={searchTerms}&{google:assistedQueryStats}",
683 "https://foo/?q=foo&aqs=chrome.0.0l6&"},
684 // Non-Google HTTPS and non-empty gs_lcrp and non-empty AQS: Success.
685 {u"foo", "chrome.0.0l6", searchbox_stats, "https://bar/",
686 "https://foo/?q={searchTerms}&{google:assistedQueryStats}",
687 "https://foo/?q=foo&aqs=chrome.0.0l6&"},
688 // No HTTPS: Failure.
689 {u"foo", "chrome.0.0l6", searchbox_stats, "http://foo/",
690 "{google:baseURL}?q={searchTerms}&{google:assistedQueryStats}",
691 "http://foo/?q=foo&"},
692 // No {google:assistedQueryStats}: Failure.
693 {u"foo", "chrome.0.0l6", searchbox_stats, "https://foo/",
694 "{google:baseURL}?q={searchTerms}", "https://foo/?q=foo"},
696 TemplateURLData data;
697 data.input_encodings.push_back("UTF-8");
698 for (const auto& entry : test_data) {
699 data.SetURL(entry.url);
700 TemplateURL url(data);
701 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
702 ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
703 TemplateURLRef::SearchTermsArgs search_terms_args(entry.search_term);
704 search_terms_args.assisted_query_stats = entry.aqs;
705 search_terms_args.searchbox_stats.MergeFrom(entry.searchbox_stats);
706 search_terms_data_.set_google_base_url(entry.base_url);
707 GURL result(url.url_ref().ReplaceSearchTerms(search_terms_args,
708 search_terms_data_));
709 ASSERT_TRUE(result.is_valid());
710 EXPECT_EQ(entry.expected_result, result.spec());
712 // Expect correct histograms to have been logged.
713 histogram_tester.ExpectTotalCount("Omnibox.AssistedQueryStats.Length", 2);
714 histogram_tester.ExpectBucketCount("Omnibox.AssistedQueryStats.Length", 12,
717 histogram_tester.ExpectTotalCount("Omnibox.SearchboxStats.Length", 0);
720 // Tests replacing searchbox stats (gs_lcrp) in various scenarios.
721 TEST_F(TemplateURLTest, ReplaceSearchboxStats) {
722 base::HistogramTester histogram_tester;
723 base::test::ScopedFeatureList feature_list;
724 feature_list.InitWithFeatures({omnibox::kReportSearchboxStats},
725 {omnibox::kReportAssistedQueryStats});
727 omnibox::metrics::ChromeSearchboxStats searchbox_stats;
728 searchbox_stats.set_client_name("chrome");
729 searchbox_stats.set_zero_prefix_enabled(true);
732 const std::u16string search_term;
733 const std::string aqs;
734 const omnibox::metrics::ChromeSearchboxStats searchbox_stats;
735 const std::string base_url;
736 const std::string url;
737 const std::string expected_result;
739 // HTTPS and non-empty gs_lcrp and non-empty AQS: Success.
740 {u"foo", "chrome.0.0l6", searchbox_stats, "https://foo/",
741 "{google:baseURL}?q={searchTerms}&{google:assistedQueryStats}",
742 "https://foo/?q=foo&gs_lcrp=EgZjaHJvbWWwAgE&"},
743 // Non-Google HTTPS and non-empty gs_lcrp and non-empty AQS: Success.
744 {u"foo", "chrome.0.0l6", searchbox_stats, "https://bar/",
745 "https://foo/?q={searchTerms}&{google:assistedQueryStats}",
746 "https://foo/?q=foo&gs_lcrp=EgZjaHJvbWWwAgE&"},
747 // No HTTPS: Failure.
748 {u"foo", "chrome.0.0l6", searchbox_stats, "http://foo/",
749 "{google:baseURL}?q={searchTerms}&{google:assistedQueryStats}",
750 "http://foo/?q=foo&"},
751 // No {google:assistedQueryStats}: Failure.
752 {u"foo", "chrome.0.0l6", searchbox_stats, "https://foo/",
753 "{google:baseURL}?q={searchTerms}", "https://foo/?q=foo"},
755 TemplateURLData data;
756 data.input_encodings.push_back("UTF-8");
757 for (const auto& entry : test_data) {
758 data.SetURL(entry.url);
759 TemplateURL url(data);
760 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
761 ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
762 TemplateURLRef::SearchTermsArgs search_terms_args(entry.search_term);
763 search_terms_args.assisted_query_stats = entry.aqs;
764 search_terms_args.searchbox_stats.MergeFrom(entry.searchbox_stats);
765 search_terms_data_.set_google_base_url(entry.base_url);
766 GURL result(url.url_ref().ReplaceSearchTerms(search_terms_args,
767 search_terms_data_));
768 ASSERT_TRUE(result.is_valid());
769 EXPECT_EQ(entry.expected_result, result.spec());
771 // Expect correct histograms to have been logged.
772 histogram_tester.ExpectTotalCount("Omnibox.AssistedQueryStats.Length", 0);
774 histogram_tester.ExpectTotalCount("Omnibox.SearchboxStats.Length", 2);
775 histogram_tester.ExpectBucketCount("Omnibox.SearchboxStats.Length", 15, 2);
778 // Tests replacing searchbox stats (gs_lcrp) and assisted query stats (AQS).
779 TEST_F(TemplateURLTest, ReplaceSearchboxStatsAndAssistedQueryStats) {
780 base::HistogramTester histogram_tester;
781 base::test::ScopedFeatureList feature_list;
782 feature_list.InitWithFeatures(
783 {omnibox::kReportSearchboxStats, omnibox::kReportAssistedQueryStats}, {});
785 omnibox::metrics::ChromeSearchboxStats searchbox_stats;
786 searchbox_stats.set_client_name("chrome");
787 searchbox_stats.set_zero_prefix_enabled(true);
790 const std::u16string search_term;
791 const std::string aqs;
792 const omnibox::metrics::ChromeSearchboxStats searchbox_stats;
793 const std::string base_url;
794 const std::string url;
795 const std::string expected_result;
797 // HTTPS and non-empty gs_lcrp and non-empty AQS: Success.
798 {u"foo", "chrome.0.0l6", searchbox_stats, "https://foo/",
799 "{google:baseURL}?q={searchTerms}&{google:assistedQueryStats}",
800 "https://foo/?q=foo&gs_lcrp=EgZjaHJvbWWwAgE&aqs=chrome.0.0l6&"},
801 // Non-Google HTTPS and non-empty gs_lcrp and non-empty AQS: Success.
802 {u"foo", "chrome.0.0l6", searchbox_stats, "https://bar/",
803 "https://foo/?q={searchTerms}&{google:assistedQueryStats}",
804 "https://foo/?q=foo&gs_lcrp=EgZjaHJvbWWwAgE&aqs=chrome.0.0l6&"},
805 // No HTTPS: Failure.
806 {u"foo", "chrome.0.0l6", searchbox_stats, "http://foo/",
807 "{google:baseURL}?q={searchTerms}&{google:assistedQueryStats}",
808 "http://foo/?q=foo&"},
809 // No {google:assistedQueryStats}: Failure.
810 {u"foo", "chrome.0.0l6", searchbox_stats, "https://foo/",
811 "{google:baseURL}?q={searchTerms}", "https://foo/?q=foo"},
813 TemplateURLData data;
814 data.input_encodings.push_back("UTF-8");
815 for (const auto& entry : test_data) {
816 data.SetURL(entry.url);
817 TemplateURL url(data);
818 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
819 ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
820 TemplateURLRef::SearchTermsArgs search_terms_args(entry.search_term);
821 search_terms_args.assisted_query_stats = entry.aqs;
822 search_terms_args.searchbox_stats.MergeFrom(entry.searchbox_stats);
823 search_terms_data_.set_google_base_url(entry.base_url);
824 GURL result(url.url_ref().ReplaceSearchTerms(search_terms_args,
825 search_terms_data_));
826 ASSERT_TRUE(result.is_valid());
827 EXPECT_EQ(entry.expected_result, result.spec());
829 // Expect correct histograms to have been logged.
830 histogram_tester.ExpectTotalCount("Omnibox.AssistedQueryStats.Length", 2);
831 histogram_tester.ExpectBucketCount("Omnibox.AssistedQueryStats.Length", 12,
834 histogram_tester.ExpectTotalCount("Omnibox.SearchboxStats.Length", 2);
835 histogram_tester.ExpectBucketCount("Omnibox.SearchboxStats.Length", 15, 2);
838 // Tests replacing cursor position.
839 TEST_F(TemplateURLTest, ReplaceCursorPosition) {
841 const std::u16string search_term;
842 size_t cursor_position;
843 const std::string url;
844 const std::string expected_result;
846 {u"foo", std::u16string::npos,
847 "{google:baseURL}?{searchTerms}&{google:cursorPosition}",
848 "http://www.google.com/?foo&"},
849 {u"foo", 2, "{google:baseURL}?{searchTerms}&{google:cursorPosition}",
850 "http://www.google.com/?foo&cp=2&"},
851 {u"foo", 15, "{google:baseURL}?{searchTerms}&{google:cursorPosition}",
852 "http://www.google.com/?foo&cp=15&"},
854 TemplateURLData data;
855 data.input_encodings.push_back("UTF-8");
856 for (const auto& entry : test_data) {
857 data.SetURL(entry.url);
858 TemplateURL url(data);
859 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
860 ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
861 TemplateURLRef::SearchTermsArgs search_terms_args(entry.search_term);
862 search_terms_args.cursor_position = entry.cursor_position;
863 GURL result(url.url_ref().ReplaceSearchTerms(search_terms_args,
864 search_terms_data_));
865 ASSERT_TRUE(result.is_valid());
866 EXPECT_EQ(entry.expected_result, result.spec());
870 // Tests replacing input type (&oit=).
871 TEST_F(TemplateURLTest, ReplaceInputType) {
873 const std::u16string search_term;
874 metrics::OmniboxInputType input_type;
875 const std::string url;
876 const std::string expected_result;
878 {u"foo", metrics::OmniboxInputType::UNKNOWN,
879 "{google:baseURL}?{searchTerms}&{google:inputType}",
880 "http://www.google.com/?foo&oit=1&"},
881 {u"foo", metrics::OmniboxInputType::URL,
882 "{google:baseURL}?{searchTerms}&{google:inputType}",
883 "http://www.google.com/?foo&oit=3&"},
885 TemplateURLData data;
886 data.input_encodings.push_back("UTF-8");
887 for (const auto& entry : test_data) {
888 data.SetURL(entry.url);
889 TemplateURL url(data);
890 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
891 ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
892 TemplateURLRef::SearchTermsArgs search_terms_args(entry.search_term);
893 search_terms_args.input_type = entry.input_type;
894 GURL result(url.url_ref().ReplaceSearchTerms(search_terms_args,
895 search_terms_data_));
896 ASSERT_TRUE(result.is_valid());
897 EXPECT_EQ(entry.expected_result, result.spec());
901 // Tests replacing omnibox focus type (&oft=).
902 TEST_F(TemplateURLTest, ReplaceOmniboxFocusType) {
904 const std::u16string search_term;
905 metrics::OmniboxFocusType focus_type;
906 const std::string url;
907 const std::string expected_result;
909 {u"foo", metrics::OmniboxFocusType::INTERACTION_DEFAULT,
910 "{google:baseURL}?{searchTerms}&{google:omniboxFocusType}",
911 "http://www.google.com/?foo&"},
912 {u"foo", metrics::OmniboxFocusType::INTERACTION_FOCUS,
913 "{google:baseURL}?{searchTerms}&{google:omniboxFocusType}",
914 "http://www.google.com/?foo&oft=1&"},
915 {u"foo", metrics::OmniboxFocusType::INTERACTION_CLOBBER,
916 "{google:baseURL}?{searchTerms}&{google:omniboxFocusType}",
917 "http://www.google.com/?foo&oft=2&"},
919 TemplateURLData data;
920 data.input_encodings.push_back("UTF-8");
921 for (const auto& entry : test_data) {
922 data.SetURL(entry.url);
923 TemplateURL url(data);
924 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
925 ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
926 TemplateURLRef::SearchTermsArgs search_terms_args(entry.search_term);
927 search_terms_args.focus_type = entry.focus_type;
928 GURL result(url.url_ref().ReplaceSearchTerms(search_terms_args,
929 search_terms_data_));
930 ASSERT_TRUE(result.is_valid());
931 EXPECT_EQ(entry.expected_result, result.spec());
935 // Tests replacing prefetch source (&pf=).
936 TEST_F(TemplateURLTest, ReplaceIsPrefetch) {
938 const std::u16string search_term;
940 const std::string url;
941 const std::string expected_result;
943 {u"foo", false, "{google:baseURL}?{searchTerms}&{google:prefetchSource}",
944 "http://www.google.com/?foo&"},
945 {u"foo", true, "{google:baseURL}?{searchTerms}&{google:prefetchSource}",
946 "http://www.google.com/?foo&pf=cs&"},
948 TemplateURLData data;
949 data.input_encodings.push_back("UTF-8");
950 for (const auto& entry : test_data) {
951 data.SetURL(entry.url);
952 TemplateURL url(data);
953 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
954 ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
955 TemplateURLRef::SearchTermsArgs search_terms_args(entry.search_term);
956 search_terms_args.is_prefetch = entry.is_prefetch;
957 GURL result(url.url_ref().ReplaceSearchTerms(search_terms_args,
958 search_terms_data_));
959 ASSERT_TRUE(result.is_valid());
960 EXPECT_EQ(entry.expected_result, result.spec());
964 // Tests replacing currentPageUrl.
965 TEST_F(TemplateURLTest, ReplaceCurrentPageUrl) {
967 const std::u16string search_term;
968 const std::string current_page_url;
969 const std::string url;
970 const std::string expected_result;
972 {u"foo", "http://www.google.com/",
973 "{google:baseURL}?{searchTerms}&{google:currentPageUrl}",
974 "http://www.google.com/?foo&url=http%3A%2F%2Fwww.google.com%2F&"},
975 {u"foo", "", "{google:baseURL}?{searchTerms}&{google:currentPageUrl}",
976 "http://www.google.com/?foo&"},
977 {u"foo", "http://g.com/+-/*&=",
978 "{google:baseURL}?{searchTerms}&{google:currentPageUrl}",
979 "http://www.google.com/?foo&url=http%3A%2F%2Fg.com%2F%2B-%2F*%26%3D&"},
981 TemplateURLData data;
982 data.input_encodings.push_back("UTF-8");
983 for (const auto& entry : test_data) {
984 data.SetURL(entry.url);
985 TemplateURL url(data);
986 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
987 ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
988 TemplateURLRef::SearchTermsArgs search_terms_args(entry.search_term);
989 search_terms_args.current_page_url = entry.current_page_url;
990 GURL result(url.url_ref().ReplaceSearchTerms(search_terms_args,
991 search_terms_data_));
992 ASSERT_TRUE(result.is_valid());
993 EXPECT_EQ(entry.expected_result, result.spec());
997 // Tests appending attribution parameter to queries originating from Play API
999 TEST_F(TemplateURLTest, PlayAPIAttribution) {
1000 const struct TestData {
1002 std::u16string terms;
1003 bool created_from_play_api;
1006 {"http://foo/?q={searchTerms}", u"bar", false, "http://foo/?q=bar"},
1007 {"http://foo/?q={searchTerms}", u"bar", true,
1008 "http://foo/?q=bar&chrome_dse_attribution=1"}};
1009 TemplateURLData data;
1010 for (const auto& entry : test_data) {
1011 data.SetURL(entry.url);
1012 data.created_from_play_api = entry.created_from_play_api;
1013 TemplateURL url(data);
1014 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
1015 ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
1016 GURL result(url.url_ref().ReplaceSearchTerms(
1017 TemplateURLRef::SearchTermsArgs(entry.terms), search_terms_data_));
1018 ASSERT_TRUE(result.is_valid());
1019 EXPECT_EQ(entry.output, result.spec());
1023 TEST_F(TemplateURLTest, Suggestions) {
1025 const int accepted_suggestion;
1026 const std::u16string original_query_for_suggestion;
1027 const std::string expected_result;
1029 {TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, std::u16string(),
1030 "http://bar/foo?q=foobar"},
1031 {TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, u"foo",
1032 "http://bar/foo?q=foobar"},
1033 {TemplateURLRef::NO_SUGGESTION_CHOSEN, std::u16string(),
1034 "http://bar/foo?q=foobar"},
1035 {TemplateURLRef::NO_SUGGESTION_CHOSEN, u"foo", "http://bar/foo?q=foobar"},
1036 {0, std::u16string(), "http://bar/foo?oq=&q=foobar"},
1037 {1, u"foo", "http://bar/foo?oq=foo&q=foobar"},
1039 TemplateURLData data;
1040 data.SetURL("http://bar/foo?{google:originalQueryForSuggestion}"
1042 data.input_encodings.push_back("UTF-8");
1043 TemplateURL url(data);
1044 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
1045 ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
1046 for (const auto& entry : test_data) {
1047 TemplateURLRef::SearchTermsArgs search_terms_args(u"foobar");
1048 search_terms_args.accepted_suggestion = entry.accepted_suggestion;
1049 search_terms_args.original_query = entry.original_query_for_suggestion;
1050 GURL result(url.url_ref().ReplaceSearchTerms(search_terms_args,
1051 search_terms_data_));
1052 ASSERT_TRUE(result.is_valid());
1053 EXPECT_EQ(entry.expected_result, result.spec());
1057 TEST_F(TemplateURLTest, RLZ) {
1058 std::u16string rlz_string = search_terms_data_.GetRlzParameterValue(false);
1060 TemplateURLData data;
1061 data.SetURL("http://bar/?{google:RLZ}{searchTerms}");
1062 TemplateURL url(data);
1063 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
1064 ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
1065 GURL result(url.url_ref().ReplaceSearchTerms(
1066 TemplateURLRef::SearchTermsArgs(u"x"), search_terms_data_));
1067 ASSERT_TRUE(result.is_valid());
1068 EXPECT_EQ("http://bar/?rlz=" + base::UTF16ToUTF8(rlz_string) + "&x",
1072 TEST_F(TemplateURLTest, RLZFromAppList) {
1073 std::u16string rlz_string = search_terms_data_.GetRlzParameterValue(true);
1075 TemplateURLData data;
1076 data.SetURL("http://bar/?{google:RLZ}{searchTerms}");
1077 TemplateURL url(data);
1078 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
1079 ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
1080 TemplateURLRef::SearchTermsArgs args(u"x");
1081 args.request_source = RequestSource::CROS_APP_LIST;
1082 GURL result(url.url_ref().ReplaceSearchTerms(args, search_terms_data_));
1083 ASSERT_TRUE(result.is_valid());
1084 EXPECT_EQ("http://bar/?rlz=" + base::UTF16ToUTF8(rlz_string) + "&x",
1088 TEST_F(TemplateURLTest, HostAndSearchTermKey) {
1090 const std::string url;
1091 const std::string host;
1092 const std::string path;
1093 const std::string search_term_key;
1095 {"http://blah/?foo=bar&q={searchTerms}&b=x", "blah", "/", "q"},
1096 {"http://blah/{searchTerms}", "blah", "", ""},
1098 // No term should result in empty values.
1099 {"http://blah/", "", "", ""},
1101 // Multiple terms should result in empty values.
1102 {"http://blah/?q={searchTerms}&x={searchTerms}", "", "", ""},
1104 // Term in the host shouldn't match.
1105 {"http://{searchTerms}", "", "", ""},
1107 {"http://blah/?q={searchTerms}", "blah", "/", "q"},
1108 {"https://blah/?q={searchTerms}", "blah", "/", "q"},
1110 // Single term with extra chars in value should match.
1111 {"http://blah/?q=stock:{searchTerms}", "blah", "/", "q"},
1114 for (const auto& entry : test_data) {
1115 TemplateURLData data;
1116 data.SetURL(entry.url);
1117 TemplateURL url(data);
1118 EXPECT_EQ(entry.host, url.url_ref().GetHost(search_terms_data_));
1119 EXPECT_EQ(entry.path, url.url_ref().GetPath(search_terms_data_));
1120 EXPECT_EQ(entry.search_term_key,
1121 url.url_ref().GetSearchTermKey(search_terms_data_));
1125 TEST_F(TemplateURLTest, SearchTermKeyLocation) {
1127 const std::string url;
1128 const url::Parsed::ComponentType location;
1129 const std::string path;
1130 const std::string key;
1131 const std::string value_prefix;
1132 const std::string value_suffix;
1134 {"http://blah/{searchTerms}/", url::Parsed::PATH, "", "", "/", "/"},
1135 {"http://blah/{searchTerms}", url::Parsed::PATH, "", "", "/", ""},
1136 {"http://blah/begin/{searchTerms}/end", url::Parsed::PATH, "", "",
1138 {"http://blah/?foo=bar&q={searchTerms}&b=x", url::Parsed::QUERY, "/", "q",
1140 {"http://blah/?foo=bar#x={searchTerms}&b=x", url::Parsed::REF, "/", "x",
1142 {"http://www.example.com/?q=chromium-{searchTerms}@chromium.org/info",
1143 url::Parsed::QUERY, "/", "q", "chromium-", "@chromium.org/info"},
1145 // searchTerms is a key, not a value, so this should result in an empty
1147 {"http://blah/?foo=bar#x=012345678901234&a=b&{searchTerms}=x",
1148 url::Parsed::QUERY, "", "", "", ""},
1150 // Multiple search terms should result in empty values.
1151 {"http://blah/{searchTerms}?q={searchTerms}", url::Parsed::QUERY, "", "",
1153 {"http://blah/{searchTerms}#x={searchTerms}", url::Parsed::QUERY, "", "",
1155 {"http://blah/?q={searchTerms}#x={searchTerms}", url::Parsed::QUERY, "",
1159 for (const auto& entry : test_data) {
1160 TemplateURLData data;
1161 data.SetURL(entry.url);
1162 TemplateURL url(data);
1163 EXPECT_EQ(entry.location,
1164 url.url_ref().GetSearchTermKeyLocation(search_terms_data_));
1165 EXPECT_EQ(entry.path, url.url_ref().GetPath(search_terms_data_));
1166 EXPECT_EQ(entry.key, url.url_ref().GetSearchTermKey(search_terms_data_));
1167 EXPECT_EQ(entry.value_prefix,
1168 url.url_ref().GetSearchTermValuePrefix(search_terms_data_));
1169 EXPECT_EQ(entry.value_suffix,
1170 url.url_ref().GetSearchTermValueSuffix(search_terms_data_));
1174 TEST_F(TemplateURLTest, GoogleBaseSuggestURL) {
1175 static const struct {
1176 const char* const base_url;
1177 const char* const base_suggest_url;
1179 { "http://google.com/", "http://google.com/complete/", },
1180 { "http://www.google.com/", "http://www.google.com/complete/", },
1181 { "http://www.google.co.uk/", "http://www.google.co.uk/complete/", },
1182 { "http://www.google.com.by/", "http://www.google.com.by/complete/", },
1183 { "http://google.com/intl/xx/", "http://google.com/complete/", },
1186 for (size_t i = 0; i < std::size(data); ++i)
1187 CheckSuggestBaseURL(data[i].base_url, data[i].base_suggest_url);
1190 TEST_F(TemplateURLTest, ParseParameterKnown) {
1191 std::string parsed_url("{searchTerms}");
1192 TemplateURLData data;
1193 data.SetURL(parsed_url);
1194 TemplateURL url(data);
1195 TemplateURLRef::Replacements replacements;
1196 EXPECT_TRUE(url.url_ref().ParseParameter(0, 12, &parsed_url, &replacements));
1197 EXPECT_EQ(std::string(), parsed_url);
1198 ASSERT_EQ(1U, replacements.size());
1199 EXPECT_EQ(0U, replacements[0].index);
1200 EXPECT_EQ(TemplateURLRef::SEARCH_TERMS, replacements[0].type);
1203 TEST_F(TemplateURLTest, ParseParameterUnknown) {
1204 std::string parsed_url("{fhqwhgads}abc");
1205 TemplateURLData data;
1206 data.SetURL(parsed_url);
1207 TemplateURL url(data);
1208 TemplateURLRef::Replacements replacements;
1210 // By default, TemplateURLRef should not consider itself prepopulated.
1211 // Therefore we should not replace the unknown parameter.
1212 EXPECT_FALSE(url.url_ref().ParseParameter(0, 10, &parsed_url, &replacements));
1213 EXPECT_EQ("{fhqwhgads}abc", parsed_url);
1214 EXPECT_TRUE(replacements.empty());
1216 // If the TemplateURLRef is prepopulated, we should remove unknown parameters.
1217 parsed_url = "{fhqwhgads}abc";
1218 data.prepopulate_id = 1;
1219 TemplateURL url2(data);
1220 EXPECT_TRUE(url2.url_ref().ParseParameter(0, 10, &parsed_url, &replacements));
1221 EXPECT_EQ("abc", parsed_url);
1222 EXPECT_TRUE(replacements.empty());
1225 TEST_F(TemplateURLTest, ParseURLEmpty) {
1226 TemplateURL url((TemplateURLData()));
1227 TemplateURLRef::Replacements replacements;
1229 EXPECT_EQ(std::string(), url.url_ref().ParseURL(std::string(), &replacements,
1231 EXPECT_TRUE(replacements.empty());
1235 TEST_F(TemplateURLTest, ParseURLNoTemplateEnd) {
1236 TemplateURLData data;
1238 TemplateURL url(data);
1239 TemplateURLRef::Replacements replacements;
1241 EXPECT_EQ(std::string(),
1242 url.url_ref().ParseURL("{", &replacements, nullptr, &valid));
1243 EXPECT_TRUE(replacements.empty());
1244 EXPECT_FALSE(valid);
1247 TEST_F(TemplateURLTest, ParseURLNoKnownParameters) {
1248 TemplateURLData data;
1250 TemplateURL url(data);
1251 TemplateURLRef::Replacements replacements;
1253 EXPECT_EQ("{}", url.url_ref().ParseURL("{}", &replacements, nullptr, &valid));
1254 EXPECT_TRUE(replacements.empty());
1258 TEST_F(TemplateURLTest, ParseURLTwoParameters) {
1259 TemplateURLData data;
1260 data.SetURL("{}{{%s}}");
1261 TemplateURL url(data);
1262 TemplateURLRef::Replacements replacements;
1264 EXPECT_EQ("{}{}", url.url_ref().ParseURL("{}{{searchTerms}}", &replacements,
1266 ASSERT_EQ(1U, replacements.size());
1267 EXPECT_EQ(3U, replacements[0].index);
1268 EXPECT_EQ(TemplateURLRef::SEARCH_TERMS, replacements[0].type);
1272 TEST_F(TemplateURLTest, ParseURLNestedParameter) {
1273 TemplateURLData data;
1275 TemplateURL url(data);
1276 TemplateURLRef::Replacements replacements;
1278 EXPECT_EQ("{", url.url_ref().ParseURL("{{searchTerms}", &replacements,
1280 ASSERT_EQ(1U, replacements.size());
1281 EXPECT_EQ(1U, replacements[0].index);
1282 EXPECT_EQ(TemplateURLRef::SEARCH_TERMS, replacements[0].type);
1286 TEST_F(TemplateURLTest, SearchClient) {
1287 const std::string base_url_str("http://google.com/?");
1288 const std::string terms_str("{searchTerms}&{google:searchClient}");
1289 const std::string full_url_str = base_url_str + terms_str;
1290 const std::u16string terms(ASCIIToUTF16(terms_str));
1291 search_terms_data_.set_google_base_url(base_url_str);
1293 TemplateURLData data;
1294 data.SetURL(full_url_str);
1295 TemplateURL url(data);
1296 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
1297 ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
1298 TemplateURLRef::SearchTermsArgs search_terms_args(u"foobar");
1300 // Check that the URL is correct when a client is not present.
1301 GURL result(url.url_ref().ReplaceSearchTerms(search_terms_args,
1302 search_terms_data_));
1303 ASSERT_TRUE(result.is_valid());
1304 EXPECT_EQ("http://google.com/?foobar&", result.spec());
1306 // Check that the URL is correct when a client is present.
1307 search_terms_data_.set_search_client("search_client");
1308 GURL result_2(url.url_ref().ReplaceSearchTerms(search_terms_args,
1309 search_terms_data_));
1310 ASSERT_TRUE(result_2.is_valid());
1311 EXPECT_EQ("http://google.com/?foobar&client=search_client&", result_2.spec());
1314 TEST_F(TemplateURLTest, SuggestClient) {
1315 const std::string base_url_str("http://google.com/?");
1316 const std::string query_params_str("client={google:suggestClient}");
1317 const std::string full_url_str = base_url_str + query_params_str;
1318 search_terms_data_.set_google_base_url(base_url_str);
1320 TemplateURLData data;
1321 data.SetURL(full_url_str);
1322 TemplateURL url(data);
1323 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
1324 ASSERT_FALSE(url.url_ref().SupportsReplacement(search_terms_data_));
1325 TemplateURLRef::SearchTermsArgs search_terms_args;
1327 // Check that the URL is correct when a client is not present.
1329 url.url_ref().ReplaceSearchTerms(search_terms_args, search_terms_data_));
1330 ASSERT_TRUE(result.is_valid());
1331 EXPECT_EQ("http://google.com/?client=", result.spec());
1333 // Check that the URL is correct when a client is present.
1334 search_terms_data_.set_suggest_client("suggest_client");
1336 url.url_ref().ReplaceSearchTerms(search_terms_args, search_terms_data_));
1337 ASSERT_TRUE(result_2.is_valid());
1338 EXPECT_EQ("http://google.com/?client=suggest_client", result_2.spec());
1341 TEST_F(TemplateURLTest, ZeroSuggestCacheDuration) {
1342 const std::string base_url_str("http://google.com/?");
1343 const std::string query_params_str("{google:clientCacheTimeToLive}");
1344 const std::string full_url_str = base_url_str + query_params_str;
1345 search_terms_data_.set_google_base_url(base_url_str);
1346 TemplateURLData data;
1347 data.SetURL(full_url_str);
1348 TemplateURL url(data);
1349 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
1350 ASSERT_FALSE(url.url_ref().SupportsReplacement(search_terms_data_));
1353 // 'ccttl' query param should not be present if no cache duration is given.
1354 TemplateURLRef::SearchTermsArgs search_terms_args;
1355 GURL result(url.url_ref().ReplaceSearchTerms(search_terms_args,
1356 search_terms_data_));
1357 ASSERT_TRUE(result.is_valid());
1358 EXPECT_EQ("http://google.com/?", result.spec());
1361 // 'ccttl' query param should be present if a positive cache duration is
1363 TemplateURLRef::SearchTermsArgs search_terms_args;
1364 search_terms_args.zero_suggest_cache_duration_sec = 300;
1365 GURL result(url.url_ref().ReplaceSearchTerms(search_terms_args,
1366 search_terms_data_));
1367 ASSERT_TRUE(result.is_valid());
1368 EXPECT_EQ("http://google.com/?ccttl=300&", result.spec());
1371 // 'ccttl' query param shouldn't be present if a zero cache duration is
1373 TemplateURLRef::SearchTermsArgs search_terms_args;
1374 search_terms_args.zero_suggest_cache_duration_sec = 0;
1375 GURL result(url.url_ref().ReplaceSearchTerms(search_terms_args,
1376 search_terms_data_));
1377 ASSERT_TRUE(result.is_valid());
1378 EXPECT_EQ("http://google.com/?", result.spec());
1381 // 'ccttl' query param should not be present if the request is not a
1382 // zero-prefix request.
1383 TemplateURLRef::SearchTermsArgs search_terms_args(u"foo");
1384 search_terms_args.zero_suggest_cache_duration_sec = 300;
1385 GURL result(url.url_ref().ReplaceSearchTerms(search_terms_args,
1386 search_terms_data_));
1387 ASSERT_TRUE(result.is_valid());
1388 EXPECT_EQ("http://google.com/?", result.spec());
1392 TEST_F(TemplateURLTest, GetURLNoSuggestionsURL) {
1393 TemplateURLData data;
1394 data.SetURL("http://google.com/?q={searchTerms}");
1395 data.alternate_urls.push_back("http://google.com/alt?q={searchTerms}");
1396 data.alternate_urls.push_back("{google:baseURL}/alt/#q={searchTerms}");
1397 TemplateURL url(data);
1398 const std::vector<TemplateURLRef>& url_refs = url.url_refs();
1399 ASSERT_EQ(3U, url_refs.size());
1400 EXPECT_EQ("http://google.com/alt?q={searchTerms}", url_refs[0].GetURL());
1401 EXPECT_EQ("{google:baseURL}/alt/#q={searchTerms}", url_refs[1].GetURL());
1402 EXPECT_EQ("http://google.com/?q={searchTerms}", url_refs[2].GetURL());
1405 TEST_F(TemplateURLTest, GetURLOnlyOneURL) {
1406 TemplateURLData data;
1407 data.SetURL("http://www.google.co.uk/");
1408 TemplateURL url(data);
1409 const std::vector<TemplateURLRef>& url_refs = url.url_refs();
1410 ASSERT_EQ(1U, url_refs.size());
1411 EXPECT_EQ("http://www.google.co.uk/", url_refs[0].GetURL());
1414 TEST_F(TemplateURLTest, ExtractSearchTermsFromURL) {
1415 TemplateURLData data;
1416 data.SetURL("http://google.com/?q={searchTerms}");
1417 data.alternate_urls.push_back("http://google.com/alt/#q={searchTerms}");
1418 data.alternate_urls.push_back(
1419 "http://google.com/alt/?ext=foo&q={searchTerms}#ref=bar");
1420 TemplateURL url(data);
1421 std::u16string result;
1423 EXPECT_TRUE(url.ExtractSearchTermsFromURL(
1424 GURL("http://google.com/?q=something"), search_terms_data_, &result));
1425 EXPECT_EQ(u"something", result);
1427 EXPECT_TRUE(url.ExtractSearchTermsFromURL(
1428 GURL("http://google.com/?q=something"), search_terms_data_, &result));
1429 EXPECT_EQ(u"something", result);
1431 EXPECT_TRUE(url.ExtractSearchTermsFromURL(
1432 GURL("http://google.com/?q=something"), search_terms_data_, &result));
1433 EXPECT_EQ(u"something", result);
1435 EXPECT_TRUE(url.ExtractSearchTermsFromURL(
1436 GURL("http://google.com/?q=something"), search_terms_data_, &result));
1437 EXPECT_EQ(u"something", result);
1439 EXPECT_TRUE(url.ExtractSearchTermsFromURL(
1440 GURL("http://google.com/alt/#q=something"),
1441 search_terms_data_, &result));
1442 EXPECT_EQ(u"something", result);
1444 EXPECT_TRUE(url.ExtractSearchTermsFromURL(
1445 GURL("http://google.com/alt/#q=something"), search_terms_data_, &result));
1446 EXPECT_EQ(u"something", result);
1448 EXPECT_TRUE(url.ExtractSearchTermsFromURL(
1449 GURL("http://google.com/alt/#q=something"), search_terms_data_, &result));
1450 EXPECT_EQ(u"something", result);
1452 EXPECT_TRUE(url.ExtractSearchTermsFromURL(
1453 GURL("http://google.com/alt/#q=something"), search_terms_data_, &result));
1454 EXPECT_EQ(u"something", result);
1456 EXPECT_FALSE(url.ExtractSearchTermsFromURL(
1457 GURL("http://google.ca/?q=something"), search_terms_data_, &result));
1458 EXPECT_EQ(std::u16string(), result);
1460 EXPECT_FALSE(url.ExtractSearchTermsFromURL(
1461 GURL("http://google.ca/?q=something&q=anything"),
1462 search_terms_data_, &result));
1463 EXPECT_EQ(std::u16string(), result);
1465 EXPECT_FALSE(url.ExtractSearchTermsFromURL(
1466 GURL("http://google.com/foo/?q=foo"), search_terms_data_, &result));
1467 EXPECT_EQ(std::u16string(), result);
1469 EXPECT_TRUE(url.ExtractSearchTermsFromURL(
1470 GURL("https://google.com/?q=foo"), search_terms_data_, &result));
1471 EXPECT_EQ(u"foo", result);
1473 EXPECT_FALSE(url.ExtractSearchTermsFromURL(
1474 GURL("http://google.com:8080/?q=foo"), search_terms_data_, &result));
1475 EXPECT_EQ(std::u16string(), result);
1477 EXPECT_TRUE(url.ExtractSearchTermsFromURL(
1478 GURL("http://google.com/?q=1+2+3&b=456"), search_terms_data_, &result));
1479 EXPECT_EQ(u"1 2 3", result);
1481 EXPECT_TRUE(url.ExtractSearchTermsFromURL(
1482 GURL("http://google.com/alt/?q=123#q=456"),
1483 search_terms_data_, &result));
1484 EXPECT_EQ(u"456", result);
1486 EXPECT_TRUE(url.ExtractSearchTermsFromURL(
1487 GURL("http://google.com/alt/?a=012&q=123&b=456#f=789"),
1488 search_terms_data_, &result));
1489 EXPECT_EQ(u"123", result);
1491 EXPECT_TRUE(url.ExtractSearchTermsFromURL(GURL(
1492 "http://google.com/alt/?a=012&q=123&b=456#j=abc&q=789&h=def9"),
1493 search_terms_data_, &result));
1494 EXPECT_EQ(u"789", result);
1496 EXPECT_FALSE(url.ExtractSearchTermsFromURL(
1497 GURL("http://google.com/alt/?q="), search_terms_data_, &result));
1498 EXPECT_EQ(std::u16string(), result);
1500 EXPECT_FALSE(url.ExtractSearchTermsFromURL(
1501 GURL("http://google.com/alt/?#q="), search_terms_data_, &result));
1502 EXPECT_EQ(std::u16string(), result);
1504 EXPECT_FALSE(url.ExtractSearchTermsFromURL(
1505 GURL("http://google.com/alt/?q=#q="), search_terms_data_, &result));
1506 EXPECT_EQ(std::u16string(), result);
1508 EXPECT_FALSE(url.ExtractSearchTermsFromURL(
1509 GURL("http://google.com/alt/?q=123#q="), search_terms_data_, &result));
1510 EXPECT_EQ(std::u16string(), result);
1512 EXPECT_TRUE(url.ExtractSearchTermsFromURL(
1513 GURL("http://google.com/alt/?q=#q=123"), search_terms_data_, &result));
1514 EXPECT_EQ(u"123", result);
1517 TEST_F(TemplateURLTest, ExtractSearchTermsFromURLPath) {
1518 TemplateURLData data;
1519 data.SetURL("http://term-in-path.com/begin/{searchTerms}/end");
1520 TemplateURL url(data);
1521 std::u16string result;
1523 EXPECT_TRUE(url.ExtractSearchTermsFromURL(
1524 GURL("http://term-in-path.com/begin/something/end"),
1525 search_terms_data_, &result));
1526 EXPECT_EQ(u"something", result);
1528 // "%20" must be converted to space.
1529 EXPECT_TRUE(url.ExtractSearchTermsFromURL(
1530 GURL("http://term-in-path.com/begin/a%20b%20c/end"),
1531 search_terms_data_, &result));
1532 EXPECT_EQ(u"a b c", result);
1534 // Plus must not be converted to space.
1535 EXPECT_TRUE(url.ExtractSearchTermsFromURL(
1536 GURL("http://term-in-path.com/begin/1+2+3/end"),
1537 search_terms_data_, &result));
1538 EXPECT_EQ(u"1+2+3", result);
1540 EXPECT_FALSE(url.ExtractSearchTermsFromURL(
1541 GURL("http://term-in-path.com/about"), search_terms_data_, &result));
1542 EXPECT_EQ(std::u16string(), result);
1544 EXPECT_FALSE(url.ExtractSearchTermsFromURL(
1545 GURL("http://term-in-path.com/begin"), search_terms_data_, &result));
1546 EXPECT_EQ(std::u16string(), result);
1548 EXPECT_FALSE(url.ExtractSearchTermsFromURL(
1549 GURL("http://term-in-path.com/end"), search_terms_data_, &result));
1550 EXPECT_EQ(std::u16string(), result);
1553 // Checks that the ExtractSearchTermsFromURL function works correctly
1554 // for urls containing non-latin characters in UTF8 encoding.
1555 TEST_F(TemplateURLTest, ExtractSearchTermsFromUTF8URL) {
1556 TemplateURLData data;
1557 data.SetURL("http://utf-8.ru/?q={searchTerms}");
1558 data.alternate_urls.push_back("http://utf-8.ru/#q={searchTerms}");
1559 data.alternate_urls.push_back("http://utf-8.ru/path/{searchTerms}");
1560 TemplateURL url(data);
1561 std::u16string result;
1563 // Russian text encoded with UTF-8.
1564 EXPECT_TRUE(url.ExtractSearchTermsFromURL(
1565 GURL("http://utf-8.ru/?q=%D0%97%D0%B4%D1%80%D0%B0%D0%B2%D1%81%D1%82"
1566 "%D0%B2%D1%83%D0%B9,+%D0%BC%D0%B8%D1%80!"),
1567 search_terms_data_, &result));
1569 u"\x0417\x0434\x0440\x0430\x0432\x0441\x0442\x0432\x0443\x0439, "
1570 u"\x043C\x0438\x0440!",
1573 EXPECT_TRUE(url.ExtractSearchTermsFromURL(
1574 GURL("http://utf-8.ru/#q=%D0%B4%D0%B2%D0%B0+%D1%81%D0%BB%D0%BE%D0%B2"
1576 search_terms_data_, &result));
1577 EXPECT_EQ(u"\x0434\x0432\x0430 \x0441\x043B\x043E\x0432\x0430", result);
1579 EXPECT_TRUE(url.ExtractSearchTermsFromURL(
1580 GURL("http://utf-8.ru/path/%D0%B1%D1%83%D0%BA%D0%B2%D1%8B%20%D0%90%20"
1582 search_terms_data_, &result));
1583 EXPECT_EQ(u"\x0431\x0443\x043A\x0432\x044B \x0410 \x0438 A", result);
1586 // Checks that the ExtractSearchTermsFromURL function works correctly
1587 // for urls containing non-latin characters in non-UTF8 encoding.
1588 TEST_F(TemplateURLTest, ExtractSearchTermsFromNonUTF8URL) {
1589 TemplateURLData data;
1590 data.SetURL("http://windows-1251.ru/?q={searchTerms}");
1591 data.alternate_urls.push_back("http://windows-1251.ru/#q={searchTerms}");
1592 data.alternate_urls.push_back("http://windows-1251.ru/path/{searchTerms}");
1593 data.input_encodings.push_back("windows-1251");
1594 TemplateURL url(data);
1595 std::u16string result;
1597 // Russian text encoded with Windows-1251.
1598 EXPECT_TRUE(url.ExtractSearchTermsFromURL(
1599 GURL("http://windows-1251.ru/?q=%C7%E4%F0%E0%E2%F1%F2%E2%F3%E9%2C+"
1601 search_terms_data_, &result));
1603 u"\x0417\x0434\x0440\x0430\x0432\x0441\x0442\x0432\x0443\x0439, "
1604 u"\x043C\x0438\x0440!",
1607 EXPECT_TRUE(url.ExtractSearchTermsFromURL(
1608 GURL("http://windows-1251.ru/#q=%E4%E2%E0+%F1%EB%EE%E2%E0"),
1609 search_terms_data_, &result));
1610 EXPECT_EQ(u"\x0434\x0432\x0430 \x0441\x043B\x043E\x0432\x0430", result);
1612 EXPECT_TRUE(url.ExtractSearchTermsFromURL(
1613 GURL("http://windows-1251.ru/path/%E1%F3%EA%E2%FB%20%C0%20%E8%20A"),
1614 search_terms_data_, &result));
1615 EXPECT_EQ(u"\x0431\x0443\x043A\x0432\x044B \x0410 \x0438 A", result);
1618 // Checks that the ExtractSearchTermsFromURL function strips constant
1619 // prefix/suffix strings from the search terms param.
1620 TEST_F(TemplateURLTest, ExtractSearchTermsWithPrefixAndSuffix) {
1621 TemplateURLData data;
1622 data.alternate_urls.push_back(
1623 "http://www.example.com/?q=chromium-{searchTerms}@chromium.org");
1624 data.alternate_urls.push_back(
1625 "http://www.example.com/chromium-{searchTerms}@chromium.org/info");
1626 TemplateURL url(data);
1627 std::u16string result;
1629 EXPECT_TRUE(url.ExtractSearchTermsFromURL(
1630 GURL("http://www.example.com/?q=chromium-dev@chromium.org"),
1631 search_terms_data_, &result));
1632 EXPECT_EQ(u"dev", result);
1634 EXPECT_TRUE(url.ExtractSearchTermsFromURL(
1635 GURL("http://www.example.com/chromium-dev@chromium.org/info"),
1636 search_terms_data_, &result));
1637 EXPECT_EQ(u"dev", result);
1639 // Don't match if the prefix and suffix aren't there.
1640 EXPECT_FALSE(url.ExtractSearchTermsFromURL(
1641 GURL("http://www.example.com/?q=invalid"), search_terms_data_, &result));
1643 // Don't match if the prefix and suffix overlap.
1644 TemplateURLData data_with_overlap;
1645 data.alternate_urls.push_back(
1646 "http://www.example.com/?q=goo{searchTerms}oogle");
1647 TemplateURL url_with_overlap(data);
1648 EXPECT_FALSE(url_with_overlap.ExtractSearchTermsFromURL(
1649 GURL("http://www.example.com/?q=google"), search_terms_data_, &result));
1652 TEST_F(TemplateURLTest, ReplaceSearchTermsInURL) {
1653 TemplateURLData data;
1654 data.SetURL("http://google.com/?q={searchTerms}");
1655 data.alternate_urls.push_back("http://google.com/alt/#q={searchTerms}");
1656 data.alternate_urls.push_back(
1657 "http://google.com/alt/?ext=foo&q={searchTerms}#ref=bar");
1658 TemplateURL url(data);
1659 TemplateURLRef::SearchTermsArgs search_terms(u"Bob Morane");
1662 EXPECT_TRUE(url.ReplaceSearchTermsInURL(
1663 GURL("http://google.com/?q=something"), search_terms,
1664 search_terms_data_, &result));
1665 EXPECT_EQ(GURL("http://google.com/?q=Bob+Morane"), result);
1667 result = GURL("http://should.not.change.com");
1668 EXPECT_FALSE(url.ReplaceSearchTermsInURL(
1669 GURL("http://google.ca/?q=something"), search_terms,
1670 search_terms_data_, &result));
1671 EXPECT_EQ(GURL("http://should.not.change.com"), result);
1673 EXPECT_FALSE(url.ReplaceSearchTermsInURL(
1674 GURL("http://google.com/foo/?q=foo"), search_terms,
1675 search_terms_data_, &result));
1677 EXPECT_TRUE(url.ReplaceSearchTermsInURL(
1678 GURL("https://google.com/?q=foo"), search_terms,
1679 search_terms_data_, &result));
1680 EXPECT_EQ(GURL("https://google.com/?q=Bob+Morane"), result);
1682 EXPECT_FALSE(url.ReplaceSearchTermsInURL(
1683 GURL("http://google.com:8080/?q=foo"), search_terms,
1684 search_terms_data_, &result));
1686 EXPECT_TRUE(url.ReplaceSearchTermsInURL(
1687 GURL("http://google.com/?q=1+2+3&b=456"), search_terms,
1688 search_terms_data_, &result));
1689 EXPECT_EQ(GURL("http://google.com/?q=Bob+Morane&b=456"), result);
1691 // Note: Spaces in REF parameters are not escaped. See TryEncoding() in
1692 // template_url.cc for details.
1693 EXPECT_TRUE(url.ReplaceSearchTermsInURL(
1694 GURL("http://google.com/alt/?q=123#q=456"), search_terms,
1695 search_terms_data_, &result));
1696 EXPECT_EQ(GURL("http://google.com/alt/?q=123#q=Bob+Morane"), result);
1698 EXPECT_TRUE(url.ReplaceSearchTermsInURL(
1699 GURL("http://google.com/alt/?a=012&q=123&b=456#f=789"), search_terms,
1700 search_terms_data_, &result));
1701 EXPECT_EQ(GURL("http://google.com/alt/?a=012&q=Bob+Morane&b=456#f=789"),
1704 EXPECT_TRUE(url.ReplaceSearchTermsInURL(
1705 GURL("http://google.com/alt/?a=012&q=123&b=456#j=abc&q=789&h=def9"),
1706 search_terms, search_terms_data_, &result));
1707 EXPECT_EQ(GURL("http://google.com/alt/?a=012&q=123&b=456"
1708 "#j=abc&q=Bob+Morane&h=def9"), result);
1710 EXPECT_FALSE(url.ReplaceSearchTermsInURL(
1711 GURL("http://google.com/alt/?q="), search_terms,
1712 search_terms_data_, &result));
1714 EXPECT_FALSE(url.ReplaceSearchTermsInURL(
1715 GURL("http://google.com/alt/?#q="), search_terms,
1716 search_terms_data_, &result));
1718 EXPECT_FALSE(url.ReplaceSearchTermsInURL(
1719 GURL("http://google.com/alt/?q=#q="), search_terms,
1720 search_terms_data_, &result));
1722 EXPECT_FALSE(url.ReplaceSearchTermsInURL(
1723 GURL("http://google.com/alt/?q=123#q="), search_terms,
1724 search_terms_data_, &result));
1726 EXPECT_TRUE(url.ReplaceSearchTermsInURL(
1727 GURL("http://google.com/alt/?q=#q=123"), search_terms,
1728 search_terms_data_, &result));
1729 EXPECT_EQ(GURL("http://google.com/alt/?q=#q=Bob+Morane"), result);
1732 TEST_F(TemplateURLTest, ReplaceSearchTermsInURLPath) {
1733 TemplateURLData data;
1734 data.SetURL("http://term-in-path.com/begin/{searchTerms}/end");
1735 TemplateURL url(data);
1736 TemplateURLRef::SearchTermsArgs search_terms(u"Bob Morane");
1739 EXPECT_TRUE(url.ReplaceSearchTermsInURL(
1740 GURL("http://term-in-path.com/begin/something/end"), search_terms,
1741 search_terms_data_, &result));
1742 EXPECT_EQ(GURL("http://term-in-path.com/begin/Bob%20Morane/end"), result);
1744 EXPECT_TRUE(url.ReplaceSearchTermsInURL(
1745 GURL("http://term-in-path.com/begin/1%202%203/end"), search_terms,
1746 search_terms_data_, &result));
1747 EXPECT_EQ(GURL("http://term-in-path.com/begin/Bob%20Morane/end"), result);
1749 result = GURL("http://should.not.change.com");
1750 EXPECT_FALSE(url.ReplaceSearchTermsInURL(
1751 GURL("http://term-in-path.com/about"), search_terms,
1752 search_terms_data_, &result));
1753 EXPECT_EQ(GURL("http://should.not.change.com"), result);
1756 // Checks that the ReplaceSearchTermsInURL function works correctly
1757 // for search terms containing non-latin characters for a search engine
1758 // using UTF-8 input encoding.
1759 TEST_F(TemplateURLTest, ReplaceSearchTermsInUTF8URL) {
1760 TemplateURLData data;
1761 data.SetURL("http://utf-8.ru/?q={searchTerms}");
1762 data.alternate_urls.push_back("http://utf-8.ru/#q={searchTerms}");
1763 data.alternate_urls.push_back("http://utf-8.ru/path/{searchTerms}");
1764 TemplateURL url(data);
1766 // Russian text which will be encoded with UTF-8.
1767 TemplateURLRef::SearchTermsArgs search_terms(
1768 u"\x0442\x0435\x043A\x0441\x0442");
1771 EXPECT_TRUE(url.ReplaceSearchTermsInURL(
1772 GURL("http://utf-8.ru/?q=a+b"), search_terms, search_terms_data_,
1774 EXPECT_EQ(GURL("http://utf-8.ru/?q=%D1%82%D0%B5%D0%BA%D1%81%D1%82"),
1777 EXPECT_TRUE(url.ReplaceSearchTermsInURL(
1778 GURL("http://utf-8.ru/#q=a+b"), search_terms, search_terms_data_,
1780 EXPECT_EQ(GURL("http://utf-8.ru/#q=%D1%82%D0%B5%D0%BA%D1%81%D1%82"),
1783 EXPECT_TRUE(url.ReplaceSearchTermsInURL(
1784 GURL("http://utf-8.ru/path/a%20b"), search_terms, search_terms_data_,
1786 EXPECT_EQ(GURL("http://utf-8.ru/path/%D1%82%D0%B5%D0%BA%D1%81%D1%82"),
1790 // Checks that the ReplaceSearchTermsInURL function works correctly
1791 // for search terms containing non-latin characters for a search engine
1792 // using non UTF-8 input encoding.
1793 TEST_F(TemplateURLTest, ReplaceSearchTermsInNonUTF8URL) {
1794 TemplateURLData data;
1795 data.SetURL("http://windows-1251.ru/?q={searchTerms}");
1796 data.alternate_urls.push_back("http://windows-1251.ru/#q={searchTerms}");
1797 data.alternate_urls.push_back("http://windows-1251.ru/path/{searchTerms}");
1798 data.input_encodings.push_back("windows-1251");
1799 TemplateURL url(data);
1801 // Russian text which will be encoded with Windows-1251.
1802 TemplateURLRef::SearchTermsArgs search_terms(
1803 u"\x0442\x0435\x043A\x0441\x0442");
1806 EXPECT_TRUE(url.ReplaceSearchTermsInURL(
1807 GURL("http://windows-1251.ru/?q=a+b"), search_terms, search_terms_data_,
1809 EXPECT_EQ(GURL("http://windows-1251.ru/?q=%F2%E5%EA%F1%F2"),
1812 EXPECT_TRUE(url.ReplaceSearchTermsInURL(
1813 GURL("http://windows-1251.ru/#q=a+b"), search_terms, search_terms_data_,
1815 EXPECT_EQ(GURL("http://windows-1251.ru/#q=%F2%E5%EA%F1%F2"),
1818 EXPECT_TRUE(url.ReplaceSearchTermsInURL(
1819 GURL("http://windows-1251.ru/path/a%20b"), search_terms,
1820 search_terms_data_, &result));
1821 EXPECT_EQ(GURL("http://windows-1251.ru/path/%F2%E5%EA%F1%F2"),
1825 // Test the |additional_query_params| field of SearchTermsArgs.
1826 TEST_F(TemplateURLTest, SuggestQueryParams) {
1827 TemplateURLData data;
1828 // Pick a URL with replacements before, during, and after the query, to ensure
1829 // we don't goof up any of them.
1830 data.SetURL("{google:baseURL}search?q={searchTerms}"
1831 "#{google:originalQueryForSuggestion}x");
1832 TemplateURL url(data);
1834 // Baseline: no |additional_query_params| field.
1835 TemplateURLRef::SearchTermsArgs search_terms(u"abc");
1836 search_terms.original_query = u"def";
1837 search_terms.accepted_suggestion = 0;
1838 EXPECT_EQ("http://www.google.com/search?q=abc#oq=def&x",
1839 url.url_ref().ReplaceSearchTerms(search_terms, search_terms_data_));
1841 // Set the |additional_query_params|.
1842 search_terms.additional_query_params = "pq=xyz";
1843 EXPECT_EQ("http://www.google.com/search?pq=xyz&q=abc#oq=def&x",
1844 url.url_ref().ReplaceSearchTerms(search_terms, search_terms_data_));
1846 // Add |append_extra_query_params_from_command_line| into the mix, and ensure
1848 search_terms.append_extra_query_params_from_command_line = true;
1849 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
1850 switches::kExtraSearchQueryParams, "a=b");
1851 EXPECT_EQ("http://www.google.com/search?a=b&pq=xyz&q=abc#oq=def&x",
1852 url.url_ref().ReplaceSearchTerms(search_terms, search_terms_data_));
1855 // Test the |search_terms.append_extra_query_params_from_command_line| field of
1857 TEST_F(TemplateURLTest, ExtraQueryParams) {
1858 TemplateURLData data;
1859 // Pick a URL with replacements before, during, and after the query, to ensure
1860 // we don't goof up any of them.
1861 data.SetURL("{google:baseURL}search?q={searchTerms}"
1862 "#{google:originalQueryForSuggestion}x");
1863 TemplateURL url(data);
1865 // Baseline: no command-line args, no
1866 // |search_terms.append_extra_query_params_from_command_line| flag.
1867 TemplateURLRef::SearchTermsArgs search_terms(u"abc");
1868 search_terms.original_query = u"def";
1869 search_terms.accepted_suggestion = 0;
1870 EXPECT_EQ("http://www.google.com/search?q=abc#oq=def&x",
1871 url.url_ref().ReplaceSearchTerms(search_terms, search_terms_data_));
1873 // Set the flag. Since there are no command-line args, this should have no
1875 search_terms.append_extra_query_params_from_command_line = true;
1876 EXPECT_EQ("http://www.google.com/search?q=abc#oq=def&x",
1877 url.url_ref().ReplaceSearchTerms(search_terms, search_terms_data_));
1879 // Now append the command-line arg. This should be inserted into the query.
1880 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
1881 switches::kExtraSearchQueryParams, "a=b");
1882 EXPECT_EQ("http://www.google.com/search?a=b&q=abc#oq=def&x",
1883 url.url_ref().ReplaceSearchTerms(search_terms, search_terms_data_));
1885 // Turn off the flag. Now the command-line arg should be ignored again.
1886 search_terms.append_extra_query_params_from_command_line = false;
1887 EXPECT_EQ("http://www.google.com/search?q=abc#oq=def&x",
1888 url.url_ref().ReplaceSearchTerms(search_terms, search_terms_data_));
1891 // Tests replacing pageClassification.
1892 TEST_F(TemplateURLTest, ReplacePageClassification) {
1893 TemplateURLData data;
1894 data.input_encodings.push_back("UTF-8");
1895 data.SetURL("{google:baseURL}?{google:pageClassification}q={searchTerms}");
1896 TemplateURL url(data);
1897 EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
1898 ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
1899 TemplateURLRef::SearchTermsArgs search_terms_args(u"foo");
1901 std::string result = url.url_ref().ReplaceSearchTerms(search_terms_args,
1902 search_terms_data_);
1903 EXPECT_EQ("http://www.google.com/?q=foo", result);
1905 search_terms_args.page_classification = metrics::OmniboxEventProto::NTP;
1906 result = url.url_ref().ReplaceSearchTerms(search_terms_args,
1907 search_terms_data_);
1908 EXPECT_EQ("http://www.google.com/?pgcl=1&q=foo", result);
1910 search_terms_args.page_classification =
1911 metrics::OmniboxEventProto::HOME_PAGE;
1912 result = url.url_ref().ReplaceSearchTerms(search_terms_args,
1913 search_terms_data_);
1914 EXPECT_EQ("http://www.google.com/?pgcl=3&q=foo", result);
1917 // Test the IsSearchURL function.
1918 TEST_F(TemplateURLTest, IsSearchURL) {
1919 TemplateURLData data;
1920 data.SetURL("http://bar/search?q={searchTerms}");
1921 data.new_tab_url = "http://bar/newtab";
1922 data.alternate_urls.push_back("http://bar/?q={searchTerms}");
1923 data.alternate_urls.push_back("http://bar/#q={searchTerms}");
1924 data.alternate_urls.push_back("http://bar/search#q{searchTerms}");
1925 data.alternate_urls.push_back("http://bar/webhp#q={searchTerms}");
1926 TemplateURL search_provider(data);
1929 const char* const url;
1932 { "http://bar/search?q=foo&oq=foo", true, },
1933 { "http://bar/?q=foo&oq=foo", true, },
1934 { "http://bar/#output=search&q=foo&oq=foo", true, },
1935 { "http://bar/webhp#q=foo&oq=foo", true, },
1936 { "http://bar/#q=foo&oq=foo", true, },
1937 { "http://bar/?ext=foo&q=foo#ref=bar", true, },
1938 { "http://bar/url?url=http://www.foo.com/&q=foo#ref=bar", false, },
1939 { "http://bar/", false, },
1940 { "http://foo/", false, },
1941 { "http://bar/newtab", false, },
1944 for (size_t i = 0; i < std::size(url_data); ++i) {
1945 EXPECT_EQ(url_data[i].result,
1946 search_provider.IsSearchURL(GURL(url_data[i].url),
1947 search_terms_data_));
1951 TEST_F(TemplateURLTest, SearchboxVersionIncludedForAnswers) {
1952 TemplateURLData data;
1953 search_terms_data_.set_google_base_url("http://bar/");
1954 data.SetURL("http://bar/search?q={searchTerms}&{google:searchVersion}xssi=t");
1956 TemplateURL url(data);
1957 TemplateURLRef::SearchTermsArgs search_terms_args(u"foo");
1958 std::string result = url.url_ref().ReplaceSearchTerms(search_terms_args,
1959 search_terms_data_);
1960 EXPECT_EQ("http://bar/search?q=foo&gs_rn=42&xssi=t", result);
1963 TEST_F(TemplateURLTest, SessionToken) {
1964 TemplateURLData data;
1965 search_terms_data_.set_google_base_url("http://bar/");
1966 data.SetURL("http://bar/search?q={searchTerms}&{google:sessionToken}xssi=t");
1968 TemplateURL url(data);
1969 TemplateURLRef::SearchTermsArgs search_terms_args(u"foo");
1970 search_terms_args.session_token = "SESSIONTOKENGOESHERE";
1971 std::string result = url.url_ref().ReplaceSearchTerms(search_terms_args,
1972 search_terms_data_);
1973 EXPECT_EQ("http://bar/search?q=foo&psi=SESSIONTOKENGOESHERE&xssi=t", result);
1975 TemplateURL url2(data);
1976 search_terms_args.session_token = "";
1977 result = url.url_ref().ReplaceSearchTerms(search_terms_args,
1978 search_terms_data_);
1979 EXPECT_EQ("http://bar/search?q=foo&xssi=t", result);
1982 TEST_F(TemplateURLTest, ContextualSearchParameters) {
1983 TemplateURLData data;
1984 search_terms_data_.set_google_base_url("http://bar/");
1985 data.SetURL("http://bar/_/contextualsearch?"
1986 "{google:contextualSearchVersion}"
1987 "{google:contextualSearchContextData}");
1989 TemplateURL url(data);
1990 TemplateURLRef::SearchTermsArgs search_terms_args(u"foo");
1991 std::string result = url.url_ref().ReplaceSearchTerms(search_terms_args,
1992 search_terms_data_);
1993 EXPECT_EQ("http://bar/_/contextualsearch?", result);
1995 // Test the current common case, which uses no home country or previous
1997 TemplateURLRef::SearchTermsArgs::ContextualSearchParams params(
1998 2, 1, std::string(), 0, 0, false, std::string(), std::string(),
1999 std::string(), std::string(), false);
2000 search_terms_args.contextual_search_params = params;
2001 result = url.url_ref().ReplaceSearchTerms(search_terms_args,
2002 search_terms_data_);
2004 "http://bar/_/contextualsearch?"
2009 // Test the home country and non-zero event data case.
2010 search_terms_args.contextual_search_params =
2011 TemplateURLRef::SearchTermsArgs::ContextualSearchParams(
2012 2, 2, "CH", 1657713458, 5, false, std::string(), std::string(),
2013 std::string(), std::string(), false);
2015 url.url_ref().ReplaceSearchTerms(search_terms_args, search_terms_data_);
2018 "http://bar/_/contextualsearch?"
2022 "ctxsl_pid=1657713458&"
2026 // Test exact-search.
2027 search_terms_args.contextual_search_params =
2028 TemplateURLRef::SearchTermsArgs::ContextualSearchParams(
2029 2, 1, std::string(), 0, 0, true, std::string(), std::string(),
2030 std::string(), std::string(), false);
2032 url.url_ref().ReplaceSearchTerms(search_terms_args, search_terms_data_);
2034 size_t found_pos = result.find("ctxsl_exact=1");
2035 EXPECT_NE(found_pos, std::string::npos);
2037 // Test source and target languages.
2038 search_terms_args.contextual_search_params =
2039 TemplateURLRef::SearchTermsArgs::ContextualSearchParams(
2040 2, 1, std::string(), 0, 0, true, "es", "de", std::string(),
2041 std::string(), false);
2043 url.url_ref().ReplaceSearchTerms(search_terms_args, search_terms_data_);
2045 size_t source_pos = result.find("tlitesl=es");
2046 EXPECT_NE(source_pos, std::string::npos);
2047 size_t target_pos = result.find("tlitetl=de");
2048 EXPECT_NE(target_pos, std::string::npos);
2050 // Test fluent languages.
2051 search_terms_args.contextual_search_params =
2052 TemplateURLRef::SearchTermsArgs::ContextualSearchParams(
2053 2, 1, std::string(), 0, 0, true, std::string(), std::string(),
2054 "es,de", std::string(), false);
2056 url.url_ref().ReplaceSearchTerms(search_terms_args, search_terms_data_);
2057 // Find our param. These may actually be URL encoded.
2058 size_t fluent_pos = result.find("&ctxs_fls=es,de");
2059 EXPECT_NE(fluent_pos, std::string::npos);
2061 // Test Related Searches.
2062 search_terms_args.contextual_search_params =
2063 TemplateURLRef::SearchTermsArgs::ContextualSearchParams(
2064 2, 1, std::string(), 0, 0, true, std::string(), std::string(),
2065 std::string(), "1RbCu", false);
2067 url.url_ref().ReplaceSearchTerms(search_terms_args, search_terms_data_);
2069 size_t ctxsl_rs_pos = result.find("&ctxsl_rs=1RbCu");
2070 EXPECT_NE(ctxsl_rs_pos, std::string::npos);
2072 // Test apply language hint.
2073 search_terms_args.contextual_search_params =
2074 TemplateURLRef::SearchTermsArgs::ContextualSearchParams(
2075 2, 1, std::string(), 0, 0, true, std::string(), std::string(),
2076 std::string(), std::string(), true);
2078 url.url_ref().ReplaceSearchTerms(search_terms_args, search_terms_data_);
2080 size_t ctxsl_applylh = result.find("&ctxsl_applylh=1");
2081 EXPECT_NE(ctxsl_applylh, std::string::npos);
2084 TEST_F(TemplateURLTest, GenerateKeyword) {
2085 ASSERT_EQ(u"foo", TemplateURL::GenerateKeyword(GURL("http://foo")));
2086 ASSERT_EQ(u"foo.", TemplateURL::GenerateKeyword(GURL("http://foo.")));
2087 // www. should be stripped for a public hostname but not a private/intranet
2089 ASSERT_EQ(u"google.com",
2090 TemplateURL::GenerateKeyword(GURL("http://www.google.com")));
2091 ASSERT_EQ(u"www.foo", TemplateURL::GenerateKeyword(GURL("http://www.foo")));
2092 // Make sure we don't get a trailing '/'.
2093 ASSERT_EQ(u"blah", TemplateURL::GenerateKeyword(GURL("http://blah/")));
2094 // Don't generate the empty string.
2095 ASSERT_EQ(u"www.", TemplateURL::GenerateKeyword(GURL("http://www.")));
2096 ASSERT_EQ(u"абв", TemplateURL::GenerateKeyword(GURL("http://xn--80acd")));
2098 // Generated keywords must always be in lowercase, because TemplateURLs always
2099 // converts keywords to lowercase in its constructor and TemplateURLService
2100 // stores TemplateURLs in maps using keyword as key.
2101 EXPECT_TRUE(IsLowerCase(TemplateURL::GenerateKeyword(GURL("http://BLAH/"))));
2102 EXPECT_TRUE(IsLowerCase(
2103 TemplateURL::GenerateKeyword(GURL("http://embeddedhtml.<head>/"))));
2106 TEST_F(TemplateURLTest, KeepSearchTermsInURL) {
2107 search_terms_data_.set_google_base_url("http://bar/");
2109 TemplateURLData data;
2110 data.SetURL("http://bar/search?q={searchTerms}&{google:sessionToken}xssi=t");
2111 data.search_intent_params = {"gs_ssp", "si"};
2112 TemplateURL turl(data);
2114 TemplateURLRef::SearchTermsArgs search_terms_args(u"FOO");
2115 search_terms_args.session_token = "SESSIONTOKEN";
2118 // Optionally keeps non-empty search intent params.
2119 search_terms_args.additional_query_params = "gs_ssp=GS_SSP";
2120 std::string original_search_url = turl.url_ref().ReplaceSearchTerms(
2121 search_terms_args, search_terms_data_);
2122 EXPECT_EQ("http://bar/search?gs_ssp=GS_SSP&q=FOO&psi=SESSIONTOKEN&xssi=t",
2123 original_search_url);
2125 GURL canonical_search_url;
2126 EXPECT_TRUE(turl.KeepSearchTermsInURL(
2127 GURL(original_search_url), search_terms_data_,
2128 /*keep_search_intent_params=*/true, /*normalize_search_terms=*/true,
2129 &canonical_search_url));
2130 EXPECT_EQ("http://bar/search?gs_ssp=GS_SSP&q=foo&xssi=t",
2131 canonical_search_url);
2133 EXPECT_TRUE(turl.KeepSearchTermsInURL(
2134 GURL(original_search_url), search_terms_data_,
2135 /*keep_search_intent_params=*/false, /*normalize_search_terms=*/true,
2136 &canonical_search_url));
2137 EXPECT_EQ("http://bar/search?q=foo&xssi=t", canonical_search_url);
2140 // Optionally keeps empty search intent params.
2141 search_terms_args.additional_query_params = "gs_ssp=";
2142 std::string original_search_url = turl.url_ref().ReplaceSearchTerms(
2143 search_terms_args, search_terms_data_);
2144 EXPECT_EQ("http://bar/search?gs_ssp=&q=FOO&psi=SESSIONTOKEN&xssi=t",
2145 original_search_url);
2147 GURL canonical_search_url;
2148 EXPECT_TRUE(turl.KeepSearchTermsInURL(
2149 GURL(original_search_url), search_terms_data_,
2150 /*keep_search_intent_params=*/true, /*normalize_search_terms=*/true,
2151 &canonical_search_url));
2152 EXPECT_EQ("http://bar/search?gs_ssp=&q=foo&xssi=t", canonical_search_url);
2154 EXPECT_TRUE(turl.KeepSearchTermsInURL(
2155 GURL(original_search_url), search_terms_data_,
2156 /*keep_search_intent_params=*/false, /*normalize_search_terms=*/true,
2157 &canonical_search_url));
2158 EXPECT_EQ("http://bar/search?q=foo&xssi=t", canonical_search_url);
2161 // Discards params besides search terms and optionally search intent params.
2162 search_terms_args.additional_query_params = "wiz=baz&gs_ssp=GS_SSP";
2163 std::string original_search_url = turl.url_ref().ReplaceSearchTerms(
2164 search_terms_args, search_terms_data_);
2166 "http://bar/search?wiz=baz&gs_ssp=GS_SSP&q=FOO&psi=SESSIONTOKEN&xssi=t",
2167 original_search_url);
2169 GURL canonical_search_url;
2170 EXPECT_TRUE(turl.KeepSearchTermsInURL(
2171 GURL(original_search_url), search_terms_data_,
2172 /*keep_search_intent_params=*/true, /*normalize_search_terms=*/true,
2173 &canonical_search_url));
2174 EXPECT_EQ("http://bar/search?gs_ssp=GS_SSP&q=foo&xssi=t",
2175 canonical_search_url);
2177 EXPECT_TRUE(turl.KeepSearchTermsInURL(
2178 GURL(original_search_url), search_terms_data_,
2179 /*keep_search_intent_params=*/false, /*normalize_search_terms=*/true,
2180 &canonical_search_url));
2181 EXPECT_EQ("http://bar/search?q=foo&xssi=t", canonical_search_url);
2184 // Optionally keeps multiple search intent params.
2185 search_terms_args.additional_query_params = "si=SI&gs_ssp=GS_SSP";
2186 std::string original_search_url = turl.url_ref().ReplaceSearchTerms(
2187 search_terms_args, search_terms_data_);
2189 "http://bar/search?si=SI&gs_ssp=GS_SSP&q=FOO&psi=SESSIONTOKEN&xssi=t",
2190 original_search_url);
2192 GURL canonical_search_url;
2193 EXPECT_TRUE(turl.KeepSearchTermsInURL(
2194 GURL(original_search_url), search_terms_data_,
2195 /*keep_search_intent_params=*/true, /*normalize_search_terms=*/true,
2196 &canonical_search_url));
2197 EXPECT_EQ("http://bar/search?si=SI&gs_ssp=GS_SSP&q=foo&xssi=t",
2198 canonical_search_url);
2200 EXPECT_TRUE(turl.KeepSearchTermsInURL(
2201 GURL(original_search_url), search_terms_data_,
2202 /*keep_search_intent_params=*/false, /*normalize_search_terms=*/true,
2203 &canonical_search_url));
2204 EXPECT_EQ("http://bar/search?q=foo&xssi=t", canonical_search_url);
2207 // Search terms extraction, normalized or not.
2208 search_terms_args.additional_query_params = "gs_ssp=GS_SSP";
2209 std::string original_search_url = turl.url_ref().ReplaceSearchTerms(
2210 search_terms_args, search_terms_data_);
2211 EXPECT_EQ("http://bar/search?gs_ssp=GS_SSP&q=FOO&psi=SESSIONTOKEN&xssi=t",
2212 original_search_url);
2214 GURL canonical_search_url;
2215 std::u16string search_terms;
2216 EXPECT_TRUE(turl.KeepSearchTermsInURL(
2217 GURL(original_search_url), search_terms_data_,
2218 /*keep_search_intent_params=*/false, /*normalize_search_terms=*/true,
2219 &canonical_search_url, &search_terms));
2220 EXPECT_EQ("http://bar/search?q=foo&xssi=t", canonical_search_url);
2221 EXPECT_EQ(u"foo", search_terms);
2223 EXPECT_TRUE(turl.KeepSearchTermsInURL(
2224 GURL(original_search_url), search_terms_data_,
2225 /*keep_search_intent_params=*/false, /*normalize_search_terms=*/false,
2226 &canonical_search_url, &search_terms));
2227 EXPECT_EQ("http://bar/search?q=FOO&xssi=t", canonical_search_url);
2228 EXPECT_EQ(u"FOO", search_terms);
2232 TEST_F(TemplateURLTest, GenerateSearchURL) {
2233 struct GenerateSearchURLCase {
2234 const char* test_name;
2236 const char* expected;
2237 } generate_url_cases[] = {
2238 { "invalid URL", "foo{searchTerms}", "" },
2239 { "URL with no replacements", "http://foo/", "http://foo/" },
2240 { "basic functionality", "http://foo/{searchTerms}",
2241 "http://foo/blah.blah.blah.blah.blah" }
2244 for (const auto& generate_url_case : generate_url_cases) {
2245 TemplateURLData data;
2246 data.SetURL(generate_url_case.url);
2247 TemplateURL t_url(data);
2248 EXPECT_EQ(t_url.GenerateSearchURL(search_terms_data_).spec(),
2249 generate_url_case.expected)
2250 << generate_url_case.test_name << " failed.";
2254 TEST_F(TemplateURLTest, GenerateSuggestionURL) {
2255 struct GenerateSuggestionURLCase {
2256 const char* test_name;
2258 const char* expected;
2259 } generate_url_cases[] = {
2260 {"invalid URL", "foo{searchTerms}", ""},
2261 {"URL with no replacements", "http://foo/", "http://foo/"},
2262 {"basic functionality", "http://foo/{searchTerms}", "http://foo/"}};
2264 for (const auto& generate_url_case : generate_url_cases) {
2265 TemplateURLData data;
2266 data.suggestions_url = generate_url_case.url;
2267 TemplateURL t_url(data);
2268 EXPECT_EQ(t_url.GenerateSuggestionURL(search_terms_data_).spec(),
2269 generate_url_case.expected)
2270 << generate_url_case.test_name << " failed.";
2274 TEST_F(TemplateURLTest, PrefetchQueryParameters) {
2275 TemplateURLData data;
2276 search_terms_data_.set_google_base_url("http://bar/");
2277 data.SetURL("http://bar/search?q={searchTerms}&{google:prefetchQuery}xssi=t");
2279 TemplateURL url(data);
2280 TemplateURLRef::SearchTermsArgs search_terms_args(u"foo");
2281 search_terms_args.prefetch_query = "full query text";
2282 search_terms_args.prefetch_query_type = "2338";
2283 std::string result =
2284 url.url_ref().ReplaceSearchTerms(search_terms_args, search_terms_data_);
2285 EXPECT_EQ("http://bar/search?q=foo&pfq=full%20query%20text&qha=2338&xssi=t",
2288 TemplateURL url2(data);
2289 search_terms_args.prefetch_query.clear();
2290 search_terms_args.prefetch_query_type.clear();
2292 url2.url_ref().ReplaceSearchTerms(search_terms_args, search_terms_data_);
2293 EXPECT_EQ("http://bar/search?q=foo&xssi=t", result);
2296 // Tests that TemplateURL works correctly after changing the Google base URL
2297 // and invalidating cached values.
2298 TEST_F(TemplateURLTest, InvalidateCachedValues) {
2299 TemplateURLData data;
2300 data.SetURL("{google:baseURL}search?q={searchTerms}");
2301 data.suggestions_url = "{google:baseSuggestURL}search?q={searchTerms}";
2302 data.image_url = "{google:baseURL}searchbyimage/upload";
2303 data.image_translate_url = "{google:baseURL}searchbyimage/upload?translate";
2304 data.new_tab_url = "{google:baseURL}_/chrome/newtab";
2305 data.contextual_search_url = "{google:baseURL}_/contextualsearch";
2306 data.alternate_urls.push_back("{google:baseURL}s#q={searchTerms}");
2307 TemplateURL url(data);
2308 TemplateURLRef::SearchTermsArgs search_terms_args(u"X");
2309 std::u16string search_terms;
2311 EXPECT_TRUE(url.HasGoogleBaseURLs(search_terms_data_));
2312 EXPECT_EQ("http://www.google.com/search?q=X",
2313 url.url_ref().ReplaceSearchTerms(search_terms_args,
2314 search_terms_data_));
2315 EXPECT_EQ("http://www.google.com/s#q=X",
2316 url.url_refs()[0].ReplaceSearchTerms(search_terms_args,
2317 search_terms_data_));
2318 EXPECT_EQ("http://www.google.com/search?q=X",
2319 url.url_refs()[1].ReplaceSearchTerms(search_terms_args,
2320 search_terms_data_));
2321 EXPECT_EQ("http://www.google.com/complete/search?q=X",
2322 url.suggestions_url_ref().ReplaceSearchTerms(search_terms_args,
2323 search_terms_data_));
2324 EXPECT_EQ("http://www.google.com/searchbyimage/upload",
2325 url.image_url_ref().ReplaceSearchTerms(search_terms_args,
2326 search_terms_data_));
2327 EXPECT_EQ("http://www.google.com/searchbyimage/upload?translate",
2328 url.image_translate_url_ref().ReplaceSearchTerms(
2329 search_terms_args, search_terms_data_));
2330 EXPECT_EQ("http://www.google.com/_/chrome/newtab",
2331 url.new_tab_url_ref().ReplaceSearchTerms(search_terms_args,
2332 search_terms_data_));
2333 EXPECT_EQ("http://www.google.com/_/contextualsearch",
2334 url.contextual_search_url_ref().ReplaceSearchTerms(
2335 search_terms_args, search_terms_data_));
2337 EXPECT_TRUE(url.ExtractSearchTermsFromURL(
2338 GURL("http://www.google.com/search?q=Y+Z"),
2339 search_terms_data_, &search_terms));
2340 EXPECT_EQ(u"Y Z", search_terms);
2341 EXPECT_TRUE(url.ExtractSearchTermsFromURL(
2342 GURL("http://www.google.com/s#q=123"),
2343 search_terms_data_, &search_terms));
2344 EXPECT_EQ(u"123", search_terms);
2346 search_terms_data_.set_google_base_url("https://www.foo.org/");
2347 url.InvalidateCachedValues();
2349 EXPECT_TRUE(url.HasGoogleBaseURLs(search_terms_data_));
2350 EXPECT_EQ("https://www.foo.org/search?q=X",
2351 url.url_ref().ReplaceSearchTerms(search_terms_args,
2352 search_terms_data_));
2353 EXPECT_EQ("https://www.foo.org/s#q=X",
2354 url.url_refs()[0].ReplaceSearchTerms(search_terms_args,
2355 search_terms_data_));
2356 EXPECT_EQ("https://www.foo.org/search?q=X",
2357 url.url_refs()[1].ReplaceSearchTerms(search_terms_args,
2358 search_terms_data_));
2359 EXPECT_EQ("https://www.foo.org/complete/search?q=X",
2360 url.suggestions_url_ref().ReplaceSearchTerms(search_terms_args,
2361 search_terms_data_));
2362 EXPECT_EQ("https://www.foo.org/searchbyimage/upload",
2363 url.image_url_ref().ReplaceSearchTerms(search_terms_args,
2364 search_terms_data_));
2365 EXPECT_EQ("https://www.foo.org/searchbyimage/upload?translate",
2366 url.image_translate_url_ref().ReplaceSearchTerms(
2367 search_terms_args, search_terms_data_));
2368 EXPECT_EQ("https://www.foo.org/_/chrome/newtab",
2369 url.new_tab_url_ref().ReplaceSearchTerms(search_terms_args,
2370 search_terms_data_));
2371 EXPECT_EQ("https://www.foo.org/_/contextualsearch",
2372 url.contextual_search_url_ref().ReplaceSearchTerms(
2373 search_terms_args, search_terms_data_));
2375 EXPECT_TRUE(url.ExtractSearchTermsFromURL(
2376 GURL("https://www.foo.org/search?q=Y+Z"),
2377 search_terms_data_, &search_terms));
2378 EXPECT_EQ(u"Y Z", search_terms);
2379 EXPECT_TRUE(url.ExtractSearchTermsFromURL(
2380 GURL("https://www.foo.org/s#q=123"),
2381 search_terms_data_, &search_terms));
2382 EXPECT_EQ(u"123", search_terms);
2384 search_terms_data_.set_google_base_url("http://www.google.com/");
2387 // Tests the use of wildcards in the path to ensure both extracting search terms
2388 // and generating a search URL work correctly.
2389 TEST_F(TemplateURLTest, PathWildcard) {
2390 TemplateURLData data;
2392 "https://www.google.com/search{google:pathWildcard}?q={searchTerms}");
2393 TemplateURL url(data);
2395 // Test extracting search terms from a URL.
2396 std::u16string search_terms;
2397 url.ExtractSearchTermsFromURL(GURL("https://www.google.com/search?q=testing"),
2398 search_terms_data_, &search_terms);
2399 EXPECT_EQ(u"testing", search_terms);
2400 url.ExtractSearchTermsFromURL(
2401 GURL("https://www.google.com/search;_this_is_a_test;_?q=testing"),
2402 search_terms_data_, &search_terms);
2403 EXPECT_EQ(u"testing", search_terms);
2405 // Tests overlapping prefix/suffix.
2407 "https://www.google.com/search{google:pathWildcard}rch?q={searchTerms}");
2408 TemplateURL overlap_url(data);
2409 overlap_url.ExtractSearchTermsFromURL(
2410 GURL("https://www.google.com/search?q=testing"), search_terms_data_,
2412 EXPECT_TRUE(search_terms.empty());
2414 // Tests wildcard at beginning of path so we only have a suffix.
2416 "https://www.google.com/{google:pathWildcard}rch?q={searchTerms}");
2417 TemplateURL suffix_url(data);
2418 suffix_url.ExtractSearchTermsFromURL(
2419 GURL("https://www.google.com/search?q=testing"), search_terms_data_,
2421 EXPECT_EQ(u"testing", search_terms);
2423 // Tests wildcard between prefix/suffix.
2424 overlap_url.ExtractSearchTermsFromURL(
2425 GURL("https://www.google.com/search_testing_rch?q=testing"),
2426 search_terms_data_, &search_terms);
2427 EXPECT_EQ(u"testing", search_terms);
2429 // Test generating a URL.
2430 TemplateURLRef::SearchTermsArgs search_terms_args(u"foo");
2432 url.ReplaceSearchTermsInURL(url.GenerateSearchURL(search_terms_data_),
2433 search_terms_args, search_terms_data_,
2435 EXPECT_EQ("https://www.google.com/search?q=foo", generated_url.spec());
2438 TEST_F(TemplateURLTest, SideImageSearchParams) {
2439 TemplateURLData data;
2440 data.side_image_search_param = "sideimagesearch";
2441 TemplateURL url(data);
2443 // Adds query param with provided version to URL.
2445 url.GenerateSideImageSearchURL(GURL("http://foo.com/?q=123"), "1");
2446 EXPECT_EQ("http://foo.com/?q=123&sideimagesearch=1", result.spec());
2448 // Does not add query param if the provided URL already has that param and
2450 result = url.GenerateSideImageSearchURL(
2451 GURL("http://foo.com/?q=123&sideimagesearch=1"), "1");
2452 EXPECT_EQ("http://foo.com/?q=123&sideimagesearch=1", result.spec());
2454 // Updates version if the version on the query param does not match.
2455 result = url.GenerateSideImageSearchURL(
2456 GURL("http://foo.com/?q=123&sideimagesearch=2"), "1");
2457 EXPECT_EQ("http://foo.com/?q=123&sideimagesearch=1", result.spec());
2459 // Does nothing if the URL does not have the param.
2460 result = url.RemoveSideImageSearchParamFromURL(GURL("http://foo.com/?q=123"));
2461 EXPECT_EQ("http://foo.com/?q=123", result.spec());
2463 // Removes the param if the provided URL has it.
2464 result = url.RemoveSideImageSearchParamFromURL(
2465 GURL("http://foo.com/?q=123&sideimagesearch=1"));
2466 EXPECT_EQ("http://foo.com/?q=123", result.spec());
2468 // Removes the first instance of the query param that exist in the URL. This
2469 // should not happen but just asserting for expected behavior.
2470 result = url.RemoveSideImageSearchParamFromURL(
2471 GURL("http://foo.com/?q=123&sideimagesearch=1&sideimagesearch=2"));
2472 EXPECT_EQ("http://foo.com/?q=123&sideimagesearch=2", result.spec());
2475 TEST_F(TemplateURLTest, ImageTranslate) {
2477 const std::string image_translate_url;
2478 const std::string image_translate_source_language_param_key;
2479 const std::string image_translate_target_language_param_key;
2480 const std::string image_translate_source_locale;
2481 const std::string image_translate_target_locale;
2482 const std::string expected_result;
2484 {"https://lens.google.com/upload?filtertype=translate"
2485 "&{imageTranslateSourceLocale}{imageTranslateTargetLocale}",
2486 "sourcelang", "targetlang", "zh-CN", "fr",
2487 "https://lens.google.com/"
2488 "upload?filtertype=translate&sourcelang=zh-CN&targetlang=fr&"},
2489 {"https://www.foo.com/images/detail/search"
2490 "?ft=tr&{imageTranslateSourceLocale}{imageTranslateTargetLocale}"
2492 "sl", "tl", "ja", "es",
2493 "https://www.foo.com/images/detail/search?ft=tr&sl=ja&tl=es&#fragment"},
2494 {"https://bar.com/images/translate/"
2495 "{imageTranslateSourceLocale}/{imageTranslateTargetLocale}/",
2496 "", "", "ko", "de", "https://bar.com/images/translate/ko/de/"},
2498 TemplateURLData data;
2499 for (const auto& entry : test_data) {
2500 data.image_translate_url = entry.image_translate_url;
2501 data.image_translate_source_language_param_key =
2502 entry.image_translate_source_language_param_key;
2503 data.image_translate_target_language_param_key =
2504 entry.image_translate_target_language_param_key;
2505 TemplateURL url(data);
2506 TemplateURLRef::SearchTermsArgs search_terms_args(u"");
2507 search_terms_args.image_translate_source_locale =
2508 entry.image_translate_source_locale;
2509 search_terms_args.image_translate_target_locale =
2510 entry.image_translate_target_locale;
2511 GURL result(url.image_translate_url_ref().ReplaceSearchTerms(
2512 search_terms_args, search_terms_data_));
2513 ASSERT_TRUE(result.is_valid());
2514 EXPECT_EQ(entry.expected_result, result.spec());
2518 TEST_F(TemplateURLTest, ImageSearchBrandingLabel) {
2519 TemplateURLData data;
2520 data.SetShortName(u"foo");
2521 TemplateURL no_image_branding_url(data);
2523 // Without an image_search_branding_label set, should return short_name
2524 EXPECT_EQ(u"foo", no_image_branding_url.image_search_branding_label());
2526 data.image_search_branding_label = u"fooimages";
2527 TemplateURL image_branding_url(data);
2528 EXPECT_EQ(u"fooimages", image_branding_url.image_search_branding_label());