1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/autocomplete/autocomplete_provider.h" 6 7 #include "base/bind.h" 8 #include "base/command_line.h" 9 #include "base/memory/scoped_ptr.h" 10 #include "base/message_loop/message_loop.h" 11 #include "base/strings/string16.h" 12 #include "base/strings/string_number_conversions.h" 13 #include "base/strings/string_util.h" 14 #include "base/strings/utf_string_conversions.h" 15 #include "chrome/browser/autocomplete/autocomplete_controller.h" 16 #include "chrome/browser/autocomplete/autocomplete_input.h" 17 #include "chrome/browser/autocomplete/autocomplete_match.h" 18 #include "chrome/browser/autocomplete/autocomplete_provider_listener.h" 19 #include "chrome/browser/autocomplete/keyword_provider.h" 20 #include "chrome/browser/autocomplete/search_provider.h" 21 #include "chrome/browser/chrome_notification_types.h" 22 #include "chrome/browser/search_engines/template_url.h" 23 #include "chrome/browser/search_engines/template_url_service.h" 24 #include "chrome/browser/search_engines/template_url_service_factory.h" 25 #include "chrome/common/chrome_switches.h" 26 #include "chrome/test/base/testing_browser_process.h" 27 #include "chrome/test/base/testing_profile.h" 28 #include "content/public/browser/notification_observer.h" 29 #include "content/public/browser/notification_registrar.h" 30 #include "content/public/browser/notification_source.h" 31 #include "testing/gtest/include/gtest/gtest.h" 32 33 static std::ostream& operator<<(std::ostream& os, 34 const AutocompleteResult::const_iterator& it) { 35 return os << static_cast<const AutocompleteMatch*>(&(*it)); 36 } 37 38 namespace { 39 const size_t kResultsPerProvider = 3; 40 const char kTestTemplateURLKeyword[] = "t"; 41 } 42 43 // Autocomplete provider that provides known results. Note that this is 44 // refcounted so that it can also be a task on the message loop. 45 class TestProvider : public AutocompleteProvider { 46 public: 47 TestProvider(int relevance, const base::string16& prefix, 48 Profile* profile, 49 const base::string16 match_keyword) 50 : AutocompleteProvider(NULL, profile, AutocompleteProvider::TYPE_SEARCH), 51 relevance_(relevance), 52 prefix_(prefix), 53 match_keyword_(match_keyword) { 54 } 55 56 virtual void Start(const AutocompleteInput& input, 57 bool minimal_changes) OVERRIDE; 58 59 void set_listener(AutocompleteProviderListener* listener) { 60 listener_ = listener; 61 } 62 63 private: 64 virtual ~TestProvider() {} 65 66 void Run(); 67 68 void AddResults(int start_at, int num); 69 void AddResultsWithSearchTermsArgs( 70 int start_at, 71 int num, 72 AutocompleteMatch::Type type, 73 const TemplateURLRef::SearchTermsArgs& search_terms_args); 74 75 int relevance_; 76 const base::string16 prefix_; 77 const base::string16 match_keyword_; 78 }; 79 80 void TestProvider::Start(const AutocompleteInput& input, 81 bool minimal_changes) { 82 if (minimal_changes) 83 return; 84 85 matches_.clear(); 86 87 // Generate 4 results synchronously, the rest later. 88 AddResults(0, 1); 89 AddResultsWithSearchTermsArgs( 90 1, 1, AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, 91 TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("echo"))); 92 AddResultsWithSearchTermsArgs( 93 2, 1, AutocompleteMatchType::NAVSUGGEST, 94 TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("nav"))); 95 AddResultsWithSearchTermsArgs( 96 3, 1, AutocompleteMatchType::SEARCH_SUGGEST, 97 TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("query"))); 98 99 if (input.matches_requested() == AutocompleteInput::ALL_MATCHES) { 100 done_ = false; 101 base::MessageLoop::current()->PostTask( 102 FROM_HERE, base::Bind(&TestProvider::Run, this)); 103 } 104 } 105 106 void TestProvider::Run() { 107 DCHECK_GT(kResultsPerProvider, 0U); 108 AddResults(1, kResultsPerProvider); 109 done_ = true; 110 DCHECK(listener_); 111 listener_->OnProviderUpdate(true); 112 } 113 114 void TestProvider::AddResults(int start_at, int num) { 115 AddResultsWithSearchTermsArgs(start_at, 116 num, 117 AutocompleteMatchType::URL_WHAT_YOU_TYPED, 118 TemplateURLRef::SearchTermsArgs( 119 base::string16())); 120 } 121 122 void TestProvider::AddResultsWithSearchTermsArgs( 123 int start_at, 124 int num, 125 AutocompleteMatch::Type type, 126 const TemplateURLRef::SearchTermsArgs& search_terms_args) { 127 for (int i = start_at; i < num; i++) { 128 AutocompleteMatch match(this, relevance_ - i, false, type); 129 130 match.fill_into_edit = prefix_ + UTF8ToUTF16(base::IntToString(i)); 131 match.destination_url = GURL(UTF16ToUTF8(match.fill_into_edit)); 132 match.allowed_to_be_default_match = true; 133 134 match.contents = match.fill_into_edit; 135 match.contents_class.push_back( 136 ACMatchClassification(0, ACMatchClassification::NONE)); 137 match.description = match.fill_into_edit; 138 match.description_class.push_back( 139 ACMatchClassification(0, ACMatchClassification::NONE)); 140 match.search_terms_args.reset( 141 new TemplateURLRef::SearchTermsArgs(search_terms_args)); 142 if (!match_keyword_.empty()) { 143 match.keyword = match_keyword_; 144 ASSERT_TRUE(match.GetTemplateURL(profile_, false) != NULL); 145 } 146 147 matches_.push_back(match); 148 } 149 } 150 151 class AutocompleteProviderTest : public testing::Test, 152 public content::NotificationObserver { 153 protected: 154 struct KeywordTestData { 155 const base::string16 fill_into_edit; 156 const base::string16 keyword; 157 const bool expected_keyword_result; 158 }; 159 160 struct AssistedQueryStatsTestData { 161 const AutocompleteMatch::Type match_type; 162 const std::string expected_aqs; 163 }; 164 165 protected: 166 // Registers a test TemplateURL under the given keyword. 167 void RegisterTemplateURL(const base::string16 keyword, 168 const std::string& template_url); 169 170 // Resets |controller_| with two TestProviders. |provider1_ptr| and 171 // |provider2_ptr| are updated to point to the new providers if non-NULL. 172 void ResetControllerWithTestProviders(bool same_destinations, 173 TestProvider** provider1_ptr, 174 TestProvider** provider2_ptr); 175 176 // Runs a query on the input "a", and makes sure both providers' input is 177 // properly collected. 178 void RunTest(); 179 180 void RunRedundantKeywordTest(const KeywordTestData* match_data, size_t size); 181 182 void RunAssistedQueryStatsTest( 183 const AssistedQueryStatsTestData* aqs_test_data, 184 size_t size); 185 186 void RunQuery(const base::string16 query); 187 188 void ResetControllerWithKeywordAndSearchProviders(); 189 void ResetControllerWithKeywordProvider(); 190 void RunExactKeymatchTest(bool allow_exact_keyword_match); 191 192 void CopyResults(); 193 194 // Returns match.destination_url as it would be set by 195 // AutocompleteController::UpdateMatchDestinationURL(). 196 GURL GetDestinationURL(AutocompleteMatch match, 197 base::TimeDelta query_formulation_time) const; 198 199 AutocompleteResult result_; 200 scoped_ptr<AutocompleteController> controller_; 201 202 private: 203 // content::NotificationObserver: 204 virtual void Observe(int type, 205 const content::NotificationSource& source, 206 const content::NotificationDetails& details) OVERRIDE; 207 208 base::MessageLoopForUI message_loop_; 209 content::NotificationRegistrar registrar_; 210 TestingProfile profile_; 211 }; 212 213 void AutocompleteProviderTest::RegisterTemplateURL( 214 const base::string16 keyword, 215 const std::string& template_url) { 216 TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse( 217 &profile_, &TemplateURLServiceFactory::BuildInstanceFor); 218 TemplateURLData data; 219 data.SetURL(template_url); 220 data.SetKeyword(keyword); 221 TemplateURL* default_t_url = new TemplateURL(&profile_, data); 222 TemplateURLService* turl_model = 223 TemplateURLServiceFactory::GetForProfile(&profile_); 224 turl_model->Add(default_t_url); 225 turl_model->SetDefaultSearchProvider(default_t_url); 226 turl_model->Load(); 227 TemplateURLID default_provider_id = default_t_url->id(); 228 ASSERT_NE(0, default_provider_id); 229 } 230 231 void AutocompleteProviderTest::ResetControllerWithTestProviders( 232 bool same_destinations, 233 TestProvider** provider1_ptr, 234 TestProvider** provider2_ptr) { 235 // TODO: Move it outside this method, after refactoring the existing 236 // unit tests. Specifically: 237 // (1) Make sure that AutocompleteMatch.keyword is set iff there is 238 // a corresponding call to RegisterTemplateURL; otherwise the 239 // controller flow will crash; this practically means that 240 // RunTests/ResetControllerXXX/RegisterTemplateURL should 241 // be coordinated with each other. 242 // (2) Inject test arguments rather than rely on the hardcoded values, e.g. 243 // don't rely on kResultsPerProvided and default relevance ordering 244 // (B > A). 245 RegisterTemplateURL(ASCIIToUTF16(kTestTemplateURLKeyword), 246 "http://aqs/{searchTerms}/{google:assistedQueryStats}"); 247 248 ACProviders providers; 249 250 // Construct two new providers, with either the same or different prefixes. 251 TestProvider* provider1 = new TestProvider( 252 kResultsPerProvider, 253 ASCIIToUTF16("http://a"), 254 &profile_, 255 ASCIIToUTF16(kTestTemplateURLKeyword)); 256 provider1->AddRef(); 257 providers.push_back(provider1); 258 259 TestProvider* provider2 = new TestProvider( 260 kResultsPerProvider * 2, 261 same_destinations ? ASCIIToUTF16("http://a") : ASCIIToUTF16("http://b"), 262 &profile_, 263 base::string16()); 264 provider2->AddRef(); 265 providers.push_back(provider2); 266 267 // Reset the controller to contain our new providers. 268 controller_.reset(new AutocompleteController(&profile_, NULL, 0)); 269 // We're going to swap the providers vector, but the old vector should be 270 // empty so no elements need to be freed at this point. 271 EXPECT_TRUE(controller_->providers_.empty()); 272 controller_->providers_.swap(providers); 273 provider1->set_listener(controller_.get()); 274 provider2->set_listener(controller_.get()); 275 276 // The providers don't complete synchronously, so listen for "result updated" 277 // notifications. 278 registrar_.Add(this, 279 chrome::NOTIFICATION_AUTOCOMPLETE_CONTROLLER_RESULT_READY, 280 content::Source<AutocompleteController>(controller_.get())); 281 282 if (provider1_ptr) 283 *provider1_ptr = provider1; 284 if (provider2_ptr) 285 *provider2_ptr = provider2; 286 } 287 288 void AutocompleteProviderTest:: 289 ResetControllerWithKeywordAndSearchProviders() { 290 TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse( 291 &profile_, &TemplateURLServiceFactory::BuildInstanceFor); 292 293 // Reset the default TemplateURL. 294 TemplateURLData data; 295 data.SetURL("http://defaultturl/{searchTerms}"); 296 TemplateURL* default_t_url = new TemplateURL(&profile_, data); 297 TemplateURLService* turl_model = 298 TemplateURLServiceFactory::GetForProfile(&profile_); 299 turl_model->Add(default_t_url); 300 turl_model->SetDefaultSearchProvider(default_t_url); 301 TemplateURLID default_provider_id = default_t_url->id(); 302 ASSERT_NE(0, default_provider_id); 303 304 // Create another TemplateURL for KeywordProvider. 305 data.short_name = ASCIIToUTF16("k"); 306 data.SetKeyword(ASCIIToUTF16("k")); 307 data.SetURL("http://keyword/{searchTerms}"); 308 TemplateURL* keyword_t_url = new TemplateURL(&profile_, data); 309 turl_model->Add(keyword_t_url); 310 ASSERT_NE(0, keyword_t_url->id()); 311 312 controller_.reset(new AutocompleteController( 313 &profile_, NULL, 314 AutocompleteProvider::TYPE_KEYWORD | AutocompleteProvider::TYPE_SEARCH)); 315 } 316 317 void AutocompleteProviderTest::ResetControllerWithKeywordProvider() { 318 TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse( 319 &profile_, &TemplateURLServiceFactory::BuildInstanceFor); 320 321 TemplateURLService* turl_model = 322 TemplateURLServiceFactory::GetForProfile(&profile_); 323 324 // Create a TemplateURL for KeywordProvider. 325 TemplateURLData data; 326 data.short_name = ASCIIToUTF16("foo.com"); 327 data.SetKeyword(ASCIIToUTF16("foo.com")); 328 data.SetURL("http://foo.com/{searchTerms}"); 329 TemplateURL* keyword_t_url = new TemplateURL(&profile_, data); 330 turl_model->Add(keyword_t_url); 331 ASSERT_NE(0, keyword_t_url->id()); 332 333 // Create another TemplateURL for KeywordProvider. 334 data.short_name = ASCIIToUTF16("bar.com"); 335 data.SetKeyword(ASCIIToUTF16("bar.com")); 336 data.SetURL("http://bar.com/{searchTerms}"); 337 keyword_t_url = new TemplateURL(&profile_, data); 338 turl_model->Add(keyword_t_url); 339 ASSERT_NE(0, keyword_t_url->id()); 340 341 controller_.reset(new AutocompleteController( 342 &profile_, NULL, AutocompleteProvider::TYPE_KEYWORD)); 343 } 344 345 void AutocompleteProviderTest::RunTest() { 346 RunQuery(ASCIIToUTF16("a")); 347 } 348 349 void AutocompleteProviderTest::RunRedundantKeywordTest( 350 const KeywordTestData* match_data, 351 size_t size) { 352 ACMatches matches; 353 for (size_t i = 0; i < size; ++i) { 354 AutocompleteMatch match; 355 match.relevance = 1000; // Arbitrary non-zero value. 356 match.allowed_to_be_default_match = true; 357 match.fill_into_edit = match_data[i].fill_into_edit; 358 match.transition = content::PAGE_TRANSITION_KEYWORD; 359 match.keyword = match_data[i].keyword; 360 matches.push_back(match); 361 } 362 363 AutocompleteResult result; 364 result.AppendMatches(matches); 365 controller_->UpdateAssociatedKeywords(&result); 366 367 for (size_t j = 0; j < result.size(); ++j) { 368 EXPECT_EQ(match_data[j].expected_keyword_result, 369 result.match_at(j)->associated_keyword.get() != NULL); 370 } 371 } 372 373 void AutocompleteProviderTest::RunAssistedQueryStatsTest( 374 const AssistedQueryStatsTestData* aqs_test_data, 375 size_t size) { 376 // Prepare input. 377 const size_t kMaxRelevance = 1000; 378 ACMatches matches; 379 for (size_t i = 0; i < size; ++i) { 380 AutocompleteMatch match(NULL, kMaxRelevance - i, false, 381 aqs_test_data[i].match_type); 382 match.allowed_to_be_default_match = true; 383 match.keyword = ASCIIToUTF16(kTestTemplateURLKeyword); 384 match.search_terms_args.reset( 385 new TemplateURLRef::SearchTermsArgs(base::string16())); 386 matches.push_back(match); 387 } 388 result_.Reset(); 389 result_.AppendMatches(matches); 390 391 // Update AQS. 392 controller_->UpdateAssistedQueryStats(&result_); 393 394 // Verify data. 395 for (size_t i = 0; i < size; ++i) { 396 EXPECT_EQ(aqs_test_data[i].expected_aqs, 397 result_.match_at(i)->search_terms_args->assisted_query_stats); 398 } 399 } 400 401 void AutocompleteProviderTest::RunQuery(const base::string16 query) { 402 result_.Reset(); 403 controller_->Start(AutocompleteInput( 404 query, base::string16::npos, base::string16(), GURL(), 405 AutocompleteInput::INVALID_SPEC, true, false, true, 406 AutocompleteInput::ALL_MATCHES)); 407 408 if (!controller_->done()) 409 // The message loop will terminate when all autocomplete input has been 410 // collected. 411 base::MessageLoop::current()->Run(); 412 } 413 414 void AutocompleteProviderTest::RunExactKeymatchTest( 415 bool allow_exact_keyword_match) { 416 // Send the controller input which exactly matches the keyword provider we 417 // created in ResetControllerWithKeywordAndSearchProviders(). The default 418 // match should thus be a search-other-engine match iff 419 // |allow_exact_keyword_match| is true. Regardless, the match should 420 // be from SearchProvider. (It provides all verbatim search matches, 421 // keyword or not.) 422 controller_->Start(AutocompleteInput( 423 ASCIIToUTF16("k test"), base::string16::npos, base::string16(), GURL(), 424 AutocompleteInput::INVALID_SPEC, true, false, allow_exact_keyword_match, 425 AutocompleteInput::SYNCHRONOUS_MATCHES)); 426 EXPECT_TRUE(controller_->done()); 427 EXPECT_EQ(AutocompleteProvider::TYPE_SEARCH, 428 controller_->result().default_match()->provider->type()); 429 EXPECT_EQ(allow_exact_keyword_match ? 430 AutocompleteMatchType::SEARCH_OTHER_ENGINE : 431 AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, 432 controller_->result().default_match()->type); 433 } 434 435 void AutocompleteProviderTest::CopyResults() { 436 result_.CopyFrom(controller_->result()); 437 } 438 439 GURL AutocompleteProviderTest::GetDestinationURL( 440 AutocompleteMatch match, 441 base::TimeDelta query_formulation_time) const { 442 controller_->UpdateMatchDestinationURL(query_formulation_time, &match); 443 return match.destination_url; 444 } 445 446 void AutocompleteProviderTest::Observe( 447 int type, 448 const content::NotificationSource& source, 449 const content::NotificationDetails& details) { 450 if (controller_->done()) { 451 CopyResults(); 452 base::MessageLoop::current()->Quit(); 453 } 454 } 455 456 // Tests that the default selection is set properly when updating results. 457 TEST_F(AutocompleteProviderTest, Query) { 458 TestProvider* provider1 = NULL; 459 TestProvider* provider2 = NULL; 460 ResetControllerWithTestProviders(false, &provider1, &provider2); 461 RunTest(); 462 463 // Make sure the default match gets set to the highest relevance match. The 464 // highest relevance matches should come from the second provider. 465 EXPECT_EQ(kResultsPerProvider * 2, result_.size()); 466 ASSERT_NE(result_.end(), result_.default_match()); 467 EXPECT_EQ(provider2, result_.default_match()->provider); 468 } 469 470 // Tests assisted query stats. 471 TEST_F(AutocompleteProviderTest, AssistedQueryStats) { 472 ResetControllerWithTestProviders(false, NULL, NULL); 473 RunTest(); 474 475 ASSERT_EQ(kResultsPerProvider * 2, result_.size()); 476 477 // Now, check the results from the second provider, as they should not have 478 // assisted query stats set. 479 for (size_t i = 0; i < kResultsPerProvider; ++i) { 480 EXPECT_TRUE( 481 result_.match_at(i)->search_terms_args->assisted_query_stats.empty()); 482 } 483 // The first provider has a test keyword, so AQS should be non-empty. 484 for (size_t i = kResultsPerProvider; i < kResultsPerProvider * 2; ++i) { 485 EXPECT_FALSE( 486 result_.match_at(i)->search_terms_args->assisted_query_stats.empty()); 487 } 488 } 489 490 TEST_F(AutocompleteProviderTest, RemoveDuplicates) { 491 TestProvider* provider1 = NULL; 492 TestProvider* provider2 = NULL; 493 ResetControllerWithTestProviders(true, &provider1, &provider2); 494 RunTest(); 495 496 // Make sure all the first provider's results were eliminated by the second 497 // provider's. 498 EXPECT_EQ(kResultsPerProvider, result_.size()); 499 for (AutocompleteResult::const_iterator i(result_.begin()); 500 i != result_.end(); ++i) 501 EXPECT_EQ(provider2, i->provider); 502 } 503 504 TEST_F(AutocompleteProviderTest, AllowExactKeywordMatch) { 505 ResetControllerWithKeywordAndSearchProviders(); 506 RunExactKeymatchTest(true); 507 RunExactKeymatchTest(false); 508 } 509 510 // Ensures matches from (only) the default search provider respect any extra 511 // query params set on the command line. 512 TEST_F(AutocompleteProviderTest, ExtraQueryParams) { 513 ResetControllerWithKeywordAndSearchProviders(); 514 CommandLine::ForCurrentProcess()->AppendSwitchASCII( 515 switches::kExtraSearchQueryParams, "a=b"); 516 RunExactKeymatchTest(true); 517 CopyResults(); 518 ASSERT_EQ(2U, result_.size()); 519 EXPECT_EQ("http://keyword/test", 520 result_.match_at(0)->destination_url.possibly_invalid_spec()); 521 EXPECT_EQ("http://defaultturl/k%20test?a=b", 522 result_.match_at(1)->destination_url.possibly_invalid_spec()); 523 } 524 525 // Test that redundant associated keywords are removed. 526 TEST_F(AutocompleteProviderTest, RedundantKeywordsIgnoredInResult) { 527 ResetControllerWithKeywordProvider(); 528 529 { 530 KeywordTestData duplicate_url[] = { 531 { ASCIIToUTF16("fo"), base::string16(), false }, 532 { ASCIIToUTF16("foo.com"), base::string16(), true }, 533 { ASCIIToUTF16("foo.com"), base::string16(), false } 534 }; 535 536 SCOPED_TRACE("Duplicate url"); 537 RunRedundantKeywordTest(duplicate_url, ARRAYSIZE_UNSAFE(duplicate_url)); 538 } 539 540 { 541 KeywordTestData keyword_match[] = { 542 { ASCIIToUTF16("foo.com"), ASCIIToUTF16("foo.com"), false }, 543 { ASCIIToUTF16("foo.com"), base::string16(), false } 544 }; 545 546 SCOPED_TRACE("Duplicate url with keyword match"); 547 RunRedundantKeywordTest(keyword_match, ARRAYSIZE_UNSAFE(keyword_match)); 548 } 549 550 { 551 KeywordTestData multiple_keyword[] = { 552 { ASCIIToUTF16("fo"), base::string16(), false }, 553 { ASCIIToUTF16("foo.com"), base::string16(), true }, 554 { ASCIIToUTF16("foo.com"), base::string16(), false }, 555 { ASCIIToUTF16("bar.com"), base::string16(), true }, 556 }; 557 558 SCOPED_TRACE("Duplicate url with multiple keywords"); 559 RunRedundantKeywordTest(multiple_keyword, 560 ARRAYSIZE_UNSAFE(multiple_keyword)); 561 } 562 } 563 564 TEST_F(AutocompleteProviderTest, UpdateAssistedQueryStats) { 565 ResetControllerWithTestProviders(false, NULL, NULL); 566 567 { 568 AssistedQueryStatsTestData test_data[] = { 569 // MSVC doesn't support zero-length arrays, so supply some dummy data. 570 { AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, "" } 571 }; 572 SCOPED_TRACE("No matches"); 573 // Note: We pass 0 here to ignore the dummy data above. 574 RunAssistedQueryStatsTest(test_data, 0); 575 } 576 577 { 578 AssistedQueryStatsTestData test_data[] = { 579 { AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, "chrome..69i57" } 580 }; 581 SCOPED_TRACE("One match"); 582 RunAssistedQueryStatsTest(test_data, ARRAYSIZE_UNSAFE(test_data)); 583 } 584 585 { 586 AssistedQueryStatsTestData test_data[] = { 587 { AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, 588 "chrome..69i57j69i58j5l2j0l3j69i59" }, 589 { AutocompleteMatchType::URL_WHAT_YOU_TYPED, 590 "chrome..69i57j69i58j5l2j0l3j69i59" }, 591 { AutocompleteMatchType::NAVSUGGEST, 592 "chrome.2.69i57j69i58j5l2j0l3j69i59" }, 593 { AutocompleteMatchType::NAVSUGGEST, 594 "chrome.3.69i57j69i58j5l2j0l3j69i59" }, 595 { AutocompleteMatchType::SEARCH_SUGGEST, 596 "chrome.4.69i57j69i58j5l2j0l3j69i59" }, 597 { AutocompleteMatchType::SEARCH_SUGGEST, 598 "chrome.5.69i57j69i58j5l2j0l3j69i59" }, 599 { AutocompleteMatchType::SEARCH_SUGGEST, 600 "chrome.6.69i57j69i58j5l2j0l3j69i59" }, 601 { AutocompleteMatchType::SEARCH_HISTORY, 602 "chrome.7.69i57j69i58j5l2j0l3j69i59" }, 603 }; 604 SCOPED_TRACE("Multiple matches"); 605 RunAssistedQueryStatsTest(test_data, ARRAYSIZE_UNSAFE(test_data)); 606 } 607 } 608 609 TEST_F(AutocompleteProviderTest, GetDestinationURL) { 610 ResetControllerWithKeywordAndSearchProviders(); 611 612 // For the destination URL to have aqs parameters for query formulation time 613 // and the field trial triggered bit, many conditions need to be satisfied. 614 AutocompleteMatch match(NULL, 1100, false, 615 AutocompleteMatchType::SEARCH_SUGGEST); 616 GURL url(GetDestinationURL(match, base::TimeDelta::FromMilliseconds(2456))); 617 EXPECT_TRUE(url.path().empty()); 618 619 // The protocol needs to be https. 620 RegisterTemplateURL(ASCIIToUTF16(kTestTemplateURLKeyword), 621 "https://aqs/{searchTerms}/{google:assistedQueryStats}"); 622 url = GetDestinationURL(match, base::TimeDelta::FromMilliseconds(2456)); 623 EXPECT_TRUE(url.path().empty()); 624 625 // There needs to be a keyword provider. 626 match.keyword = ASCIIToUTF16(kTestTemplateURLKeyword); 627 url = GetDestinationURL(match, base::TimeDelta::FromMilliseconds(2456)); 628 EXPECT_TRUE(url.path().empty()); 629 630 // search_terms_args needs to be set. 631 match.search_terms_args.reset( 632 new TemplateURLRef::SearchTermsArgs(base::string16())); 633 url = GetDestinationURL(match, base::TimeDelta::FromMilliseconds(2456)); 634 EXPECT_TRUE(url.path().empty()); 635 636 // assisted_query_stats needs to have been previously set. 637 match.search_terms_args->assisted_query_stats = 638 "chrome.0.69i57j69i58j5l2j0l3j69i59"; 639 url = GetDestinationURL(match, base::TimeDelta::FromMilliseconds(2456)); 640 EXPECT_EQ("//aqs=chrome.0.69i57j69i58j5l2j0l3j69i59.2456j0j0&", url.path()); 641 642 // Test field trial triggered bit set. 643 controller_->search_provider_->field_trial_triggered_in_session_ = true; 644 EXPECT_TRUE( 645 controller_->search_provider_->field_trial_triggered_in_session()); 646 url = GetDestinationURL(match, base::TimeDelta::FromMilliseconds(2456)); 647 EXPECT_EQ("//aqs=chrome.0.69i57j69i58j5l2j0l3j69i59.2456j1j0&", url.path()); 648 649 // Test page classification set. 650 controller_->input_.current_page_classification_ = AutocompleteInput::OTHER; 651 controller_->search_provider_->field_trial_triggered_in_session_ = false; 652 EXPECT_FALSE( 653 controller_->search_provider_->field_trial_triggered_in_session()); 654 url = GetDestinationURL(match, base::TimeDelta::FromMilliseconds(2456)); 655 EXPECT_EQ("//aqs=chrome.0.69i57j69i58j5l2j0l3j69i59.2456j0j4&", url.path()); 656 657 // Test page classification and field trial triggered set. 658 controller_->search_provider_->field_trial_triggered_in_session_ = true; 659 EXPECT_TRUE( 660 controller_->search_provider_->field_trial_triggered_in_session()); 661 url = GetDestinationURL(match, base::TimeDelta::FromMilliseconds(2456)); 662 EXPECT_EQ("//aqs=chrome.0.69i57j69i58j5l2j0l3j69i59.2456j1j4&", url.path()); 663 } 664