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